Skip to content

Commit

Permalink
update to indy-credx 0.4
Browse files Browse the repository at this point in the history
Signed-off-by: Andrew Whitehead <[email protected]>
  • Loading branch information
andrewwhitehead committed Jul 11, 2023
1 parent 43952b3 commit c21b8c0
Show file tree
Hide file tree
Showing 13 changed files with 101 additions and 38 deletions.
11 changes: 11 additions & 0 deletions aries_cloudagent/config/argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,15 @@ def add_arguments(self, parser: ArgumentParser):
"revocation received."
),
)
parser.add_argument(
"--refuse-legacy-revocation",
action="store_true",
env_var="ACAPY_REFUSE_LEGACY_REVOCATION",
help=(
"Specifies that aca-py will refuse older proofs of non-revocation "
"for anoncreds credentials."
),
)

def get_settings(self, args: Namespace) -> dict:
"""Extract revocation settings."""
Expand All @@ -780,6 +789,8 @@ def get_settings(self, args: Namespace) -> dict:
settings[
"revocation.monitor_notification"
] = args.monitor_revocation_notification
if args.refuse_legacy_revocation:
settings["revocation.anoncreds_accept_legacy"] = False
return settings


Expand Down
36 changes: 18 additions & 18 deletions aries_cloudagent/indy/credx/holder.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
Credential,
CredentialRequest,
CredentialRevocationState,
MasterSecret,
LinkSecret,
Presentation,
PresentCredentials,
)
Expand All @@ -28,7 +28,7 @@
LOGGER = logging.getLogger(__name__)

CATEGORY_CREDENTIAL = "credential"
CATEGORY_MASTER_SECRET = "master_secret"
CATEGORY_LINK_SECRET = "master_secret"


def _make_cred_info(cred_id, cred: Credential):
Expand All @@ -51,7 +51,7 @@ def _normalize_attr_name(name: str) -> str:
class IndyCredxHolder(IndyHolder):
"""Indy-credx holder class."""

MASTER_SECRET_ID = "default"
LINK_SECRET_ID = "default"

