@@ -269,29 +269,37 @@ def create_rev_reg_def() -> Tuple[
269269
270270 rev_reg_def = RevRegDef .from_native (rev_reg_def )
271271
272- # Generate a temporary identifier for storing the private key
273- # We don't know the final rev_reg_def_id until after registry creation
274- temp_private_key_id = f"temp_private_{ uuid4 ()} "
272+ # Generate and set the public tails URI
273+ public_tails_uri = self .generate_public_tails_uri (rev_reg_def )
274+ rev_reg_def .value .tails_location = public_tails_uri
275+
276+ # Upload tails file
277+ await self .upload_tails_file (rev_reg_def )
278+
279+ # We want to store the private key now so we can recover it in case of failure
280+ # Example of failure and recovery scenario:
281+ # - Rev reg creation is requested, but agent terminates before it completes.
282+ # - Rev reg creation actually succeeded on the ledger, but the agent never
283+ # got the response to emit next event, so on recovery, tries to recreate it.
284+ # - The ledger should return the existing rev reg, instead of recreating it.
285+ # We don't know the rev_reg_def_id until after registry creation, so to link
286+ # the rev reg with the private key, we can instead use the tails hash, which
287+ # is known, and then we recover the private key from storage using the tails
288+ # file hash of the returned RevRegDefResult
275289
276290 # Store the private definition with temporary identifier to avoid losing it
291+ private_key_storage_id = self ._get_private_key_storage_id (rev_reg_def )
277292 LOGGER .debug (
278- "Storing private revocation registry definition with temp ID: %s" ,
279- temp_private_key_id ,
293+ "Storing private revocation registry definition with storage ID: %s" ,
294+ private_key_storage_id ,
280295 )
281296 async with self .profile .session () as session :
282297 await session .handle .insert (
283298 CATEGORY_REV_REG_DEF_PRIVATE ,
284- temp_private_key_id ,
299+ private_key_storage_id ,
285300 rev_reg_def_private .to_json_buffer (),
286301 )
287302
288- # Generate and set the public tails URI
289- public_tails_uri = self .generate_public_tails_uri (rev_reg_def )
290- rev_reg_def .value .tails_location = public_tails_uri
291-
292- # Upload tails file
293- await self .upload_tails_file (rev_reg_def )
294-
295303 # Register on network
296304 anoncreds_registry = self .profile .inject (AnonCredsRegistry )
297305 result = await anoncreds_registry .register_revocation_registry_definition (
@@ -308,14 +316,11 @@ def create_rev_reg_def() -> Tuple[
308316 tag ,
309317 max_cred_num ,
310318 )
311- # Include temp_private_key_id in options for potential recovery
312- options_with_temp_id = options .copy ()
313- options_with_temp_id ["temp_private_key_id" ] = temp_private_key_id
314319
315320 event = RevRegDefCreateResponseEvent .with_payload (
316321 rev_reg_def_result = result ,
317322 rev_reg_def = rev_reg_def ,
318- options = options_with_temp_id ,
323+ options = options ,
319324 )
320325 await self .notify (event )
321326
@@ -337,11 +342,6 @@ def create_rev_reg_def() -> Tuple[
337342
338343 LOGGER .warning (f"{ error_msg } . Emitting failure event." )
339344
340- # Include temp_private_key_id in options for potential recovery
341- failure_options = options .copy ()
342- if "temp_private_key_id" in locals ():
343- failure_options ["temp_private_key_id" ] = temp_private_key_id
344-
345345 event = RevRegDefCreateResponseEvent .with_failure (
346346 error_msg = error_msg ,
347347 should_retry = should_retry ,
@@ -351,7 +351,7 @@ def create_rev_reg_def() -> Tuple[
351351 registry_type = registry_type ,
352352 tag = tag ,
353353 max_cred_num = max_cred_num ,
354- options = failure_options ,
354+ options = options ,
355355 )
356356 await self .notify (event )
357357
@@ -481,20 +481,18 @@ async def store_revocation_registry_definition( # ✅
481481 rev_reg_def_state = result .revocation_registry_definition_state .state
482482
483483 try :
484- temp_private_key_id = options .pop ("temp_private_key_id" , None )
485- if not temp_private_key_id :
486- LOGGER .error ("No temp private key id found in options" )
487- raise AnonCredsRevocationError ("No temp private key id found in options" )
484+ private_key_storage_id = self ._get_private_key_storage_id (rev_reg_def )
488485
489486 # Read the private definition from storage (stored immediately after creation)
490487 async with self .profile .session () as session :
491488 rev_reg_def_private_entry = await session .handle .fetch (
492- CATEGORY_REV_REG_DEF_PRIVATE , temp_private_key_id
489+ CATEGORY_REV_REG_DEF_PRIVATE , private_key_storage_id
493490 )
494491
495492 if not rev_reg_def_private_entry :
496493 raise AnonCredsRevocationError (
497- f"Private revocation registry definition not found for { temp_private_key_id } " # noqa: E501
494+ "Private revocation registry definition "
495+ f"not found for { private_key_storage_id } "
498496 )
499497
500498 async with self .profile .transaction () as txn :
@@ -513,9 +511,12 @@ async def store_revocation_registry_definition( # ✅
513511 identifier ,
514512 rev_reg_def_private_entry .value ,
515513 )
516- await txn .handle .remove (CATEGORY_REV_REG_DEF_PRIVATE , temp_private_key_id )
514+ await txn .handle .remove (
515+ CATEGORY_REV_REG_DEF_PRIVATE , private_key_storage_id
516+ )
517517 LOGGER .debug (
518- "Removed temp private key id %s from storage" , temp_private_key_id
518+ "Removed rev reg def private %s from storage" ,
519+ private_key_storage_id ,
519520 )
520521 await txn .commit ()
521522 LOGGER .debug ("Revocation registry definition storage transaction committed" )
@@ -2209,3 +2210,7 @@ async def set_rev_reg_state(self, rev_reg_id: str, state: str) -> RevRegDef:
22092210 def _generate_backup_registry_tag (self ) -> str :
22102211 """Generate a unique tag for a backup registry."""
22112212 return str (uuid4 ())
2213+
2214+ def _get_private_key_storage_id (self , rev_reg_def : RevRegDef ) -> str :
2215+ """Get the private key storage identifier for a revocation registry definition."""
2216+ return f"rev_reg_def_private_{ rev_reg_def .value .tails_hash } "
0 commit comments