Skip to content

Commit

Permalink
update send_entry on calling publish-revocations
Browse files Browse the repository at this point in the history
Signed-off-by: Shaanjot Gill <gill.shaanjots@gmail.com>
  • Loading branch information
shaangill025 committed Oct 19, 2023
1 parent cdf5751 commit 5d3a5ea
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 4 deletions.
28 changes: 26 additions & 2 deletions aries_cloudagent/revocation/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,8 @@ async def revoke_credential(
)
except StorageNotFoundError:
raise RevocationManagerError(
f"No connection record found for id: {connection_id}"
"No endorser connection record found "
f"for id: {connection_id}"
)
endorser_info = await connection_record.metadata_get(
session, "endorser_info"
Expand Down Expand Up @@ -206,6 +207,7 @@ async def update_rev_reg_revoked_state(
async def publish_pending_revocations(
self,
rrid2crid: Mapping[Text, Sequence[Text]] = None,
connection_id: str = None,
) -> Mapping[Text, Sequence[Text]]:
"""Publish pending revocations to the ledger.
Expand All @@ -226,6 +228,7 @@ async def publish_pending_revocations(
- all pending revocations from all revocation registry tagged 0
- pending ["1", "2"] from revocation registry tagged 1
- no pending revocations from any other revocation registries.
connection_id: connection identifier for endorser connection to use
Returns: mapping from each revocation registry id to its cred rev ids published.
"""
Expand Down Expand Up @@ -263,7 +266,28 @@ async def publish_pending_revocations(
await txn.commit()
await self.set_cred_revoked_state(issuer_rr_rec.revoc_reg_id, crids)
if delta_json:
await issuer_rr_upd.send_entry(self._profile)
if connection_id:
async with self._profile.session() as session:
try:
connection_record = await ConnRecord.retrieve_by_id(
session, connection_id
)
except StorageNotFoundError:
raise RevocationManagerError(
"No endorser connection record found "
f"for id: {connection_id}"
)
endorser_info = await connection_record.metadata_get(
session, "endorser_info"
)
endorser_did = endorser_info["endorser_did"]
await issuer_rr_upd.send_entry(
self._profile,
write_ledger=False,
endorser_did=endorser_did,
)
else:
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
await notify_revocation_published_event(
Expand Down
10 changes: 8 additions & 2 deletions aries_cloudagent/revocation/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -594,10 +594,16 @@ async def publish_revocations(request: web.BaseRequest):
rrid2crid = body.get("rrid2crid")

rev_manager = RevocationManager(context.profile)

profile = context.profile
connection_id = None
if is_author_role(profile):
connection_id = await get_endorser_connection_id(profile)
if not connection_id:
raise web.HTTPBadRequest(reason="No endorser connection found")
try:
rev_reg_resp = await rev_manager.publish_pending_revocations(
rrid2crid,
rrid2crid=rrid2crid,
connection_id=connection_id,
)
except (RevocationError, StorageError, IndyIssuerError, LedgerError) as err:
raise web.HTTPBadRequest(reason=err.roll_up) from err
Expand Down
139 changes: 139 additions & 0 deletions aries_cloudagent/revocation/tests/test_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,145 @@ async def test_revoke_credential_pend(self):

issuer.revoke_credentials.assert_not_awaited()

async def test_publish_pending_revocations_endorser(self):
deltas = [
{
"ver": "1.0",
"value": {"prevAccum": "1 ...", "accum": "21 ...", "issued": [1, 2, 3]},
},
{
"ver": "1.0",
"value": {
"prevAccum": "21 ...",
"accum": "36 ...",
"issued": [1, 2, 3],
},
},
]

mock_issuer_rev_reg_records = [
async_mock.MagicMock(
record_id=0,
revoc_reg_id=REV_REG_ID,
tails_local_path=TAILS_LOCAL,
pending_pub=["1", "2"],
send_entry=async_mock.CoroutineMock(),
clear_pending=async_mock.CoroutineMock(),
),
async_mock.MagicMock(
record_id=1,
revoc_reg_id=f"{TEST_DID}:4:{CRED_DEF_ID}:CL_ACCUM:tag2",
tails_local_path=TAILS_LOCAL,
pending_pub=["9", "99"],
send_entry=async_mock.CoroutineMock(),
clear_pending=async_mock.CoroutineMock(),
),
]
conn_record = ConnRecord(
their_label="Hello",
their_role=ConnRecord.Role.RESPONDER.rfc160,
alias="Bob",
)
session = await self.profile.session()
await conn_record.save(session)
await conn_record.metadata_set(
session,
key="endorser_info",
value={
"endorser_did": "test_endorser_did",
"endorser_name": "test_endorser_name",
},
)
conn_id = conn_record.connection_id
assert conn_id is not None
with async_mock.patch.object(
test_module.IssuerRevRegRecord,
"query_by_pending",
async_mock.CoroutineMock(return_value=mock_issuer_rev_reg_records),
), async_mock.patch.object(
test_module.IssuerRevRegRecord,
"retrieve_by_id",
async_mock.CoroutineMock(
side_effect=lambda _, id, **args: mock_issuer_rev_reg_records[id]
),
):
issuer = async_mock.MagicMock(IndyIssuer, autospec=True)
issuer.merge_revocation_registry_deltas = async_mock.CoroutineMock(
side_effect=deltas
)

issuer.revoke_credentials = async_mock.CoroutineMock(
side_effect=[(json.dumps(delta), []) for delta in deltas]
)
self.profile.context.injector.bind_instance(IndyIssuer, issuer)
manager = RevocationManager(self.profile)
result = await manager.publish_pending_revocations(
rrid2crid={REV_REG_ID: "2"}, connection_id=conn_id
)
assert result == {REV_REG_ID: ["2"]}
mock_issuer_rev_reg_records[0].clear_pending.assert_called_once()
mock_issuer_rev_reg_records[1].clear_pending.assert_not_called()

async def test_publish_pending_revocations_endorser_x(self):
deltas = [
{
"ver": "1.0",
"value": {"prevAccum": "1 ...", "accum": "21 ...", "issued": [1, 2, 3]},
},
{
"ver": "1.0",
"value": {
"prevAccum": "21 ...",
"accum": "36 ...",
"issued": [1, 2, 3],
},
},
]

mock_issuer_rev_reg_records = [
async_mock.MagicMock(
record_id=0,
revoc_reg_id=REV_REG_ID,
tails_local_path=TAILS_LOCAL,
pending_pub=["1", "2"],
send_entry=async_mock.CoroutineMock(),
clear_pending=async_mock.CoroutineMock(),
),
async_mock.MagicMock(
record_id=1,
revoc_reg_id=f"{TEST_DID}:4:{CRED_DEF_ID}:CL_ACCUM:tag2",
tails_local_path=TAILS_LOCAL,
pending_pub=["9", "99"],
send_entry=async_mock.CoroutineMock(),
clear_pending=async_mock.CoroutineMock(),
),
]
with async_mock.patch.object(
test_module.IssuerRevRegRecord,
"query_by_pending",
async_mock.CoroutineMock(return_value=mock_issuer_rev_reg_records),
), async_mock.patch.object(
test_module.IssuerRevRegRecord,
"retrieve_by_id",
async_mock.CoroutineMock(
side_effect=lambda _, id, **args: mock_issuer_rev_reg_records[id]
),
):
issuer = async_mock.MagicMock(IndyIssuer, autospec=True)
issuer.merge_revocation_registry_deltas = async_mock.CoroutineMock(
side_effect=deltas
)

issuer.revoke_credentials = async_mock.CoroutineMock(
side_effect=[(json.dumps(delta), []) for delta in deltas]
)
self.profile.context.injector.bind_instance(IndyIssuer, issuer)
manager = RevocationManager(self.profile)
with self.assertRaises(RevocationManagerError):
result = await manager.publish_pending_revocations(
rrid2crid={REV_REG_ID: "2"}, connection_id="invalid_conn_id"
)

async def test_publish_pending_revocations_basic(self):
deltas = [
{
Expand Down
38 changes: 38 additions & 0 deletions aries_cloudagent/revocation/tests/test_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,44 @@ async def test_publish_revocations_x(self):
with self.assertRaises(test_module.web.HTTPBadRequest):
await test_module.publish_revocations(self.request)

async def test_publish_revocations_endorser(self):
self.author_request.json = async_mock.CoroutineMock()

with async_mock.patch.object(
test_module, "RevocationManager", autospec=True
) as mock_mgr, async_mock.patch.object(
test_module,
"get_endorser_connection_id",
async_mock.CoroutineMock(return_value="dummy-conn-id"),
), async_mock.patch.object(
test_module.web, "json_response"
) as mock_response:
pub_pending = async_mock.CoroutineMock()
mock_mgr.return_value.publish_pending_revocations = pub_pending

await test_module.publish_revocations(self.author_request)

mock_response.assert_called_once_with(
{"rrid2crid": pub_pending.return_value}
)

async def test_publish_revocations_endorser_x(self):
self.author_request.json = async_mock.CoroutineMock()

with async_mock.patch.object(
test_module, "RevocationManager", autospec=True
) as mock_mgr, async_mock.patch.object(
test_module,
"get_endorser_connection_id",
async_mock.CoroutineMock(return_value=None),
), async_mock.patch.object(
test_module.web, "json_response"
) as mock_response:
pub_pending = async_mock.CoroutineMock()
mock_mgr.return_value.publish_pending_revocations = pub_pending
with self.assertRaises(test_module.web.HTTPBadRequest):
await test_module.publish_revocations(self.author_request)

async def test_clear_pending_revocations(self):
self.request.json = async_mock.CoroutineMock()

Expand Down

0 comments on commit 5d3a5ea

Please sign in to comment.