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

Unexpected behavior during the issuance of anoncreds. #3496

Open
cl0ete opened this issue Feb 7, 2025 · 2 comments · May be fixed by #3497
Open

Unexpected behavior during the issuance of anoncreds. #3496

cl0ete opened this issue Feb 7, 2025 · 2 comments · May be fixed by #3497

Comments

@cl0ete
Copy link
Contributor

cl0ete commented Feb 7, 2025

I am in the process of migrating our project from the askr to askar-anoncreds wallet-type. I have come across unexpected behavior during the issuance of anoncreds.

Summary of unexpected behavior

We run 2 agents in our stack, author (ACAPY_MULTITENANT: true) and endorser. We restrict the creation of schemas to the endorser agent.

In the create_offer function of the anoncreds implementation acapy_agent/protocols/issue_credential/v2_0/formats/anoncreds/handler.py the current profile session uses the cred_def_id to find the schemaId associated with the cred_def and then attempts to fetch the schema from the agent's askar db. However since our endorser agent created the schema this fetch comes back as None

Looking at the indy implementation acapy_agent/protocols/issue_credential/v2_0/formats/indy/handler.py the ledger is used to resolve the schema.

More detail

Below is a modified version of the anoncreds create_offer function with added print statements followed by a stack trace of the error I see when I attempt to issue an anon cred :

    async def create_offer(
        self, cred_proposal_message: V20CredProposal
    ) -> CredFormatAttachment:
        """Create anoncreds credential offer."""

        issuer = AnonCredsIssuer(self.profile)
        cache = self.profile.inject_or(BaseCache)

        anoncreds_attachment = cred_proposal_message.attachment(
            AnonCredsCredFormatHandler.format
        )

        if not anoncreds_attachment:
            anoncreds_attachment = cred_proposal_message.attachment(
                V20CredFormat.Format.INDY.api
            )

        cred_def_id = await issuer.match_created_credential_definitions(
            **anoncreds_attachment
        )

        async def _create():
            offer_json = await issuer.create_credential_offer(cred_def_id)
            return json.loads(offer_json)

        async with self.profile.session() as session:
            cred_def_entry = await session.handle.fetch(CATEGORY_CRED_DEF, cred_def_id)
            cred_def_dict = CredentialDefinition.load(cred_def_entry.value).to_dict()
            print(f" <><><><> {cred_def_dict["schemaId"]} <><><><> ")
            schema_entry = await session.handle.fetch(
                CATEGORY_SCHEMA, cred_def_dict["schemaId"]
            )
            print(f" <><><><> {schema_entry} <><><><> ")
            schema_dict = Schema.load(schema_entry.value).to_dict()

        schema_attrs = set(schema_dict["attrNames"])
        preview_attrs = set(cred_proposal_message.credential_preview.attr_dict())
        if preview_attrs != schema_attrs:
            raise V20CredFormatError(
                f"Preview attributes {preview_attrs} "
                f"mismatch corresponding schema attributes {schema_attrs}"
            )
     ...

The stack trace

2025-02-07 06:10:13,102 acapy_agent.admin.server DEBUG Incoming request: POST /issue-credential-2.0/send
2025-02-07 06:10:13,102 acapy_agent.admin.server DEBUG Match info: <MatchInfo {}: <ResourceRoute [POST] <PlainResource  /issue-credential-2.0/send> -> <function credential_exchange_send at 0x721ffb35b740>>
2025-02-07 06:10:13,103 acapy_agent.admin.server DEBUG Body: {"auto_remove":false,"connection_id":"6b77b11e-0a70-4d82-8509-00214090234c","credential_preview":{"attributes":[{"name":"name","value":"123"},{"name":"age","value":"456"}]},"filter":{"anoncreds":{"cred_def_id":"2TJHA4uMgEfRchKcgHRMMV:3:CL:10:default","issuer_id":"did:sov:2TJHA4uMgEfRchKcgHRMMV"}}}
2025-02-07 06:10:13,113 acapy_agent.utils.classloader DEBUG Successfully loaded class V20CredPreviewSchema from module acapy_agent.protocols.issue_credential.v2_0.messages.inner.cred_preview
2025-02-07 06:10:13,122 acapy_agent.utils.classloader DEBUG Successfully loaded class V20CredProposalSchema from module acapy_agent.protocols.issue_credential.v2_0.messages.cred_proposal
2025-02-07 06:10:13,130 acapy_agent.utils.classloader DEBUG Successfully loaded class AnonCredsCredFormatHandler from module acapy_agent.protocols.issue_credential.v2_0.formats.anoncreds.handler
 <><><><> 2WkBvUzBd1iFSHXhJNBwXi:2:test_schema:0.3 <><><><> 
 <><><><> None <><><><> 
2025-02-07 06:10:13,152 acapy_agent.core.dispatcher ERROR Handler error: upgrade_middleware
Traceback (most recent call last):
  File "/usr/local/lib/python3.12/asyncio/tasks.py", line 314, in __step_run_and_handle_result
    result = coro.send(None)
             ^^^^^^^^^^^^^^^
  File "/home/aries/.local/lib/python3.12/site-packages/acapy_agent/admin/server.py", line 222, in upgrade_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/home/aries/.local/lib/python3.12/site-packages/aiohttp_apispec/middlewares.py", line 51, in validation_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/home/aries/.local/lib/python3.12/site-packages/acapy_agent/admin/decorators/auth.py", line 84, in tenant_auth
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/home/aries/.local/lib/python3.12/site-packages/acapy_agent/protocols/issue_credential/v2_0/routes.py", line 852, in credential_exchange_send
    (cred_ex_record, cred_offer_message) = await cred_manager.prepare_send(
                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/aries/.local/lib/python3.12/site-packages/acapy_agent/protocols/issue_credential/v2_0/manager.py", line 83, in prepare_send
    return await self.create_offer(
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/aries/.local/lib/python3.12/site-packages/acapy_agent/protocols/issue_credential/v2_0/manager.py", line 240, in create_offer
    await cred_format.handler(self.profile).create_offer(
  File "/home/aries/.local/lib/python3.12/site-packages/acapy_agent/protocols/issue_credential/v2_0/formats/anoncreds/handler.py", line 215, in create_offer
    schema_dict = Schema.load(schema_entry.value).to_dict()
                              ^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'value'

As we can see from the prints surrounded by <><><><> the schemaId is resolved from the cred_def_dict but the schema_entry comes back as None

If I have missed something or going about this the wrong way etc. please enlighten me.

@swcurran
Copy link
Contributor

swcurran commented Feb 7, 2025

@jamshale @PatStLouis — please take a look. Thanks.

@jamshale
Copy link
Contributor

jamshale commented Feb 7, 2025

The handler should be using the anoncreds registry here instead of the wallet/db.

I'll fix it. I'm not sure when this was introduced, but this would only work if the issuer created the schema and it should get the objects through the registry anyway.

@jamshale jamshale linked a pull request Feb 7, 2025 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants