Skip to content

Commit

Permalink
Merge pull request #2458 from usingtechnology/2432-revocation-endpoints
Browse files Browse the repository at this point in the history
Revocation API using anoncreds-rs
  • Loading branch information
dbluhm authored Sep 25, 2023
2 parents 0d90414 + e4a6be5 commit 40bb283
Show file tree
Hide file tree
Showing 12 changed files with 553 additions and 842 deletions.
1 change: 1 addition & 0 deletions .devcontainer/post-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ WORKSPACE_DIR=$(pwd)
# install all ACA-Py requirements
python -m pip install --upgrade pip
pip3 install -r requirements.txt -r requirements.askar.txt -r requirements.bbs.txt -r requirements.dev.txt -r requirements.indy.txt -r requirements.anoncreds.txt
pip3 install -r demo/requirements.behave.txt -r demo/requirements.txt

# install black for formatting
pip3 install black
29 changes: 23 additions & 6 deletions aries_cloudagent/anoncreds/default/legacy_indy/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -491,10 +491,7 @@ def _indexes_to_bit_array(self, indexes: List[int], size: int) -> List[int]:
"""Turn a sequence of indexes into a full state bit array."""
return [1 if index in indexes else 0 for index in range(1, size + 1)]

async def get_revocation_list(
self, profile: Profile, rev_reg_def_id: str, timestamp: int
) -> GetRevListResult:
"""Get a revocation list from the registry."""
async def _get_ledger(self, profile: Profile, rev_reg_def_id: str):
async with profile.session() as session:
multitenant_mgr = session.inject_or(BaseMultitenantManager)
if multitenant_mgr:
Expand All @@ -512,6 +509,14 @@ async def get_revocation_list(
reason += ": missing wallet-type?"
raise AnonCredsResolutionError(reason)

return ledger_id, ledger

async def get_revocation_registry_delta(
self, profile: Profile, rev_reg_def_id: str, timestamp: None
) -> Tuple[dict, int]:
"""Fetch the revocation registry delta."""
ledger_id, ledger = await self._get_ledger(profile, rev_reg_def_id)

async with ledger:
delta, timestamp = await ledger.get_revoc_reg_delta(
rev_reg_def_id, timestamp_to=timestamp
Expand All @@ -522,8 +527,20 @@ async def get_revocation_list(
f"Revocation list not found for rev reg def: {rev_reg_def_id}",
{"ledger_id": ledger_id},
)
LOGGER.debug("Retrieved delta: %s", delta)
return delta, timestamp

async def get_revocation_list(
self, profile: Profile, rev_reg_def_id: str, timestamp: int
) -> GetRevListResult:
"""Get the revocation registry list."""
_, ledger = await self._get_ledger(profile, rev_reg_def_id)

LOGGER.debug("Retrieved delta: %s", delta)
delta, timestamp = await self.get_revocation_registry_delta(
profile, rev_reg_def_id, timestamp
)

async with ledger:
max_cred_num = await self._get_or_fetch_rev_reg_def_max_cred_num(
profile, ledger, rev_reg_def_id
)
Expand Down Expand Up @@ -582,7 +599,7 @@ async def _revoc_reg_entry_with_fix(
profile,
rev_list,
True,
ledger.genesis_txns,
ledger.pool.genesis_txns,
)
rev_entry_res = {"result": res}
LOGGER.warn("Ledger update/fix applied")
Expand Down
24 changes: 24 additions & 0 deletions aries_cloudagent/anoncreds/revocation.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,22 @@ async def get_created_revocation_registry_definitions(
# entry.name was stored as the credential_definition's ID
return [entry.name for entry in rev_reg_defs]

async def get_created_revocation_registry_definition_state(
self,
rev_reg_def_id: str,
) -> Optional[str]:
"""Retrieve rev reg def by ID from rev reg defs previously created."""
async with self.profile.session() as session:
rev_reg_def_entry = await session.handle.fetch(
CATEGORY_REV_REG_DEF,
name=rev_reg_def_id,
)

if rev_reg_def_entry:
return rev_reg_def_entry.tags.get("state")

return None

async def get_created_revocation_registry_definition(
self,
rev_reg_def_id: str,
Expand Down Expand Up @@ -1140,3 +1156,11 @@ async def clear_pending_revocations(
value_json=value,
tags=tags,
)

async def set_tails_file_public_uri(self, rev_reg_id, tails_public_uri):
"""Update Revocation Registy tails file public uri."""
pass

async def set_rev_reg_state(self, rev_reg_id, state):
"""Update Revocation Registy state."""
pass
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from asynctest import TestCase as AsyncTestCase
from asynctest import mock as async_mock
import pytest

from ....admin.request_context import AdminRequestContext
from ....core.in_memory import InMemoryProfile
Expand Down Expand Up @@ -63,7 +64,8 @@ def setUp(self):
__getitem__=lambda _, k: self.request_dict[k],
)

async def anoncreds_break_test_send_credential_definition(self):
@pytest.mark.skip(reason="anoncreds-rs breaking change")
async def test_send_credential_definition(self):
self.request.json = async_mock.CoroutineMock(
return_value={
"schema_id": "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0",
Expand All @@ -75,8 +77,10 @@ async def anoncreds_break_test_send_credential_definition(self):
self.request.query = {"create_transaction_for_endorser": "false"}

with async_mock.patch.object(test_module.web, "json_response") as mock_response:
result = await test_module.anoncreds_break_credential_definitions_send_credential_definition(
self.request
result = (
await test_module.credential_definitions_send_credential_definition(
self.request
)
)
assert result == mock_response.return_value
mock_response.assert_called_once_with(
Expand All @@ -86,7 +90,8 @@ async def anoncreds_break_test_send_credential_definition(self):
}
)

async def anoncreds_break_test_send_credential_definition_create_transaction_for_endorser(
@pytest.mark.skip(reason="anoncreds-rs breaking change")
async def test_send_credential_definition_create_transaction_for_endorser(
self,
):
self.request.json = async_mock.CoroutineMock(
Expand Down Expand Up @@ -124,8 +129,10 @@ async def anoncreds_break_test_send_credential_definition_create_transaction_for
}
)
)
result = await test_module.anoncreds_break_credential_definitions_send_credential_definition(
self.request
result = (
await test_module.credential_definitions_send_credential_definition(
self.request
)
)
assert result == mock_response.return_value
mock_response.assert_called_once_with(
Expand All @@ -135,7 +142,8 @@ async def anoncreds_break_test_send_credential_definition_create_transaction_for
}
)

async def anoncreds_break_test_send_credential_definition_create_transaction_for_endorser_storage_x(
@pytest.mark.skip(reason="anoncreds-rs breaking change")
async def test_send_credential_definition_create_transaction_for_endorser_storage_x(
self,
):
self.request.json = async_mock.CoroutineMock(
Expand Down Expand Up @@ -171,11 +179,12 @@ async def anoncreds_break_test_send_credential_definition_create_transaction_for
)

with self.assertRaises(test_module.web.HTTPBadRequest):
await test_module.anoncreds_break_credential_definitions_send_credential_definition(
await test_module.credential_definitions_send_credential_definition(
self.request
)

async def anoncreds_break_test_send_credential_definition_create_transaction_for_endorser_not_found_x(
@pytest.mark.skip(reason="anoncreds-rs breaking change")
async def test_send_credential_definition_create_transaction_for_endorser_not_found_x(
self,
):
self.request.json = async_mock.CoroutineMock(
Expand All @@ -197,11 +206,12 @@ async def anoncreds_break_test_send_credential_definition_create_transaction_for
mock_conn_rec_retrieve.side_effect = test_module.StorageNotFoundError()

with self.assertRaises(test_module.web.HTTPNotFound):
await test_module.anoncreds_break_credential_definitions_send_credential_definition(
await test_module.credential_definitions_send_credential_definition(
self.request
)

async def anoncreds_break_test_send_credential_definition_create_transaction_for_endorser_base_model_x(
@pytest.mark.skip(reason="anoncreds-rs breaking change")
async def test_send_credential_definition_create_transaction_for_endorser_base_model_x(
self,
):
self.request.json = async_mock.CoroutineMock(
Expand All @@ -223,11 +233,12 @@ async def anoncreds_break_test_send_credential_definition_create_transaction_for
mock_conn_rec_retrieve.side_effect = test_module.BaseModelError()

with self.assertRaises(test_module.web.HTTPBadRequest):
await test_module.anoncreds_break_credential_definitions_send_credential_definition(
await test_module.credential_definitions_send_credential_definition(
self.request
)

async def anoncreds_break_test_send_credential_definition_create_transaction_for_endorser_no_endorser_info_x(
@pytest.mark.skip(reason="anoncreds-rs breaking change")
async def test_send_credential_definition_create_transaction_for_endorser_no_endorser_info_x(
self,
):
self.request.json = async_mock.CoroutineMock(
Expand All @@ -250,11 +261,12 @@ async def anoncreds_break_test_send_credential_definition_create_transaction_for
metadata_get=async_mock.CoroutineMock(return_value=None)
)
with self.assertRaises(test_module.web.HTTPForbidden):
await test_module.anoncreds_break_credential_definitions_send_credential_definition(
await test_module.credential_definitions_send_credential_definition(
self.request
)

async def anoncreds_break_test_send_credential_definition_create_transaction_for_endorser_no_endorser_did_x(
@pytest.mark.skip(reason="anoncreds-rs breaking change")
async def test_send_credential_definition_create_transaction_for_endorser_no_endorser_did_x(
self,
):
self.request.json = async_mock.CoroutineMock(
Expand All @@ -281,11 +293,12 @@ async def anoncreds_break_test_send_credential_definition_create_transaction_for
)
)
with self.assertRaises(test_module.web.HTTPForbidden):
await test_module.anoncreds_break_credential_definitions_send_credential_definition(
await test_module.credential_definitions_send_credential_definition(
self.request
)

async def anoncreds_break_test_send_credential_definition_no_ledger(self):
@pytest.mark.skip(reason="anoncreds-rs breaking change")
async def test_send_credential_definition_no_ledger(self):
self.request.json = async_mock.CoroutineMock(
return_value={
"schema_id": "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0",
Expand All @@ -297,11 +310,12 @@ async def anoncreds_break_test_send_credential_definition_no_ledger(self):
self.context.injector.clear_binding(BaseLedger)
self.profile_injector.clear_binding(BaseLedger)
with self.assertRaises(test_module.web.HTTPForbidden):
await test_module.anoncreds_break_credential_definitions_send_credential_definition(
await test_module.credential_definitions_send_credential_definition(
self.request
)

async def anoncreds_break_test_send_credential_definition_ledger_x(self):
@pytest.mark.skip(reason="anoncreds-rs breaking change")
async def test_send_credential_definition_ledger_x(self):
self.request.json = async_mock.CoroutineMock(
return_value={
"schema_id": "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0",
Expand All @@ -316,11 +330,12 @@ async def anoncreds_break_test_send_credential_definition_ledger_x(self):
side_effect=test_module.LedgerError("oops")
)
with self.assertRaises(test_module.web.HTTPBadRequest):
await test_module.anoncreds_break_credential_definitions_send_credential_definition(
await test_module.credential_definitions_send_credential_definition(
self.request
)

async def anoncreds_break_test_created(self):
@pytest.mark.skip(reason="anoncreds-rs breaking change")
async def test_created(self):
self.request.match_info = {"cred_def_id": CRED_DEF_ID}

with async_mock.patch.object(test_module.web, "json_response") as mock_response:
Expand All @@ -330,7 +345,8 @@ async def anoncreds_break_test_created(self):
{"credential_definition_ids": [CRED_DEF_ID]}
)

async def anoncreds_break_test_get_credential_definition(self):
@pytest.mark.skip(reason="anoncreds-rs breaking change")
async def test_get_credential_definition(self):
self.profile_injector.bind_instance(
IndyLedgerRequestsExecutor,
async_mock.MagicMock(
Expand All @@ -352,7 +368,8 @@ async def anoncreds_break_test_get_credential_definition(self):
}
)

async def anoncreds_break_test_get_credential_definition_multitenant(self):
@pytest.mark.skip(reason="anoncreds-rs breaking change")
async def test_get_credential_definition_multitenant(self):
self.profile_injector.bind_instance(
BaseMultitenantManager,
async_mock.MagicMock(MultitenantManager, autospec=True),
Expand All @@ -374,7 +391,8 @@ async def anoncreds_break_test_get_credential_definition_multitenant(self):
}
)

async def anoncreds_break_test_get_credential_definition_no_ledger(self):
@pytest.mark.skip(reason="anoncreds-rs breaking change")
async def test_get_credential_definition_no_ledger(self):
self.profile_injector.bind_instance(
IndyLedgerRequestsExecutor,
async_mock.MagicMock(
Expand Down
Loading

0 comments on commit 40bb283

Please sign in to comment.