Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update demo with anoncreds format
Browse files Browse the repository at this point in the history
Signed-off-by: jamshale <jamiehalebc@gmail.com>
jamshale committed Nov 17, 2024
1 parent 7b61f92 commit 7eacdfa
Showing 3 changed files with 119 additions and 93 deletions.
100 changes: 72 additions & 28 deletions demo/runners/agent_container.py
Original file line number Diff line number Diff line change
@@ -36,6 +36,8 @@
log_timer,
)

from .support.agent import CRED_FORMAT_ANONCREDS

CRED_PREVIEW_TYPE = "https://didcomm.org/issue-credential/2.0/credential-preview"
SELF_ATTESTED = os.getenv("SELF_ATTESTED")
TAILS_FILE_COUNT = int(os.getenv("TAILS_FILE_COUNT", 100))
@@ -272,16 +274,25 @@ async def handle_issue_credential_v2_0(self, message):

elif state == "offer-received":
log_status("#15 After receiving credential offer, send credential request")

def _should_send_request_without_data(message):
"""Formats that do not require credential request data."""
cred_offer_by_format = message["by_format"].get("cred_offer")

return (
not message.get("by_format")
or cred_offer_by_format.get("anoncreds")
or cred_offer_by_format.get("indy")
or cred_offer_by_format.get("vc_di")
)

# Should wait for a tiny bit for the delete tests
await asyncio.sleep(0.2)
if not message.get("by_format"):
# this should not happen, something hinky when running in IDE...
# this will work if using indy payloads
self.log(f"No 'by_format' in message: {message}")
await self.admin_POST(
f"/issue-credential-2.0/records/{cred_ex_id}/send-request"
)
elif message["by_format"]["cred_offer"].get("indy"):
elif _should_send_request_without_data(message):
await self.admin_POST(
f"/issue-credential-2.0/records/{cred_ex_id}/send-request"
)
@@ -294,10 +305,6 @@ async def handle_issue_credential_v2_0(self, message):
await self.admin_POST(
f"/issue-credential-2.0/records/{cred_ex_id}/send-request", data
)
elif message["by_format"]["cred_offer"].get("vc_di"):
await self.admin_POST(
f"/issue-credential-2.0/records/{cred_ex_id}/send-request"
)

elif state == "done":
pass
@@ -327,6 +334,26 @@ async def handle_issue_credential_v2_0_indy(self, message):
self.log(f"Revocation registry ID: {rev_reg_id}")
self.log(f"Credential revocation ID: {cred_rev_id}")

async def handle_issue_credential_v2_0_anoncreds(self, message):
rev_reg_id = message.get("rev_reg_id")
cred_rev_id = message.get("cred_rev_id")
cred_id_stored = message.get("cred_id_stored")

if cred_id_stored:
cred_id = message["cred_id_stored"]
log_status(f"#18.1 Stored credential {cred_id} in wallet")
cred = await self.admin_GET(f"/credential/{cred_id}")
log_json(cred, label="Credential details:")
self.log("credential_id", cred_id)
self.log("cred_def_id", cred["cred_def_id"])
self.log("schema_id", cred["schema_id"])
# track last successfully received credential
self.last_credential_received = cred

if rev_reg_id and cred_rev_id:
self.log(f"Revocation registry ID: {rev_reg_id}")
self.log(f"Credential revocation ID: {cred_rev_id}")

async def handle_issue_credential_v2_0_vc_di(self, message):
self.log(f"Handle VC_DI Credential: message = {message}")

@@ -442,16 +469,20 @@ async def handle_present_proof_v2_0(self, message):
# this should not happen, something hinky when running in IDE...
self.log(f"No 'by_format' in message: {message}")
else:
pres_request_indy = (
message["by_format"].get("pres_request", {}).get("indy")
)
pres_request_dif = message["by_format"].get("pres_request", {}).get("dif")
pres_request_by_format = message["by_format"].get("pres_request", {})
pres_request = pres_request_by_format.get(
"indy"
) or pres_request_by_format.get("anoncreds")

