Skip to content

Commit

Permalink
Add vcdm 2.0 model and context (openwallet-foundation#3436)
Browse files Browse the repository at this point in the history
* add vcdm 2.0 model and context

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

* add backwards compatibility checks: limit proof type and add issuance date with vcdm 1.1

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

* seperate test fixtures, lint

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

* replace issuanceDate tests

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

* remove askar issuanceDate sorting

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

* rename credential context constant

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

* linting

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

* updated linting

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

* remove askar sorting step

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

* add vcdm 2.0 tests, fix presentation route default cryptosuite

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

* Fix broken tests, add v2 context to test document loader

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

* Lint

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

* Debugging unit tests

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

* rename test function to v2

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

* add list of support cryptosuites for vcdm 2.0

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

* add list of supported cryptosuites for vcdm 2.0

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

* fix presentation fixture

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

* fix created format check

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

* fix tset fixtures

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

* lint

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

* add authentication proof purpose

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

* add holder proof type derivation when creating a vp

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

* linting

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>

---------

Signed-off-by: PatStLouis <patrick.st-louis@opsecid.ca>
  • Loading branch information
PatStLouis authored and ff137 committed Feb 28, 2025
1 parent b19e8c5 commit 1d5c591
Show file tree
Hide file tree
Showing 17 changed files with 1,029 additions and 93 deletions.
14 changes: 10 additions & 4 deletions acapy_agent/messaging/valid.py
Original file line number Diff line number Diff line change
Expand Up @@ -898,19 +898,25 @@ class CredentialContext(Validator):
"""Credential Context."""

FIRST_CONTEXT = "https://www.w3.org/2018/credentials/v1"
EXAMPLE = [FIRST_CONTEXT, "https://www.w3.org/2018/credentials/examples/v1"]
VALID_CONTEXTS = [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/ns/credentials/v2",
]
EXAMPLE = [VALID_CONTEXTS[0], "https://www.w3.org/2018/credentials/examples/v1"]

def __init__(self) -> None:
"""Initialize the instance."""
super().__init__()

def __call__(self, value):
"""Validate input value."""
length = len(value)

if length < 1 or value[0] != CredentialContext.FIRST_CONTEXT:
if not isinstance(value, list):
raise ValidationError("Value must be a non-empty list.")

if not value or value[0] not in CredentialContext.VALID_CONTEXTS:
raise ValidationError(
f"First context must be {CredentialContext.FIRST_CONTEXT}"
f"First context must be one of {CredentialContext.VALID_CONTEXTS}"
)

return value
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
TEST_DID_SOV = "did:sov:LjgpST2rjsoxYegQDRm7EL"
TEST_DID_KEY = "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL"

LD_PROOF_VC_DETAIL = {
"credential": {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1",
],
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"credentialSubject": {"test": "key"},
"issuanceDate": "2021-04-12",
"issuer": TEST_DID_KEY,
},
"options": {
"proofType": "Ed25519Signature2018",
"created": "2019-12-11T03:50:55",
},
}
LD_PROOF_VC_DETAIL_BBS = {
"credential": {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1",
],
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"credentialSubject": {"test": "key"},
"issuanceDate": "2021-04-12",
"issuer": TEST_DID_KEY,
},
"options": {
"proofType": "BbsBlsSignature2020",
"created": "2019-12-11T03:50:55",
},
}
LD_PROOF_VC_DETAIL_ED25519_2020 = {
"credential": {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1",
],
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"credentialSubject": {"test": "key"},
"issuanceDate": "2021-04-12",
"issuer": TEST_DID_KEY,
},
"options": {
"proofType": "Ed25519Signature2020",
"created": "2019-12-11T03:50:55",
},
}
LD_PROOF_VC = {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1",
],
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"credentialSubject": {"test": "key"},
"issuanceDate": "2021-04-12",
"issuer": TEST_DID_KEY,
"proof": {
"proofPurpose": "assertionMethod",
"created": "2019-12-11T03:50:55",
"type": "Ed25519Signature2018",
"verificationMethod": "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL#z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL",
"jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..Q6amIrxGiSbM7Ce6DxlfwLCjVcYyclas8fMxaecspXFUcFW9DAAxKzgHx93FWktnlZjM_biitkMgZdStgvivAQ",
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,75 +43,12 @@
from ..handler import LOGGER as LD_PROOF_LOGGER
from ..handler import LDProofCredFormatHandler
from ..models.cred_detail import LDProofVCDetail

TEST_DID_SOV = "did:sov:LjgpST2rjsoxYegQDRm7EL"
TEST_DID_KEY = "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL"

LD_PROOF_VC_DETAIL = {
"credential": {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1",
],
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"credentialSubject": {"test": "key"},
"issuanceDate": "2021-04-12",
"issuer": TEST_DID_KEY,
},
"options": {
"proofType": "Ed25519Signature2018",
"created": "2019-12-11T03:50:55",
},
}
LD_PROOF_VC_DETAIL_BBS = {
"credential": {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1",
],
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"credentialSubject": {"test": "key"},
"issuanceDate": "2021-04-12",
"issuer": TEST_DID_KEY,
},
"options": {
"proofType": "BbsBlsSignature2020",
"created": "2019-12-11T03:50:55",
},
}
LD_PROOF_VC_DETAIL_ED25519_2020 = {
"credential": {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1",
],
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"credentialSubject": {"test": "key"},
"issuanceDate": "2021-04-12",
"issuer": TEST_DID_KEY,
},
"options": {
"proofType": "Ed25519Signature2020",
"created": "2019-12-11T03:50:55",
},
}
LD_PROOF_VC = {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1",
],
"type": ["VerifiableCredential", "UniversityDegreeCredential"],
"credentialSubject": {"test": "key"},
"issuanceDate": "2021-04-12",
"issuer": TEST_DID_KEY,
"proof": {
"proofPurpose": "assertionMethod",
"created": "2019-12-11T03:50:55",
"type": "Ed25519Signature2018",
"verificationMethod": "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL#z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL",
"jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..Q6amIrxGiSbM7Ce6DxlfwLCjVcYyclas8fMxaecspXFUcFW9DAAxKzgHx93FWktnlZjM_biitkMgZdStgvivAQ",
},
}
from .fixtures import (
LD_PROOF_VC_DETAIL,
LD_PROOF_VC_DETAIL_BBS,
LD_PROOF_VC_DETAIL_ED25519_2020,
LD_PROOF_VC,
)


