Skip to content

Fix: Use correct profile context for ledger signing during revocation setup (#3624) #3649

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

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
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
24 changes: 15 additions & 9 deletions acapy_agent/anoncreds/default/legacy_indy/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,8 @@ async def _revoc_reg_entry_with_fix(
rev_list.issuer_id,
write_ledger=write_ledger,
endorser_did=endorser_did,
# Temporary fix for #3624 / #3649
profile=profile, # Added profile (#3624 / #3649)
)
except LedgerTransactionError as err:
if "InvalidClientRequest" in err.roll_up:
Expand Down Expand Up @@ -1209,20 +1211,24 @@ async def txn_submit(
taa_accept: Optional[bool] = None,
sign_did: DIDInfo = sentinel,
write_ledger: bool = True,
profile: Optional[Profile] = None, # Added profile (#3624 / #3649)
) -> str:
"""Submit a transaction to the ledger."""

try:
async with ledger:
return await shield(
ledger.txn_submit(
ledger_transaction,
sign=sign,
taa_accept=taa_accept,
sign_did=sign_did,
write_ledger=write_ledger,
)
)
kwargs = {
"sign": sign,
"taa_accept": taa_accept,
"sign_did": sign_did,
"write_ledger": write_ledger,
}

# Temporary fix to include profile to resolve #3624 / #3649
if profile is not None:
kwargs["profile"] = profile

return await shield(ledger.txn_submit(ledger_transaction, **kwargs))
except LedgerError as err:
raise AnonCredsRegistrationError(err.roll_up) from err

Expand Down
91 changes: 91 additions & 0 deletions acapy_agent/anoncreds/default/legacy_indy/tests/test_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
RevRegDefValue,
)
from ....models.schema import AnonCredsSchema, GetSchemaResult, SchemaResult
from .....core.profile import Profile
from .....wallet.did_info import DIDInfo

B58 = alphabet if isinstance(alphabet, str) else alphabet.decode("ascii")
INDY_DID = rf"^(did:sov:)?[{B58}]{{21,22}}$"
Expand Down Expand Up @@ -1215,3 +1217,92 @@ async def test_get_schem_info(self):
assert result.issuer_id == "XduBsoPyEA4szYMy3pZ8De"
assert result.name == "minimal-33279d005748b3cc"
assert result.version == "1.0"

@mock.patch.object(
IndyLedgerRequestsExecutor,
"get_ledger_for_identifier",
return_value=(
"mock_ledger_id",
mock.MagicMock(
spec=BaseLedger,
send_revoc_reg_entry=mock.CoroutineMock(return_value="mock_seq_no"),
__aenter__=mock.CoroutineMock(return_value=mock.MagicMock()),
__aexit__=mock.CoroutineMock(return_value=None),
profile=mock.MagicMock(spec=Profile),
),
),
)
@mock.patch.object(AskarAnonCredsProfileSession, "handle")
async def test_register_revocation_list_passes_profile(
self, mock_askar_handle, mock_get_ledger_for_id
):
"""Test register_revocation_list passes profile kwarg via helper."""
self.profile.inject_or = mock.MagicMock()

test_profile = self.profile

test_rev_reg_def = RevRegDef(
tag="tag",
cred_def_id="IssuerDID:3:CL:1:tag",
value=RevRegDefValue(
max_cred_num=100, public_keys={}, tails_hash="", tails_location=""
),
issuer_id="IssuerDID",
type="CL_ACCUM",
)
test_rev_list = RevList(
issuer_id="IssuerDID",
current_accumulator="dummy_accum_value",
revocation_list=[0],
timestamp=1234567890,
rev_reg_def_id="IssuerDID:4:IssuerDID:3:CL:1:tag:CL_ACCUM:tag",
)

await self.registry.register_revocation_list(
test_profile,
test_rev_reg_def,
test_rev_list,
{},
)

mock_ledger_instance = mock_get_ledger_for_id.return_value[1]

mock_ledger_instance.send_revoc_reg_entry.assert_called_once()

_call_args, call_kwargs = mock_ledger_instance.send_revoc_reg_entry.call_args

assert "profile" in call_kwargs
assert call_kwargs["profile"] is test_profile
assert call_kwargs["write_ledger"] is True

async def test_registry_txn_submit_passes_profile(self):
"""Test registry txn_submit passes profile kwarg to ledger txn_submit."""
mock_ledger = mock.MagicMock(BaseLedger, autospec=True)
mock_ledger.txn_submit = mock.CoroutineMock(return_value="mock_ledger_response")
mock_ledger.__aenter__ = mock.CoroutineMock(return_value=mock_ledger)
mock_ledger.__aexit__ = mock.CoroutineMock(return_value=None)

