Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use anoncreds registry for holder credential endpoints #3063

Merged
merged 6 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion aries_cloudagent/anoncreds/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,11 @@ async def get_revocation_registry_definition(

@abstractmethod
async def get_revocation_list(
self, profile: Profile, revocation_registry_id: str, timestamp: int
self,
profile: Profile,
revocation_registry_id: str,
timestamp_from: Optional[int] = 0,
timestamp_to: Optional[int] = None,
) -> GetRevListResult:
"""Get a revocation list from the registry."""

Expand Down
6 changes: 5 additions & 1 deletion aries_cloudagent/anoncreds/default/did_indy/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,11 @@ async def register_revocation_registry_definition(
raise NotImplementedError()

async def get_revocation_list(
self, profile: Profile, revocation_registry_id: str, timestamp: int
self,
profile: Profile,
revocation_registry_id: str,
timestamp_from: Optional[int] = 0,
timestamp_to: Optional[int] = None,
) -> GetRevListResult:
"""Get a revocation list from the registry."""
raise NotImplementedError()
Expand Down
16 changes: 12 additions & 4 deletions aries_cloudagent/anoncreds/default/legacy_indy/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -740,14 +740,18 @@ async def _get_ledger(self, profile: Profile, rev_reg_def_id: str):
return ledger_id, ledger

async def get_revocation_registry_delta(
self, profile: Profile, rev_reg_def_id: str, timestamp: None
self,
profile: Profile,
rev_reg_def_id: str,
timestamp_from: Optional[int] = 0,
timestamp_to: Optional[int] = 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
rev_reg_def_id, timestamp_from=timestamp_from, timestamp_to=timestamp_to
)

if delta is None:
Expand All @@ -759,13 +763,17 @@ async def get_revocation_registry_delta(
return delta, timestamp

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

delta, timestamp = await self.get_revocation_registry_delta(
profile, rev_reg_def_id, timestamp
profile, rev_reg_def_id, timestamp_from, timestamp_to
)

async with ledger:
Expand Down
33 changes: 16 additions & 17 deletions aries_cloudagent/anoncreds/holder.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@
from ..askar.profile_anon import AskarAnoncredsProfile
from ..core.error import BaseError
from ..core.profile import Profile
from ..ledger.base import BaseLedger
from ..wallet.error import WalletNotFoundError
from .error_messages import ANONCREDS_PROFILE_REQUIRED_MSG
from .models.anoncreds_cred_def import CredDef
from .registry import AnonCredsRegistry

LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -477,7 +477,7 @@ async def _get_credential(self, credential_id: str) -> Credential:
raise AnonCredsHolderError("Error loading requested credential") from err

async def credential_revoked(
self, ledger: BaseLedger, credential_id: str, fro: int = None, to: int = None
self, credential_id: str, fro: int = None, to: int = None
) -> bool:
"""Check ledger for revocation status of credential by cred id.

Expand All @@ -488,18 +488,18 @@ async def credential_revoked(
cred = await self._get_credential(credential_id)
rev_reg_id = cred.rev_reg_id

# TODO Use anoncreds registry
# check if cred.rev_reg_id is returning None or 'None'
if rev_reg_id:
cred_rev_id = cred.rev_reg_index
(rev_reg_delta, _) = await ledger.get_revoc_reg_delta(
rev_reg_id,
fro,
to,
anoncreds_registry = self.profile.inject(AnonCredsRegistry)
rev_list = (
await anoncreds_registry.get_revocation_list(
self.profile, rev_reg_id, fro, to
)
return cred_rev_id in rev_reg_delta["value"].get("revoked", [])
else:
return False
).revocation_list

set_revoked = {
index for index, value in enumerate(rev_list.revocation_list) if value == 1
}

return cred.rev_reg_index in set_revoked

async def delete_credential(self, credential_id: str):
"""Remove a credential stored in the wallet.
Expand All @@ -515,10 +515,9 @@ async def delete_credential(self, credential_id: str):
AnonCredsHolder.RECORD_TYPE_MIME_TYPES, credential_id
)
except AskarError as err:
if err.code == AskarErrorCode.NOT_FOUND:
pass
else:
raise AnonCredsHolderError("Error deleting credential") from err
raise AnonCredsHolderError(
"Error deleting credential", error_code=err.code
) from err # noqa: E501

async def get_mime_type(
self, credential_id: str, attr: str = None
Expand Down
16 changes: 9 additions & 7 deletions aries_cloudagent/anoncreds/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,7 @@
BaseAnonCredsRegistrar,
BaseAnonCredsResolver,
)
from .models.anoncreds_cred_def import (
CredDef,
CredDefResult,
GetCredDefResult,
)
from .models.anoncreds_cred_def import CredDef, CredDefResult, GetCredDefResult
from .models.anoncreds_revocation import (
GetRevListResult,
GetRevRegDefResult,
Expand Down Expand Up @@ -149,11 +145,17 @@ async def register_revocation_registry_definition(
)

async def get_revocation_list(
self, profile: Profile, rev_reg_def_id: str, timestamp: int
self,
profile: Profile,
rev_reg_def_id: str,
timestamp_from: Optional[int] = 0,
timestamp_to: Optional[int] = None,
) -> GetRevListResult:
"""Get a revocation list from the registry."""
resolver = await self._resolver_for_identifier(rev_reg_def_id)
return await resolver.get_revocation_list(profile, rev_reg_def_id, timestamp)
return await resolver.get_revocation_list(
profile, rev_reg_def_id, timestamp_from, timestamp_to
)

async def register_revocation_list(
self,
Expand Down
40 changes: 25 additions & 15 deletions aries_cloudagent/anoncreds/tests/test_holder.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
)
from aries_askar import AskarError, AskarErrorCode

from ..holder import AnonCredsHolder, AnonCredsHolderError
from aries_cloudagent.anoncreds.tests.mock_objects import (
MOCK_CRED,
MOCK_CRED_DEF,
Expand All @@ -35,7 +34,10 @@
from aries_cloudagent.wallet.error import WalletNotFoundError

from .. import holder as test_module
from ..holder import AnonCredsHolder, AnonCredsHolderError
from ..models.anoncreds_cred_def import CredDef, CredDefValue, CredDefValuePrimary
from ..models.anoncreds_revocation import GetRevListResult, RevList
from ..registry import AnonCredsRegistry


class MockCredReceived:
Expand Down Expand Up @@ -84,6 +86,8 @@ def __init__(self, rev_reg=False) -> None:
mock_cred = deepcopy(MOCK_CRED)
if rev_reg:
mock_cred["rev_reg_id"] = "rev-reg-id"

mock_cred["rev_reg_index"] = 1
self.name = "name"
self.value = mock_cred
self.raw_value = mock_cred
Expand Down Expand Up @@ -377,22 +381,27 @@ async def test_get_credential(self, mock_handle):

@mock.patch.object(InMemoryProfileSession, "handle")
async def test_credential_revoked(self, mock_handle):
mock_ledger = mock.MagicMock(
get_revoc_reg_delta=mock.CoroutineMock(
return_value=(
{
"value": {
"revoked": [100],
}
},
0,
),
)
self.profile.context.injector.bind_instance(
AnonCredsRegistry,
mock.MagicMock(
get_revocation_list=mock.CoroutineMock(
return_value=GetRevListResult(
revocation_list=RevList(
issuer_id="CsQY9MGeD3CQP4EyuVFo5m",
current_accumulator="21 124C594B6B20E41B681E92B2C43FD165EA9E68BC3C9D63A82C8893124983CAE94 21 124C5341937827427B0A3A32113BD5E64FB7AB39BD3E5ABDD7970874501CA4897 6 5438CB6F442E2F807812FD9DC0C39AFF4A86B1E6766DBB5359E86A4D70401B0F 4 39D1CA5C4716FFC4FE0853C4FF7F081DFD8DF8D2C2CA79705211680AC77BF3A1 6 70504A5493F89C97C225B68310811A41AD9CD889301F238E93C95AD085E84191 4 39582252194D756D5D86D0EED02BF1B95CE12AED2FA5CD3C53260747D891993C",
revocation_list=[0, 1, 1, 0],
timestamp=1669640864487,
rev_reg_def_id="4xE68b6S5VRFrKMMG1U95M:4:4xE68b6S5VRFrKMMG1U95M:3:CL:59232:default:CL_ACCUM:4ae1cc6c-f6bd-486c-8057-88f2ce74e960",
),
resolution_metadata={},
revocation_registry_metadata={},
)
)
),
)
mock_handle.fetch = mock.CoroutineMock(return_value=MockCredEntry())
assert (
await self.holder.credential_revoked(
ledger=mock_ledger,
credential_id="cred-id",
to=None,
fro=None,
Expand All @@ -415,8 +424,9 @@ async def test_delete_credential(self, mock_handle):
mock_handle.remove.call_args_list[0].args == ("credential", "cred-id")
mock_handle.remove.call_args_list[0].args == ("attribute-mime-types", "cred-id")

# not found, don't raise error
await self.holder.delete_credential("cred-id")
# not found
with self.assertRaises(AnonCredsHolderError):
await self.holder.delete_credential("cred-id")
# other asker error, raise error
with self.assertRaises(AnonCredsHolderError):
await self.holder.delete_credential("cred-id")
Expand Down
2 changes: 1 addition & 1 deletion aries_cloudagent/anoncreds/verifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ async def process_pres_identifiers(
result = await anoncreds_registry.get_revocation_list(
self.profile,
identifier["rev_reg_id"],
identifier["timestamp"],
timestamp_to=identifier["timestamp"],
)
rev_lists[identifier["rev_reg_id"]][
identifier["timestamp"]
Expand Down
Loading
Loading