def __init__(self, profile: AskarProfile):
"""
Expand All @@ -68,37 +68,37 @@ def profile(self) -> AskarProfile:
"""Accessor for the profile instance."""
return self._profile

async def get_master_secret(self) -> MasterSecret:
"""Get or create the default master secret."""
async def get_link_secret(self) -> LinkSecret:
"""Get or create the default link secret."""

while True:
async with self._profile.session() as session:
try:
record = await session.handle.fetch(
CATEGORY_MASTER_SECRET, IndyCredxHolder.MASTER_SECRET_ID
CATEGORY_LINK_SECRET, IndyCredxHolder.LINK_SECRET_ID
)
except AskarError as err:
raise IndyHolderError("Error fetching master secret") from err
raise IndyHolderError("Error fetching link secret") from err
if record:
try:
secret = MasterSecret.load(record.raw_value)
secret = LinkSecret.load(record.raw_value)
except CredxError as err:
raise IndyHolderError("Error loading master secret") from err
raise IndyHolderError("Error loading link secret") from err
break
else:
try:
secret = MasterSecret.create()
secret = LinkSecret.create()
except CredxError as err:
raise IndyHolderError("Error creating master secret") from err
raise IndyHolderError("Error creating link secret") from err
try:
await session.handle.insert(
CATEGORY_MASTER_SECRET,
IndyCredxHolder.MASTER_SECRET_ID,
CATEGORY_LINK_SECRET,
IndyCredxHolder.LINK_SECRET_ID,
secret.to_json_buffer(),
)
except AskarError as err:
if err.code != AskarErrorCode.DUPLICATE:
raise IndyHolderError("Error saving master secret") from err
raise IndyHolderError("Error saving link secret") from err
# else: lost race to create record, retry
else:
break
Expand All @@ -120,7 +120,7 @@ async def create_credential_request(
"""
try:
secret = await self.get_master_secret()
secret = await self.get_link_secret()
(
cred_req,
cred_req_metadata,
Expand All @@ -130,7 +130,7 @@ async def create_credential_request(
holder_did,
credential_definition,
secret,
IndyCredxHolder.MASTER_SECRET_ID,
IndyCredxHolder.LINK_SECRET_ID,
credential_offer,
)
except CredxError as err:
Expand Down Expand Up @@ -176,7 +176,7 @@ async def store_credential(
"""
try:
secret = await self.get_master_secret()
secret = await self.get_link_secret()
cred = Credential.load(credential_data)
cred_recvd = await asyncio.get_event_loop().run_in_executor(
None,
Expand Down Expand Up @@ -523,7 +523,7 @@ def get_rev_state(cred_id: str, detail: dict):
)

try:
secret = await self.get_master_secret()
secret = await self.get_link_secret()
presentation = await asyncio.get_event_loop().run_in_executor(
None,
Presentation.create,
Expand Down
47 changes: 38 additions & 9 deletions aries_cloudagent/indy/credx/issuer.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
CredxError,
RevocationRegistry,
RevocationRegistryDefinition,
RevocationRegistryDefinitionPrivate,
RevocationRegistryDelta,
Schema,
)
Expand Down Expand Up @@ -332,7 +333,6 @@ async def create_credential(
rev_reg.raw_value,
rev_reg_index,
rev_info.get("used_ids") or [],
tails_file_path,
)
credential_revocation_id = str(rev_reg_index)
else:
Expand Down Expand Up @@ -362,6 +362,7 @@ async def create_credential(

async def revoke_credentials(
self,
cred_def_id: str,
revoc_reg_id: str,
tails_file_path: str,
cred_revoc_ids: Sequence[str],
Expand All @@ -370,6 +371,7 @@ async def revoke_credentials(
Revoke a set of credentials in a revocation registry.
Args:
cred_def_id: ID of the credential definition
revoc_reg_id: ID of the revocation registry
tails_file_path: path to the local tails file
cred_revoc_ids: sequences of credential indexes in the revocation registry
Expand All @@ -390,29 +392,60 @@ async def revoke_credentials(
raise IndyIssuerError("Repeated conflict attempting to update registry")
try:
async with self._profile.session() as session:
cred_def = await session.handle.fetch(
CATEGORY_CRED_DEF, cred_def_id
)
rev_reg_def = await session.handle.fetch(
CATEGORY_REV_REG_DEF, revoc_reg_id
)
rev_reg_def_private = await session.handle.fetch(
CATEGORY_REV_REG_DEF_PRIVATE, revoc_reg_id
)
rev_reg = await session.handle.fetch(CATEGORY_REV_REG, revoc_reg_id)
rev_reg_info = await session.handle.fetch(
CATEGORY_REV_REG_INFO, revoc_reg_id
)
if not cred_def:
raise IndyIssuerError("Credential definition not found")
if not rev_reg_def:
raise IndyIssuerError("Revocation registry definition not found")
if not rev_reg_def_private:
raise IndyIssuerError(
"Revocation registry definition private key not found"
)
if not rev_reg:
raise IndyIssuerError("Revocation registry not found")
if not rev_reg_info:
raise IndyIssuerError("Revocation registry metadata not found")
except AskarError as err:
raise IndyIssuerError("Error retrieving revocation registry") from err

try:
cred_def = CredentialDefinition.load(cred_def.raw_value)
except CredxError as err:
raise IndyIssuerError("Error loading credential definition") from err

try:
rev_reg_def = RevocationRegistryDefinition.load(rev_reg_def.raw_value)
except CredxError as err:
raise IndyIssuerError(
"Error loading revocation registry definition"
) from err

try:
rev_reg_def_private = RevocationRegistryDefinitionPrivate.load(
rev_reg_def_private.raw_value
)
except CredxError as err:
raise IndyIssuerError(
"Error loading revocation registry private key"
) from err

try:
rev_reg = RevocationRegistry.load(rev_reg.raw_value)
except CredxError as err:
raise IndyIssuerError("Error loading revocation registry") from err

rev_crids = set()
failed_crids = set()
max_cred_num = rev_reg_def.max_cred_num
Expand Down Expand Up @@ -451,19 +484,15 @@ async def revoke_credentials(
if not rev_crids:
break

try:
rev_reg = RevocationRegistry.load(rev_reg.raw_value)
except CredxError as err:
raise IndyIssuerError("Error loading revocation registry") from err

try:
delta = await asyncio.get_event_loop().run_in_executor(
None,
lambda: rev_reg.update(
cred_def,
rev_reg_def,
None, # issued
list(rev_crids), # revoked
tails_file_path,
rev_reg_def_private,
issued=None,
revoked=list(rev_crids), # revoked
),
)
except CredxError as err:
Expand Down
2 changes: 1 addition & 1 deletion aries_cloudagent/indy/credx/tests/test_cred_issuance.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ async def test_issue_store_rev(self):
rev_delta_init = {"ver": "1.0", "value": rev_state_init["rev_reg"]}

(rev_delta_2_json, skipped_ids) = await self.issuer.revoke_credentials(
reg_id, tails_path, (1,)
cd_id, reg_id, tails_path, (1,)
)
assert not skipped_ids
rev_delta_2 = json.loads(rev_delta_2_json)
Expand Down
8 changes: 7 additions & 1 deletion aries_cloudagent/indy/credx/verifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import asyncio
import logging

from typing import Tuple

from indy_credx import CredxError, Presentation

from ...core.profile import Profile
Expand Down Expand Up @@ -33,7 +35,7 @@ async def verify_presentation(
credential_definitions,
rev_reg_defs,
rev_reg_entries,
) -> (bool, list):
) -> Tuple[bool, list]:
"""
Verify a presentation.
Expand All @@ -46,6 +48,9 @@ async def verify_presentation(
rev_reg_entries: revocation registry entries
"""

accept_legacy_revocation = bool(
self.profile.settings.get("revocation.anoncreds_accept_legacy", True)
)
msgs = []
try:
msgs += self.non_revoc_intervals(pres_req, pres, credential_definitions)
Expand All @@ -72,6 +77,7 @@ async def verify_presentation(
credential_definitions.values(),
rev_reg_defs.values(),
rev_reg_entries,
accept_legacy_revocation,
)
except CredxError as err:
s = str(err)
Expand Down
2 changes: 2 additions & 0 deletions aries_cloudagent/indy/issuer.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ async def create_credential(
@abstractmethod
async def revoke_credentials(
self,
cred_def_id: str,
revoc_reg_id: str,
tails_file_path: str,
cred_rev_ids: Sequence[str],
Expand All @@ -152,6 +153,7 @@ async def revoke_credentials(
Revoke a set of credentials in a revocation registry.
Args:
cred_def_id: ID of the credential definition
revoc_reg_id: ID of the revocation registry
tails_file_path: path to the local tails file
cred_rev_ids: sequences of credential indexes in the revocation registry
Expand Down
2 changes: 2 additions & 0 deletions aries_cloudagent/indy/sdk/issuer.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ async def create_credential(

async def revoke_credentials(
self,
cred_def_id: str,
rev_reg_id: str,
tails_file_path: str,
cred_rev_ids: Sequence[str],
Expand All @@ -252,6 +253,7 @@ async def revoke_credentials(
Revoke a set of credentials in a revocation registry.
Args:
cred_def_id: ID of the credential definition
rev_reg_id: ID of the revocation registry
tails_file_path: path to the local tails file
cred_rev_ids: sequences of credential indexes in the revocation registry
Expand Down
10 changes: 8 additions & 2 deletions aries_cloudagent/indy/sdk/tests/test_issuer.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,10 @@ async def test_create_revoke_credentials(
mock_indy_revoke_credential.return_value = json.dumps(TEST_RR_DELTA)
mock_indy_merge_rr_deltas.return_value = json.dumps(TEST_RR_DELTA)
(result, failed) = await self.issuer.revoke_credentials(
REV_REG_ID, tails_file_path="dummy", cred_rev_ids=test_cred_rev_ids
CRED_DEF_ID,
REV_REG_ID,
tails_file_path="dummy",
cred_rev_ids=test_cred_rev_ids,
)
assert json.loads(result) == TEST_RR_DELTA
assert not failed
Expand Down Expand Up @@ -296,7 +299,10 @@ def mock_revoke(_h, _t, _r, cred_rev_id):
mock_indy_revoke_credential.side_effect = mock_revoke
mock_indy_merge_rr_deltas.return_value = json.dumps(TEST_RR_DELTA)
(result, failed) = await self.issuer.revoke_credentials(
REV_REG_ID, tails_file_path="dummy", cred_rev_ids=test_cred_rev_ids
CRED_DEF_ID,
REV_REG_ID,
tails_file_path="dummy",
cred_rev_ids=test_cred_rev_ids,
)
assert json.loads(result) == TEST_RR_DELTA
assert failed == ["54", "103"]
Expand Down
4 changes: 3 additions & 1 deletion aries_cloudagent/indy/sdk/verifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import json
import logging

from typing import Tuple

import indy.anoncreds
from indy.error import IndyError

Expand Down Expand Up @@ -34,7 +36,7 @@ async def verify_presentation(
credential_definitions,
rev_reg_defs,
rev_reg_entries,
) -> (bool, list):
) -> Tuple[bool, list]:
"""
Verify a presentation.
Expand Down
4 changes: 2 additions & 2 deletions aries_cloudagent/indy/verifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from abc import ABC, ABCMeta, abstractmethod
from enum import Enum
from time import time
from typing import Mapping
from typing import Mapping, Tuple

from ..core.profile import Profile
from ..ledger.multiple_ledger.ledger_requests_executor import (
Expand Down Expand Up @@ -397,7 +397,7 @@ def verify_presentation(
credential_definitions,
rev_reg_defs,
rev_reg_entries,
) -> (bool, list):
) -> Tuple[bool, list]:
"""
Verify a presentation.
Expand Down
Loading

0 comments on commit c21b8c0

Please sign in to comment.