print("****************************")
print(pres_request_by_format)
pres_request_dif = pres_request_by_format.get("dif")
request = {}

if not pres_request_dif and not pres_request_indy:
if not pres_request_dif and not pres_request:
raise Exception("Invalid presentation request received")

if pres_request_indy:
if pres_request:
# include self-attested attributes (not included in credentials)
creds_by_reft = {}
revealed = {}
@@ -463,7 +494,6 @@ async def handle_present_proof_v2_0(self, message):
creds = await self.admin_GET(
f"/present-proof-2.0/records/{pres_ex_id}/credentials"
)
# print(">>> creds:", creds)
if creds:
# select only indy credentials
creds = [x for x in creds if "cred_info" in x]
@@ -484,7 +514,7 @@ async def handle_present_proof_v2_0(self, message):

# submit the proof wit one unrevealed revealed attribute
revealed_flag = False
for referent in pres_request_indy["requested_attributes"]:
for referent in pres_request["requested_attributes"]:
if referent in creds_by_reft:
revealed[referent] = {
"cred_id": creds_by_reft[referent]["cred_info"][
@@ -496,23 +526,23 @@ async def handle_present_proof_v2_0(self, message):
else:
self_attested[referent] = "my self-attested value"

for referent in pres_request_indy["requested_predicates"]:
for referent in pres_request["requested_predicates"]:
if referent in creds_by_reft:
predicates[referent] = {
"cred_id": creds_by_reft[referent]["cred_info"][
"referent"
]
}

log_status("#25 Generate the indy proof")
indy_request = {
"indy": {
log_status("#25 Generate the proof")
request = {
"indy" if "indy" in pres_request_by_format else "anoncreds": {
"requested_predicates": predicates,
"requested_attributes": revealed,
"self_attested_attributes": self_attested,
}
}
request.update(indy_request)
request.update(request)
except ClientError:
pass

@@ -779,7 +809,7 @@ def __init__(
# endorsers and authors need public DIDs (assume cred_type is Indy)
if endorser_role == "author" or endorser_role == "endorser":
self.public_did = True
self.cred_type = CRED_FORMAT_INDY
# self.cred_type = CRED_FORMAT_INDY

self.reuse_connections = reuse_connections
self.multi_use_invitations = multi_use_invitations
@@ -938,7 +968,7 @@ async def create_schema_and_cred_def(
):
if not self.public_did:
raise Exception("Can't create a schema/cred def without a public DID :-(")
if self.cred_type in [CRED_FORMAT_INDY, CRED_FORMAT_VC_DI]:
if self.cred_type in [CRED_FORMAT_ANONCREDS, CRED_FORMAT_INDY, CRED_FORMAT_VC_DI]:
# need to redister schema and cred def on the ledger
self.cred_def_id = await self.agent.create_schema_and_cred_def(
schema_name,
@@ -981,20 +1011,26 @@ async def issue_credential(
self,
cred_def_id: str,
cred_attrs: list,
filter_type: str = "indy",
):
log_status("#13 Issue credential offer to X")

if self.cred_type in [CRED_FORMAT_INDY, CRED_FORMAT_VC_DI]:
if self.cred_type in [CRED_FORMAT_ANONCREDS, CRED_FORMAT_INDY, CRED_FORMAT_VC_DI]:
cred_preview = {
"@type": CRED_PREVIEW_TYPE,
"attributes": cred_attrs,
}
if filter_type == "indy":
_filter = {"indy": {"cred_def_id": cred_def_id}}
else:
_filter = {"anoncreds": {"cred_def_id": cred_def_id}}

offer_request = {
"connection_id": self.agent.connection_id,
"comment": f"Offer on cred def id {cred_def_id}",
"auto_remove": False,
"credential_preview": cred_preview,
"filter": {"indy": {"cred_def_id": cred_def_id}},
"filter": _filter,
"trace": self.exchange_tracing,
}
cred_exchange = await self.agent.admin_POST(
@@ -1044,7 +1080,7 @@ async def receive_credential(
async def request_proof(self, proof_request, explicit_revoc_required: bool = False):
log_status("#20 Request proof of degree from alice")

if self.cred_type in [CRED_FORMAT_INDY, CRED_FORMAT_VC_DI]:
if self.cred_type in [CRED_FORMAT_ANONCREDS, CRED_FORMAT_INDY, CRED_FORMAT_VC_DI]:
indy_proof_request = {
"name": (
proof_request["name"] if "name" in proof_request else "Proof of stuff"
@@ -1125,7 +1161,7 @@ async def verify_proof(self, proof_request):

# log_status(f">>> last proof received: {self.agent.last_proof_received}")

if self.cred_type in [CRED_FORMAT_INDY, CRED_FORMAT_VC_DI]:
if self.cred_type in [CRED_FORMAT_ANONCREDS, CRED_FORMAT_INDY, CRED_FORMAT_VC_DI]:
# return verified status
return self.agent.last_proof_received["verified"]

@@ -1514,12 +1550,14 @@ async def create_agent_with_args(args, ident: str = None, extra_args: list = Non
aip = 20

if "cred_type" in args and args.cred_type not in [
CRED_FORMAT_ANONCREDS,
CRED_FORMAT_INDY,
CRED_FORMAT_VC_DI,
]:
public_did = None
aip = 20
elif "cred_type" in args and args.cred_type in [
CRED_FORMAT_ANONCREDS,
CRED_FORMAT_INDY,
CRED_FORMAT_VC_DI,
]:
@@ -1528,6 +1566,12 @@ async def create_agent_with_args(args, ident: str = None, extra_args: list = Non
public_did = args.public_did if "public_did" in args else None

cred_type = args.cred_type if "cred_type" in args else None

# Set anoncreds agent to use anoncreds credential format
wallet_type = arg_file_dict.get("wallet-type") or args.wallet_type
if wallet_type == "askar-anoncreds":
cred_type = CRED_FORMAT_ANONCREDS

log_msg(
f"Initializing demo agent {agent_ident} with AIP {aip} and credential type {cred_type}"
)
@@ -1564,7 +1608,7 @@ async def create_agent_with_args(args, ident: str = None, extra_args: list = Non
mediation=args.mediation,
cred_type=cred_type,
use_did_exchange=(aip == 20) if ("aip" in args) else args.did_exchange,
wallet_type=arg_file_dict.get("wallet-type") or args.wallet_type,
wallet_type=wallet_type,
public_did=public_did,
seed="random" if public_did else None,
arg_file=arg_file,
109 changes: 45 additions & 64 deletions demo/runners/faber.py
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@
create_agent_with_args,
)
from runners.support.agent import ( # noqa:E402
CRED_FORMAT_ANONCREDS,
CRED_FORMAT_INDY,
CRED_FORMAT_JSON_LD,
CRED_FORMAT_VC_DI,
@@ -111,7 +112,7 @@ def generate_credential_offer(self, aip, cred_type, cred_def_id, exchange_tracin
return offer_request

elif aip == 20:
if cred_type == CRED_FORMAT_INDY:
if cred_type == CRED_FORMAT_ANONCREDS or cred_type == CRED_FORMAT_INDY:
self.cred_attrs[cred_def_id] = {
"name": "Alice Smith",
"date": "2018-05-28",
@@ -127,12 +128,16 @@ def generate_credential_offer(self, aip, cred_type, cred_def_id, exchange_tracin
for (n, v) in self.cred_attrs[cred_def_id].items()
],
}
if cred_type == CRED_FORMAT_ANONCREDS:
_filter = {"anoncreds": {"cred_def_id": cred_def_id}}
else:
_filter = {"indy": {"cred_def_id": cred_def_id}}
offer_request = {
"connection_id": self.connection_id,
"comment": f"Offer on cred def id {cred_def_id}",
"auto_remove": False,
"credential_preview": cred_preview,
"filter": {"indy": {"cred_def_id": cred_def_id}},
"filter": _filter,
"trace": exchange_tracing,
}
return offer_request
@@ -249,7 +254,7 @@ def generate_proof_request_web_request(
"restrictions": [{"schema_name": "degree schema"}],
}
]
indy_proof_request = {
proof_request = {
"name": "Proof of Education",
"version": "1.0",
"requested_attributes": {
@@ -261,18 +266,18 @@ def generate_proof_request_web_request(
}

if revocation:
indy_proof_request["non_revoked"] = {"to": int(time.time())}
proof_request["non_revoked"] = {"to": int(time.time())}

proof_request_web_request = {
"proof_request": indy_proof_request,
"proof_request": proof_request,
"trace": exchange_tracing,
}
if not connectionless:
proof_request_web_request["connection_id"] = self.connection_id
return proof_request_web_request

elif aip == 20:
if cred_type == CRED_FORMAT_INDY:
if cred_type == CRED_FORMAT_ANONCREDS or cred_type == CRED_FORMAT_INDY:
req_attrs = [
{
"name": "name",
@@ -312,7 +317,7 @@ def generate_proof_request_web_request(
"restrictions": [{"schema_name": "degree schema"}],
}
]
indy_proof_request = {
proof_request = {
"name": "Proof of Education",
"version": "1.0",
"requested_attributes": {
@@ -325,14 +330,19 @@ def generate_proof_request_web_request(
}

if revocation:
indy_proof_request["non_revoked"] = {"to": int(time.time())}
proof_request["non_revoked"] = {"to": int(time.time())}

if cred_type == CRED_FORMAT_ANONCREDS:
presentation_request = {"anoncreds": proof_request}
else:
presentation_request = {"indy": proof_request}
proof_request_web_request = {
"presentation_request": {"indy": indy_proof_request},
"presentation_request": presentation_request,
"trace": exchange_tracing,
}
if not connectionless:
proof_request_web_request["connection_id"] = self.connection_id

return proof_request_web_request

elif cred_type == CRED_FORMAT_VC_DI:
@@ -537,7 +547,11 @@ async def main(args):
"birthdate_dateint",
"timestamp",
]
if faber_agent.cred_type in [CRED_FORMAT_INDY, CRED_FORMAT_VC_DI]:
if faber_agent.cred_type in [
CRED_FORMAT_ANONCREDS,
CRED_FORMAT_INDY,
CRED_FORMAT_VC_DI,
]:
faber_agent.public_did = True
await faber_agent.initialize(
the_agent=agent,
@@ -569,6 +583,7 @@ async def main(args):
exchange_tracing = False
options = " (1) Issue Credential\n"
if faber_agent.cred_type in [
CRED_FORMAT_ANONCREDS,
CRED_FORMAT_INDY,
CRED_FORMAT_VC_DI,
]:
@@ -664,12 +679,14 @@ async def main(args):

elif option == "1a":
new_cred_type = await prompt(
"Enter credential type ({}, {}): ".format(
"Enter credential type ({}, {}, {}): ".format(
CRED_FORMAT_ANONCREDS,
CRED_FORMAT_INDY,
CRED_FORMAT_VC_DI,
)
)
if new_cred_type in [
CRED_FORMAT_ANONCREDS,
CRED_FORMAT_INDY,
CRED_FORMAT_VC_DI,
]:
@@ -689,7 +706,11 @@ async def main(args):
)

elif faber_agent.aip == 20:
if faber_agent.cred_type == CRED_FORMAT_INDY:
if faber_agent.cred_type in [
CRED_FORMAT_ANONCREDS,
CRED_FORMAT_INDY,
CRED_FORMAT_VC_DI,
]:
offer_request = faber_agent.agent.generate_credential_offer(
faber_agent.aip,
faber_agent.cred_type,
@@ -705,14 +726,6 @@ async def main(args):
exchange_tracing,
)

elif faber_agent.cred_type == CRED_FORMAT_VC_DI:
offer_request = faber_agent.agent.generate_credential_offer(
faber_agent.aip,
faber_agent.cred_type,
faber_agent.cred_def_id,
exchange_tracing,
)

else:
raise Exception(
f"Error invalid credential type: {faber_agent.cred_type}"
@@ -742,27 +755,12 @@ async def main(args):
pass

elif faber_agent.aip == 20:
if faber_agent.cred_type == CRED_FORMAT_INDY:
proof_request_web_request = (
faber_agent.agent.generate_proof_request_web_request(
faber_agent.aip,
faber_agent.cred_type,
faber_agent.revocation,
exchange_tracing,
)
)

elif faber_agent.cred_type == CRED_FORMAT_JSON_LD:
proof_request_web_request = (
faber_agent.agent.generate_proof_request_web_request(
faber_agent.aip,
faber_agent.cred_type,
faber_agent.revocation,
exchange_tracing,
)
)

elif faber_agent.cred_type == CRED_FORMAT_VC_DI:
if faber_agent.cred_type in [
CRED_FORMAT_ANONCREDS,
CRED_FORMAT_INDY,
CRED_FORMAT_VC_DI,
CRED_FORMAT_JSON_LD,
]:
proof_request_web_request = (
faber_agent.agent.generate_proof_request_web_request(
faber_agent.aip,
@@ -771,7 +769,6 @@ async def main(args):
exchange_tracing,
)
)

else:
raise Exception(
"Error invalid credential type:" + faber_agent.cred_type
@@ -819,28 +816,12 @@ async def main(args):
qr.print_ascii(invert=True)

elif faber_agent.aip == 20:
if faber_agent.cred_type == CRED_FORMAT_INDY:
proof_request_web_request = (
faber_agent.agent.generate_proof_request_web_request(
faber_agent.aip,
faber_agent.cred_type,
faber_agent.revocation,
exchange_tracing,
connectionless=True,
)
)
elif faber_agent.cred_type == CRED_FORMAT_JSON_LD:
proof_request_web_request = (
faber_agent.agent.generate_proof_request_web_request(
faber_agent.aip,
faber_agent.cred_type,
faber_agent.revocation,
exchange_tracing,
connectionless=True,
)
)

elif faber_agent.cred_type == CRED_FORMAT_VC_DI:
if faber_agent.cred_type in [
CRED_FORMAT_ANONCREDS,
CRED_FORMAT_INDY,
CRED_FORMAT_VC_DI,
CRED_FORMAT_JSON_LD,
]:
proof_request_web_request = (
faber_agent.agent.generate_proof_request_web_request(
faber_agent.aip,
3 changes: 2 additions & 1 deletion demo/runners/support/agent.py
Original file line number Diff line number Diff line change
@@ -70,6 +70,7 @@
WALLET_TYPE_ASKAR = "askar"
WALLET_TYPE_ANONCREDS = "askar-anoncreds"

CRED_FORMAT_ANONCREDS = "anoncreds"
CRED_FORMAT_INDY = "indy"
CRED_FORMAT_JSON_LD = "json-ld"
CRED_FORMAT_VC_DI = "vc_di"
@@ -672,7 +673,7 @@ async def register_did(
role: str = "TRUST_ANCHOR",
cred_type: str = CRED_FORMAT_INDY,
):
if cred_type in [CRED_FORMAT_INDY, CRED_FORMAT_VC_DI]:
if cred_type in [CRED_FORMAT_ANONCREDS, CRED_FORMAT_INDY, CRED_FORMAT_VC_DI]:
# if registering a did for issuing indy credentials, publish the did on the ledger
self.log(f"Registering {self.ident} ...")
if not ledger_url:

0 comments on commit 7eacdfa

Please sign in to comment.