async def main(start_port: int, show_timing: bool = False): genesis = await default_genesis_txns() if not genesis: print("Error retrieving ledger genesis transactions") sys.exit(1) agent = None try: log_status("#1 Provision an agent and wallet, get back configuration details") agent = CoordinatorAgent( start_port, start_port + 1, genesis_data=genesis, timing=show_timing ) await agent.listen_webhooks(start_port + 2) with log_timer("Startup duration:"): await agent.start_process() log_msg("Admin url is at:", agent.admin_url) log_msg("Endpoint url is at:", agent.endpoint) with log_timer("Generate invitation duration:"): # Generate an invitation log_status( "#5 Create a connection to alice and print out the invite details" ) connection = await agent.admin_POST("/connections/create-invitation") agent.active_connection_id = connection["connection_id"] agent.connection_list.append(connection["connection_id"]) log_json(connection, label="Invitation response:") log_msg("*****************") log_msg(json.dumps(connection["invitation"]), label="Invitation:", color=None) log_msg("*****************") # log_msg("Waiting for connection...") # await agent.detect_connection() async for option in prompt_loop( "(1) Request proof of Verified Hospital \n" + "(2) Input New Invitation \n" + "(3) Create New Invitation \n" + "(4) List trusted connections \n" + "(5) Initiate Learning \n" + "(6) Reset trusted connections \n" + "(X) Exit? \n[1/2/3/4/5/6/X] " ): if option is None or option in "xX": break elif option == "1": log_status("#20 Request proof of degree from alice") req_attrs = [ {"name": "date", "restrictions": [{"issuer_did": agent.nhsheadoffice_did}]}, {"name": "hospital_name", "restrictions": [{"issuer_did": agent.nhsheadoffice_did}]}, ] # req_preds = [ # { # "name": "age", # "p_type": ">=", # "p_value": 18, # "restrictions": [{"issuer_did": agent.did}], # } # ] indy_proof_request = { "name": "Proof of Verified Hospital", "version": "1.0", "nonce": str(uuid4().int), "requested_attributes": { f"0_{req_attr['name']}_uuid": req_attr for req_attr in req_attrs }, "requested_predicates": { }, } print("Asking for this proof: ", indy_proof_request) proof_request_web_request = { "connection_id": agent.active_connection_id, "proof_request": indy_proof_request, } await agent.admin_POST( "/present-proof/send-request", proof_request_web_request ) elif option == "2": # handle new invitation log_status("Input new invitation details") await input_invitation(agent) elif option == "3": # handle new invitation with log_timer("Generate invitation duration:"): # Generate an invitation log_status( "#5 Create a connection to alice and print out the invite details" ) connection = await agent.admin_POST("/connections/create-invitation") agent.active_connection_id = connection["connection_id"] agent.connection_list.append(connection["connection_id"]) log_msg("all connections :", agent.connection_list) log_json(connection, label="Invitation response:") log_msg("*****************") log_msg(json.dumps(connection["invitation"]), label="Invitation:", color=None) log_msg("*****************") agent._connection_ready = asyncio.Future() log_msg("Waiting for connection...") await agent.detect_connection() elif option == "4": # handle new invitation log_status("List of Trusted Connections") log_msg(agent.trusted_connection_ids) # log_msg(agent.trusted_hospitals) elif option == "5": # handle new invitation log_status("Initiate Learning") # TODO Need to get the updated file somehow # Some sort of await until coordinator recieved message back successfully_generated = await generate_model() successfully_validated = await validate_model(agent.current_model_file) # f = open(agent.current_model_file, "rb") if successfully_generated: log_msg("MODEL CREATED AND SAVED SUCCESSFULLY") f = open(agent.current_model_file, "rb") log_msg("MODEL OPENED FOR TRANSPORT") contents = f.read() f.close() await agent.admin_POST( f"/connections/{agent.trusted_connection_ids[0]}/send-message", {"content": contents.hex()} ) await agent.learning_complete else: log_msg("THERE WAS A PROBLEM WITH THE MODEL CREATION") elif option == "6": # handle new invitation log_status("Reset trusted connection list") agent.trusted_connection_ids = [] agent.trusted_hospitals = [] if show_timing: timing = await agent.fetch_timing() if timing: for line in agent.format_timing(timing): log_msg(line) finally: terminated = True try: if agent: await agent.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False await asyncio.sleep(0.1) if not terminated: os._exit(1)
async def main(start_port: int, show_timing: bool = False): genesis = await default_genesis_txns() if not genesis: print("Error retrieving ledger genesis transactions") sys.exit(1) agent = None try: log_status( "#1 Provision an agent and wallet, get back configuration details") agent = NhsheadofficeAgent(start_port, start_port + 1, genesis_data=genesis, timing=show_timing) await agent.listen_webhooks(start_port + 2) await agent.register_did() log_msg("HEAD OFFICE DID: ", agent.did) with log_timer("Startup duration:"): await agent.start_process() log_msg("Admin url is at:", agent.admin_url) log_msg("Endpoint url is at:", agent.endpoint) # Create a schema with log_timer("Publish schema/cred def duration:"): log_status("#3/4 Create a new schema/cred def on the ledger") version = format("%d.%d.%d" % ( random.randint(1, 101), random.randint(1, 101), random.randint(1, 101), )) ( _, # schema id credential_definition_id, ) = await agent.register_schema_and_creddef( "Verified Hospital schema", version, ["date", "hospital_name"]) # TODO add an additional credential for Student ID with log_timer("Generate invitation duration:"): # Generate an invitation log_status( "#5 Create a connection to Hospital and print out the invite details" ) connection = await agent.admin_POST( "/connections/create-invitation") agent.active_connection_id = connection["connection_id"] agent.connection_list.append(connection["connection_id"]) log_json(connection, label="Invitation response:") log_msg("*****************") log_msg(json.dumps(connection["invitation"]), label="Invitation:", color=None) log_msg("*****************") log_msg("Waiting for connection...") await agent.detect_connection() async for option in prompt_loop( "(1) Request Hospital name, (2) Issue Verified Hospital Credential, (3) Create a New Invitation, (X) Exit? [1/2/X] " ): if option is None or option in "xX": break elif option == "1": log_status("#20 Request Self Attested Hospital Name") req_attrs = [{"name": "name"}] indy_proof_request = { "name": "Proof of Hospital Name", "version": "1.0", "nonce": str(uuid4().int), "requested_attributes": { f"0_{req_attr['name']}_uuid": req_attr for req_attr in req_attrs }, "requested_predicates": {}, } proof_request_web_request = { "connection_id": agent.active_connection_id, "proof_request": indy_proof_request, } await agent.admin_POST("/present-proof/send-request", proof_request_web_request) elif option == "2": log_status("#13 Issue Verified Hospital credential offer to X") today = date.today() # TODO define attributes to send for credential agent.cred_attrs[credential_definition_id] = { "hospital_name": agent.current_hospital_name, "date": str(today), # "degree": "Health", # "age": "24", } cred_preview = { "@type": CRED_PREVIEW_TYPE, "attributes": [{ "name": n, "value": v } for (n, v) in agent.cred_attrs[credential_definition_id].items()], } offer_request = { "connection_id": agent.active_connection_id, "credential_definition_id": credential_definition_id, "comment": f"Offer on cred def id {credential_definition_id}", "credential_preview": cred_preview, } await agent.admin_POST("/issue-credential/send-offer", offer_request) # elif option == "3": # msg = await prompt("Enter message: ") # await agent.admin_POST( # f"/connections/{agent.active_connection_id}/send-message", {"content": msg} # ) elif option == "3": # handle new invitation with log_timer("Generate invitation duration:"): # Generate an invitation log_status( "#5 Create a connection to alice and print out the invite details" ) connection = await agent.admin_POST( "/connections/create-invitation") agent.active_connection_id = connection["connection_id"] agent.connection_list.append(connection["connection_id"]) log_msg("all connections :", agent.connection_list) log_json(connection, label="Invitation response:") log_msg("*****************") log_msg(json.dumps(connection["invitation"]), label="Invitation:", color=None) log_msg("*****************") agent._connection_ready = asyncio.Future() log_msg("Waiting for connection...") await agent.detect_connection() if show_timing: timing = await agent.fetch_timing() if timing: for line in agent.format_timing(timing): log_msg(line) finally: terminated = True try: if agent: await agent.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False await asyncio.sleep(0.1) if not terminated: os._exit(1)
async def main( start_port: int, no_auto: bool = False, revocation: bool = False, show_timing: bool = False, ): genesis = await default_genesis_txns() if not genesis: print("Error retrieving ledger genesis transactions") sys.exit(1) agent = None try: log_status( "#1 Provision an agent and wallet, get back configuration details") agent = CourtAgent( start_port, start_port + 1, genesis_data=genesis, no_auto=no_auto, timing=show_timing, ) await agent.listen_webhooks(start_port + 2) await agent.register_did() with log_timer("Startup duration:"): await agent.start_process() log_msg("Admin URL is at:", agent.admin_url) log_msg("Endpoint URL is at:", agent.endpoint) # Create a schema with log_timer("Publish schema/cred def duration:"): log_status("#3/4 Create a new schema/cred def on the ledger") version = format("%d.%d.%d" % ( random.randint(1, 101), random.randint(1, 101), random.randint(1, 101), )) ( _, # schema id credential_definition_id, ) = await agent.register_schema_and_creddef( "custody schema", version, [ "issuanceDate", "issuer", "trustFrameworkURI", "auditURI", "appealURI", "caseResult", "credentialSubject.holder.type", "credentialSubject.holder.role", "credentialSubject.holder.rationaleURI", "credentialSubject.holder.firstName", "credentialSubject.holder.lastName", "credentialSubject.holder.kinshipStatus", "credentialSubject.holder.constraints.boundaries", "credentialSubject.holder.constraints.pointOfOrigin", "credentialSubject.holder.constraints.radiusKM", "credentialSubject.holder.constraints.jurisdictions", "credentialSubject.holder.constraints.trigger", "credentialSubject.holder.constraints.circumstances", "credentialSubject.holder.constraints.startTime", "credentialSubject.holder.constraints.endTime", "credentialSubject.proxied.type", "credentialSubject.proxied.firstName", "credentialSubject.proxied.lastName", "credentialSubject.proxied.birthDate", "credentialSubject.proxied.photo", "credentialSubject.proxied.iris", "credentialSubject.proxied.fingerprint", "credentialSubject.holder.permissions" ], support_revocation=revocation, ) if revocation: with log_timer("Publish revocation registry duration:"): log_status( "#5/6 Create and publish the revocation registry on the ledger" ) await agent.create_and_publish_revocation_registry( credential_definition_id, TAILS_FILE_COUNT) with log_timer("Generate invitation duration:"): # Generate an invitation log_status( "#7 Create a connection to alice and print out the invite details" ) connection = await agent.admin_POST( "/connections/create-invitation") agent.connection_id = connection["connection_id"] log_msg(json.dumps(connection["invitation"]), label="Invitation Data:", color=None) log_msg("Waiting for connection...") await agent.detect_connection() exchange_tracing = False options = (" (1) Issue Credential\n" " (2) Send Proof Request\n" " (3) Send Message\n") if revocation: options += (" (4) Revoke Credential\n" " (5) Publish Revocations\n" " (6) Add Revocation Registry\n") options += " (T) Toggle tracing on credential/proof exchange\n" options += " (X) Exit?\n[1/2/3/{}T/X] ".format( "4/5/6/" if revocation else "") async for option in prompt_loop(options): if option is not None: option = option.strip() if option is None or option in "xX": break elif option in "tT": exchange_tracing = not exchange_tracing log_msg(">>> Credential/Proof Exchange Tracing is {}".format( "ON" if exchange_tracing else "OFF")) elif option == "1": log_status("# Issue credential offer to X") offer_request = perform_time_measurement( agent, credential_definition_id, exchange_tracing) # offer_request = await prepare_cred(agent, credential_definition_id, exchange_tracing) await issue_cred(agent, offer_request) elif option == "2": log_status("#20 Request proof of degree from alice") req_attrs = [ { "name": "name", "restrictions": [{ "issuer_did": agent.did }] }, { "name": "date", "restrictions": [{ "issuer_did": agent.did }] }, ] if revocation: req_attrs.append( { "name": "degree", "restrictions": [{ "issuer_did": agent.did }], "non_revoked": { "to": int(time.time() - 1) }, }, ) else: req_attrs.append({ "name": "degree", "restrictions": [{ "issuer_did": agent.did }] }) if SELF_ATTESTED: # test self-attested claims req_attrs.append({"name": "self_attested_thing"}, ) req_preds = [ # test zero-knowledge proofs { "name": "caseResult", "p_type": "==", "p_value": "joint-custody", "restrictions": [{ "issuer_did": agent.did }], } ] indy_proof_request = { "name": "Proof of Education", "version": "1.0", "requested_attributes": { f"0_{req_attr['name']}_uuid": req_attr for req_attr in req_attrs }, "requested_predicates": { f"0_{req_pred['name']}_GE_uuid": req_pred for req_pred in req_preds }, } if revocation: indy_proof_request["non_revoked"] = { "to": int(time.time()) } proof_request_web_request = { "connection_id": agent.connection_id, "proof_request": indy_proof_request, "trace": exchange_tracing, } await agent.admin_POST("/present-proof/send-request", proof_request_web_request) elif option == "3": msg = await prompt("Enter message: ") await agent.admin_POST( f"/connections/{agent.connection_id}/send-message", {"content": msg}) elif option == "4" and revocation: rev_reg_id = ( await prompt("Enter revocation registry ID: ")).strip() cred_rev_id = ( await prompt("Enter credential revocation ID: ")).strip() publish = json.dumps( (await prompt("Publish now? [Y/N]: ", default="N") ).strip() in ("yY")) try: await agent.admin_POST("/issue-credential/revoke" f"?publish={publish}" f"&rev_reg_id={rev_reg_id}" f"&cred_rev_id={cred_rev_id}") except ClientError: pass elif option == "5" and revocation: try: resp = await agent.admin_POST( "/issue-credential/publish-revocations", {}) agent.log( "Published revocations for {} revocation registr{} {}". format( len(resp["rrid2crid"]), "y" if len(resp) == 1 else "ies", json.dumps([k for k in resp["rrid2crid"]], indent=4), )) except ClientError: pass elif option == "6" and revocation: log_status("#19 Add another revocation registry") await agent.create_and_publish_revocation_registry( credential_definition_id, TAILS_FILE_COUNT) if show_timing: timing = await agent.fetch_timing() if timing: for line in agent.format_timing(timing): log_msg(line) finally: terminated = True try: if agent: await agent.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False await asyncio.sleep(0.1) if not terminated: os._exit(1)
async def main(start_port: int, show_timing: bool = False): genesis = await default_genesis_txns() if not genesis: print("Error retrieving ledger genesis transactions") sys.exit(1) agent = None try: log_status( "#1 Provision an agent and wallet, get back configuration details") agent = RegulatorAgent(start_port, start_port + 1, genesis_data=genesis, timing=show_timing) await agent.listen_webhooks(start_port + 2) # await agent.register_did() with log_timer("Startup duration:"): await agent.start_process() log_msg("Admin url is at:", agent.admin_url) log_msg("Endpoint url is at:", agent.endpoint) # Create a schema with log_timer("Publish schema/cred def duration:"): log_status("#3/4 Create a new schema/cred def on the ledger") version = format("%d.%d.%d" % ( random.randint(1, 101), random.randint(1, 101), random.randint(1, 101), )) ( _, # schema id credential_definition_id, ) = await agent.register_schema_and_creddef( "Certified Researcher schema", version, ["institution", "date"]) # TODO add an additional credential for Student ID with log_timer("Generate invitation duration:"): # Generate an invitation log_status( "#5 Create a connection to a Coordinator and print out the invite details" ) connection = await agent.admin_POST( "/connections/create-invitation") agent.active_connection_id = connection["connection_id"] agent.connection_list.append(connection["connection_id"]) log_json(connection, label="Invitation response:") log_msg("*****************") log_msg(json.dumps(connection["invitation"]), label="Invitation:", color=None) log_msg("*****************") log_msg("Waiting for connection...") await agent.detect_connection() async for option in prompt_loop( "(1) Issue Credential \n(2) Create a New Invitation \n(X) Exit? \n[1/2/X] " ): if option is None or option in "xX": break elif option == "1": log_status("#13 Issue credential offer to X") today = date.today() # TODO define attributes to send for credential agent.cred_attrs[credential_definition_id] = { "date": str(today), "institution": "Edinburgh Napier University", } cred_preview = { "@type": CRED_PREVIEW_TYPE, "attributes": [{ "name": n, "value": v } for (n, v) in agent.cred_attrs[credential_definition_id].items()], } offer_request = { "connection_id": agent.active_connection_id, "credential_definition_id": credential_definition_id, "comment": f"Offer on cred def id {credential_definition_id}", "credential_preview": cred_preview, } await agent.admin_POST("/issue-credential/send-offer", offer_request) elif option == "2": # handle new invitation with log_timer("Generate invitation duration:"): # Generate an invitation log_status( "#5 Create a connection to alice and print out the invite details" ) connection = await agent.admin_POST( "/connections/create-invitation") agent.active_connection_id = connection["connection_id"] agent.connection_list.append(connection["connection_id"]) log_msg("all connections :", agent.connection_list) log_json(connection, label="Invitation response:") log_msg("*****************") log_msg(json.dumps(connection["invitation"]), label="Invitation:", color=None) log_msg("*****************") agent._connection_ready = asyncio.Future() log_msg("Waiting for connection...") await agent.detect_connection() if show_timing: timing = await agent.fetch_timing() if timing: for line in agent.format_timing(timing): log_msg(line) finally: terminated = True try: if agent: await agent.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False await asyncio.sleep(0.1) if not terminated: os._exit(1)
async def main( start_port: int, no_auto: bool = False, revocation: bool = False, tails_server_base_url: str = None, show_timing: bool = False, multitenant: bool = False, use_did_exchange: bool = False, wallet_type: str = None, ): genesis = await default_genesis_txns() if not genesis: print("Error retrieving ledger genesis transactions") sys.exit(1) agent = None try: log_status( "#1 Provision an agent and wallet, get back configuration details" + (f" (Wallet type: {wallet_type})" if wallet_type else "")) agent = FaberAgent( "Faber.Agent", start_port, start_port + 1, genesis_data=genesis, no_auto=no_auto, tails_server_base_url=tails_server_base_url, timing=show_timing, multitenant=multitenant, wallet_type=wallet_type, ) await agent.listen_webhooks(start_port + 2) await agent.register_did() with log_timer("Startup duration:"): await agent.start_process() log_msg("Admin URL is at:", agent.admin_url) log_msg("Endpoint URL is at:", agent.endpoint) if multitenant: # create an initial managed sub-wallet await agent.register_or_switch_wallet("Faber.initial", public_did=True) # Create a schema credential_definition_id = await create_schema_and_cred_def( agent, revocation) # TODO add an additional credential for Student ID await generate_invitation(agent, use_did_exchange) log_msg("Waiting for connection...") await agent.detect_connection() exchange_tracing = False options = (" (1) Issue Credential\n" " (2) Send Proof Request\n" " (3) Send Message\n" " (4) Create New Invitation\n") if revocation: options += " (5) Revoke Credential\n" " (6) Publish Revocations\n" if multitenant: options += " (W) Create and/or Enable Wallet\n" options += " (T) Toggle tracing on credential/proof exchange\n" options += " (X) Exit?\n[1/2/3/4/{}{}T/X] ".format( "5/6/" if revocation else "", "W/" if multitenant else "", ) async for option in prompt_loop(options): if option is not None: option = option.strip() if option is None or option in "xX": break elif option in "wW" and multitenant: target_wallet_name = await prompt("Enter wallet name: ") created = await agent.register_or_switch_wallet( target_wallet_name, public_did=True) # create a schema and cred def for the new wallet # TODO check first in case we are switching between existing wallets if created: # TODO this fails because the new wallet doesn't get a public DID credential_definition_id = await create_schema_and_cred_def( agent, revocation) elif option in "tT": exchange_tracing = not exchange_tracing log_msg(">>> Credential/Proof Exchange Tracing is {}".format( "ON" if exchange_tracing else "OFF")) elif option == "1": log_status("#13 Issue credential offer to X") # TODO define attributes to send for credential agent.cred_attrs[credential_definition_id] = { "name": "Alice Smith", "date": "2018-05-28", "degree": "Maths", "age": "24", "timestamp": str(int(time.time())), } cred_preview = { "@type": CRED_PREVIEW_TYPE, "attributes": [{ "name": n, "value": v } for (n, v) in agent.cred_attrs[credential_definition_id].items()], } offer_request = { "connection_id": agent.connection_id, "cred_def_id": credential_definition_id, "comment": f"Offer on cred def id {credential_definition_id}", "auto_remove": False, "credential_preview": cred_preview, "trace": exchange_tracing, } await agent.admin_POST("/issue-credential/send-offer", offer_request) # TODO issue an additional credential for Student ID elif option == "2": log_status("#20 Request proof of degree from alice") req_attrs = [ { "name": "name", "restrictions": [{ "schema_name": "degree schema" }], }, { "name": "date", "restrictions": [{ "schema_name": "degree schema" }], }, ] if revocation: req_attrs.append( { "name": "degree", "restrictions": [{ "schema_name": "degree schema" }], "non_revoked": { "to": int(time.time() - 1) }, }, ) else: req_attrs.append({ "name": "degree", "restrictions": [{ "schema_name": "degree schema" }], }) if SELF_ATTESTED: # test self-attested claims req_attrs.append({"name": "self_attested_thing"}, ) req_preds = [ # test zero-knowledge proofs { "name": "age", "p_type": ">=", "p_value": 18, "restrictions": [{ "schema_name": "degree schema" }], } ] indy_proof_request = { "name": "Proof of Education", "version": "1.0", "requested_attributes": { f"0_{req_attr['name']}_uuid": req_attr for req_attr in req_attrs }, "requested_predicates": { f"0_{req_pred['name']}_GE_uuid": req_pred for req_pred in req_preds }, } if revocation: indy_proof_request["non_revoked"] = { "to": int(time.time()) } proof_request_web_request = { "connection_id": agent.connection_id, "proof_request": indy_proof_request, "trace": exchange_tracing, } await agent.admin_POST("/present-proof/send-request", proof_request_web_request) elif option == "3": msg = await prompt("Enter message: ") await agent.admin_POST( f"/connections/{agent.connection_id}/send-message", {"content": msg}) elif option == "4": log_msg( "Creating a new invitation, please Receive and Accept this invitation using Alice agent" ) await generate_invitation(agent, use_did_exchange) elif option == "5" and revocation: rev_reg_id = ( await prompt("Enter revocation registry ID: ")).strip() cred_rev_id = ( await prompt("Enter credential revocation ID: ")).strip() publish = (await prompt("Publish now? [Y/N]: ", default="N")).strip() in "yY" try: await agent.admin_POST( "/revocation/revoke", { "rev_reg_id": rev_reg_id, "cred_rev_id": cred_rev_id, "publish": publish, }, ) except ClientError: pass elif option == "6" and revocation: try: resp = await agent.admin_POST( "/revocation/publish-revocations", {}) agent.log( "Published revocations for {} revocation registr{} {}". format( len(resp["rrid2crid"]), "y" if len(resp["rrid2crid"]) == 1 else "ies", json.dumps([k for k in resp["rrid2crid"]], indent=4), )) except ClientError: pass if show_timing: timing = await agent.fetch_timing() if timing: for line in agent.format_timing(timing): log_msg(line) finally: terminated = True try: if agent: await agent.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False await asyncio.sleep(0.1) if not terminated: os._exit(1)
async def main(start_port: int, show_timing: bool = False): genesis = await default_genesis_txns() if not genesis: print("Error retrieving ledger genesis transactions") sys.exit(1) agent = None try: log_status( "#7 Provision an agent and wallet, get back configuration details") agent = AliceAgent(start_port, start_port + 1, genesis_data=genesis, timing=show_timing) await agent.listen_webhooks(start_port + 2) with log_timer("Startup duration:"): await agent.start_process() log_msg("Admin url is at:", agent.admin_url) log_msg("Endpoint url is at:", agent.endpoint) log_status("#9 Input faber.py invitation details") await input_invitation(agent) async for option in prompt_loop( "(3) Send Message (4) Input New Invitation (X) Exit? [3/4/X]: " ): if option is None or option in "xX": break elif option == "3": msg = await prompt("Enter message: ") if msg: await agent.admin_POST( f"/connections/{agent.connection_id}/send-message", {"content": msg}, ) elif option == "4": # handle new invitation log_status("Input new invitation details") await input_invitation(agent) if show_timing: timing = await agent.fetch_timing() if timing: for line in agent.format_timing(timing): log_msg(line) finally: terminated = True try: if agent: await agent.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False await asyncio.sleep(0.1) if not terminated: os._exit(1)
async def main(start_port: int, show_timing: bool = False): genesis = await default_genesis_txns() if not genesis: print("Error retrieving ledger genesis transactions") sys.exit(1) agent = None try: log_status( "#1 Provision an agent and wallet, get back configuration details") agent = FaberAgent(start_port, start_port + 1, genesis_data=genesis, timing=show_timing) await agent.listen_webhooks(start_port + 2) await agent.register_did() with log_timer("Startup duration:"): await agent.start_process() log_msg("Admin url is at:", agent.admin_url) log_msg("Endpoint url is at:", agent.endpoint) # Create a schema with log_timer("Publish schema/cred def duration:"): log_status("#3/4 Create a new schema/cred def on the ledger") version = format("%d.%d.%d" % ( random.randint(1, 101), random.randint(1, 101), random.randint(1, 101), )) ( schema_id, credential_definition_id, ) = await agent.register_schema_and_creddef( "degree schema", version, ["name", "date", "degree", "age"]) # TODO add an additional credential for Student ID with log_timer("Generate invitation duration:"): # Generate an invitation log_status( "#5 Create a connection to alice and print out the invite details" ) connection = await agent.admin_POST( "/connections/create-invitation") agent.connection_id = connection["connection_id"] log_json(connection, label="Invitation response:") log_msg("*****************") log_msg(json.dumps(connection["invitation"]), label="Invitation:", color=None) log_msg("*****************") log_msg("Waiting for connection...") await agent.detect_connection() async for option in prompt_loop( "(1) Issue Credential, (2) Send Proof Request, " + "(3) Send Message (X) Exit? [1/2/3/X] "): if option is None or option in "xX": break elif option == "1": log_status("#13 Issue credential offer to X") offer = { "credential_definition_id": credential_definition_id, "connection_id": agent.connection_id, } # TODO define attributes to send for credential agent.cred_attrs[credential_definition_id] = { "name": "Alice Smith", "date": "2018-05-28", "degree": "Maths", "age": "24", } await agent.admin_POST("/credential_exchange/send-offer", offer) # TODO issue an additional credential for Student ID elif option == "2": log_status("#20 Request proof of degree from alice") proof_attrs = [ { "name": "name", "restrictions": [{ "issuer_did": agent.did }] }, { "name": "date", "restrictions": [{ "issuer_did": agent.did }] }, { "name": "degree", "restrictions": [{ "issuer_did": agent.did }] }, { "name": "self_attested_thing" }, ] proof_predicates = [{ "name": "age", "p_type": ">=", "p_value": 18 }] proof_request = { "name": "Proof of Education", "version": "1.0", "connection_id": agent.connection_id, "requested_attributes": proof_attrs, "requested_predicates": proof_predicates, } await agent.admin_POST("/presentation_exchange/send_request", proof_request) elif option == "3": msg = await prompt("Enter message: ") await agent.admin_POST( f"/connections/{agent.connection_id}/send-message", {"content": msg}) if show_timing: timing = await agent.fetch_timing() if timing: for line in agent.format_timing(timing): log_msg(line) finally: terminated = True try: if agent: await agent.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False await asyncio.sleep(0.1) if not terminated: os._exit(1)
async def initialize( self, the_agent: DemoAgent = None, schema_name: str = None, schema_attrs: list = None, ): """Startup agent(s), register DID, schema, cred def as appropriate.""" if not the_agent: log_status( "#1 Provision an agent and wallet, get back configuration details" + (f" (Wallet type: {self.wallet_type})" if self. wallet_type else "")) self.agent = AriesAgent( self.ident, self.start_port, self.start_port + 1, genesis_data=self.genesis_txns, no_auto=self.no_auto, tails_server_base_url=self.tails_server_base_url, timing=self.show_timing, revocation=self.revocation, multitenant=self.multitenant, mediation=self.mediation, wallet_type=self.wallet_type, seed=self.seed, aip=self.aip, arg_file=self.arg_file, ) else: self.agent = the_agent await self.agent.listen_webhooks(self.start_port + 2) if self.public_did and self.cred_type != CRED_FORMAT_JSON_LD: await self.agent.register_did(cred_type=self.cred_type) log_msg("Created public DID") with log_timer("Startup duration:"): await self.agent.start_process() log_msg("Admin URL is at:", self.agent.admin_url) log_msg("Endpoint URL is at:", self.agent.endpoint) if self.mediation: self.mediator_agent = await start_mediator_agent( self.start_port + 4, self.genesis_txns) if not self.mediator_agent: raise Exception("Mediator agent returns None :-(") else: self.mediator_agent = None if self.multitenant: # create an initial managed sub-wallet (also mediated) rand_name = str(random.randint(100_000, 999_999)) await self.agent.register_or_switch_wallet( self.ident + ".initial." + rand_name, public_did=self.public_did, webhook_port=None, mediator_agent=self.mediator_agent, ) elif self.mediation: # we need to pre-connect the agent to its mediator if not await connect_wallet_to_mediator(self.agent, self.mediator_agent): raise Exception("Mediation setup FAILED :-(") if self.public_did and self.cred_type == CRED_FORMAT_JSON_LD: # create did of appropriate type data = { "method": DID_METHOD_KEY, "options": { "key_type": KEY_TYPE_BLS } } new_did = await self.agent.admin_POST("/wallet/did/create", data=data) self.agent.did = new_did["result"]["did"] log_msg("Created DID key") if schema_name and schema_attrs: # Create a schema/cred def self.cred_def_id = await self.create_schema_and_cred_def( schema_name, schema_attrs)
async def create_schema_and_cred_def(agent, revocation): with log_timer("Publish schema/cred def duration:"): log_status("#3/4 Create a new schema/cred def on the ledger") # create identity schema version_for_identity_schema = format("%d.%d.%d" % ( random.randint(1, 101), random.randint(1, 101), random.randint(1, 101), )) ( _, identity_cred_def_id, ) = await agent.register_schema_and_creddef( # schema id "identity schema", version_for_identity_schema, [ "firstname", "lastname", "placeofbirth", "dateofbirth", "gender", "timestamp" ], support_revocation=revocation, revocation_registry_size=TAILS_FILE_COUNT if revocation else None, ) log_msg("Identity Credential Definition ID:", identity_cred_def_id) # create university degree schema version_for_degree_schema = format("%d.%d.%d" % ( random.randint(1, 101), random.randint(1, 101), random.randint(1, 101), )) ( _, uni_degree_cred_def_id, ) = await agent.register_schema_and_creddef( # schema id "university degree schema", version_for_degree_schema, [ "university", "degreename", "studentname", "gpa", "completedate", "timestamp" ], support_revocation=revocation, revocation_registry_size=TAILS_FILE_COUNT if revocation else None, ) log_msg("University Credential Definition ID:", uni_degree_cred_def_id) # create degree schema version = format("%d.%d.%d" % ( random.randint(1, 101), random.randint(1, 101), random.randint(1, 101), )) ( _, degree_cred_def_id, ) = await agent.register_schema_and_creddef( # schema id "degree schema", version, ["name", "date", "degree", "age", "timestamp"], support_revocation=revocation, revocation_registry_size=TAILS_FILE_COUNT if revocation else None, ) # log_msg("Degree Credential Definition ID:", degree_cred_def_id) return degree_cred_def_id
async def main(start_port: int, show_timing: bool = False, routing: bool = False): genesis = await default_genesis_txns() if not genesis: print("Error retrieving ledger genesis transactions") sys.exit(1) alice = None faber = None alice_router = None run_timer = log_timer("Total runtime:") run_timer.start() try: alice = AliceAgent(start_port, genesis_data=genesis, timing=show_timing) await alice.listen_webhooks(start_port + 2) faber = FaberAgent(start_port + 3, genesis_data=genesis, timing=show_timing) await faber.listen_webhooks(start_port + 5) await faber.register_did() if routing: alice_router = RoutingAgent(start_port + 6, genesis_data=genesis, timing=show_timing) await alice_router.listen_webhooks(start_port + 8) await alice_router.register_did() with log_timer("Startup duration:"): if alice_router: await alice_router.start_process() await alice.start_process() await faber.start_process() with log_timer("Publish duration:"): await faber.publish_defs() with log_timer("Connect duration:"): if routing: router_invite = await alice_router.get_invite() alice_router_conn_id = await alice.receive_invite(router_invite ) await asyncio.wait_for(alice.detect_connection(), 30) invite = await faber.get_invite() if routing: conn_id = await alice.receive_invite(invite, accept="manual") await alice.establish_inbound(conn_id, alice_router_conn_id) await alice.accept_invite(conn_id) await asyncio.wait_for(alice.detect_connection(), 30) else: await alice.receive_invite(invite) await asyncio.wait_for(faber.detect_connection(), 30) if show_timing: await alice.reset_timing() await faber.reset_timing() if routing: await alice_router.reset_timing() issue_count = 300 batch_size = 100 semaphore = asyncio.Semaphore(10) async def send(): await semaphore.acquire() asyncio.ensure_future(faber.send_credential()).add_done_callback( lambda fut: semaphore.release()) recv_timer = alice.log_timer(f"Received {issue_count} credentials in ") recv_timer.start() batch_timer = faber.log_timer( f"Started {batch_size} credential exchanges in ") batch_timer.start() async def check_received(agent, issue_count, pb): reported = 0 iter_pb = iter(pb) if pb else None while True: pending, total = agent.check_received_creds() if iter_pb and total > reported: try: while next(iter_pb) < total: pass except StopIteration: iter_pb = None reported = total if total == issue_count and not pending: break await asyncio.wait_for(agent.update_creds(), 30) with progress() as pb: receive_task = None try: issue_pg = pb(range(issue_count), label="Issuing credentials") receive_pg = pb(range(issue_count), label="Receiving credentials") issue_task = asyncio.ensure_future( check_received(faber, issue_count, issue_pg)) receive_task = asyncio.ensure_future( check_received(alice, issue_count, receive_pg)) with faber.log_timer( f"Done starting {issue_count} credential exchanges in " ): for idx in range(0, issue_count): await send() if not (idx + 1) % batch_size and idx < issue_count - 1: batch_timer.reset() await issue_task await receive_task except KeyboardInterrupt: if receive_task: receive_task.cancel() print("Canceled") recv_timer.stop() avg = recv_timer.duration / issue_count alice.log(f"Average time per credential: {avg:.2f}s ({1/avg:.2f}/s)") if show_timing: timing = await alice.fetch_timing() if timing: for line in alice.format_timing(timing): alice.log(line) timing = await faber.fetch_timing() if timing: for line in faber.format_timing(timing): faber.log(line) if routing: timing = await alice_router.fetch_timing() if timing: for line in alice_router.format_timing(timing): alice_router.log(line) finally: terminated = True try: if alice: await alice.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False try: if faber: await faber.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False try: if alice_router: await alice_router.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False run_timer.stop() await asyncio.sleep(0.1) if not terminated: os._exit(1)
async def main( start_port: int, threads: int = 20, action: str = None, show_timing: bool = False, multitenant: bool = False, mediation: bool = False, use_did_exchange: bool = False, revocation: bool = False, tails_server_base_url: str = None, issue_count: int = 300, wallet_type: str = None, ): genesis = await default_genesis_txns() if not genesis: print("Error retrieving ledger genesis transactions") sys.exit(1) alice = None faber = None alice_mediator_agent = None faber_mediator_agent = None run_timer = log_timer("Total runtime:") run_timer.start() try: alice = AliceAgent( start_port, genesis_data=genesis, timing=show_timing, multitenant=multitenant, mediation=mediation, wallet_type=wallet_type, ) await alice.listen_webhooks(start_port + 2) faber = FaberAgent( start_port + 3, genesis_data=genesis, timing=show_timing, tails_server_base_url=tails_server_base_url, multitenant=multitenant, mediation=mediation, wallet_type=wallet_type, ) await faber.listen_webhooks(start_port + 5) await faber.register_did() with log_timer("Startup duration:"): await alice.start_process() await faber.start_process() if mediation: alice_mediator_agent = await start_mediator_agent( start_port + 8, genesis) if not alice_mediator_agent: raise Exception("Mediator agent returns None :-(") faber_mediator_agent = await start_mediator_agent( start_port + 11, genesis) if not faber_mediator_agent: raise Exception("Mediator agent returns None :-(") else: alice_mediator_agent = None faber_mediator_agent = None with log_timer("Connect duration:"): if multitenant: # create an initial managed sub-wallet (also mediated) await alice.register_or_switch_wallet( "Alice.initial", webhook_port=None, mediator_agent=alice_mediator_agent, ) await faber.register_or_switch_wallet( "Faber.initial", public_did=True, webhook_port=None, mediator_agent=faber_mediator_agent, ) elif mediation: # we need to pre-connect the agent(s) to their mediator (use the same # mediator for both) if not await connect_wallet_to_mediator( alice, alice_mediator_agent): log_msg("Mediation setup FAILED :-(") raise Exception("Mediation setup FAILED :-(") if not await connect_wallet_to_mediator( faber, faber_mediator_agent): log_msg("Mediation setup FAILED :-(") raise Exception("Mediation setup FAILED :-(") invite = await faber.get_invite(use_did_exchange) await alice.receive_invite(invite["invitation"]) await asyncio.wait_for(faber.detect_connection(), 30) if action != "ping": with log_timer("Publish duration:"): await faber.publish_defs(revocation) # cache the credential definition await alice.fetch_credential_definition( faber.credential_definition_id) if show_timing: await alice.reset_timing() await faber.reset_timing() if mediation: await alice_mediator_agent.reset_timing() await faber_mediator_agent.reset_timing() batch_size = 100 semaphore = asyncio.Semaphore(threads) def done_propose(fut: asyncio.Task): semaphore.release() alice.check_task_exception(fut) def done_send(fut: asyncio.Task): semaphore.release() faber.check_task_exception(fut) def test_cred(index: int) -> dict: return { "name": "Alice Smith", "date": f"{2020+index}-05-28", "degree": "Maths", "age": "24", } async def propose_credential(index: int): await semaphore.acquire() comment = f"propose test credential {index}" attributes = test_cred(index) asyncio.ensure_future( alice.propose_credential( attributes, faber.credential_definition_id, comment, not revocation)).add_done_callback(done_propose) async def send_credential(index: int): await semaphore.acquire() comment = f"issue test credential {index}" attributes = test_cred(index) asyncio.ensure_future( faber.send_credential( attributes, comment, not revocation)).add_done_callback(done_send) async def check_received_creds(agent, issue_count, pb): reported = 0 iter_pb = iter(pb) if pb else None while True: pending, total = await agent.check_received_creds() complete = total - pending if reported == complete: await asyncio.wait_for(agent.update_creds(), 30) continue if iter_pb and complete > reported: try: while next(iter_pb) < complete: pass except StopIteration: iter_pb = None reported = complete if reported == issue_count: break async def send_ping(index: int): await semaphore.acquire() asyncio.ensure_future(faber.send_ping( str(index))).add_done_callback(done_send) async def check_received_pings(agent, issue_count, pb): reported = 0 iter_pb = iter(pb) if pb else None while True: pings = await agent.check_received_pings() complete = sum(len(tids) for tids in pings.values()) if complete == reported: await asyncio.wait_for(agent.update_pings(), 30) continue if iter_pb and complete > reported: try: while next(iter_pb) < complete: pass except StopIteration: iter_pb = None reported = complete if reported >= issue_count: break if action == "ping": recv_timer = faber.log_timer( f"Completed {issue_count} ping exchanges in") batch_timer = faber.log_timer( f"Started {batch_size} ping exchanges in") else: recv_timer = faber.log_timer( f"Completed {issue_count} credential exchanges in") batch_timer = faber.log_timer( f"Started {batch_size} credential exchanges in") recv_timer.start() batch_timer.start() with progress() as pb: receive_task = None try: if action == "ping": issue_pg = pb(range(issue_count), label="Sending pings") receive_pg = pb(range(issue_count), label="Responding pings") check_received = check_received_pings send = send_ping completed = f"Done sending {issue_count} pings in" else: issue_pg = pb(range(issue_count), label="Issuing credentials") receive_pg = pb(range(issue_count), label="Receiving credentials") check_received = check_received_creds if action == "propose": send = propose_credential else: send = send_credential completed = f"Done starting {issue_count} credential exchanges in" issue_task = asyncio.ensure_future( check_received(faber, issue_count, issue_pg)) issue_task.add_done_callback(faber.check_task_exception) receive_task = asyncio.ensure_future( check_received(alice, issue_count, receive_pg)) receive_task.add_done_callback(alice.check_task_exception) with faber.log_timer(completed): for idx in range(0, issue_count): await send(idx + 1) if not (idx + 1) % batch_size and idx < issue_count - 1: batch_timer.reset() await issue_task await receive_task except KeyboardInterrupt: if receive_task: receive_task.cancel() print("Cancelled") recv_timer.stop() avg = recv_timer.duration / issue_count item_short = "ping" if action == "ping" else "cred" item_long = "ping exchange" if action == "ping" else "credential" faber.log(f"Average time per {item_long}: {avg:.2f}s ({1/avg:.2f}/s)") if alice.postgres: await alice.collect_postgres_stats(f"{issue_count} {item_short}s") for line in alice.format_postgres_stats(): alice.log(line) if faber.postgres: await faber.collect_postgres_stats(f"{issue_count} {item_short}s") for line in faber.format_postgres_stats(): faber.log(line) if revocation and faber.revocations: (rev_reg_id, cred_rev_id) = next(iter(faber.revocations)) print(f"Revoking and publishing cred rev id {cred_rev_id} " f"from rev reg id {rev_reg_id}") if show_timing: timing = await alice.fetch_timing() if timing: for line in alice.format_timing(timing): alice.log(line) timing = await faber.fetch_timing() if timing: for line in faber.format_timing(timing): faber.log(line) if mediation: timing = await alice_mediator_agent.fetch_timing() if timing: for line in alice_mediator_agent.format_timing(timing): alice_mediator_agent.log(line) timing = await faber_mediator_agent.fetch_timing() if timing: for line in faber_mediator_agent.format_timing(timing): faber_mediator_agent.log(line) finally: terminated = True try: if alice: await alice.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False try: if faber: await faber.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False try: if alice_mediator_agent: await alice_mediator_agent.terminate() if faber_mediator_agent: await faber_mediator_agent.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False run_timer.stop() await asyncio.sleep(0.1) if not terminated: os._exit(1)
async def main(start_port: int, no_auto: bool = False, show_timing: bool = False): genesis = await default_genesis_txns() if not genesis: print("Error retrieving ledger genesis transactions") sys.exit(1) agent = None try: log_status( "#1 Provision an agent and wallet, get back configuration details") agent = FaberAgent( start_port, start_port + 1, genesis_data=genesis, no_auto=no_auto, timing=show_timing, ) await agent.listen_webhooks(start_port + 2) await agent.register_did() with log_timer("Startup duration:"): await agent.start_process() log_msg("Admin url is at:", agent.admin_url) log_msg("Endpoint url is at:", agent.endpoint) # Create a schema with log_timer("Publish schema/cred def duration:"): log_status("#3/4 Create a new schema/cred def on the ledger") version = format("%d.%d.%d" % ( random.randint(1, 101), random.randint(1, 101), random.randint(1, 101), )) ( _, # schema id credential_definition_id, ) = await agent.register_schema_and_creddef( "ethereum_identity", version, ["name", "address"]) # TODO add an additional credential for Student ID with log_timer("Generate invitation duration:"): # Generate an invitation log_status( "#5 Create a connection to alice and print out the invite details" ) connection = await agent.admin_POST( "/connections/create-invitation") agent.connection_id = connection["connection_id"] log_json(connection, label="Invitation response:") log_msg("*****************") log_msg(json.dumps(connection["invitation"]), label="Invitation:", color=None) log_msg("*****************") log_msg("Waiting for connection...") await agent.detect_connection() async for option in prompt_loop( "(1) Issue Credential, (2) Send Proof Request, " + "(3) Send Message (X) Exit? [1/2/3/X] "): if option is None or option in "xX": break elif option == "1": log_status("#13 Issue credential offer to X") # TODO define attributes to send for credential agent.cred_attrs[credential_definition_id] = { "name": "Kai Jun Eer", "address": "0xEDB4400a8b1DEccc6C62DFDDBD6F73E48537012A" } cred_preview = { "@type": CRED_PREVIEW_TYPE, "attributes": [{ "name": n, "value": v } for (n, v) in agent.cred_attrs[credential_definition_id].items()], } offer_request = { "connection_id": agent.connection_id, "cred_def_id": credential_definition_id, "comment": f"Offer on cred def id {credential_definition_id}", "credential_preview": cred_preview, } await agent.admin_POST("/issue-credential/send-offer", offer_request) # TODO issue an additional credential for Student ID elif option == "2": log_status("#20 Request proof of degree from alice") req_attrs = [ { "name": "name", "restrictions": [{ "issuer_did": agent.did }] }, { "name": "address", "restrictions": [{ "issuer_did": agent.did }] }, { "name": "self_attested_thing" }, ] req_preds = [{ "name": "age", "p_type": ">=", "p_value": 18, "restrictions": [{ "issuer_did": agent.did }], }] indy_proof_request = { "name": "Proof of Ethereum Identity", "version": "1.0", "nonce": str(uuid4().int), "requested_attributes": { f"0_{req_attr['name']}_uuid": req_attr for req_attr in req_attrs }, } proof_request_web_request = { "connection_id": agent.connection_id, "proof_request": indy_proof_request, } await agent.admin_POST("/present-proof/send-request", proof_request_web_request) elif option == "3": msg = await prompt("Enter message: ") await agent.admin_POST( f"/connections/{agent.connection_id}/send-message", {"content": msg}) if show_timing: timing = await agent.fetch_timing() if timing: for line in agent.format_timing(timing): log_msg(line) finally: terminated = True try: if agent: await agent.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False await asyncio.sleep(0.1) if not terminated: os._exit(1)
async def main(start_port: int, show_timing: bool = False): genesis = await default_genesis_txns() if not genesis: print("Error retrieving ledger genesis transactions") sys.exit(1) agent = None try: log_status( "#1 Provision an agent and wallet, get back configuration details") agent = CoordinatorAgent(start_port, start_port + 1, genesis_data=genesis, timing=show_timing) await agent.listen_webhooks(start_port + 2) with log_timer("Startup duration:"): await agent.start_process() log_msg("Admin url is at:", agent.admin_url) log_msg("Endpoint url is at:", agent.endpoint) with log_timer("Generate invitation duration:"): # Generate an invitation log_status( "#5 Create a connection to alice and print out the invite details" ) connection = await agent.admin_POST( "/connections/create-invitation") agent.active_connection_id = connection["connection_id"] agent.connection_list.append(connection["connection_id"]) log_json(connection, label="Invitation response:") log_msg("*****************") log_msg(json.dumps(connection["invitation"]), label="Invitation:", color=None) log_msg("*****************") # log_msg("Waiting for connection...") # await agent.detect_connection() async for option in prompt_loop( "(1) Send Proof Request, " + "(2) Send Message (3) New Connection (4) Input New Invitation Details (X) Exit? [1/2/3/4/X] " ): if option is None or option in "xX": break elif option == "1": log_status("#20 Request proof of degree from alice") req_attrs = [ { "name": "date", "restrictions": [{ "issuer_did": agent.nhsheadoffice_did }] }, { "name": "hospital_name", "restrictions": [{ "issuer_did": agent.nhsheadoffice_did }] }, ] # req_preds = [ # { # "name": "age", # "p_type": ">=", # "p_value": 18, # "restrictions": [{"issuer_did": agent.did}], # } # ] indy_proof_request = { "name": "Proof of Verified Hospital", "version": "1.0", "nonce": str(uuid4().int), "requested_attributes": { f"0_{req_attr['name']}_uuid": req_attr for req_attr in req_attrs }, "requested_predicates": {}, } print("Asking for this proof: ", indy_proof_request) proof_request_web_request = { "connection_id": agent.active_connection_id, "proof_request": indy_proof_request, } await agent.admin_POST("/present-proof/send-request", proof_request_web_request) elif option == "2": msg = await prompt("Enter message: ") await agent.admin_POST( f"/connections/{agent.active_connection_id}/send-message", {"content": msg}) elif option == "3": # handle new invitation with log_timer("Generate invitation duration:"): # Generate an invitation log_status( "#5 Create a connection to alice and print out the invite details" ) connection = await agent.admin_POST( "/connections/create-invitation") agent.active_connection_id = connection["connection_id"] agent.connection_list.append(connection["connection_id"]) log_msg("all connections :", agent.connection_list) log_json(connection, label="Invitation response:") log_msg("*****************") log_msg(json.dumps(connection["invitation"]), label="Invitation:", color=None) log_msg("*****************") agent._connection_ready = asyncio.Future() log_msg("Waiting for connection...") await agent.detect_connection() elif option == "4": # handle new invitation log_status("Input new invitation details") await input_invitation(agent) if show_timing: timing = await agent.fetch_timing() if timing: for line in agent.format_timing(timing): log_msg(line) finally: terminated = True try: if agent: await agent.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False await asyncio.sleep(0.1) if not terminated: os._exit(1)
async def main(start_port: int, show_timing: bool = False): genesis = await default_genesis_txns() if not genesis: print("Error retrieving ledger genesis transactions") sys.exit(1) agent = None try: log_status( "#1 Provision an agent and wallet, get back configuration details") agent = EAPAgent(start_port, start_port + 1, genesis_data=genesis, timing=show_timing) await agent.listen_webhooks(start_port + 2) await agent.register_did() with log_timer("Startup duration:"): await agent.start_process() log_msg("Admin url is at:", agent.admin_url) log_msg("Endpoint url is at:", agent.endpoint) # Create a schema with log_timer("Publish schema/cred def duration:"): log_status("#3/4 Create a new schema/cred def on the ledger") version = format("%d.%d.%d" % ( random.randint(1, 101), random.randint(1, 101), random.randint(1, 101), )) ( _, # schema id credential_definition_id, ) = await agent.register_schema_and_creddef( "degree schema", version, ["name", "date", "degree", "average"]) # TODO add an additional credential for Student ID async for option in prompt_loop( "(1) Issue Credential, (2) Send Proof Request, " + "(3) Send Message (X) Exit? [1/2/3/X] "): if option is None or option in "xX": break elif option == "1": log_status("#13 Issue credential offer to X") # TODO define attributes to send for credential agent.cred_attrs[credential_definition_id] = { "name": "Alice Smith", "date": "2018-05-28", "degree": "Maths", "age": "24", } cred_preview = { "@type": CRED_PREVIEW_TYPE, "attributes": [{ "name": n, "value": v } for (n, v) in agent.cred_attrs[credential_definition_id].items()], } offer_request = { "connection_id": agent.connection_id, "cred_def_id": credential_definition_id, "comment": f"Offer on cred def id {credential_definition_id}", "credential_preview": cred_preview, } await agent.admin_POST("/issue-credential/send-offer", offer_request) # TODO issue an additional credential for Student ID elif option == "2": log_status("#20 Request proof of degree from alice") req_attrs = [ { "name": "name", "restrictions": [{ "issuer_did": agent.did }] }, { "name": "date", "restrictions": [{ "issuer_did": agent.did }] }, { "name": "degree", "restrictions": [{ "issuer_did": agent.did }] }, { "name": "self_attested_thing" }, ] req_preds = [{ "name": "age", "p_type": ">=", "p_value": 18, "restrictions": [{ "issuer_did": agent.did }], }] indy_proof_request = { "name": "Proof of Education", "version": "1.0", "nonce": str(uuid4().int), "requested_attributes": { f"0_{req_attr['name']}_uuid": req_attr for req_attr in req_attrs }, "requested_predicates": { f"0_{req_pred['name']}_GE_uuid": req_pred for req_pred in req_preds }, } proof_request_web_request = { "connection_id": agent.connection_id, "proof_request": indy_proof_request, } await agent.admin_POST("/present-proof/send-request", proof_request_web_request) elif option == "3": msg = await prompt("Enter message: ") await agent.admin_POST( f"/connections/{agent.connection_id}/send-message", {"content": msg}) if show_timing: timing = await agent.fetch_timing() if timing: for line in agent.format_timing(timing): log_msg(line) finally: terminated = True try: if agent: await agent.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False await asyncio.sleep(0.1) if not terminated: os._exit(1)
async def main( start_port: int, no_auto: bool = False, show_timing: bool = False, multitenant: bool = False, mediation: bool = False, wallet_type: str = None, ): genesis = await default_genesis_txns() if not genesis: print("Error retrieving ledger genesis transactions") sys.exit(1) agent = None mediator_agent = None try: log_status( "#7 Provision an agent and wallet, get back configuration details" + (f" (Wallet type: {wallet_type})" if wallet_type else "")) agent = AliceAgent( "Alice.Agent", start_port, start_port + 1, genesis_data=genesis, no_auto=no_auto, timing=show_timing, multitenant=multitenant, mediation=mediation, wallet_type=wallet_type, ) await agent.listen_webhooks(start_port + 2) with log_timer("Startup duration:"): await agent.start_process() log_msg("Admin URL is at:", agent.admin_url) log_msg("Endpoint URL is at:", agent.endpoint) if mediation: mediator_agent = await start_mediator_agent( start_port + 4, genesis) if not mediator_agent: raise Exception("Mediator agent returns None :-(") else: mediator_agent = None if multitenant: # create an initial managed sub-wallet (also mediated) await agent.register_or_switch_wallet( "Alice.initial", webhook_port=agent.get_new_webhook_port(), mediator_agent=mediator_agent, ) elif mediation: # we need to pre-connect the agent to its mediator if not await connect_wallet_to_mediator(agent, mediator_agent): log_msg("Mediation setup FAILED :-(") raise Exception("Mediation setup FAILED :-(") log_status("#9 Input faber.py invitation details") await input_invitation(agent) options = " (3) Send Message\n" " (4) Input New Invitation\n" if multitenant: options += " (W) Create and/or Enable Wallet\n" options += " (X) Exit?\n[3/4/{}X] ".format( "W/" if multitenant else "", ) async for option in prompt_loop(options): if option is not None: option = option.strip() if option is None or option in "xX": break elif option in "wW" and multitenant: target_wallet_name = await prompt("Enter wallet name: ") include_subwallet_webhook = await prompt( "(Y/N) Create sub-wallet webhook target: ") if include_subwallet_webhook.lower() == "y": await agent.register_or_switch_wallet( target_wallet_name, webhook_port=agent.get_new_webhook_port(), mediator_agent=mediator_agent, ) else: await agent.register_or_switch_wallet( target_wallet_name, mediator_agent=mediator_agent, ) elif option == "3": msg = await prompt("Enter message: ") if msg: await agent.admin_POST( f"/connections/{agent.connection_id}/send-message", {"content": msg}, ) elif option == "4": # handle new invitation log_status("Input new invitation details") await input_invitation(agent) if show_timing: timing = await agent.fetch_timing() if timing: for line in agent.format_timing(timing): log_msg(line) finally: terminated = True try: if mediator_agent: log_msg("Shutting down mediator agent ...") await mediator_agent.terminate() if agent: log_msg("Shutting down alice agent ...") await agent.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False await asyncio.sleep(0.1) if not terminated: os._exit(1)
async def main(start_port: int, show_timing: bool = False): global agent genesis = await default_genesis_txns() if not genesis: print("Error retrieving ledger genesis transactions") sys.exit(1) try: log_status( "Provision an agent and wallet, get back configuration details") agent = MSPAgent(start_port, start_port + 1, genesis_data=genesis, timing=show_timing) await agent.listen_webhooks(start_port + 2) with log_timer("Startup duration:"): await agent.start_process() log_msg("Admin url is at:", agent.admin_url) log_msg("Endpoint url is at:", agent.endpoint) async with aiofile.AIOFile("verifier_logger.csv", 'w') as afp: writer = aiofile.Writer(afp) await writer("") await afp.fsync() app = web.Application() app.add_routes([ web.get('/create_invitation', handle_create_invitation), web.post('/verify_signature', handle_verify_signature), web.post('/verify_proof', handle_verify_proof), web.get('/readCommentsFromLogger', readCommentsFromLogger), ]) cors = aiohttp_cors.setup( app, defaults={ "*": aiohttp_cors.ResourceOptions( allow_credentials=True, expose_headers="*", allow_headers="*", allow_methods="*", ) }, ) for route in app.router.routes(): cors.add(route) setup_aiohttp_apispec(app=app, title="Aries Cloud Agent two", version="v1", swagger_path="/api/doc") app.on_startup.append(on_startup) return app except Exception: log_status( "Error while provision an agent and wallet, get back configuration details" )
async def main(start_port: int, show_timing: bool = False): genesis = await default_genesis_txns() if not genesis: print("Error retrieving ledger genesis transactions") sys.exit(1) agent = None try: log_status("#1 Provision an agent and wallet, get back configuration details") agent = AcmeAgent( start_port, start_port + 1, genesis_data=genesis, timing=show_timing ) await agent.listen_webhooks(start_port + 2) await agent.register_did() with log_timer("Startup duration:"): await agent.start_process() log_msg("Admin URL is at:", agent.admin_url) log_msg("Endpoint URL is at:", agent.endpoint) # Create a schema log_status("#3 Create a new schema on the ledger") with log_timer("Publish schema duration:"): version = format( "%d.%d.%d" % ( random.randint(1, 101), random.randint(1, 101), random.randint(1, 101), ) ) ( schema_id, credential_definition_id, ) = await agent.register_schema_and_creddef( "employee id schema", version, ["employee_id", "name", "date", "position"], ) with log_timer("Generate invitation duration:"): # Generate an invitation log_status( "#5 Create a connection to alice and print out the invite details" ) connection = await agent.admin_POST("/connections/create-invitation") agent.connection_id = connection["connection_id"] log_json(connection, label="Invitation response:") log_msg("*****************") log_msg(json.dumps(connection["invitation"]), label="Invitation:", color=None) log_msg("*****************") log_msg("Waiting for connection...") await agent.detect_connection() async for option in prompt_loop( "(1) Issue Credential, (2) Send Proof Request, " + "(3) Send Message (X) Exit? [1/2/3/X] " ): option = option.strip() if option in "xX": break elif option == "1": log_status("#13 Issue credential offer to X") agent.cred_attrs[credential_definition_id] = { "employee_id": "ACME0009", "name": "Alice Smith", "date": date.isoformat(date.today()), "position": "CEO" } offer_request = { "connection_id": agent.connection_id, "cred_def_id": credential_definition_id, "comment": f"Offer on cred def id {credential_definition_id}", } await agent.admin_POST( "/issue-credential/send-offer", offer_request ) elif option == "2": log_status("#20 Request proof of degree from alice") req_attrs = [ { "name": "name", "restrictions": [{"schema_name": "degree schema"}] }, { "name": "date", "restrictions": [{"schema_name": "degree schema"}] }, { "name": "degree", "restrictions": [{"schema_name": "degree schema"}] } ] req_preds = [] indy_proof_request = { "name": "Proof of Education", "version": "1.0", "nonce": str(uuid4().int), "requested_attributes": { f"0_{req_attr['name']}_uuid": req_attr for req_attr in req_attrs }, "requested_predicates": {} } proof_request_web_request = { "connection_id": agent.connection_id, "proof_request": indy_proof_request } # this sends the request to our agent, which forwards it to Alice # (based on the connection_id) await agent.admin_POST( "/present-proof/send-request", proof_request_web_request ) elif option == "3": msg = await prompt("Enter message: ") await agent.admin_POST( f"/connections/{agent.connection_id}/send-message", {"content": msg} )
async def main( start_port: int, no_auto: bool = False, revocation: bool = False, show_timing: bool = False, ): genesis = await default_genesis_txns() if not genesis: print("Error retrieving ledger genesis transactions") sys.exit(1) agent = None try: log_status( "#1 Provision an agent and wallet, get back configuration details") agent = FaberAgent( start_port, start_port + 1, genesis_data=genesis, no_auto=no_auto, timing=show_timing, ) await agent.listen_webhooks(start_port + 2) await agent.register_did() with log_timer("Startup duration:"): await agent.start_process() log_msg("Admin URL is at:", agent.admin_url) log_msg("Endpoint URL is at:", agent.endpoint) # Create a schema with log_timer("Publish schema/cred def duration:"): log_status("#3/4 Create a new schema/cred def on the ledger") version = format("%d.%d.%d" % ( random.randint(1, 101), random.randint(1, 101), random.randint(1, 101), )) ( _, # schema id credential_definition_id, ) = await agent.register_schema_and_creddef( "degree schema", version, ["name", "date", "degree", "age", "timestamp"], support_revocation=revocation, ) if revocation: with log_timer("Publish revocation registry duration:"): log_status( "#5/6 Create and publish the revocation registry on the ledger" ) await agent.create_and_publish_revocation_registry( credential_definition_id, TAILS_FILE_COUNT) # TODO add an additional credential for Student ID with log_timer("Generate invitation duration:"): # Generate an invitation log_status( "#7 Create a connection to Thapelo and print out the invite details" ) connection = await agent.admin_POST( "/connections/create-invitation") agent.connection_id = connection["connection_id"] qr = QRCode() qr.add_data(connection["invitation_url"]) log_msg( "Use the following JSON to accept the invite from another demo agent. Or use the QR code to connect from a mobile agent." ) log_msg(json.dumps(connection["invitation"]), label="Invitation Data:", color=None) qr.print_ascii(invert=True) log_msg("Waiting for connection...") await agent.detect_connection() exchange_tracing = False options = (" (1) Issue Credential\n" " (2) Send Proof Request\n" " (3) Send Message\n") if revocation: options += (" (4) Revoke Credential\n" " (5) Publish Revocations\n" " (6) Add Revocation Registry\n") options += " (T) Toggle tracing on credential/proof exchange\n" options += " (X) Exit?\n[1/2/3/{}T/X] ".format( "4/5/6/" if revocation else "") async for option in prompt_loop(options): option = option.strip() if option is None or option in "xX": break elif option in "tT": exchange_tracing = not exchange_tracing log_msg(">>> Credential/Proof Exchange Tracing is {}".format( "ON" if exchange_tracing else "OFF")) elif option == "1": log_status("#13 Issue credential offer to X") # TODO define attributes to send for credential agent.cred_attrs[credential_definition_id] = { "name": "Thapelo Sekwena", "date": "2020-06-01", "degree": "MBA", "age": "26", "timestamp": str(int(time.time())), } cred_preview = { "@type": CRED_PREVIEW_TYPE, "attributes": [{ "name": n, "value": v } for (n, v) in agent.cred_attrs[credential_definition_id].items()], } offer_request = { "connection_id": agent.connection_id, "cred_def_id": credential_definition_id, "comment": f"Offer on cred def id {credential_definition_id}", "auto_remove": False, "credential_preview": cred_preview, "trace": exchange_tracing, } await agent.admin_POST("/issue-credential/send-offer", offer_request) # TODO issue an additional credential for Student ID elif option == "2": log_status("#20 Request proof of degree from Thapelo") req_attrs = [ { "name": "name", "restrictions": [{ "issuer_did": agent.did }] }, { "name": "date", "restrictions": [{ "issuer_did": agent.did }] }, ] if revocation: req_attrs.append( { "name": "degree", "restrictions": [{ "issuer_did": agent.did }], "non_revoked": { "to": int(time.time() - 1) }, }, ) else: req_attrs.append({ "name": "degree", "restrictions": [{ "issuer_did": agent.did }] }) if SELF_ATTESTED: # test self-attested claims req_attrs.append({"name": "self_attested_thing"}, ) req_preds = [ # test zero-knowledge proofs { "name": "age", "p_type": ">=", "p_value": 18, "restrictions": [{ "issuer_did": agent.did }], } ] indy_proof_request = { "name": "Proof of Education", "version": "1.0", "requested_attributes": { f"0_{req_attr['name']}_uuid": req_attr for req_attr in req_attrs }, "requested_predicates": { f"0_{req_pred['name']}_GE_uuid": req_pred for req_pred in req_preds }, } if revocation: indy_proof_request["non_revoked"] = { "to": int(time.time()) } proof_request_web_request = { "connection_id": agent.connection_id, "proof_request": indy_proof_request, "trace": exchange_tracing, } await agent.admin_POST("/present-proof/send-request", proof_request_web_request) elif option == "3": msg = await prompt("Enter message: ") await agent.admin_POST( f"/connections/{agent.connection_id}/send-message", {"content": msg}) elif option == "4" and revocation: rev_reg_id = ( await prompt("Enter revocation registry ID: ")).strip() cred_rev_id = ( await prompt("Enter credential revocation ID: ")).strip() publish = json.dumps( (await prompt("Publish now? [Y/N]: ", default="N") ).strip() in ("yY")) try: await agent.admin_POST("/issue-credential/revoke" f"?publish={publish}" f"&rev_reg_id={rev_reg_id}" f"&cred_rev_id={cred_rev_id}") except ClientError: pass elif option == "5" and revocation: try: resp = await agent.admin_POST( "/issue-credential/publish-revocations") agent.log( "Published revocations for {} revocation registr{} {}". format( len(resp["results"]), "y" if len(resp) == 1 else "ies", json.dumps([k for k in resp["results"]], indent=4), )) except ClientError: pass elif option == "6" and revocation: log_status("#19 Add another revocation registry") await agent.create_and_publish_revocation_registry( credential_definition_id, TAILS_FILE_COUNT) if show_timing: timing = await agent.fetch_timing() if timing: for line in agent.format_timing(timing): log_msg(line) finally: terminated = True try: if agent: await agent.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False await asyncio.sleep(0.1) if not terminated: os._exit(1)
async def main(start_port: int, show_timing: bool = False): genesis = await default_genesis_txns() if not genesis: print("Error retrieving ledger genesis transactions") sys.exit(1) agent = None try: log_status("#7 Provision an agent and wallet, get back configuration details") agent = Hospital1Agent( start_port, start_port + 1, genesis_data=genesis, timing=show_timing ) await agent.listen_webhooks(start_port + 2) with log_timer("Startup duration:"): await agent.start_process() log_msg("Admin url is at:", agent.admin_url) log_msg("Endpoint url is at:", agent.endpoint) log_status("#9 Input the invitation details") await input_invitation(agent) async for option in prompt_loop( "(3) Send Message (4) Input New Invitation (5) Send Proof Request to the Issuer (X) Exit? [3/4/5/X]: " ): if option is None or option in "xX": break elif option == "3": msg = await prompt("Enter message: ") if msg: await agent.admin_POST( f"/connections/{agent.connection_id}/send-message", {"content": msg}, ) elif option == "4": # handle new invitation log_status("Input new invitation details") await input_invitation(agent) elif option == "5": log_status("#20 Request proof of Research Certification") req_attrs = [ {"name": "date", "restrictions": [{"issuer_did": agent.regulator_did}]}, {"name": "institution", "restrictions": [{"issuer_did": agent.regulator_did}]}, ] indy_proof_request = { "name": "Proof of Verified Research Institution", "version": "1.0", "nonce": str(uuid4().int), "requested_attributes": { f"0_{req_attr['name']}_uuid": req_attr for req_attr in req_attrs }, "requested_predicates": { }, } print("Asking for this proof: ", indy_proof_request) proof_request_web_request = { "connection_id": agent.connection_id, "proof_request": indy_proof_request, } await agent.admin_POST( "/present-proof/send-request", proof_request_web_request ) if show_timing: timing = await agent.fetch_timing() if timing: for line in agent.format_timing(timing): log_msg(line) finally: terminated = True try: if agent: await agent.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False await asyncio.sleep(0.1) if not terminated: os._exit(1)
async def main(start_port: int, show_timing: bool = False): genesis = await default_genesis_txns() if not genesis: print("Error retrieving ledger genesis transactions") sys.exit(1) agent = None try: log_status( "#1 Provision an agent and wallet, get back configuration details") agent = AcmeAgent(start_port, start_port + 1, genesis_data=genesis, timing=show_timing) await agent.listen_webhooks(start_port + 2) await agent.register_did() with log_timer("Startup duration:"): await agent.start_process() log_msg("Admin URL is at:", agent.admin_url) log_msg("Endpoint URL is at:", agent.endpoint) # Create a schema log_status("#3 Create a new schema on the ledger") with log_timer("Publish schema and cred def duration:"): pass # TODO define schema # version = format( # "%d.%d.%d" # % ( # random.randint(1, 101), # random.randint(1, 101), # random.randint(1, 101), # ) # ) # (schema_id, cred_def_id) = await agent.register_schema_and_creddef( # "employee id schema", # version, # ["employee_id", "name", "date", "position"], # support_revocation=False, # revocation_registry_size=TAILS_FILE_COUNT, # ) with log_timer("Generate invitation duration:"): # Generate an invitation log_status( "#5 Create a connection to alice and print out the invite details" ) invi_msg = await agent.admin_POST( "/out-of-band/create-invitation", {"include_handshake": True}, ) log_msg(json.dumps(invi_msg["invitation"]), label="Invitation Data:", color=None) log_msg("*****************") log_msg("Waiting for connection...") await agent.detect_connection() async for option in prompt_loop( "(1) Issue Credential, (2) Send Proof Request, " + "(3) Send Message (X) Exit? [1/2/3/X] "): option = option.strip() if option in "xX": break elif option == "1": log_status("#13 Issue credential offer to X") # TODO credential offers elif option == "2": log_status("#20 Request proof of degree from alice") # TODO presentation requests elif option == "3": msg = await prompt("Enter message: ") await agent.admin_POST( f"/connections/{agent.connection_id}/send-message", {"content": msg}) if show_timing: timing = await agent.fetch_timing() if timing: for line in agent.format_timing(timing): log_msg(line) finally: terminated = True try: if agent: await agent.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False await asyncio.sleep(0.1) if not terminated: os._exit(1)
async def main( start_port: int, threads: int = 20, ping_only: bool = False, show_timing: bool = False, routing: bool = False, issue_count: int = 300, ): genesis = await default_genesis_txns() if not genesis: print("Error retrieving ledger genesis transactions") sys.exit(1) alice = None faber = None alice_router = None run_timer = log_timer("Total runtime:") run_timer.start() try: alice = AliceAgent(start_port, genesis_data=genesis, timing=show_timing) await alice.listen_webhooks(start_port + 2) faber = FaberAgent(start_port + 3, genesis_data=genesis, timing=show_timing) await faber.listen_webhooks(start_port + 5) await faber.register_did() if routing: alice_router = RoutingAgent(start_port + 6, genesis_data=genesis, timing=show_timing) await alice_router.listen_webhooks(start_port + 8) await alice_router.register_did() with log_timer("Startup duration:"): if alice_router: await alice_router.start_process() await alice.start_process() await faber.start_process() if not ping_only: with log_timer("Publish duration:"): await faber.publish_defs() # await alice.set_tag_policy(faber.credential_definition_id, ["name"]) with log_timer("Connect duration:"): if routing: router_invite = await alice_router.get_invite() alice_router_conn_id = await alice.receive_invite(router_invite ) await asyncio.wait_for(alice.detect_connection(), 30) invite = await faber.get_invite() if routing: conn_id = await alice.receive_invite(invite, accept="manual") await alice.establish_inbound(conn_id, alice_router_conn_id) await alice.accept_invite(conn_id) await asyncio.wait_for(alice.detect_connection(), 30) else: await alice.receive_invite(invite) await asyncio.wait_for(faber.detect_connection(), 30) if show_timing: await alice.reset_timing() await faber.reset_timing() if routing: await alice_router.reset_timing() batch_size = 100 semaphore = asyncio.Semaphore(threads) def done_send(fut: asyncio.Task): semaphore.release() faber.check_task_exception(fut) async def send_credential(index: int): await semaphore.acquire() comment = f"issue test credential {index}" attributes = { "name": "Alice Smith", "date": "2018-05-28", "degree": "Maths", "age": "24", } asyncio.ensure_future(faber.send_credential( attributes, comment)).add_done_callback(done_send) async def check_received_creds(agent, issue_count, pb): reported = 0 iter_pb = iter(pb) if pb else None while True: pending, total = await agent.check_received_creds() complete = total - pending if reported == complete: await asyncio.wait_for(agent.update_creds(), 30) continue if iter_pb and complete > reported: try: while next(iter_pb) < complete: pass except StopIteration: iter_pb = None reported = complete if reported == issue_count: break async def send_ping(index: int): await semaphore.acquire() asyncio.ensure_future(faber.send_ping( str(index))).add_done_callback(done_send) async def check_received_pings(agent, issue_count, pb): reported = 0 iter_pb = iter(pb) if pb else None while True: pings = await agent.check_received_pings() complete = sum(len(tids) for tids in pings.values()) if complete == reported: await asyncio.wait_for(agent.update_pings(), 30) continue if iter_pb and complete > reported: try: while next(iter_pb) < complete: pass except StopIteration: iter_pb = None reported = complete if reported >= issue_count: break if ping_only: recv_timer = faber.log_timer( f"Completed {issue_count} ping exchanges in") batch_timer = faber.log_timer( f"Started {batch_size} ping exchanges in") else: recv_timer = faber.log_timer( f"Completed {issue_count} credential exchanges in") batch_timer = faber.log_timer( f"Started {batch_size} credential exchanges in") recv_timer.start() batch_timer.start() with progress() as pb: receive_task = None try: if ping_only: issue_pg = pb(range(issue_count), label="Sending pings") receive_pg = pb(range(issue_count), label="Responding pings") check_received = check_received_pings send = send_ping completed = f"Done sending {issue_count} pings in" else: issue_pg = pb(range(issue_count), label="Issuing credentials") receive_pg = pb(range(issue_count), label="Receiving credentials") check_received = check_received_creds send = send_credential completed = f"Done starting {issue_count} credential exchanges in" issue_task = asyncio.ensure_future( check_received(faber, issue_count, issue_pg)) issue_task.add_done_callback(faber.check_task_exception) receive_task = asyncio.ensure_future( check_received(alice, issue_count, receive_pg)) receive_task.add_done_callback(alice.check_task_exception) with faber.log_timer(completed): for idx in range(0, issue_count): await send(idx + 1) if not (idx + 1) % batch_size and idx < issue_count - 1: batch_timer.reset() await issue_task await receive_task except KeyboardInterrupt: if receive_task: receive_task.cancel() print("Canceled") recv_timer.stop() avg = recv_timer.duration / issue_count item_short = "ping" if ping_only else "cred" item_long = "ping exchange" if ping_only else "credential" faber.log(f"Average time per {item_long}: {avg:.2f}s ({1/avg:.2f}/s)") if alice.postgres: await alice.collect_postgres_stats(f"{issue_count} {item_short}s") for line in alice.format_postgres_stats(): alice.log(line) if faber.postgres: await faber.collect_postgres_stats(f"{issue_count} {item_short}s") for line in faber.format_postgres_stats(): faber.log(line) if show_timing: timing = await alice.fetch_timing() if timing: for line in alice.format_timing(timing): alice.log(line) timing = await faber.fetch_timing() if timing: for line in faber.format_timing(timing): faber.log(line) if routing: timing = await alice_router.fetch_timing() if timing: for line in alice_router.format_timing(timing): alice_router.log(line) finally: terminated = True try: if alice: await alice.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False try: if faber: await faber.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False try: if alice_router: await alice_router.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False run_timer.stop() await asyncio.sleep(0.1) if not terminated: os._exit(1)
async def main( start_port: int, no_auto: bool = False, revocation: bool = False, show_timing: bool = False, ): genesis = await default_genesis_txns() if not genesis: print("Error retrieving ledger genesis transactions") sys.exit(1) agent = None try: log_status( "#1 Provision an agent and wallet, get back configuration details") agent = FaberAgent( start_port, start_port + 1, genesis_data=genesis, no_auto=no_auto, timing=show_timing, ) await agent.listen_webhooks(start_port + 2) await agent.register_did() with log_timer("Startup duration:"): await agent.start_process() log_msg("Admin url is at:", agent.admin_url) log_msg("Endpoint url is at:", agent.endpoint) # Create a schema with log_timer("Publish schema/cred def duration:"): log_status("#3/4 Create a new schema/cred def on the ledger") version = format("%d.%d.%d" % ( random.randint(1, 101), random.randint(1, 101), random.randint(1, 101), )) ( _, # schema id credential_definition_id, ) = await agent.register_schema_and_creddef( "degree schema", version, ["name", "date", "degree", "age", "timestamp"], support_revocation=revocation, ) if revocation: with log_timer("Publish revocation registry duration:"): log_status( "#5/6 Create and publish the revocation registry on the ledger" ) revocation_registry_id = await ( agent.create_and_publish_revocation_registry( credential_definition_id, TAILS_FILE_COUNT)) else: revocation_registry_id = None # TODO add an additional credential for Student ID with log_timer("Generate invitation duration:"): # Generate an invitation log_status( "#7 Create a connection to alice and print out the invite details" ) connection = await agent.admin_POST( "/connections/create-invitation") agent.connection_id = connection["connection_id"] log_json(connection, label="Invitation response:") log_msg("*****************") log_msg(json.dumps(connection["invitation"]), label="Invitation:", color=None) log_msg("*****************") log_msg("Waiting for connection...") await agent.detect_connection() options = (" (1) Issue Credential\n" " (2) Send Proof Request\n" " (3) Send Message\n") if revocation: options += (" (4) Revoke Credential\n" " (5) Publish Revocations\n" " (6) Add Revocation Registry\n") options += " (X) Exit?\n[1/2/3/{}X] ".format( "4/5/6/" if revocation else "") async for option in prompt_loop(options): if option is None or option in "xX": break elif option == "1": log_status("#13 Issue credential offer to X") # TODO define attributes to send for credential agent.cred_attrs[credential_definition_id] = { "name": "Alice Smith", "date": "2018-05-28", "degree": "Maths", "age": "24", "timestamp": str(int(time.time())), } cred_preview = { "@type": CRED_PREVIEW_TYPE, "attributes": [{ "name": n, "value": v } for (n, v) in agent.cred_attrs[credential_definition_id].items()], } offer_request = { "connection_id": agent.connection_id, "cred_def_id": credential_definition_id, "comment": f"Offer on cred def id {credential_definition_id}", "auto_remove": False, "credential_preview": cred_preview, "revoc_reg_id": revocation_registry_id, } await agent.admin_POST("/issue-credential/send-offer", offer_request) # TODO issue an additional credential for Student ID elif option == "2": log_status("#20 Request proof of degree from alice") req_attrs = [ { "name": "name", "restrictions": [{ "issuer_did": agent.did }] }, { "name": "date", "restrictions": [{ "issuer_did": agent.did }] }, ] if revocation: req_attrs.append( { "name": "degree", "restrictions": [{ "issuer_did": agent.did }], "non_revoked": { "to": int(time.time() - 1) }, }, ) else: req_attrs.append({ "name": "degree", "restrictions": [{ "issuer_did": agent.did }] }) # test self-attested claims req_attrs.append({"name": "self_attested_thing"}, ) req_preds = [ # test zero-knowledge proofs { "name": "age", "p_type": ">=", "p_value": 18, "restrictions": [{ "issuer_did": agent.did }], } ] indy_proof_request = { "name": "Proof of Education", "version": "1.0", "nonce": str(uuid4().int), "requested_attributes": { f"0_{req_attr['name']}_uuid": req_attr for req_attr in req_attrs }, "requested_predicates": { f"0_{req_pred['name']}_GE_uuid": req_pred for req_pred in req_preds }, } if revocation: indy_proof_request["non_revoked"] = { "to": int(time.time()) } proof_request_web_request = { "connection_id": agent.connection_id, "proof_request": indy_proof_request, } await agent.admin_POST("/present-proof/send-request", proof_request_web_request) elif option == "3": msg = await prompt("Enter message: ") await agent.admin_POST( f"/connections/{agent.connection_id}/send-message", {"content": msg}) elif option == "4" and revocation: revoking_cred_id = await prompt( "Enter credential exchange id: ") publish = json.dumps( await prompt("Publish now? [Y/N]: ", default="N") in ( 'yY')) await agent.admin_POST( f"/issue-credential/records/{revoking_cred_id}" f"/revoke?publish={publish}") elif option == "5" and revocation: resp = await agent.admin_POST( "/issue-credential/publish-revocations") agent.log( "Published revocations for {} revocation registr{} {}". format(len(resp), "y" if len(resp) == 1 else "ies", json.dumps([k for k in resp], indent=4))) elif option == "6" and revocation: log_status("#19 Add another revocation registry") revocation_registry_id = await ( agent.create_and_publish_revocation_registry( credential_definition_id, TAILS_FILE_COUNT)) if show_timing: timing = await agent.fetch_timing() if timing: for line in agent.format_timing(timing): log_msg(line) finally: terminated = True try: if agent: await agent.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False await asyncio.sleep(0.1) if not terminated: os._exit(1)
async def main(start_port: int, show_timing: bool = False): genesis = await default_genesis_txns() if not genesis: print("Error retrieving ledger genesis transactions") sys.exit(1) agent = None try: log_status( "#1 Provision an agent and wallet, get back configuration details") agent = AcmeAgent(start_port, start_port + 1, genesis_data=genesis, timing=show_timing) await agent.listen_webhooks(start_port + 2) await agent.register_did() with log_timer("Startup duration:"): await agent.start_process() log_msg("Admin URL is at:", agent.admin_url) log_msg("Endpoint URL is at:", agent.endpoint) # Create a schema log_status("#3 Create a new schema on the ledger") with log_timer("Publish schema and cred def duration:"): # TODO define schema version = format("%d.%d.%d" % ( random.randint(1, 101), random.randint(1, 101), random.randint(1, 101), )) (schema_id, cred_def_id) = await agent.register_schema_and_creddef( "employee id schema", version, ["employee_id", "name", "date", "position"], support_revocation=False, revocation_registry_size=TAILS_FILE_COUNT, ) with log_timer("Generate invitation duration:"): # Generate an invitation log_status( "#5 Create a connection to alice and print out the invite details" ) invi_msg = await agent.admin_POST( "/out-of-band/create-invitation", {"handshake_protocols": ["rfc23"]}, ) log_msg(json.dumps(invi_msg["invitation"]), label="Invitation Data:", color=None) log_msg("*****************") log_msg("Waiting for connection...") await agent.detect_connection() async for option in prompt_loop( "(1) Issue Credential, (2) Send Proof Request, " + "(3) Send Message (X) Exit? [1/2/3/X] "): option = option.strip() if option in "xX": break elif option == "1": log_status("#13 Issue credential offer to X") # TODO credential offers agent.cred_attrs[cred_def_id] = { "employee_id": "ACME0009", "name": "Alice Smith", "date": date.isoformat(date.today()), "position": "CEO" } cred_preview = { "@type": CRED_PREVIEW_TYPE, "attributes": [{ "name": n, "value": v } for (n, v) in agent.cred_attrs[cred_def_id].items()], } offer_request = { "connection_id": agent.connection_id, "comment": f"Offer on cred def id {cred_def_id}", "credential_preview": cred_preview, "filter": { "indy": { "cred_def_id": cred_def_id } }, } await agent.admin_POST("/issue-credential-2.0/send-offer", offer_request) elif option == "2": log_status("#20 Request proof of degree from alice") # TODO presentation requests req_attrs = [{ "name": "name", "restrictions": [{ "schema_name": "degree schema" }] }, { "name": "date", "restrictions": [{ "schema_name": "degree schema" }] }, { "name": "degree", "restrictions": [{ "schema_name": "degree schema" }] }] req_preds = [] indy_proof_request = { "name": "Proof of Education", "version": "1.0", "nonce": str(uuid4().int), "requested_attributes": { f"0_{req_attr['name']}_uuid": req_attr for req_attr in req_attrs }, "requested_predicates": {} } proof_request_web_request = { "connection_id": agent.connection_id, "proof_request": indy_proof_request } log_msg( "POST request to /present-proof/send-request, payload:\n", json.dumps(proof_request_web_request)) # this sends the request to our agent, which forwards it to Alice # (based on the connection_id) await agent.admin_POST("/present-proof/send-request", proof_request_web_request) elif option == "3": msg = await prompt("Enter message: ") await agent.admin_POST( f"/connections/{agent.connection_id}/send-message", {"content": msg}) if show_timing: timing = await agent.fetch_timing() if timing: for line in agent.format_timing(timing): log_msg(line) finally: terminated = True try: if agent: await agent.terminate() except Exception: LOGGER.exception("Error terminating agent:") terminated = False await asyncio.sleep(0.1) if not terminated: os._exit(1)