test_profile = self.profile
test_txn_data = '{"a": 1}'
test_sign_did = mock.MagicMock(spec=DIDInfo)

await self.registry.txn_submit(
ledger=mock_ledger,
ledger_transaction=test_txn_data,
sign=True,
taa_accept=True,
sign_did=test_sign_did,
write_ledger=True,
profile=test_profile,
)

mock_ledger.txn_submit.assert_called_once()

_call_args, call_kwargs = mock_ledger.txn_submit.call_args

assert "profile" in call_kwargs
assert call_kwargs["profile"] is test_profile
assert call_kwargs["sign"] is True
assert call_kwargs["taa_accept"] is True
assert call_kwargs["sign_did"] is test_sign_did
assert call_kwargs["write_ledger"] is True
57 changes: 51 additions & 6 deletions acapy_agent/ledger/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from hashlib import sha256
from typing import List, Optional, Sequence, Tuple, Union

from ..core.profile import Profile
from ..indy.issuer import DEFAULT_CRED_DEF_TAG, IndyIssuer, IndyIssuerError
from ..messaging.valid import IndyDID
from ..utils import sentinel
Expand Down Expand Up @@ -175,8 +176,17 @@ async def rotate_public_did_keypair(self, next_seed: Optional[str] = None) -> No
"""

@abstractmethod
async def get_wallet_public_did(self) -> DIDInfo:
"""Fetch the public DID from the wallet."""
async def get_wallet_public_did(
# Added profile (#3624 / #3649)
self,
profile: Optional[Profile] = None,
) -> DIDInfo:
"""Fetch the public DID from the wallet.

Args:
profile: The profile instance to use for this operation.
Temporary fix for #3624. Ideally obtained via context.
"""

@abstractmethod
async def get_txn_author_agreement(self, reload: bool = False):
Expand All @@ -193,8 +203,17 @@ async def accept_txn_author_agreement(
"""Save a new record recording the acceptance of the TAA."""

@abstractmethod
async def get_latest_txn_author_acceptance(self):
"""Look up the latest TAA acceptance."""
async def get_latest_txn_author_acceptance(
# Added profile (#3624 / #3649)
self,
profile: Optional[Profile] = None,
):
"""Look up the latest TAA acceptance.

Args:
profile: The profile instance to use for this operation.
Temporary fix for #3624. Ideally obtained via context.
"""

def taa_digest(self, version: str, text: str):
"""Generate the digest of a TAA record."""
Expand All @@ -219,8 +238,22 @@ async def txn_submit(
taa_accept: Optional[bool] = None,
sign_did: DIDInfo = sentinel,
write_ledger: bool = True,
profile: Optional[Profile] = None, # Added profile (#3624 / #3649)
) -> str:
"""Write the provided (signed and possibly endorsed) transaction to the ledger."""
"""Write the provided (signed and possibly endorsed) transaction to the ledger.

Args:
request_json: Anoncreds-style ledger transaction as a JSON string.
sign: Whether to sign the transaction using using `sign_did`.
taa_accept: Accept the Transaction Author Agreement, if required.
sign_did: DID to sign with. Required if `sign` is True.
write_ledger: whether to write the request to the ledger
profile: The profile instance to use for this operation.
Temporary fix for #3624. Ideally obtained via context.

Returns:
str: JSON response from the ledger.
"""

@abstractmethod
async def fetch_schema_by_id(self, schema_id: str) -> dict:
Expand Down Expand Up @@ -414,8 +447,20 @@ async def send_revoc_reg_entry(
issuer_did: Optional[str] = None,
write_ledger: bool = True,
endorser_did: Optional[str] = None,
profile: Optional[Profile] = None, # Added profile (#3624 / #3649)
) -> dict:
"""Publish a revocation registry entry to the ledger."""
"""Publish a revocation registry entry to the ledger.

Args:
revoc_reg_id: ID of the revocation registry.
revoc_def_type: Type of revocation registry (e.g. CL_ACCUM).
revoc_reg_entry: Entry data to publish.
issuer_did: DID of the issuer writing the entry.
write_ledger: If False, prepare but don't submit the entry.
endorser_did: DID of the endorser if endorsement is required.
profile: The profile instance to use for this operation.
Temporary fix for #3624. Ideally obtained via context.
"""

async def create_and_send_credential_definition(
self,
Expand Down
Loading
Loading