diff --git a/aries_cloudagent/anoncreds/default/legacy_indy/registry.py b/aries_cloudagent/anoncreds/default/legacy_indy/registry.py index c302f2348d..f092d61f43 100644 --- a/aries_cloudagent/anoncreds/default/legacy_indy/registry.py +++ b/aries_cloudagent/anoncreds/default/legacy_indy/registry.py @@ -47,6 +47,7 @@ BaseAnonCredsRegistrar, BaseAnonCredsResolver, ) +from ...events import RevListFinishedEvent from ...issuer import AnonCredsIssuer, AnonCredsIssuerError from ...models.anoncreds_cred_def import ( CredDef, @@ -966,6 +967,11 @@ async def update_revocation_list( ) if write_ledger: + await self.notify( + RevListFinishedEvent.with_payload( + curr_list.rev_reg_def_id, newly_revoked_indices + ) + ) return RevListResult( job_id=None, revocation_list_state=RevListState( @@ -983,6 +989,7 @@ async def update_revocation_list( "context": { "job_id": job_id, "rev_reg_def_id": rev_reg_def_id, + "rev_list": curr_list.serialize(), "options": { "endorser_connection_id": endorser_connection_id, "create_transaction_for_endorser": create_transaction, diff --git a/aries_cloudagent/anoncreds/events.py b/aries_cloudagent/anoncreds/events.py index 992feb21f6..7be3bc8603 100644 --- a/aries_cloudagent/anoncreds/events.py +++ b/aries_cloudagent/anoncreds/events.py @@ -109,7 +109,8 @@ def payload(self) -> RevRegDefFinishedPayload: class RevListFinishedPayload(NamedTuple): """Payload of rev list finished event.""" - rev_reg_def_id: str + rev_reg_id: str + revoked: list options: dict @@ -131,11 +132,12 @@ def __init__(self, payload: RevListFinishedPayload): @classmethod def with_payload( cls, - rev_reg_def_id: str, + rev_reg_id: str, + revoked: list, options: Optional[dict] = None, ): """With payload.""" - payload = RevListFinishedPayload(rev_reg_def_id, options) + payload = RevListFinishedPayload(rev_reg_id, revoked, options) return cls(payload) @property diff --git a/aries_cloudagent/anoncreds/revocation.py b/aries_cloudagent/anoncreds/revocation.py index 70cea45e64..0854c4a0b4 100644 --- a/aries_cloudagent/anoncreds/revocation.py +++ b/aries_cloudagent/anoncreds/revocation.py @@ -494,7 +494,7 @@ async def store_revocation_registry_list(self, result: RevListResult): if result.revocation_list_state.state == STATE_FINISHED: await self.notify( - RevListFinishedEvent.with_payload(rev_list.rev_reg_def_id) + RevListFinishedEvent.with_payload(rev_list.rev_reg_def_id, rev_list) ) except AskarError as err: @@ -502,7 +502,9 @@ async def store_revocation_registry_list(self, result: RevListResult): "Error saving new revocation registry" ) from err - async def finish_revocation_list(self, job_id: str, rev_reg_def_id: str): + async def finish_revocation_list( + self, job_id: str, rev_reg_def_id: str, revoked: list + ): """Mark a revocation list as finished.""" async with self.profile.transaction() as txn: # Finish the registration if the list is new, otherwise already updated @@ -519,7 +521,10 @@ async def finish_revocation_list(self, job_id: str, rev_reg_def_id: str): state=STATE_FINISHED, ) await txn.commit() - await self.notify(RevListFinishedEvent.with_payload(rev_reg_def_id)) + # Notify about revoked creds on any list update + await self.notify( + RevListFinishedEvent.with_payload(rev_reg_def_id, revoked) + ) async def update_revocation_list( self, diff --git a/aries_cloudagent/anoncreds/revocation_setup.py b/aries_cloudagent/anoncreds/revocation_setup.py index 8f16b382c9..c12b9060a8 100644 --- a/aries_cloudagent/anoncreds/revocation_setup.py +++ b/aries_cloudagent/anoncreds/revocation_setup.py @@ -8,6 +8,7 @@ from ..anoncreds.revocation import AnonCredsRevocation from ..core.event_bus import EventBus from ..core.profile import Profile +from ..revocation.util import notify_revocation_published_event from .events import ( CRED_DEF_FINISHED_PATTERN, REV_LIST_FINISHED_PATTERN, @@ -105,4 +106,6 @@ async def on_rev_reg_def(self, profile: Profile, event: RevRegDefFinishedEvent): async def on_rev_list(self, profile: Profile, event: RevListFinishedEvent): """Handle rev list finished.""" - LOGGER.debug("Revocation list finished: %s", event.payload.rev_reg_def_id) + await notify_revocation_published_event( + profile, event.payload.rev_reg_id, event.payload.revoked + ) diff --git a/aries_cloudagent/anoncreds/tests/test_revocation.py b/aries_cloudagent/anoncreds/tests/test_revocation.py index 4e82db18c1..26a75d57c2 100644 --- a/aries_cloudagent/anoncreds/tests/test_revocation.py +++ b/aries_cloudagent/anoncreds/tests/test_revocation.py @@ -596,15 +596,13 @@ async def test_finish_revocation_list(self, mock_finish, mock_handle): # Fetch doesn't find list then it should be created await self.revocation.finish_revocation_list( - job_id="test-job-id", - rev_reg_def_id="test-rev-reg-def-id", + job_id="test-job-id", rev_reg_def_id="test-rev-reg-def-id", revoked=[] ) assert mock_finish.called # Fetch finds list then there's nothing to do, it's already finished and updated await self.revocation.finish_revocation_list( - job_id="test-job-id", - rev_reg_def_id="test-rev-reg-def-id", + job_id="test-job-id", rev_reg_def_id="test-rev-reg-def-id", revoked=[] ) assert mock_finish.call_count == 1 diff --git a/aries_cloudagent/protocols/endorse_transaction/v1_0/manager.py b/aries_cloudagent/protocols/endorse_transaction/v1_0/manager.py index 03472f5f84..b59b4352cb 100644 --- a/aries_cloudagent/protocols/endorse_transaction/v1_0/manager.py +++ b/aries_cloudagent/protocols/endorse_transaction/v1_0/manager.py @@ -863,14 +863,17 @@ async def endorsed_txn_post_processing( elif ledger_response["result"]["txn"]["type"] == "114": # revocation entry transaction rev_reg_id = ledger_response["result"]["txn"]["data"]["revocRegDefId"] + revoked = ledger_response["result"]["txn"]["data"]["value"].get( + "revoked", [] + ) meta_data["context"]["rev_reg_id"] = rev_reg_id if is_anoncreds: await AnonCredsRevocation(self._profile).finish_revocation_list( - meta_data["context"]["job_id"], rev_reg_id + meta_data["context"]["job_id"], rev_reg_id, revoked ) else: await notify_revocation_entry_endorsed_event( - self._profile, rev_reg_id, meta_data + self._profile, rev_reg_id, meta_data, revoked ) elif ledger_response["result"]["txn"]["type"] == "1": diff --git a/aries_cloudagent/protocols/endorse_transaction/v1_0/tests/test_manager.py b/aries_cloudagent/protocols/endorse_transaction/v1_0/tests/test_manager.py index b46e989f5d..7ed097a921 100644 --- a/aries_cloudagent/protocols/endorse_transaction/v1_0/tests/test_manager.py +++ b/aries_cloudagent/protocols/endorse_transaction/v1_0/tests/test_manager.py @@ -940,7 +940,7 @@ async def test_endorsed_txn_post_processing_anoncreds( "txn": { "type": "114", "metadata": {"from": TEST_DID}, - "data": {"revocRegDefId": REV_REG_ID}, + "data": {"revocRegDefId": REV_REG_ID, "value": {"revoked": [1]}}, }, "txnMetadata": {"txnId": REV_REG_ID}, }, diff --git a/aries_cloudagent/revocation/manager.py b/aries_cloudagent/revocation/manager.py index 824efe79c0..e74c0b525a 100644 --- a/aries_cloudagent/revocation/manager.py +++ b/aries_cloudagent/revocation/manager.py @@ -4,24 +4,24 @@ import logging from typing import Mapping, Optional, Sequence, Text, Tuple -from ..protocols.revocation_notification.v1_0.models.rev_notification_record import ( - RevNotificationRecord, -) from ..connections.models.conn_record import ConnRecord from ..core.error import BaseError from ..core.profile import Profile from ..indy.issuer import IndyIssuer -from ..storage.error import StorageNotFoundError -from .indy import IndyRevocation -from .models.issuer_cred_rev_record import IssuerCredRevRecord -from .models.issuer_rev_reg_record import IssuerRevRegRecord -from .util import notify_pending_cleared_event, notify_revocation_published_event from ..protocols.issue_credential.v1_0.models.credential_exchange import ( V10CredentialExchange, ) from ..protocols.issue_credential.v2_0.models.cred_ex_record import ( V20CredExRecord, ) +from ..protocols.revocation_notification.v1_0.models.rev_notification_record import ( + RevNotificationRecord, +) +from ..storage.error import StorageNotFoundError +from .indy import IndyRevocation +from .models.issuer_cred_rev_record import IssuerCredRevRecord +from .models.issuer_rev_reg_record import IssuerRevRegRecord +from .util import notify_pending_cleared_event, notify_revocation_published_event class RevocationManagerError(BaseError): @@ -296,10 +296,6 @@ async def publish_pending_revocations( rev_entry_resp = await issuer_rr_upd.send_entry(self._profile) published = sorted(crid for crid in crids if crid not in failed_crids) result[issuer_rr_rec.revoc_reg_id] = published - if not connection_id: - await notify_revocation_published_event( - self._profile, issuer_rr_rec.revoc_reg_id, crids - ) return rev_entry_resp, result diff --git a/aries_cloudagent/revocation/tests/test_manager.py b/aries_cloudagent/revocation/tests/test_manager.py index 4d0689664f..6ebc48a330 100644 --- a/aries_cloudagent/revocation/tests/test_manager.py +++ b/aries_cloudagent/revocation/tests/test_manager.py @@ -1,11 +1,10 @@ import json - -from aries_cloudagent.tests import mock from unittest import IsolatedAsyncioTestCase from aries_cloudagent.revocation.models.issuer_cred_rev_record import ( IssuerCredRevRecord, ) +from aries_cloudagent.tests import mock from ...connections.models.conn_record import ConnRecord from ...core.in_memory import InMemoryProfile @@ -14,11 +13,8 @@ V10CredentialExchange, ) from ...protocols.issue_credential.v2_0.models.cred_ex_record import V20CredExRecord - - -from ..manager import RevocationManager, RevocationManagerError - from .. import manager as test_module +from ..manager import RevocationManager, RevocationManagerError TEST_DID = "LjgpST2rjsoxYegQDRm7EL" SCHEMA_NAME = "bc-reg" diff --git a/aries_cloudagent/revocation/util.py b/aries_cloudagent/revocation/util.py index df40a17630..cc8c55209e 100644 --- a/aries_cloudagent/revocation/util.py +++ b/aries_cloudagent/revocation/util.py @@ -5,7 +5,6 @@ from ..core.profile import Profile - REVOCATION_EVENT_PREFIX = "acapy::REVOCATION::" EVENT_LISTENER_PATTERN = re.compile(f"^{REVOCATION_EVENT_PREFIX}(.*)?$") REVOCATION_REG_INIT_EVENT = "REGISTRY_INIT" @@ -52,11 +51,12 @@ async def notify_revocation_reg_endorsed_event( async def notify_revocation_entry_endorsed_event( - profile: Profile, rev_reg_id: str, meta_data: dict + profile: Profile, rev_reg_id: str, meta_data: dict, revoked: list ): """Send notification for a revocation registry entry endorsement event.""" topic = f"{REVOCATION_EVENT_PREFIX}{REVOCATION_ENTRY_ENDORSED_EVENT}::{rev_reg_id}" await profile.notify(topic, meta_data) + await notify_revocation_published_event(profile, rev_reg_id, revoked) async def notify_revocation_published_event( diff --git a/aries_cloudagent/revocation_anoncreds/manager.py b/aries_cloudagent/revocation_anoncreds/manager.py index a846396146..52e914ed23 100644 --- a/aries_cloudagent/revocation_anoncreds/manager.py +++ b/aries_cloudagent/revocation_anoncreds/manager.py @@ -16,7 +16,6 @@ ) from ..revocation.util import ( notify_pending_cleared_event, - notify_revocation_published_event, ) from ..storage.error import StorageNotFoundError from .models.issuer_cred_rev_record import IssuerCredRevRecord @@ -129,9 +128,6 @@ async def revoke_credential( result.revoked, options=options, ) - await notify_revocation_published_event( - self._profile, rev_reg_id, [cred_rev_id] - ) else: await revoc.mark_pending_revocations(rev_reg_id, int(cred_rev_id)) @@ -237,9 +233,6 @@ async def publish_pending_revocations( rrid, result.prev, result.curr, result.revoked, options ) published_crids[rrid] = sorted(result.revoked) - await notify_revocation_published_event( - self._profile, rrid, [str(crid) for crid in result.revoked] - ) return published_crids