@@ -993,46 +993,49 @@ def _has_required_id_and_tails_path():
993993 rev_list = None
994994
995995 if _has_required_id_and_tails_path ():
996- async with self .profile .session () as session :
997- rev_reg_def = await session .handle .fetch (
998- CATEGORY_REV_REG_DEF , rev_reg_def_id
999- )
1000- rev_list = await session .handle .fetch (CATEGORY_REV_LIST , rev_reg_def_id )
1001- rev_key = await session .handle .fetch (
996+ # We need to make sure the read, index increment, and write
997+ # operations are done in a transaction.
998+ # TODO: This isn't fully atomic in a clustered environment as the
999+ # read transaction may happen concurrently with another.
1000+ async with self .profile .transaction () as txn :
1001+ rev_reg_def = await txn .handle .fetch (CATEGORY_REV_REG_DEF , rev_reg_def_id )
1002+ rev_list = await txn .handle .fetch (CATEGORY_REV_LIST , rev_reg_def_id )
1003+ rev_key = await txn .handle .fetch (
10021004 CATEGORY_REV_REG_DEF_PRIVATE , rev_reg_def_id
10031005 )
10041006
1005- _handle_missing_entries (rev_list , rev_reg_def , rev_key )
1007+ _handle_missing_entries (rev_list , rev_reg_def , rev_key )
10061008
1007- rev_list_value_json = rev_list .value_json
1008- rev_list_tags = rev_list .tags
1009+ rev_list_value_json = rev_list .value_json
1010+ rev_list_tags = rev_list .tags
10091011
1010- # If the rev_list state is failed then the tails file was never uploaded,
1011- # try to upload it now and finish the revocation list
1012- if rev_list_tags .get ("state" ) == RevListState .STATE_FAILED :
1013- await self .upload_tails_file (
1014- RevRegDef .deserialize (rev_reg_def .value_json )
1015- )
1016- rev_list_tags ["state" ] = RevListState .STATE_FINISHED
1017-
1018- rev_reg_index = rev_list_value_json ["next_index" ]
1019- try :
1020- rev_reg_def = RevocationRegistryDefinition .load (rev_reg_def .raw_value )
1021- rev_list = RevocationStatusList .load (rev_list_value_json ["rev_list" ])
1022- except AnoncredsError as err :
1023- raise AnonCredsRevocationError (
1024- "Error loading revocation registry"
1025- ) from err
1012+ # If the rev_list state is failed then the tails file was never uploaded,
1013+ # try to upload it now and finish the revocation list
1014+ if rev_list_tags .get ("state" ) == RevListState .STATE_FAILED :
1015+ await self .upload_tails_file (
1016+ RevRegDef .deserialize (rev_reg_def .value_json )
1017+ )
1018+ rev_list_tags ["state" ] = RevListState .STATE_FINISHED
10261019
1027- # NOTE: we increment the index ahead of time to keep the
1028- # transaction short. The revocation registry itself will NOT
1029- # be updated because we always use ISSUANCE_BY_DEFAULT.
1030- # If something goes wrong later, the index will be skipped.
1031- # FIXME - double check issuance type in case of upgraded wallet?
1032- if rev_reg_index > rev_reg_def .max_cred_num :
1033- raise AnonCredsRevocationRegistryFullError ("Revocation registry is full" )
1034- rev_list_value_json ["next_index" ] = rev_reg_index + 1
1035- async with self .profile .transaction () as txn :
1020+ rev_reg_index = rev_list_value_json ["next_index" ]
1021+ try :
1022+ rev_reg_def = RevocationRegistryDefinition .load (rev_reg_def .raw_value )
1023+ rev_list = RevocationStatusList .load (rev_list_value_json ["rev_list" ])
1024+ except AnoncredsError as err :
1025+ raise AnonCredsRevocationError (
1026+ "Error loading revocation registry"
1027+ ) from err
1028+
1029+ # NOTE: we increment the index ahead of time to keep the
1030+ # transaction short. The revocation registry itself will NOT
1031+ # be updated because we always use ISSUANCE_BY_DEFAULT.
1032+ # If something goes wrong later, the index will be skipped.
1033+ # FIXME - double check issuance type in case of upgraded wallet?
1034+ if rev_reg_index > rev_reg_def .max_cred_num :
1035+ raise AnonCredsRevocationRegistryFullError (
1036+ "Revocation registry is full"
1037+ )
1038+ rev_list_value_json ["next_index" ] = rev_reg_index + 1
10361039 await txn .handle .replace (
10371040 CATEGORY_REV_LIST ,
10381041 rev_reg_def_id ,
0 commit comments