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