class TestV20LDProofCredFormatHandler(IsolatedAsyncioTestCase):
Expand Down Expand Up @@ -166,7 +103,7 @@ async def test_validate_fields(self):

incorrect_detail = {
**LD_PROOF_VC_DETAIL,
"credential": {**LD_PROOF_VC_DETAIL["credential"], "issuanceDate": None},
"credential": {**LD_PROOF_VC_DETAIL["credential"], "credentialSubject": None},
}

# test incorrect proposal
Expand All @@ -184,8 +121,7 @@ async def test_validate_fields(self):
# test incorrect cred
with self.assertRaises(ValidationError):
incorrect_cred = LD_PROOF_VC.copy()
incorrect_cred.pop("issuanceDate")

incorrect_cred.pop("credentialSubject")
self.handler.validate_fields(CRED_20_ISSUE, incorrect_cred)

async def test_get_ld_proof_detail_record(self):
Expand Down
12 changes: 1 addition & 11 deletions acapy_agent/storage/vc_holder/askar.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
import json
from typing import Mapping, Optional, Sequence

from dateutil.parser import ParserError
from dateutil.parser import parse as dateutil_parser

from ...askar.profile import AskarProfile
from ..askar import AskarStorage, AskarStorageSearch, AskarStorageSearchSession
from ..record import StorageRecord
Expand Down Expand Up @@ -174,14 +171,7 @@ async def fetch(self, max_count: Optional[int] = None) -> Sequence[VCRecord]:
"""
rows = await self._search.fetch(max_count)
records = [storage_to_vc_record(r) for r in rows]
try:
records.sort(
key=lambda v: dateutil_parser(v.cred_value.get("issuanceDate")),
reverse=True,
)
return records
except ParserError:
return records
return records


def storage_to_vc_record(record: StorageRecord) -> VCRecord:
Expand Down
4 changes: 2 additions & 2 deletions acapy_agent/storage/vc_holder/tests/test_askar_vc_holder.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,11 +268,11 @@ async def test_sorting_vcrecord(holder: VCHolder):
},
)
await holder.store_credential(record_c)
expected = [record_b, record_a, record_c]
# expected = [record_b, record_a, record_c]

search = holder.search_credentials()
rows = await search.fetch()
assert rows == expected
assert rows # == expected


@pytest.mark.asyncio
Expand Down
1 change: 1 addition & 0 deletions acapy_agent/vc/ld_proofs/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
SECURITY_CONTEXT_URL = SECURITY_CONTEXT_V2_URL
DID_V1_CONTEXT_URL = "https://www.w3.org/ns/did/v1"
CREDENTIALS_CONTEXT_V1_URL = "https://www.w3.org/2018/credentials/v1"
CREDENTIALS_CONTEXT_V2_URL = "https://www.w3.org/ns/credentials/v2"
SECURITY_CONTEXT_BBS_URL = "https://w3id.org/security/bbs/v1"
SECURITY_CONTEXT_ED25519_2020_URL = "https://w3id.org/security/suites/ed25519-2020/v1"
SECURITY_CONTEXT_MULTIKEY_URL = "https://w3id.org/security/multikey/v1"
Expand Down
1 change: 1 addition & 0 deletions acapy_agent/vc/ld_proofs/document_downloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class StaticCacheJsonLdDownloader:

CONTEXT_FILE_MAPPING = {
"https://www.w3.org/2018/credentials/v1": "credentials_context.jsonld",
"https://www.w3.org/ns/credentials/v2": "credentials_v2_context.jsonld",
"https://w3id.org/vc/status-list/2021/v1": "status_list_context.jsonld",
"https://www.w3.org/ns/did/v1": "did_documents_context.jsonld",
"https://w3id.org/security/v1": "security-v1-context.jsonld",
Expand Down
Loading

0 comments on commit 1d5c591

Please sign in to comment.