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

VC DI proof request #2960

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
23ad5bd
WIP: vc di proof request - authored by ianco(https://github.com/hyper…
sarthakvijayvergiya Jun 18, 2024
742a7df
fixed lint checks, cleanup
sarthakvijayvergiya Jun 20, 2024
92db3ea
fix: verify_pres, get_sign_key_credential_subject_id
EmadAnwer Jun 28, 2024
dd800b0
WIP: debugging revocation & fixes
sarthakvijayvergiya Jun 28, 2024
c7077dd
WIP: fix ununsed import
sarthakvijayvergiya Jun 28, 2024
147fbb9
refactor: create_signed_anoncreds_presentation, faber vcdi proof_re…
EmadAnwer Jun 29, 2024
72f2d08
Refactor:Add W3cCredential loading for VCDI format handler
EmadAnwer Jun 30, 2024
6ad8125
fix: tests
EmadAnwer Jul 1, 2024
c13a3df
WPA: using static data to test the revocation validation
EmadAnwer Jul 4, 2024
2626b19
feat: Add revocation support to VCDI
EmadAnwer Jul 6, 2024
1034c80
Remove unused code for credential definition and revocation
EmadAnwer Jul 7, 2024
d02441e
Merge branch 'main' into whatscookin/feat/vc-di-proof
EmadAnwer Jul 7, 2024
5083bc3
WPA: fix lint
EmadAnwer Jul 7, 2024
e760786
Fix cred search for vc_di proof
EmadAnwer Jul 8, 2024
d25bb56
Merge branch 'main' into whatscookin/feat/vc-di-proof
EmadAnwer Jul 8, 2024
4adf5a1
Additional integration tests for vc_di and revocation
ianco Jul 8, 2024
432923b
refactor: remove unused comments and TODO's
EmadAnwer Jul 8, 2024
e58f1aa
refactor: split create_signed_anoncreds_presentation
EmadAnwer Jul 8, 2024
a037382
refactor: `create_signed_anoncreds_presentation`
EmadAnwer Jul 9, 2024
dc351a4
Merge pull request #3 from ianco/w3c-proof-req-2
sarthakvijayvergiya Jul 9, 2024
852fa6a
Merge branch 'main' into whatscookin/feat/vc-di-proof
sarthakvijayvergiya Jul 9, 2024
c10c928
add: tests
EmadAnwer Jul 10, 2024
494ab81
add: tests, remove todos
EmadAnwer Jul 11, 2024
b623dae
add: tests
EmadAnwer Jul 11, 2024
6365822
Merge branch 'main' into whatscookin/feat/vc-di-proof
EmadAnwer Jul 11, 2024
b30d88d
fix: linter
EmadAnwer Jul 11, 2024
d13136c
fix: remove unused imports
EmadAnwer Jul 11, 2024
0170055
add: tests
EmadAnwer Jul 11, 2024
116a992
refactor: remove extra variables and comments
EmadAnwer Jul 12, 2024
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
5 changes: 4 additions & 1 deletion aries_cloudagent/anoncreds/default/legacy_indy/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ def __init__(self):
B58 = alphabet if isinstance(alphabet, str) else alphabet.decode("ascii")
INDY_DID = rf"^(did:sov:)?[{B58}]{{21,22}}$"
INDY_SCHEMA_ID = rf"^[{B58}]{{21,22}}:2:.+:[0-9.]+$"
# the schema id can be just a number
# (this is how the schema_id is referenced in a cred def)
INDY_SCHEMA_TXN_ID = r"^[0-9.]+$"
INDY_CRED_DEF_ID = (
rf"^([{B58}]{{21,22}})" # issuer DID
f":3" # cred def id marker
Expand All @@ -131,7 +134,7 @@ def __init__(self):
rf"CL_ACCUM:(.+$)"
)
self._supported_identifiers_regex = re.compile(
rf"{INDY_DID}|{INDY_SCHEMA_ID}|{INDY_CRED_DEF_ID}|{INDY_REV_REG_DEF_ID}"
rf"{INDY_DID}|{INDY_SCHEMA_ID}|{INDY_SCHEMA_TXN_ID}|{INDY_CRED_DEF_ID}|{INDY_REV_REG_DEF_ID}"
)

@property
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
B58 = alphabet if isinstance(alphabet, str) else alphabet.decode("ascii")
INDY_DID = rf"^(did:sov:)?[{B58}]{{21,22}}$"
INDY_SCHEMA_ID = rf"^[{B58}]{{21,22}}:2:.+:[0-9.]+$"
INDY_SCHEMA_TXN_ID = r"^[0-9.]+$"
INDY_CRED_DEF_ID = (
rf"^([{B58}]{{21,22}})" # issuer DID
f":3" # cred def id marker
Expand All @@ -73,7 +74,7 @@
rf"CL_ACCUM:(.+$)"
)
SUPPORTED_ID_REGEX = re.compile(
rf"{INDY_DID}|{INDY_SCHEMA_ID}|{INDY_CRED_DEF_ID}|{INDY_REV_REG_DEF_ID}"
rf"{INDY_DID}|{INDY_SCHEMA_ID}|{INDY_SCHEMA_TXN_ID}|{INDY_CRED_DEF_ID}|{INDY_REV_REG_DEF_ID}"
)

TEST_INDY_DID = "WgWxqztrNooG92RXvxSTWv"
Expand Down
109 changes: 104 additions & 5 deletions aries_cloudagent/anoncreds/holder.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
import asyncio
import json
import logging
from marshmallow import INCLUDE
import re
from typing import Dict, Optional, Sequence, Tuple, Union
from pyld import jsonld
from pyld.jsonld import JsonLdProcessor

from anoncreds import (
AnoncredsError,
Expand All @@ -14,6 +17,7 @@
Presentation,
PresentCredentials,
W3cCredential,
W3cPresentation,
create_link_secret,
)
from aries_askar import AskarError, AskarErrorCode
Expand All @@ -23,6 +27,10 @@
from ..askar.profile_anon import AskarAnoncredsProfile
from ..core.error import BaseError
from ..core.profile import Profile
from ..storage.vc_holder.base import VCHolder
from ..storage.vc_holder.vc_record import VCRecord
from ..vc.vc_ld import VerifiableCredential
from ..vc.ld_proofs import DocumentLoader
from ..wallet.error import WalletNotFoundError
from .error_messages import ANONCREDS_PROFILE_REQUIRED_MSG
from .models.anoncreds_cred_def import CredDef
Expand Down Expand Up @@ -307,7 +315,7 @@ async def store_credential_w3c(
try:
secret = await self.get_master_secret()
cred_w3c = W3cCredential.load(credential_data)
await asyncio.get_event_loop().run_in_executor(
cred_w3c_recvd = await asyncio.get_event_loop().run_in_executor(
None,
cred_w3c.process,
credential_request_metadata,
Expand All @@ -327,7 +335,7 @@ async def store_credential_w3c(
except AnoncredsError as err:
raise AnonCredsHolderError("Error processing received credential") from err

return await self._finish_store_credential(
credential_id = await self._finish_store_credential(
credential_definition,
cred_recvd,
credential_request_metadata,
Expand All @@ -336,6 +344,45 @@ async def store_credential_w3c(
rev_reg_def,
)

# also store in W3C format
# create VC record for storage
cred_w3c_recvd_dict = cred_w3c_recvd.to_dict()
cred_w3c_recvd_dict["proof"] = cred_w3c_recvd_dict["proof"][0]
cred_w3c_recvd_vc = VerifiableCredential.deserialize(
cred_w3c_recvd_dict, unknown=INCLUDE
)

# Saving expanded type as a cred_tag
document_loader = self.profile.inject(DocumentLoader)
expanded = jsonld.expand(
cred_w3c_recvd_dict, options={"documentLoader": document_loader}
)
types = JsonLdProcessor.get_values(
expanded[0],
"@type",
)

vc_record = VCRecord(
contexts=cred_w3c_recvd_vc.context_urls,
expanded_types=types,
issuer_id=cred_w3c_recvd_vc.issuer_id,
subject_ids=cred_w3c_recvd_vc.credential_subject_ids,
schema_ids=[], # Schemas not supported yet
proof_types=[cred_w3c_recvd_vc.proof.type],
cred_value=cred_w3c_recvd_vc.serialize(),
given_id=cred_w3c_recvd_vc.id,
record_id=credential_id,
cred_tags=None, # Tags should be derived from credential values
)

# save credential in storage
async with self.profile.session() as session:
vc_holder = session.inject(VCHolder)

await vc_holder.store_credential(vc_record)

return credential_id

async def get_credentials(self, start: int, count: int, wql: dict):
"""Get credentials stored in the wallet.

Expand Down Expand Up @@ -384,16 +431,13 @@ async def get_credentials_for_presentation_request_by_referent(
extra_query: wql query dict

"""

if not referents:
referents = (
*presentation_request["requested_attributes"],
*presentation_request["requested_predicates"],
)
extra_query = extra_query or {}

creds = {}

for reft in referents:
names = set()
if reft in presentation_request["requested_attributes"]:
Expand Down Expand Up @@ -646,6 +690,61 @@ def get_rev_state(cred_id: str, detail: dict):

return presentation.to_json()

async def create_presentation_w3c(
self,
presentation_request: dict,
requested_credentials_w3c: list,
credentials_w3c_metadata: list,
schemas: Dict[str, AnonCredsSchema],
credential_definitions: Dict[str, CredDef],
rev_states: dict = None,
) -> dict:
"""Get credentials stored in the wallet.

Args:
presentation_request: Valid indy format presentation request
requested_credentials_w3c: W3C format requested credentials
credentials_w3c_metadata: W3C format credential metadata
schemas: Indy formatted schemas JSON
credential_definitions: Indy formatted credential definitions JSON
rev_states: Indy format revocation states JSON

"""
present_creds = PresentCredentials()
for idx, cred in enumerate(requested_credentials_w3c):
meta = credentials_w3c_metadata[idx]
rev_state = rev_states.get(meta["rev_reg_id"]) if rev_states else None
for attr in meta["proof_attrs"]:
present_creds.add_attributes(
cred,
attr,
reveal=True,
timestamp=meta.get("timestamp"),
rev_state=rev_state,
)

for pred in meta["proof_preds"]:
present_creds.add_predicates(
cred,
pred,
timestamp=meta.get("timestamp"),
rev_state=rev_state,
)

try:
secret = await self.get_master_secret()
presentation = W3cPresentation.create(
presentation_request,
present_creds,
secret,
schemas,
credential_definitions,
)
except AnoncredsError as err:
raise AnonCredsHolderError("Error creating presentation") from err

return presentation.to_dict()

async def create_revocation_state(
self,
cred_rev_id: str,
Expand Down
Loading
Loading