# June 13, 2023 - AnonCreds Project Report - Significant refactors - Cleaning up which components are responsible for what - Refined records used to track anoncreds objects in issuer - MVP Revocation completed - Items completed: - Marking credential for revocation - Publishing pending revocation - Presenting and verifying revocable credentials - What's next - Automated registry setup - Plan in place; implementation thus far has been building to this point - Should be relatively quick to execute but additional refactors and refinements anticipated - Genericize revocation registry recovery? - Catching ledger up with wallet state - Adapt original Indy anoncreds interface? - Schema, Cred def, revocation? - What else is required to smoothly transition? - Retain both systems? - Test updates - Cleaning Up #### Links PR to ACA-Py: https://github.com/hyperledger/aries-cloudagent-python/pull/2191 Active branch: https://github.com/Indicio-tech/aries-cloudagent-python/tree/feature/anoncreds-revocation-again # May 30, 2023 - AnonCreds Project Report - Updated anoncreds-rs build - Tails file handling now uses tails hash as the file name - Updates to indy-tails-server: https://github.com/Indicio-tech/indy-tails-server/tree/fix/tails-file-hash-update - Basic checks, investigating further validation on the uploaded file - "MVP" Revocation nearly complete - Issuance and presentation completed - Working on publishing revocation updates - Focus for this week: - Finishing off publishing revocation updates - Automated registry setup - Unit test updates - Cleaning up #### Links PR to ACA-Py: https://github.com/hyperledger/aries-cloudagent-python/pull/2191 Active branch: https://github.com/Indicio-tech/aries-cloudagent-python/tree/feature/anoncreds-revocation-again # May 2, 2023 - AnonCreds Project Report - Short on resources during the month of April; more resources to address it now - Biggest focus area remains to be Revocation support - This week: - Updating to more recent builds of anoncreds-rs - Tails file handling changes (more discussion below) - Reassessing existing revocation components to determine what to reuse and what to deprecate - We have diagrams. Lots of diagrams. - MVP Revocation using AnonCreds interface - Isolating the core operations - No automation, no batching - Answering questions - Batching updates to revocation list - Level of backwards compatibility - Assessing changes in what needs to be stored (generic vs indy, revocation list vs deltas) - Next week and beyond: - Consolidating diagrams, design doc into docs for the repo - AnonCreds method plugin author guide - Updating unit and integration tests - Adapt/deprecate Admin APIs for publishing AnonCreds objects for Indy - Complete integration with Issue Credential and Present Proof ### Tails File Handling **The problem:** - Indy Tails Server expects revocation registry ID - AnonCreds Interface must know tails location in order to publish - Revocation registry ID not known until after publishing **Solutions?** - Relax expectations of tails server - Simpler, reusable by other methods - Just accept a file by hash, do basic hash validation on the contents of the file - No AnonCreds registry communication at all - AnonCreds Method plugins responsible for tails file upload - Indy method could continue to use Indy Tails Server unmodified (rev reg ID known prior to publishing so it can behave the same as before) - Each method has its own tails server? - Make Indy Tails Server more generic? - Problem: If we want same level of validation as currently exists, tails server would need a universal resolver for AnonCreds objects. Complexity increases. **Current conclusion:** relax tails server, make tails file upload generic ### Batching Updates to Revocation Lists **Question:** Whose responsibility is it to batch revocation updates? Plugin or ACA-Py? - It is a bit early in the lifecycle of the AnonCreds as a legder-agnostic protocol to be too sure about exact behavior of revocation for all methods. It's possible some methods will be like Indy; Indy has a fee structure around transactions that incentivizes collecting changes and then publishing only after reaching a certain threshold or on a regular schedule. Other methods may also desire to batch to reduce costs. **_Batching is probably widely desirable._** - ACA-Py just provides the handles for implementing this kind of a schedule or threshold matching and is not opinionated about when or how often this occurs. **_ACA-Py's implementation for batching is decently generic._** - Other methods may be wildly different. Or **_other methods may have more sophisticated batching needs._** - If ACA-Py implements a default batching scheme, that doesn't necessarily restrict whether or not the plugin could implement its own. **_ACA-Py default batching and Method-specific batching can coexist._** - Also, Stephen made the point that batching is as much a business decision as it is a network optimization decision. **Current conclusion:** still targeting an MVP where we will not batch updates but expect that the final interface will provide a batching strategy (expected to be the same as currently implemented) that method plugins can bypass if needed. # April 4, 2023 - AnonCreds Project Report ## Acknowledgments - Credit to Adam Burdett and Char Howland for doing the lion's share of the work - Animo and others working on anoncreds-rs project and for a lot of the interface design ## Progress - Pluggable Interface for AnonCreds Methods - Essentially replaces use of the BaseLedger for AnonCreds object resolution and registration - Inspired by our past work on DID Resolution - Each plugin implements a `supports` method that takes an Identifier and returns whether it supports it or not - `AnonCredsRegistry` acts as an aggregate interface. ```plantuml package anoncreds { class AnonCredsIssuer { + create_schema() + create_and_store_credential_definition() + create_credential_offer() + create_credential() + revoke_credentials() + create_and_store_revocation_registry() + merge_revocation_registry_deltas() } class AnonCredsHolder { + create_credential_request() + store_credential() + get_credential() + create_presentation() + create_revocation_state() } class AnonCredsVerifier { + verify_presentation() } abstract class BaseAnonCredsRegistrar { async def register_schema() -> SchemaResult async def register_credential_definition() -> CredDefResult async def register_revocation_registry_definition() -> RevRegDefResult async def register_revocation_status_list() -> RevStatusListResult } abstract class BaseAnonCredsResolver { async def get_schema() -> GetSchemaResult async def get_credential_definition() -> GetCredDefResult async def get_revocation_registry_definition() -> GetRevRegDefResult async def get_revocation_status_list() -> GetRevStatusListResult } class AnonCredsRegistry { async def _registrar_for_identifier() async def _resolver_for_identifier() {method} ... } } together { class DidIndyRegistry class LegacyIndyRegistry class DidWebRegistry } LegacyIndyRegistry ..|> BaseAnonCredsRegistrar LegacyIndyRegistry ..|> BaseAnonCredsResolver DidIndyRegistry ..|> BaseAnonCredsRegistrar DidIndyRegistry ..|> BaseAnonCredsResolver DidWebRegistry ..|> BaseAnonCredsRegistrar DidWebRegistry ..|> BaseAnonCredsResolver BaseAnonCredsRegistrar <.. AnonCredsRegistry BaseAnonCredsResolver <.. AnonCredsRegistry AnonCredsRegistry <.. AnonCredsHolder AnonCredsRegistry <.. AnonCredsIssuer AnonCredsRegistry <.. AnonCredsVerifier ``` ```json // Example result object for SchemaResult { "job_id": "string", "schema_state": { "state": "string", "schema_id": "string", "schema": { "attrNames": ["string"], "name": "string", "version": "string", "issuerId": "string" } }, "registration_metadata": {}, "schema_metadata": { // For indy, schema_metadata will contain the seqNo "seqNo": "12345" } } ``` - Adjusted the Credential Issuance and Presentation flows to use AnonCreds Interface - Cred Defs resolved through `AnonCredsRegistry` - Revocation lists resolved through `AnonCredsRegistry` (theoretically...) - Credential offers and requests prepared through `anoncreds-rs`, accepting the new models for cred defs, others - Revocation state generated through new models (theoretically...) - Admin API for creating AnonCreds Objects - Schema and Credential Definitions completed - Revocation Registry Definitions and Revocation Lists in progress ## Challenges ```plantuml package "indy" { abstract class IndyIssuer { + create_schema() + create_and_store_credential_definition() + create_credential_offer() + create_credential() + revoke_credentials() + create_and_store_revocation_registry() + merge_revocation_registry_deltas() } abstract class IndyHolder { + create_credential_request() + store_credential() + get_credential() + create_presentation() + create_revocation_state() } abstract class IndyVerifier { + verify_presentation() } class IndyCredxVerifier { } class IndyCredxIssuer { } class IndyCredxHolder { } class IndySdkVerifier { } class IndySdkIssuer { } class IndySdkHolder { } } IndyCredxHolder --|> IndyHolder IndyCredxIssuer --|> IndyIssuer IndyCredxVerifier --|> IndyVerifier IndySdkHolder --|> IndyHolder IndySdkIssuer --|> IndyIssuer IndySdkVerifier --|> IndyVerifier ' ## Dependent stuff ## together { abstract class BaseLedger { + create_and_send_schema() + create_and_send_credential_definition() + send_revoc_reg_def() + send_revoc_reg_entry() } class IndyPresExchHandler { + return_presentation() + verify_pres() } class PresentationManager { + verify_presentation() } ' Issue Credential V2 class IndyCredFormatHandler { + create_ofer() + create_request() + issue_credential() + store_credential() } ' Issue Credential V1 class CredentialManager { + create_offer() + create_request() + issue_credential() + store_credential() } together { class RevocationManager { + revoke_credential() + publish_pending_revocations() } class IssuerRevRegRecord { + generate_registry() + send_def() + send_entry() } entity "revocation/routes.py" as rev_routes { + on_revocation_registry_init_event() } class IndyRevocation { + init_issuer_registry() + handle_full_registry() } entity "credential_definitions/routes.py" as cred_def_routes { + on_cred_def_event() } } } BaseLedger -up-> IndyIssuer IndyCredFormatHandler -up-> IndyIssuer IndyCredFormatHandler -up-> IndyHolder IndyCredFormatHandler -down-> IndyRevocation CredentialManager -up-> IndyIssuer CredentialManager -up-> IndyHolder IndyPresExchHandler -up-> IndyHolder IndyPresExchHandler -up-> IndyVerifier PresentationManager -up-> IndyVerifier RevocationManager -up-> IndyIssuer RevocationManager -left-> IssuerRevRegRecord IssuerRevRegRecord -up-> IndyIssuer IssuerRevRegRecord -up-> BaseLedger rev_routes -up-> IssuerRevRegRecord IndyRevocation -left-> rev_routes cred_def_routes -left-> IndyRevocation ``` - Some prior held core assumptions have been broken - Identifiers for objects known before registration -> Identifiers for objects are only guaranteed to be known after reaching `finished` state. - Revocation registry definitions and revocation status lists are closely tied together - Revocation status lists must have the revocation registry definition ID in order to create the list - Identifiers are not known until after registration of objects - Therefore, revocation status lists must be registered strictly after the revocation registry definition has been finished. - Much of the logic surrounding revocation is split across many locations - Event handlers - Present Proof - Admin API Routes ## Additional Discussion Points - Endorsement