diff --git a/docs/README.md b/docs/README.md index 5e6e9c59..5247e052 100644 --- a/docs/README.md +++ b/docs/README.md @@ -10,15 +10,16 @@ - Network Permission modules: - [Auth](design/auth.md) - control user permissions - - role control - manage roles assigned to accounts + - role control - manage roles assigned to accounts - access control - first level validation: whether to accept write transactions (execute target contract method) from a given account - [Upgrading contracts](design/upgradability.md) - control versions of deployed contracts (proposing and approving new versions). - [Validators node management](design/network.md) - control the list of network validator nodes -- Identity: - - [DID Method](design/did-method.md) - Supported DID method +- Identity: + - [DID Methods](design/did-methods.md) - Supported DID method + - [IndyBesu DID Registry](design/indybesu-did-registry.md) - `indybesu` DID Registry - [CL Registry](design/cl-registry.md) - [Client](design/vdr.md) - design of VDR library - + ### Migration documents - [Indy Migration](migration/migration.md) diff --git a/docs/design/cl-registry.md b/docs/design/cl-registry.md index 5461ef30..08597c16 100644 --- a/docs/design/cl-registry.md +++ b/docs/design/cl-registry.md @@ -1,16 +1,5 @@ # CL Registry -## Design - -Smart contracts for schema and credential definition registries are designed to follow an approach used for DID:ethr -method: - -* Contract Events are used for storing data -* Contracts hold mapping for more efficient events look up -* Gas efficient data types are used in contract method -* Provided methods for delegating signing - * Nonce is not needed because only `create` methods provided (no `update` method) - ## Schema ### ID Syntax @@ -20,30 +9,55 @@ method: | parameter | value | |-------------|-----------------------------------------------------------------| | id | “did:” method-name “:” namespace “:” method-specific-id | -| method-name | “ethr” | +| method-name | “indybesu”, “ethr” | | namespace | “testnet”/"mainnet" | | indy-id | /anoncreds/v0/SCHEMA// | ``` -Example: did:ethr:mainnet:Y6LRXGU3ZCpm7yzjVRSaGu/anoncreds/v0/SCHEMA/BasicIdentity/1.0.0 +Example: did:indybesu:mainnet:0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266/anoncreds/v0/SCHEMA/BasicIdentity/1.0.0 ``` ### Storage format -* Created schemas mapping: - * Description: Mapping to track created schemas by their id to the block number when it was created. +* Schemas collection: + * Description: Mapping holding the list of Schema ID's to their data and metadata. * Format: ``` - mapping(bytes32 id => uint block); + mapping(bytes32 id => SchemaRecord schemaRecord); + + struct SchemaRecord { + bytes data; + SchemaMetadata metadata; + } + + struct SchemaMetadata { + uint256 created; + } ``` * Example: ``` { - "0x8ae64c08cf45da3364623a7235a9e7d132fdc8e9f6e63858b53a90d9db32c3af": 110, + "0x8ae64c08cf45da3364623a7235a9e7d132fdc8e9f6e63858b53a90d9db32c3af": { + schema: [1,2,3,4,5,6,7,8,9,....], + metadata: { + created: 1234 + }, + }, ... } ``` +#### Types definition + +##### Schema + +Schema must match to +the [specification](https://hyperledger.github.io/anoncreds-spec/#schema-publisher-publish-schema-object). + +##### Schema Metadata + +* `created` - timestamp of schema creation. + ### Transactions (Smart Contract's methods) Contract name: **SchemaRegistry** @@ -51,86 +65,55 @@ Contract name: **SchemaRegistry** #### Create a new schema * Method: `createSchema` - * Description: Transaction to create a new AnonCreds Schema matching to the [specification](https://hyperledger.github.io/anoncreds-spec/#schema-publisher-publish-schema-object) + * Description: Transaction to create a new AnonCreds Schema * Parameters: * `identity` - Account address of schema issuer - * `id` - KECCAK256 hash of schema id to be created - * `schema` - AnonCreds Schema object as bytes + * `id` - Keccak hash of Schema id to be created + * `issuerId` - DID of Schema issuer + * `schema` - AnonCreds schema JSON as bytes. * Restrictions: * Schema id must be unique. - * Corresponding issuer account must exist and owned by sender. + * Corresponding issuer DID must exist, be active, and owned by sender. * Format: ``` SchemaRegistry.createSchema( address identity, bytes32 id, - bytes schema + string calldata issuerId, + bytes calldata schema ) ``` - * Raised Event: - ``` - SchemaCreated(bytes32 indexed id, address identity, bytes schema)` - ``` * Example: ``` SchemaRegistry.createSchema( - "0x173CC02518a355040F5Faee93D3AAAb1259F010c", + "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", "0x8ae64c08cf45da3364623a7235a9e7d132fdc8e9f6e63858b53a90d9db32c3af", - [34, 123, 92, 34, 105, 100, 92, 34, 58, 92, 34, 100, ...] + "did:ethr:0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + [1,2,3,4,5,6,7,8,9,....] ) + * Raised Event: + * `SchemaCreated(id, identity)` + +#### Resolve schema -* Method: `createSchemaSigned` - * Description: Transaction to endorse a new AnonCreds Schema (off-chain author signature) +* Method: `resolveSchema` + * Description: Transaction to resolve Schema for giving id * Parameters: - * `identity` - Account address of schema issuer - * `sigV` - Part of EcDSA signature. - * `sigR` - Part of EcDSA signature. - * `sigS` - Part of EcDSA signature. - * `id` - KECCAK256 hash of schema id to be created - * `schema` - AnonCreds schema object as bytes + * `id` - Keccak hash of Schema id to be resolved * Restrictions: - * Schema id must be unique. - * Corresponding issuer account must exist and owned by sender. + * Schema must exist. * Format: ``` - SchemaRegistry.createSchemaSigned( - address identity, - uint8 sigV, - bytes32 sigR, - bytes32 sigS, - bytes32 id, - bytes schema - ) + SchemaRegistry.resolveSchema( + bytes32 id + ) returns (SchemaRecord sschemaRecord) ``` - * Raised Event: - ``` - SchemaCreated(bytes32 indexed id, address identity, bytes schema)` - ``` * Example: ``` - SchemaRegistry.createSchemaSigned( - "0x173CC02518a355040F5Faee93D3AAAb1259F010c", - 27, - [1, 2, 3, 4, 5, 6, 7, 8, ...], - [11, 21, 33, 44, 55, 73, ...], - "0x8ae64c08cf45da3364623a7235a9e7d132fdc8e9f6e63858b53a90d9db32c3af", - [34, 123, 92, 34, 105, 100, 92, 34, 58, 92, 34, 100, ...] + SchemaRegistry.resolveSchema( + "0x8ae64c08cf45da3364623a7235a9e7d132fdc8e9f6e63858b53a90d9db32c3af" ) - -#### Resolve schema - -In order to resolve a Schema the following steps must be done: - -* Call `SchemaRegistry.created(bytes32 id)` contract method passing KECCAK256 hash of target Schema id to get the block number when the Schema was created. - * Schemas are stored in the transaction logs. - * Query log events from the whole transaction history is very inefficient lookup mechanism. -* Query ledger for `SchemaCreated` events specifying following data: - * `address`: Address of `SchemaRegistry - * `topics`: KECCAK256 hash of target Schema id as the second topic - * `from_block`: block number when the Schema was created - * `to_block`: block number when the Schema was created -* If result is empty, schema does not exist. -* If result contains more than one event, its unexpected case and ledger history is broken + * Raised Event: `None` ## Credential Definition @@ -141,30 +124,56 @@ In order to resolve a Schema the following steps must be done: | parameter | value | |-------------|---------------------------------------------------------| | id | “did:” method-name “:” namespace “:” method-specific-id | -| method-name | “indy2”, “indy”, “sov”, “ethr” | +| method-name | “indybesu”, “ethr” | | namespace | “testnet”/"mainnet" | | indy-id | /anoncreds/v0/CLAIM_DEF// | ``` -Example: did:indy2:sovrin:Gs6cQcvrtWoZKsbBhD3dQJ/anoncreds/v0/CLAIM_DEF/56495/mctc +Example: did:indybesu:sovrin:0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266/anoncreds/v0/CLAIM_DEF/56495/mctc ``` ### Storage format -* Created credential definitions mapping: - * Description: Mapping to track created credential definitions by their id to the block number when it was created. +* Credential Definitions collection: + * Description: Mapping holding the list of Credential Definition ID's to their data and metadata. * Format: ``` - mapping(bytes32 id => uint block); + mapping(bytes32 id => CredentialDefinitionRecord credentialDefinitionRecord); + + struct CredentialDefinitionRecord { + bytes credDef; + CredentialDefinitionMetadata metadata; + } + + struct CredentialDefinitionMetadata { + uint256 created; + } ``` * Example: ``` { - "0x8ae64c08cf45da3364623a7235a9e7d132fdc8e9f6e63858b53a90d9db32c3af": 110, + "0x8ae64c08cf45da3364623a7235a9e7d132fdc8e9f6e63858b53a90d9db32c3af": { + credDef: [1,2,3,4,5,6,7,8,9,....], + metadata: { + created: 1234 + }, + }, ... } ``` +#### Types definition + +##### CredentialDefinitionData + +Schema must match to +the [specification](https://hyperledger.github.io/anoncreds-spec/#generating-a-credential-definition-without-revocation-support) +. + +##### CredentialDefinitionMetadata + +* `created` - timestamp of credential definition creation. + ### Transactions (Smart Contract's methods) Contract name: **CredentialDefinitionRegistry** @@ -172,93 +181,58 @@ Contract name: **CredentialDefinitionRegistry** #### Create a new credential definition * Method: `createCredentialDefinition` - * Description: Transaction to create a new AnonCreds Credential Definition matching to the [specification](https://hyperledger.github.io/anoncreds-spec/#generating-a-credential-definition-without-revocation-support) + * Description: Transaction to create a new AnonCreds Credential Definition * Parameters: * `identity` - Account address of credential definition issuer - * `id` - KECCAK256 hash of credential definition id to be created - * `schemaId` - KECCAK256 hash of schema id to be created - * `credDef` - AnonCreds Credential Definition object as bytes + * `id` - Keccak hash of Credential Definition id to be created + * `issuerId` - DID of Credential Definition issuer + * `schemaId` - Keccak hash of Schema id + * `credDef` - AnonCreds Credential Definition JSON as bytes * Restrictions: * Credential Definition must be unique. - * Corresponding issuer DID must exist and owned by sender. + * Corresponding issuer DID must exist, be active, and owned by sender. * Corresponding schema must exist. * Format: ``` CredentialDefinitionRegistry.createCredentialDefinition( address identity, bytes32 id, + string calldata issuerId, bytes32 schemaId, - bytes credDef + bytes calldata credDef ) ``` - * Raised Event: - ``` - CredentialDefinitionCreated(bytes32 indexed id, address identity, bytes credDef)` - ``` * Example: ``` - CredentialDefinitionCreated.createCredentialDefinition( - "0x173CC02518a355040F5Faee93D3AAAb1259F010c", - "0x76943530d3587e81f029e8ce20edb64f9254350d81c59ecf6b7e3ed553e9a8f6", + CredentialDefinitionRegistry.createCredentialDefinition( + "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", "0x8ae64c08cf45da3364623a7235a9e7d132fdc8e9f6e63858b53a90d9db32c3af", - [34, 123, 92, 34, 105, 100, 92, 34, 58, 92, 34, 100, ...] + did:ethr:0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + 0x32ds23fd23445da3364623a7235a9e7d132fdc8e9f6e63858b53adshg234je2f2", + [1,2,3,4,5,6,7,8,9,....] ) + * Raised Event: + * `CredentialDefinitionCreated(id, identity)` + +#### Resolve credential definition -* Method: `createCredentialDefinitionSigned` - * Description: Transaction to endorse a new AnonCreds Credential Definition (off-chain author signature) +* Method: `resolveCredentialDefinition` + * Description: Transaction to resolve Credential Definition for giving id * Parameters: - * `identity` - Account address of credential definition issuer - * `sigV` - Part of EcDSA signature. - * `sigR` - Part of EcDSA signature. - * `sigS` - Part of EcDSA signature. - * `id` - KECCAK256 hash of credential definition id to be created - * `schemaId` - KECCAK256 hash of schema id - * `credDef` - AnonCreds credential definition object as bytes + * `id` - Keccak hash of the Credential Definition to be resolved * Restrictions: - * Credential Definition must be unique. - * Corresponding issuer DID must exist and owned by sender. - * Corresponding schema must exist. + * Credential Definition must exist. * Format: ``` - CredentialDefinitionRegistry.createCredentialDefinitionSigned( - address identity, - uint8 sigV, - bytes32 sigR, - bytes32 sigS, - bytes32 id, - bytes32 schemaId, - bytes credDef - ) + CredentialDefinitionRegistry.resolveCredentialDefinition( + bytes32 id + ) returns (CredentialDefinitionRecord credentialDefinitionRecord) ``` - * Raised Event: - ``` - CredentialDefinitionCreated(bytes32 indexed id, address identity, bytes credDef)` - ``` * Example: ``` - CredentialDefinitionRegistry.createCredentialDefinitionSigned( - "0x173CC02518a355040F5Faee93D3AAAb1259F010c", - 27, - [1, 2, 3, 4, 5, 6, 7, 8, ...], - [11, 21, 33, 44, 55, 73, ...], - "0x76943530d3587e81f029e8ce20edb64f9254350d81c59ecf6b7e3ed553e9a8f6", - "0x8ae64c08cf45da3364623a7235a9e7d132fdc8e9f6e63858b53a90d9db32c3af", - [34, 123, 92, 34, 105, 100, 92, 34, 58, 92, 34, 100, ...] + CredentialDefinitionRegistry.resolveCredentialDefinition( + "0x8ae64c08cf45da3364623a7235a9e7d132fdc8e9f6e63858b53a90d9db32c3af" ) - -#### Resolve credential definition - -In order to resolve a Credential Definition the following steps must be done: - -* Call `CredentialDefinitionRegistry.created(bytes32 id)` contract method passing KECCAK256 hash of target Credential Definition id to get the block number when the Credential Definition was created. - * Credential Definitions are stored in the transaction logs. - * Query log events from the whole transaction history is very inefficient lookup mechanism. -* Query ledger for `CredentialDefinitionCreated` events specifying following data: - * `address`: Address of `CredentialDefinitionRegistry` - * `topics`: KECCAK256 hash of target Credential Definition id as the second topic - * `from_block`: block number when the Credential Definition was created - * `to_block`: block number when the Credential Definition was created -* If result is empty, Credential Definition does not exist. -* If result contains more than one event, its unexpected case and ledger history is broken + * Raised Event: `None` diff --git a/docs/design/conmponents.png b/docs/design/conmponents.png index e5d0c2d2..400a613e 100644 Binary files a/docs/design/conmponents.png and b/docs/design/conmponents.png differ diff --git a/docs/design/conmponents.puml b/docs/design/conmponents.puml index 5a717d34..0bb44028 100644 --- a/docs/design/conmponents.puml +++ b/docs/design/conmponents.puml @@ -7,7 +7,9 @@ package "Ethereum Network" { component [Account Control] component [Validator Control] component [Upgrade Control] + component [IndyBesu Did Registry] component [Ethereum Did Registry] + component [Universal Did Resolver] component [Schema Registry] component [Credential Definition Registry] } @@ -37,7 +39,6 @@ together { Interact with a network node - ping network - submit transaction - - submit event query - retrieve transaction receipt end note } diff --git a/docs/design/contracts.png b/docs/design/contracts.png index 7c2d886d..70d04086 100644 Binary files a/docs/design/contracts.png and b/docs/design/contracts.png differ diff --git a/docs/design/contracts.puml b/docs/design/contracts.puml index 957a9593..a0a644e2 100644 --- a/docs/design/contracts.puml +++ b/docs/design/contracts.puml @@ -42,6 +42,13 @@ package "Smart Contracts" { package "DID" { + component [IndyBesu Did Registry] + note bottom of [IndyBesu Did Registry] + Manage `indybesu` DID method records + - did doc stored in the contract storage + - one-to-one relationship with account + end note + component [Ethereum Did Registry] note bottom of [Ethereum Did Registry] Manage `ethr` DID method records @@ -51,6 +58,12 @@ package "Smart Contracts" { - uses events approach - extended to control versioning end note + + component [Universal Did Resolver] + note bottom of [Universal Did Resolver] + Resolve Issuer DID from various DID registries + - used by CL contracts to verify did existence and owner + end note } package "CL" { @@ -58,23 +71,21 @@ package "Smart Contracts" { component [Schema Registry] note bottom of [Schema Registry] Store CL schemas - - uses events approach - - uses KECCAK256 hash of id for indexing end note component [Credential Definition Registry] note top of [Credential Definition Registry] Store CL Credential Definitions - - uses events approach - - uses KECCAK256 hash of id for indexing end note } } [Identity] --> [Role Control] [Identity] --> [Upgrade Control] - [Schema Registry] --> [Ethereum Did Registry] - [Credential Definition Registry] --> [Ethereum Did Registry] + [Universal Did Resolver] --> [IndyBesu Did Registry] + [Universal Did Resolver] --> [Ethereum Did Registry] + [Schema Registry] --> [Universal Did Resolver] + [Credential Definition Registry] --> [Universal Did Resolver] } @enduml diff --git a/docs/design/did-method.md b/docs/design/did-method.md deleted file mode 100644 index e5b5cd44..00000000 --- a/docs/design/did-method.md +++ /dev/null @@ -1,10 +0,0 @@ -# DID Method - -The extended version of Ethr DID method (`did:ethr`) in used on the ledger. -The core specification of `did:ethr` can be found [here](https://github.com/decentralized-identity/ethr-did-resolver/blob/master/doc/did-method-spec.md) in great details is used on the Ledger. - -Example DID: `did:ethr:0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266` - -The following extension logic is applied to DID ethr smart contract to integrate it with permission related modules: -* Control contract upgrade versions -* Control account roles executing write transactions diff --git a/docs/design/did-methods.md b/docs/design/did-methods.md new file mode 100644 index 00000000..cfef9722 --- /dev/null +++ b/docs/design/did-methods.md @@ -0,0 +1,42 @@ +# DID Methods + +Out of box Ledger provides an ability to use one of two supported DID methods: `did:ethr` or `did:indybesu`. + +Contracts implementing both methods are deployed on the network and integrated with `CL Registry`. + +Ledger `permission` related modules are implemented in a way to use **account address** but not a DID. + +It is up to a User which DID method to use. + +> Moreover, users having an appropriate permissions can even deploy contracts adding support for another DID methods +> (need to integrate into `CLRegistry`). + +## Ethereum DID method: did:ethr + +Ethereum DID Method `did:ethr` described in +the [specification](https://github.com/decentralized-identity/ethr-did-resolver/blob/master/doc/did-method-spec.md). + +Example DID: `did:ethr:0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266` + +## IndyBesu DID method: did:indybesu + +The identifier of `indybesu` DID method is an identity address similarly to `did:ethr` method, but there multiple +significant differences between them: +* API consist of more traditional `create`, `update`, `deactivate` methods +* The associated `Did Document` is stored in the contract storage in complete form +* In order to resolve Did Document you only need to call single method +* DID must be registered by executing one of `create` contract methods +* State proof can be obtained for resolved Did Record + +Example: + +Example DID: `did:indybesu:0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266` + +### DID Syntax + +| parameter | value | +|--------------------|---------------------------------------------------------| +| did | “did:” method-name “:” namespace “:” method-specific-id | +| method-name | “indybesu” | +| namespace | “testnet”/"mainnet" | +| method-specific-id | ethereum-address | diff --git a/docs/design/endorsement.md b/docs/design/endorsement.md index b5bdba0d..a15a6a73 100644 --- a/docs/design/endorsement.md +++ b/docs/design/endorsement.md @@ -1,8 +1,71 @@ ## Endorsement Not all identity owners may have permissions for writing transactions on the ledger. -The goal of this document to define a mechanism of doing transaction writes to the ledger by a special parties having an -Endorser role with preserving of original author as an entity owner. +We need to define a mechanism of doing transaction writes by an Endorser with preserving original author as an entity +owner. + +### DID Indy registry + +#### Flow + +* Author steps: + * Step 1: Author prepares a Did Document object + * Step 2: Execute VDR method to calculate hash need to be signed - contract signed data according + to [EIP](https://eips.ethereum.org/EIPS/eip-191). + ``` + keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createDid", document)) + // Arguments when calculating hash to validate + // 1: byte(0x19) - the initial 0x19 byte + // 2: byte(0) - the version byte + // 3: address(this) - the validator address + // 4-7: Application specific data + // identity - author account address + // `createDid` original contract method - added to be aligned with did:ethr contract + // document - document as JSON bytes + ``` + * Step 3: Performs EcDSA signing using his ethereum identity account keys + * Step 4: Author passes Did Document and Signature to Endorser +* Endorser steps: + * Step 1: Endorser builds transaction to endorse + DID: `createDidSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes calldata document)` + * Step 2: Endorser does regular EcDSA signing of the **Transaction** + * Step 3: Endorser submit the signed transaction to the ledger which executes + deployed `SchemaRegistry.createDidSigned` + contract method +* Ethereum: + * Checks the validity of the transaction level signature (Endorser's signature) +* Contract: + * Step 1: Calculate the hash of signed data: same as for Author Step 3 + * Step 2: Checks the validity of the provided signature against identity passed as the parameter `ecrecover(...);` + * `ecrecover` returns an account signed the message + +#### Contracts + +``` +mapping(address => uint) public nonce; + +function createDidSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes calldata document) public; +``` + +#### VDR + +```rust +// Prepared data for endorsing IndyDidRegistry.createDid contract method +async fn build_create_did_endorsing_data( + client: &LedgerClient, + did: &DID, + did_doc: &DidDocument, +) -> VdrResult; + +// Build transaction to execute IndyDidRegistry.createDidSigned contract method to endorse a new DID +async fn build_create_did_signed_transaction( + client: &LedgerClient, + from: &Address, + did: &DID, + did_doc: &DidDocument, + signature: &SignatureData, +) -> VdrResult {} +``` ### DID Ethr registry @@ -45,25 +108,26 @@ Endorsing for schemas and credential definition is designed to match existing `d * Step 2: Execute VDR method to calculate hash need to be signed - contract signed data according to [EIP](https://eips.ethereum.org/EIPS/eip-191). ``` - keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createSchema", id, schema)) + keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createSchema", id, issuerId, schema)) // Arguments when calculating hash to validate // 1: byte(0x19) - the initial 0x19 byte // 2: byte(0) - the version byte // 3: address(this) - the validator address - // 4-7: Application specific data + // 4-8: Application specific data // identity - author account address // `createSchema` original contract method - added to be aligned with did:ethr contract // id - id of schema to be created - // schema - schema as JSON string + // issuerId - DID of Schema issuer + // schema - schema as JSON bytes ``` * Step 3: Performs EcDSA signing using his ethereum identity account keys * Step 4: Author passes Schema and Signature to Endorser * Endorser steps: * Step 1: Endorser builds transaction to endorse - DID: `endorseSchema(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 id, bytes schema)` + DID: `createSchemaSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 id, bytes schema)` * Step 2: Endorser does regular EcDSA signing of the **Transaction** * Step 3: Endorser submit the signed transaction to the ledger which executes - deployed `SchemaRegistry.endorseSchema` + deployed `SchemaRegistry.createSchemaSigned` contract method * Ethereum: * Checks the validity of the transaction level signature (Endorser's signature) @@ -82,17 +146,18 @@ Endorsing for schemas and credential definition is designed to match existing `d * Step 2: Execute VDR method to calculate hash need to be signed - contract signed data according to [EIP](https://eips.ethereum.org/EIPS/eip-191). ``` - keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createCredentialDefinition", id, schemaId, credDef)) + keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createCredentialDefinition", id, issuerId, schemaId, credDef)) // Arguments when calculating hash to validate // 1: byte(0x19) - the initial 0x19 byte // 2: byte(0) - the version byte // 3: address(this) - the validator address - // 4-8: Application specific data + // 4-9: Application specific data // identity - author account address // `createSchema` original contract method - added to be aligned with did:ethr contract // id - id of schema to be created + // issuerId - DID of Schema issuer // schemaId - id of schema - // credDef - credential definition as JSON string + // credDef - credential definition as JSON bytes ``` * Step 3: Performs EcDSA signing using his ethereum identity account keys * Step 4: Author passes Credential Definition and Signature to Endorser @@ -107,11 +172,11 @@ function createSchemaSigned( bytes32 sigR, bytes32 sigS bytes32 id, - bytes schema, - + string calldata issuerId, + bytes schema ) public virtual { // validate identity signature - bytes32 hash = keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createSchema", id, schema)); + bytes32 hash = keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createSchema", id, issuerId, schema)); checkSignature(identity, hash, sigV, sigR, sigS); // store schema @@ -124,11 +189,12 @@ function endorseCredentialDefinition( bytes32 sigR, bytes32 sigS, byets32 id, + string calldata issuerId, byets32 schemaId, byets credDef ) public virtual { // validate identity signature - bytes32 hash = keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createCredentialDefinition", id, schemaId, credDef)); + bytes32 hash = keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createCredentialDefinition", id, issuerId, schemaId, credDef)); checkSignature(identity, hash, sigV, sigR, sigS); // store credential definition @@ -142,7 +208,6 @@ function endorseCredentialDefinition( // Prepare schema endorsing bytes which need to be signed by an identity owner pub async fn build_create_schema_endorsing_data( client: &LedgerClient, - id: &SchemaId, schema: &Schema, ) -> VdrResult; @@ -150,7 +215,6 @@ pub async fn build_create_schema_endorsing_data( pub async fn build_create_schema_signed_transaction( client: &LedgerClient, sender: &Address, - id: &SchemaId, schema: &Schema, signature: &SignatureData, ) -> VdrResult; @@ -158,7 +222,6 @@ pub async fn build_create_schema_signed_transaction( // Prepare credential definition endorsing bytes which need to be signed by an identity owner pub async fn build_create_credential_definition_endorsing_data( client: &LedgerClient, - id: &CredentialDefinitionId, credential_definition: &CredentialDefinition, ) -> VdrResult; @@ -166,7 +229,6 @@ pub async fn build_create_credential_definition_endorsing_data( pub async fn build_create_credential_definition_signed_transaction( client: &LedgerClient, from: &Address, - id: &CredentialDefinitionId, credential_definition: &CredentialDefinition, signature: &SignatureData, ) -> VdrResult; diff --git a/docs/design/flow.png b/docs/design/flow.png index 7b26b8eb..47607d72 100644 Binary files a/docs/design/flow.png and b/docs/design/flow.png differ diff --git a/docs/design/flow.puml b/docs/design/flow.puml index d1592b68..b4a472a0 100644 --- a/docs/design/flow.puml +++ b/docs/design/flow.puml @@ -44,6 +44,14 @@ T->TV: Submit transaction TV->C: Send transaction C-->C: Execute RoleControl.assignRole contract +== Create Indy Did == + +E->EV: Build Did Document +E->EV: Build and sign transaction to create Did +E->EV: Submit transaction +EV->C: Send transaction +C-->C: Execute IndyDidRegistry.createDid contract + == Create Ethr Did == note across @@ -53,44 +61,46 @@ end note E->EV: Build and sign transaction to add DID attribute (Service) E->EV: Submit transaction EV->C: Send transaction -C-->C: Execute `EthrExtDidRegistry.setAttribute` contract +C-->C: Execute EthrExtDidRegistry.setAttribute contract + +== Endorse Indy Did == + +F->FV: Build Did Document +F->FV: Prepare author endorsement data +F->FW: EdDSA sign endorsement data bytes +F-->E: Pass Did Document, Signature +E->EV: Build and sign transaction to endorse Did +E->EV: Submit transaction +EV->C: Send transaction +C-->C: Execute IndyDidRegistry.createDidSigned contract == Endorse Ethr Did == note across - Not needed for creation as DID imply to be written by default - Required for adding of a resource + Not needed as DID imply to be written by default + Owner can add resource without endorsement need end note -F->FV: Build Service attribute -F->FV: Prepare endorsement data for setting attribute -F->FW: EdDSA sign endorsement data -F-->E: Pass Service attribute and Signature -E->EV: Build and sign transaction for setting signed attribute -E->EV: Submit transaction -EV->C: Send transaction -C-->C: Execute `EthrExtDidRegistry.setAttributeSigned` contract - -== Create Schema == +== Create Schema (any DID method) == E->EV: Build Schema E->EV: Build and sign transaction to create Schema E->EV: Submit transaction EV->C: Send transaction -C-->C: Execute `SchemaRegistry.createSchema` contract +C-->C: Execute SchemaRegistry.createSchema contract C-->C: Resolve and verify issuerDid ownership -== Endorse Schema == +== Endorse Schema (any DID method) == F->FV: Build Schema -F->FV: Prepare endorsement data for creating schema -F->FW: EdDSA sign endorsement data -F-->E: Pass Schema and Signature -E->EV: Build and sign transaction to creating signed schema +F->FV: Prepare author endorsement data +F->FW: EdDSA sign endorsement data bytes +F-->E: Pass Schema, Signature +E->EV: Build and sign transaction to endorse Schema E->EV: Submit transaction EV->C: Send transaction C-->C: Execute SchemaRegistry.createSchemaSigned contract -C-->C: Resolve and verify issuerId ownership +C-->C: Resolve and verify issuerDid ownership == == diff --git a/docs/design/indybesu-did-registry.md b/docs/design/indybesu-did-registry.md new file mode 100644 index 00000000..b0594cf8 --- /dev/null +++ b/docs/design/indybesu-did-registry.md @@ -0,0 +1,186 @@ +# Indy DID Registry + +## Storage format + +* DID Records collection: + * Description: Mapping holding the list of DID's to their DID Document and metadata. + * Format: + ``` + mapping(address identity => DidRecord didRecord); + + struct DidDocStorage { + bytes document; + DidMetadata metadata; + } + + struct DidMetadata { + address owner; + address sender; + uint256 created; + uint256 updated; + uint256 versionId; + bool deactivated; + } + ``` + * Example: + ``` + { + "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266": { + document: bytes(" + { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/ed25519-2020/v1" + ], + "id": "did:indybesu:0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "verificationMethod": [{ + "id": "did:indybesu:0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266#key-1", + "type": "Ed25519VerificationKey2020", + "controller": "did:indybesu:0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "publicKeyMultibase": "zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" + }], + "authentication": ["did:indybesu:0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266#key-1"], + } + "), + metadata: { + owner: 0x93917cadbace5dfce132b991732c6cda9bcc5b8a, + sender: 0x93917cadbace5dfce132b991732c6cda9bcc5b8a, + created: 1234, + updated: 1234, + versionId: 1234, + deactivated: false + }, + }, + ... + } + ``` + +### Types definition + +#### DidDocument + +DID Document must match to the [specification](https://www.w3.org/TR/did-core/). + +#### DID Document metadata + +Each DID Document MUST have a metadata section when a representation is produced. It can have the following properties: + +* owner (address): An address of DID owner +* sender (address): An address of DID Document sender +* created (timestamp): Time of a block ordered a transaction for DID Doc creation +* updated (timestamp): The updated field is null if an Update operation has never been performed on the DID document + Time of a block ordered a transaction changed a DID Doc last time +* versionId (number): Block number when DID was created or updated +* deactivated (string): If DID has been deactivated, DID document metadata MUST include this property with the boolean + value true. By default, this is set to false. + +## Transactions (Smart Contract's methods) + +Contract name: **IndyDidRegistry** + +### Create DID + +* Method: `createDid` + * Description: Transaction to create a new DID record (DID Document and corresponding DID Metadata) + * Parameters: + * `identity` - Address of DID owner + * `document` - DID Document JSON as bytes + * Restrictions: + * DID must not exist + * Valid DID must be provided + * Format: + ``` + IndyDidRegistry.createDid( + address identity, + bytes document + ) + ``` + * Example: + ``` + IndyDidRegistry.createDid( + "0xa9b7df62c953c4c49deebea05d3c8fee1f47c1f6", + "{ did document as json bytes }" + ) + ``` + * Raised Event: + * `DIDCreated(identity)` + +### Update DID + +* Method: `updateDid` + * Description: Transaction to update an existing DidDocStorage entry + * Parameters: + * `identity` - Address of DID owner + * `document` - DID Document JSON as bytes + * Restrictions: + * DID must exist + * DID must be active + * Sender must be authorized to perform update (owner or sender) + * Format: + ``` + IndyDidRegistry.updateDid( + address identity, + bytes calldata document + ) + ``` + * Example: + ``` + IndyDidRegistry.updatedDid( + "0xa9b7df62c953c4c49deebea05d3c8fee1f47c1f6" + "{ did document as json bytes }" + ) + ``` + * Raised Event: + * `DIDUpdated(identity)` + +### Deactivate DID + +* Method: `deactivateDid` + * Description: Transaction to deactivate an existing DID + * Parameters: + * `did` - Address of DID owner + * Restrictions: + * DID must exist + * DID must be active + * Sender must be authorized to perform deactivation (owner or sender) + * Format: + ``` + IndyDidRegistry.deactivateDid( + address identity + ) + ``` + * Example: + ``` + IndyDidRegistry.deactivateDid( + "0xa9b7df62c953c4c49deebea05d3c8fee1f47c1f6" + ) + ``` + * Raised Event: + * `DIDDeactivated(identity)` + +### Resolve DID Document with Meta + +* Method: `resolveDid` + * Description: Transaction to resolve DidDocStorage entry (DID Document and corresponding DID Doc Metadata) + * Parameters: + * `identity` - Address of the DID identity to be resolved + * Restrictions: + * DID must exist + * Format: + ``` + IndyDidRegistry.resolveDid( + address identity, + ) returns (DidRecord didRecord) + ``` + * Example: + ``` + IndyDidRegistry.resolveDid( + "0xa9b7df62c953c4c49deebea05d3c8fee1f47c1f6" + ) + ``` + * Raised Event: `None` + + + + + diff --git a/docs/design/legacy-identifiers-support.md b/docs/design/legacy-identifiers-support.md index 296569b8..74beccce 100644 --- a/docs/design/legacy-identifiers-support.md +++ b/docs/design/legacy-identifiers-support.md @@ -1,14 +1,14 @@ ## Legacy identifiers support The idea is using of a basic mapping between legacy DIDs identifiers and ethereum accounts instead of introducing a new -`did:indy2` DID method. +`did:indybesu` DID method. So that legacy DID can be associated with a new `did:ethr` and we can only use `did:ethr` in the network. * Create a new `LegacyIdMappingRegistry` smart contract which will be holding mapping of legacy identifiers to ethereum accounts/new ids: ``` contract LegacyIdMappingRegistry { // did:sov: -> ethr account address - mapping(string => address) public didMappings; + mapping(string => string) public didMappings; // legacy formated ids of schemas and cred defs -> new id mapping(string => string) public clMappings; @@ -69,3 +69,4 @@ So that legacy DID can be associated with a new `did:ethr` and we can only use ` * for Schema/Credential Definition firstly must resolve new identifier using `LegacyIdMappingRegistry.clMappings(identifier)`, and next resolve Schema/Credential Definition as it described in the corresponding specification. + diff --git a/docs/design/vdr.md b/docs/design/vdr.md index fd433017..49e0dce4 100644 --- a/docs/design/vdr.md +++ b/docs/design/vdr.md @@ -44,7 +44,7 @@ enum Status { } impl LedgerClient { - /// Create indy2 client interacting with ledger + /// Create indybesu client interacting with ledger /// /// # Params /// - `chain_id` - chain id of network (chain ID is part of the transaction signing process to protect against transaction replay attack) @@ -272,6 +272,99 @@ struct SignatureData { ## Contracts/Requests methods +### DID IndyBesu + +#### Writes + +```rust +/// Prepare transaction executing `DidRegistry.createDid` smart contract method to create a new DID on the Ledger +/// +/// #Params +/// param: client: LedgerClient - Ledger client +/// param: from: string - sender account address +/// param: did: string - DID to create +/// param: did_document: DidDocument - DID Document matching to the specification: https://www.w3.org/TR/did-core/ +/// +/// #Returns +/// transaction: Transaction - prepared transaction object +fn indy_vdr_build_create_did_transaction( + client: LedgerClient, + from: String, + did: String, + did_document: DidDoc, +) -> Transaction { + unimplemented!(); +} +``` + +```rust +/// Prepare transaction executing `DidRegistry.updateDid` smart contract method to update an existing DID Document +/// +/// #Params +/// param: client: LedgerClient - Ledger client +/// param: from: string - sender account address +/// param: did: string - DID to update +/// param: did_document: DidDocument - DID Document matching to the specification: https://www.w3.org/TR/did-core/ +/// +/// #Returns +/// transaction: Transaction - prepared transaction object +fn indy_vdr_build_update_did_transaction( + client: LedgerClient, + from: String, + did: String, + did_document: DidDoc, +) -> Transaction; +``` + +```rust +/// Prepare transaction executing `DidRegistry.deactivateDid` smart contract method to deactivate an existing DID +/// +/// #Params +/// param: client: LedgerClient - Ledger client +/// param: from: string - sender account address +/// param: did: string - did to deactivate +/// +/// #Returns +/// transaction: Transaction - prepared transaction object +fn indy_vdr_build_deactivate_did_transaction( + client: LedgerClient, + from: String, + did: String, +) -> Transaction; +``` + +#### Resolve + +```rust +/// Prepare transaction executing `DidRegistry.resolveDid` smart contract method to resolve a DID +/// +/// #Params +/// param: client: Ledger - client (Ethereum client - for example web3::Http) +/// param: did - DID to resolve +/// +/// #Returns +/// transaction: Transaction - prepared transaction object +fn indy_vdr_build_resolve_did_transaction( + client: LedgerClient, + did: String, +) -> Transaction; +``` + +```rust +/// Parse response for of `DidRegistry.resolveDid` smart contract +/// +/// #Params +/// param: client: Ledger - client (Ethereum client - for example web3::Http) +/// param: response: bytes - received response +/// +/// #Returns +/// transaction: Transaction - prepared transaction object +fn indy_vdr_parse_resolve_did_response( + client: LedgerClient, + response: bytes, +) -> DidDocumentWithMeta; +``` + ### DID Ethr #### Writes @@ -726,7 +819,11 @@ pub fn parse_did_owner_changed_event_response( /// # Returns /// Parsed DID event object pub fn parse_did_event_response(client: &LedgerClient, event: &EventLog) -> VdrResult; +``` + +### Resolve DID +```rust /// Single step function to resolve a DidDocument with metadata for the given DID /// /// # Params @@ -743,7 +840,6 @@ pub async fn resolve_did( ) -> VdrResult ``` - ### Schema #### Create Schema @@ -754,123 +850,62 @@ pub async fn resolve_did( /// # Params /// - `client` client connected to the network where contract will be executed /// - `from` transaction sender account address -/// - `id` id of schema to be created /// - `schema` Schema object matching to the specification - https://hyperledger.github.io/anoncreds-spec/#term:schema /// -/// # Returns -/// Write transaction to sign and submit -pub async fn build_create_schema_transaction( - client: &LedgerClient, - from: &Address, - id: &SchemaId, - schema: &Schema, -) -> VdrResult; - -/// Prepared data for execution of SchemaRegistry.createSchema contract method to endorse a new Schema -/// -/// #Params -/// - `client` client connected to the network where contract will be executed -/// - `id` id of schema to be created -/// - `schema` Schema object matching to the specification - https://hyperledger.github.io/anoncreds-spec/#term:schema -/// /// #Returns -/// data: TransactionEndorsingData - transaction endorsement data to sign -pub async fn build_create_schema_endorsing_data( - client: &LedgerClient, - id: &SchemaId, - schema: &Schema, -) -> VdrResult; - -/// Build transaction to execute SchemaRegistry.createSchemaSigned contract method to -/// endorse a new Schema -/// Endorsing version of the method - sender is not identity owner -/// -/// #Params -/// - `client` client connected to the network where contract will be executed -/// - `id` id of schema to be created -/// - `schema` Schema object matching to the specification - https://hyperledger.github.io/anoncreds-spec/#term:schema -/// - `signature` signature of schema issuer -/// -/// #Returns -/// transaction: Transaction - prepared write transaction object to sign and submit -pub async fn build_create_schema_signed_transaction( - client: &LedgerClient, - sender: &Address, - id: &SchemaId, - schema: &Schema, - signature: &SignatureData, -) -> VdrResult +/// transaction: Transaction - prepared transaction object +fn indy_vdr_build_create_schema_transaction( + client: LedgerClient, + from: String, + schema: Schema, +) -> Transaction; ``` #### Resolve Schema ```rust -/// Build transaction to execute SchemaRegistry.schemasCreated contract method to get -/// block number when Schema was created +/// Prepare transaction executing `SchemaRegistry.resolveSchema` smart contract method /// /// #Params -/// - `client` client connected to the network where contract will be executed -/// - `id` identifier of target schema -/// -/// #Returns -/// transaction: Transaction - prepared read transaction object to submit -pub async fn build_get_schema_created_transaction( - client: &LedgerClient, - id: &SchemaId, -) -> VdrResult; - -/// Build event query to get SchemaRegistry.SchemaCreated event from the ledger -/// -/// #Params -/// - `client` client connected to the network where contract will be executed -/// - `id` identifier of target schema -/// - `from_block` start block -/// - `to_block` finish block +/// param: client: Ledger - client (Ethereum client - for example web3::Http) +/// param: id - id of Schema to resolve /// /// #Returns -/// query: EventQuery - prepared event query to send -#[logfn(Ifo)] -pub async fn build_get_schema_query( - client: &LedgerClient, - id: &SchemaId, - from_block: Option<&Block>, - to_block: Option<&Block>, -) -> VdrResult +/// transaction: Transaction - prepared transaction object +fn indy_vdr_build_resolve_schema_transaction( + client: LedgerClient, + id: String, +) -> Transaction; ``` ```rust -/// Parse the result of execution SchemaRegistry.schemas contract method to receive -/// block number when a schema was created -/// -/// # Params -/// - `client` client connected to the network where contract will be executed -/// - `bytes` result bytes returned from the ledger -/// -/// # Returns -/// Block when the schema was created -pub fn parse_schema_created_result(client: &LedgerClient, bytes: &[u8]) -> VdrResult; - -/// Parse SchemaRegistry.SchemaCreated from the event log. +/// Parse response for of `SchemaRegistry.resolveSchema` smart contract /// -/// # Params -/// - `client` client connected to the network where contract will be executed -/// - `bytes` result bytes returned from the ledger +/// #Params +/// param: client: Ledger - client (Ethereum client - for example web3::Http) +/// param: response: bytes - received response bytes /// -/// # Returns -/// Parsed Schema object -pub fn parse_schema_created_event(client: &LedgerClient, log: &EventLog) -> VdrResult +/// #Returns +/// transaction: Transaction - prepared transaction object +fn indy_vdr_parse_resolve_schema_response( + client: LedgerClient, + response: bytes, +) -> SchemaWithMeta; ``` ```rust -/// Single step function to resolve a Schema for the given ID +/// Single step function to resolve schema from the ledger /// -/// # Params -/// - `client` client connected to the network where contract will be executed -/// - `id` id of schema to resolve +/// #Params +/// param: client: Ledger - client (Ethereum client - for example web3::Http) +/// param: id - id of Schema to resolve /// -/// # Returns -/// Resolved Schema object -pub async fn resolve_schema(client: &LedgerClient, id: &SchemaId) -> VdrResult; +/// #Returns +/// transaction: Transaction - prepared transaction object +fn indy_vdr_resolve_schema( + client: LedgerClient, + id: String, +) -> Schema; ``` ### Credential Definition @@ -878,128 +913,71 @@ pub async fn resolve_schema(client: &LedgerClient, id: &SchemaId) -> VdrResult VdrResult; - -/// Prepared data for endorsing CredentialDefinitionRegistry.createCredentialDefinition contract method -/// -/// #Params -/// - `client` client connected to the network where contract will be executed -/// - `id` id of credential definition to be created -/// - `credential_definition` Credential Definition object matching to the specification - https://hyperledger.github.io/anoncreds-spec/#term:credential-definition -/// -/// #Returns -/// data: TransactionEndorsingData - transaction endorsement data to sign -pub async fn build_create_credential_definition_endorsing_data( - client: &LedgerClient, - id: &CredentialDefinitionId, - credential_definition: &CredentialDefinition, -) -> VdrResult; - -/// Build transaction to execute CredentialDefinitionRegistry.createCredentialDefinitionSigned contract method to -/// endorse a new Credential Definition -/// Endorsing version of the method - sender is not identity owner +/// Prepare transaction executing CredentialDefinitionRegistry.createCredentialDefinition smart contract method /// /// #Params -/// - `client` client connected to the network where contract will be executed -/// - `id` id of credential definition to be created -/// - `credential_definition` Credential Definition object matching to the specification - https://hyperledger.github.io/anoncreds-spec/#term:credential-definition -/// - `signature` signature of schema issuer +/// param: client: Ledger - client (Ethereum client - for example web3::Http) +/// param: from: string - sender account address +/// param: cred_def - Credential Definition object matching to the specification - https://hyperledger.github.io/anoncreds-spec/#term:credential-definition +/// param: options: Option - (Optional) extra data required for transaction preparation /// /// #Returns -/// transaction: Transaction - prepared write transaction object to sign and submit -pub async fn build_create_credential_definition_signed_transaction( - client: &LedgerClient, - from: &Address, - id: &CredentialDefinitionId, - credential_definition: &CredentialDefinition, - signature: &SignatureData, -) -> VdrResult +/// transaction: Transaction - prepared transaction object +fn indy_vdr_build_create_credential_definition_transaction( + client: LedgerClient, + from: String, + cred_def: CredentialDefinition, + options: Option, +) -> Transaction; ``` #### Resolve Credential DefinitionCredential Definition ```rust -/// Build transaction to execute CredentialDefinitionRegistry.credDefs contract method to get -/// block number when a Credential Definition was created +/// Prepare transaction executing CredentialDefinitionRegistry.resolveCredentialDefinition smart contract method /// /// #Params -/// - `client` client connected to the network where contract will be executed -/// - `id` identifier of target credential definition -/// -/// #Returns -/// transaction: Transaction - prepared read transaction object to submit -pub async fn build_get_credential_definition_created_transaction( - client: &LedgerClient, - id: &CredentialDefinitionId, -) -> VdrResult; - -/// Build event query to get CredentialDefinitionRegistry.CredentialDefinitionCreated event from the ledger -/// -/// #Params -/// - `client` client connected to the network where contract will be executed -/// - `id` identifier of target credential definition -/// - `from_block` start block -/// - `to_block` finish block +/// param: client: Ledger - client (Ethereum client - for example web3::Http) +/// param: id - id of Credential Definition to resolve +/// param: options: Option - (Optional) extra data required for transaction preparation /// /// #Returns -/// query: EventQuery - prepared event query to send -pub async fn build_get_credential_definition_query( - client: &LedgerClient, - id: &CredentialDefinitionId, - from_block: Option<&Block>, - to_block: Option<&Block>, -) -> VdrResult +/// transaction: Transaction - prepared transaction object +fn indy_vdr_build_resolve_credential_definition_transaction( + client: LedgerClient, + id: String, + options: Option, +) -> Transaction; ``` ```rust -/// Parse the result of execution CredentialDefinitionRegistry.credDefs contract method to receive -/// block number when a credential definition was created +/// Parse response for of `CredentialDefinitionRegistry.resolveCredentialDefinition` smart contract /// -/// # Params -/// - `client` client connected to the network where contract will be executed -/// - `bytes` result bytes returned from the ledger -/// -/// # Returns -/// Block when the credential definition was created -pub fn parse_credential_definition_created_result(client: &LedgerClient, bytes: &[u8]) -> VdrResult; - -/// Parse CredentialDefinitionRegistry.CredentialDefinitionCreated from the event log. -/// -/// # Params -/// - `client` client connected to the network where contract will be executed -/// - `bytes` result bytes returned from the ledger +/// #Params +/// param: client: Ledger - client (Ethereum client - for example web3::Http) +/// param: response: bytes - received response bytes /// -/// # Returns -/// Parsed Credential Definition event object -pub fn parse_credential_definition_created_event(client: &LedgerClient, log: &EventLog) -> VdrResult +/// #Returns +/// transaction: Transaction - prepared transaction object +fn indy_vdr_parse_resolve_credential_definition_response( + client: LedgerClient, + response: bytes, +) -> CredentialDefinitionWithMeta; ``` ```rust -/// Single step function to resolve a Credential Definition for the given ID +/// Single step function to resolve credential definition from the ledger /// -/// # Params -/// - `client` client connected to the network where contract will be executed -/// - `id` id of schema to resolve +/// #Params +/// param: client: Ledger - client (Ethereum client - for example web3::Http) +/// param: id - id of Credential Definition to resolve /// -/// # Returns -/// Resolved Credential Definition object -pub async fn resolve_credential_definition(client: &LedgerClient, id: &CredentialDefinitionId) -> VdrResult; +/// #Returns +/// transaction: Transaction - prepared transaction object +fn indy_vdr_resolve_credential_definition( + client: LedgerClient, + id: String, +) -> CredentialDefinition; ``` ### Auth @@ -1165,3 +1143,218 @@ struct ValidatorList { validators: Vec } ``` + +### DID Ethr + +#### Writes + +```rust +/// Change owner of ethr DID +/// +/// #Params +/// param: client: Ledger - client (Ethereum client - for example web3::Http) +/// param: from: string - sender account address +/// param: did: string - DID to change ownership +/// param: new_owner: string - account addres sof new owner +/// +/// #Returns +/// transaction: Transaction - prepared transaction object +pub async fn build_did_change_owner_transaction( + client: &LedgerClient, + from: &Address, + did: &DID, + new_owner: &Address, +) -> VdrResult; + +/// Endorsing version of method to change owner for ethr DID +pub async fn build_did_change_owner_signed_transaction( + client: &LedgerClient, + from: &Address, + did: &DID, + new_owner: &Address, + signature: &Signature, +) -> VdrResult; + +/// An identity can assign multiple delegates to manage signing on their behalf for specific purposes. +/// Function to add a new delegate for a DID +/// +/// #Params +/// param: client: Ledger - client (Ethereum client - for example web3::Http) +/// param: from: string - sender account address +/// param: did: string - DID to add delegate +/// param: delegate_type: string - type of delegation +/// param: delegate: string - account address of delegate +/// param: validity: Option - delegate validity time +/// +/// #Returns +/// transaction: Transaction - prepared transaction object +pub async fn build_did_add_delegate_transaction( + client: &LedgerClient, + from: &Address, + did: &DID, + delegate_type: &DelegateType, + delegate: &Address, + validity: Option, +) -> VdrResult; + +/// Endorsing version of method to add a delegate for ethr DID +pub async fn build_did_add_delegate_signed_transaction( + client: &LedgerClient, + from: &Address, + did: &DID, + delegate_type: &DelegateType, + delegate: &Address, + validity: Option, + signature: &Signature, +) -> VdrResult; + +/// An identity can assign multiple delegates to manage signing on their behalf for specific purposes. +/// Function to remove a delegate for a DID +/// +/// #Params +/// param: client: Ledger - client (Ethereum client - for example web3::Http) +/// param: from: string - sender account address +/// param: did: string - DID to remove delegate +/// param: delegate_type: string - type of delegation +/// param: delegate: number - account address of delegate +/// +/// #Returns +/// transaction: Transaction - prepared transaction object +pub async fn build_did_revoke_delegate_transaction( + client: &LedgerClient, + from: &Address, + did: &DID, + delegate_type: &DelegateType, + delegate: &Address, +) -> VdrResult; + +/// Endorsing version of method to remove a delegate for ethr DID +pub async fn build_did_revoke_delegate_signed_transaction( + client: &LedgerClient, + from: &Address, + did: &DID, + delegate_type: &DelegateType, + delegate: &Address, + signature: &Signature, +) -> VdrResult; + +/// An identity may need to publish some information that is only needed off-chain but still requires the security benefits of using a blockchain. +/// Function to add an attribute associated with the DID +/// +/// #Params +/// param: client: Ledger - client (Ethereum client - for example web3::Http) +/// param: from: string - sender account address +/// param: did: string - DID to add attribute +/// param: attribute: DidDocAttribute - attribute to add +/// param: validity: Option - attribute validity time +/// +/// #Returns +/// transaction: Transaction - prepared transaction object +pub async fn build_did_set_attribute_transaction( + client: &LedgerClient, + from: &Address, + did: &DID, + attribute: &DidDocAttribute, + validity: Option, +) -> VdrResult; + +/// Endorsing version of method to add an attribute for ethr DID +pub async fn build_did_set_attribute_signed_transaction( + client: &LedgerClient, + from: &Address, + did: &DID, + attribute: &DidDocAttribute, + validity: Option, + signature: &Signature, +) -> VdrResult; + +/// An identity may need to publish some information that is only needed off-chain but still requires the security benefits of using a blockchain. +/// Function to remove an attribute associated with the DID +/// +/// #Params +/// param: client: Ledger - client (Ethereum client - for example web3::Http) +/// param: from: string - sender account address +/// param: did: string - DID to add attribute +/// param: attribute: DidDocAttribute - attribute to add +/// param: validity: Option - attribute validity time +/// +/// #Returns +/// transaction: Transaction - prepared transaction object +pub async fn build_did_revoke_attribute_transaction( + client: &LedgerClient, + _from: &Address, + did: &DID, + attribute: &DidDocAttribute, +) -> VdrResult; + +/// Endorsing version of method to remove an attribute for ethr DID +pub async fn build_did_revoke_attribute_signed_transaction( + client: &LedgerClient, + from: &Address, + _did: &DID, + attribute: &DidDocAttribute, + signature: &Signature, +) -> VdrResult; +``` + +#### Resolve + +```rust +/// Build a transaction to query a block when a DID was changed lst time. +/// +/// #Params +/// param: client: Ledger - client (Ethereum client - for example web3::Http) +/// param: did: string - DID to get the chnaged block number +/// +/// #Returns +/// transaction: Transaction - prepared transaction object +pub async fn build_did_changed_transaction( + client: &LedgerClient, + did: &DID, +) -> VdrResult; + +/// Parse response of `EthrDidRegistry.changed` smart contract +/// +/// #Params +/// param: client: Ledger - client (Ethereum client - for example web3::Http) +/// param: response: bytes - received response +/// +/// #Returns +/// block - block number when an identity was changed last time (0 - mean that identity has never been changed) +pub fn parse_did_changed_result(client: &LedgerClient, bytes: &[u8]) -> VdrResult; + +/// Build an query to retrieve log events raised for the given DID +/// +/// #Params +/// param: client: Ledger - client (Ethereum client - for example web3::Http) +/// param: did: string - DID to query log events +/// param: block: Option - Specific block number to retrieve events +/// +/// #Returns +/// query: EventQuery - prepared event query to submit +pub async fn build_get_did_event_query( + client: &LedgerClient, + did: &DID, + block: Option<&Block>, +) -> VdrResult; + +/// Parse log response of query for DID events +/// +/// #Params +/// param: client: Ledger - client (Ethereum client - for example web3::Http) +/// param: log: RawLog - received log events +/// +/// #Returns +/// events - parsed events raised for the DID +pub fn parse_did_event_response(client: &LedgerClient, log: &RawLog) -> VdrResult; + +/// Single step function to resolve DID DDocument for teh given DID +/// +/// #Params +/// param: client: Ledger - client (Ethereum client - for example web3::Http) +/// param: did: string - DID to get a DID Document +/// +/// #Returns +/// DidDocument - Received DID DDocument +pub async fn resolve_did(client: &LedgerClient, did: &DID) -> VdrResult; +``` diff --git a/docs/migration/migration.md b/docs/migration/migration.md index 054a0edd..3bb7d53a 100644 --- a/docs/migration/migration.md +++ b/docs/migration/migration.md @@ -9,13 +9,13 @@ All Issuers need to run migration by itself to move their data (DID Document, Sc ## Step by step Indy based applications migration flow This section provides example steps demonstrating the process of migration for applications using Indy ledger to Besu Ledger. -The parties involved into the flow: +The parties involved into the flow: * Trustee - publish Issuer DID on the Ledger - * Write data to Ledger + * Write data to Ledger * Issuer - publish DID, Schema, and Credential Definition on the Ledger + Issue Credential for a Holder - * Write data to Ledger + * Write data to Ledger * Holder - accept Credential and share Proof - * Read data from the Ledger + * Read data from the Ledger * Verifier - request Proof from a Holder * Read data from the Ledger @@ -35,7 +35,7 @@ At this point, all parties acts as usual and use Indy Ledger as a verifiable dat } ``` 3. Issuer publish Service Endpoint to Indy Ledger using ATTRIB - > According to [indy did method specification](https://hyperledger.github.io/indy-did-method/) data published as NYM and ATTRIB transactions should be used to construct DID Document + > According to [indy did method specification](https://hyperledger.github.io/indy-did-method/) data published as NYM and ATTRIB transactions should be used to construct DID Document 4. Issuer create and publish Credential Schema to Indy Ledger using SCHEMA ``` { @@ -75,51 +75,51 @@ At this point, all parties acts as usual and use Indy Ledger as a verifiable dat ### Migration -At some point company managing (Issuer,Holder,Verifier) decide to migrate from Indy to Besu Ledger. +At some point company managing (Issuer,Holder,Verifier) decide to migrate from Indy to Besu Ledger. In order to do that, their Issuer's applications need to publish their data to Besu Ledger. Issuer need to run migration tool manually (on the machine containing Indy Wallet storing Credential Definitions) which migrate data. -* Issuer: - * All issuer applications need run migration tool manually (on the machine containing Indy Wallet with Keys and Credential Definitions) in order to move data to Besu Ledger properly. The migration process consist of multiple steps which will be described later. - * After the data migration, issuer services should issue new credentials using Besu ledger. -* Holder: - * Holder applications can keep stored credentials as is. There is no need to run migration for credentials which already stored in the wallet. - * Holder applications should start using Besu ledger to resolve Schemas and Credential Definition once Issuer completed migration. +* Issuer: + * All issuer applications need run migration tool manually (on the machine containing Indy Wallet with Keys and Credential Definitions) in order to move data to Besu Ledger properly. The migration process consist of multiple steps which will be described later. + * After the data migration, issuer services should issue new credentials using Besu ledger. +* Holder: + * Holder applications can keep stored credentials as is. There is no need to run migration for credentials which already stored in the wallet. + * Holder applications should start using Besu ledger to resolve Schemas and Credential Definition once Issuer completed migration. * Verifier: - * Verifier applications should start using Besu ledger to resolve Schemas and Credential Definition once Issuer completed migration. - * Verifier applications should keep using old styled restriction in order to request credentials which were received before the migration. + * Verifier applications should start using Besu ledger to resolve Schemas and Credential Definition once Issuer completed migration. + * Verifier applications should keep using old styled restriction in order to request credentials which were received before the migration. -> * Question: Should it be an extra library working with both ledger or application should combine usage of indy and besu clients? +> * Question: Should it be an extra library working with both ledger or application should combine usage of indy and besu clients? > * Besu vdr can provide a feature module including migration helpers. > * Applications still need to use indy client and besu client. 1. Wallet and Client setup - 1. All applications need to integrate Besu vdr library + 1. All applications need to integrate Besu vdr library ``` let signer = BasicSigner::new(); let client = LedgerClient::new(CHAIN_ID, NODE_ADDRESS, contracts, signer); ``` - * `CHAIN_ID` - chain id of network (chain ID is part of the transaction signing process to protect against transaction replay attack) - * `NODE_ADDRESS` - an address of node to connect for sending transactions - * `contracts` - specifications for contracts deployed on the network - * `signer` - transactions signer + * `CHAIN_ID` - chain id of network (chain ID is part of the transaction signing process to protect against transaction replay attack) + * `NODE_ADDRESS` - an address of node to connect for sending transactions + * `contracts` - specifications for contracts deployed on the network + * `signer` - transactions signer 2. DID ownership moving to Besu Ledger: 1. Issuer create Ed25518 key (with seed) in the Besu wallet 2. Issuer create a new Secp256k1 keypair in Besu wallet 3. Issuer publish Secp256k1 key to Indy ledger using ATTRIB transaction: `{ "besu": { "key": secp256k1_key } }` - * Now Besu Secp256k1 key is associated with the Issuer DID which is published on the Indy Ledger. - * ATTRIB transaction is signed with Ed25518 key. No signature request for `secp256k1_key`. + * Now Besu Secp256k1 key is associated with the Issuer DID which is published on the Indy Ledger. + * ATTRIB transaction is signed with Ed25518 key. No signature request for `secp256k1_key`. 3. Issuer build DID Document which will include: * DID - fully qualified form should be used: `did:besu:network:` of DID which was published as NYM transaction to Indy Ledger * Two Verification Methods must be included: * `Ed25519VerificationKey2018` key published as NYM transaction to Indy Ledger - * Key must be represented in multibase as base58 form was deprecated + * Key must be represented in multibase as base58 form was deprecated * `EcdsaSecp256k1VerificationKey2019` key published as ATTRIB transaction to Indy Ledger - * Key must be represented in multibase - * This key will be used in future to sign transactions sending to Besu ledger - * Transaction signature proves ownership of the key - * Besu account will be derived from the public key part + * Key must be represented in multibase + * This key will be used in future to sign transactions sending to Besu ledger + * Transaction signature proves ownership of the key + * Besu account will be derived from the public key part * Two corresponding authentication methods must be included. * Service including endpoint which was published as ATTRIB transaction to Indy Ledger 4. Issuer publish DID Document to Besu ledger: @@ -127,12 +127,12 @@ Issuer need to run migration tool manually (on the machine containing Indy Walle let did_doc = build_did_doc(&issuer.did, &issuer.edkey, &issuer.secpkey, &issuer.service); let receipt = DidRegistry::create_did(&client, &did_document).await ``` - * Transaction is signed using Secp256k1 key `EcdsaSecp256k1VerificationKey2019`. - * This key is also included into Did Document associated with DID. - * Transaction level signature validated by the ledger that proves key ownership. + * Transaction is signed using Secp256k1 key `EcdsaSecp256k1VerificationKey2019`. + * This key is also included into Did Document associated with DID. + * Transaction level signature validated by the ledger that proves key ownership. * `Ed25519VerificationKey2018` - Besu ledger will not require signature for proving ownership this key. - * key just stored as part of DID Document and is not validated - * potentially, we can add verification through the passing an additional signature + * key just stored as part of DID Document and is not validated + * potentially, we can add verification through the passing an additional signature ``` { context: "https://www.w3.org/ns/did/v1", @@ -174,7 +174,7 @@ Issuer need to run migration tool manually (on the machine containing Indy Walle let schema = Schema::from_indy_format(&indy_schema); let receipt = SchemaRegistry::create_schema(client, &issuer.account, &schema).await ``` - * Migration tool will provide a helper method to convert Schema. + * Migration tool will provide a helper method to convert Schema. ``` { id: "did:indy:testnet:KWdimUkZrdHURBkQsWv12r/anoncreds/v0/SCHEMA/test_credential/1.0.0", @@ -218,7 +218,7 @@ Now credential issuance and credential verification flow can run as before but w let schema_id = SchemaId::from_indy_format(&indy_schema_id); let schema = SchemaRegistry::resolve_schema(&client, &schema_id).await ``` - * Migration tool will provide helper to convert old style indy schema id into new format + * Migration tool will provide helper to convert old style indy schema id into new format 2. Holder resolve Credential Definition from Besu Ledger (VDR converts indy cred definition id representation into Besu form) ``` let cred_def_id = CredentialDefinitionId::from_indy_format(cred_def_id); @@ -232,7 +232,7 @@ Now credential issuance and credential verification flow can run as before but w let schema_id = SchemaId::from_indy_format(&indy_schema_id); let schema = SchemaRegistry::resolve_schema(&client, &schema_id).await ``` - * Schema id must be converted as well because proof will contain old style ids + * Schema id must be converted as well because proof will contain old style ids 2. Holder resolve Credential Definition from Besu Ledger (VDR converts indy cred definition id representation into Besu form) ``` let cred_def_id = CredentialDefinitionId::from_indy_format(cred_def_id); diff --git a/network/config/besu/genesis.json b/network/config/besu/genesis.json index 29c74459..1fc54b85 100644 --- a/network/config/besu/genesis.json +++ b/network/config/besu/genesis.json @@ -153,11 +153,27 @@ "balance": "0", "code": "0x6080604052600436106100705760003560e01c80637e5465ba1161004e5780637e5465ba146100d2578063ad3cb1cc146100f2578063c4d66de814610130578063e8f158641461015057600080fd5b80634f1ef2861461007557806352d1902d1461008a578063574a81d7146100b2575b600080fd5b610088610083366004610c59565b610170565b005b34801561009657600080fd5b5061009f61018f565b6040519081526020015b60405180910390f35b3480156100be57600080fd5b506100886100cd366004610d1b565b6101ac565b3480156100de57600080fd5b506100886100ed366004610d1b565b6101d3565b3480156100fe57600080fd5b50610123604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100a99190610d72565b34801561013c57600080fd5b5061008861014b366004610da5565b610475565b34801561015c57600080fd5b5061008861016b366004610d1b565b610565565b610178610791565b61018182610838565b61018b8282610845565b5050565b6000610199610902565b50600080516020610f6083398151915290565b6101b6828261094b565b61018b57604051638af69cf160e01b815260040160405180910390fd5b600054604051634f4bdc7b60e11b81526001600160a01b0390911690639e97b8f690610206906001903390600401610de2565b602060405180830381865afa158015610223573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102479190610e08565b61026b5760405163472511eb60e11b81523360048201526024015b60405180910390fd5b6001600160a01b0380831660009081526001602090815260408083209385168352929052908120600201548391839190036102cc57604051633af3b55760e01b81526001600160a01b03808416600483015282166024820152604401610262565b6001600160a01b0380851660009081526001602090815260408083209387168352928152828220338352905220548490849060ff1615610332576040516316d5788b60e31b81526001600160a01b03808416600483015282166024820152604401610262565b6001600160a01b038087166000908152600160208181526040808420948a16808552858352818520338652808452918520805460ff191685179055845293905291909101805463ffffffff169161038883610e40565b91906101000a81548163ffffffff021916908363ffffffff16021790555050336001600160a01b0316856001600160a01b0316876001600160a01b03167fc42e62d9f6b29d37599fcb472a6f30bc6e8c8d6fbbcb774ac585c02b314bd2ad60405160405180910390a46103fb868661094b565b1561046d576040805163278f794360e11b81526001600160a01b03878116600483015260248201929092526000604482015290871690634f1ef28690606401600060405180830381600087803b15801561045457600080fd5b505af1158015610468573d6000803e3d6000fd5b505050505b505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460019190600160401b900460ff16806104bf5750805467ffffffffffffffff808416911610155b156104dd5760405163f92ee8a960e01b815260040160405180910390fd5b8054600160401b67ffffffffffffffff841668ffffffffffffffffff199092168217178255600080546001600160a01b0319166001600160a01b038616179055815468ff0000000000000000191682556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a1505050565b600054604051634f4bdc7b60e11b81526001600160a01b0390911690639e97b8f690610598906001903390600401610de2565b602060405180830381865afa1580156105b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d99190610e08565b6105f85760405163472511eb60e11b8152336004820152602401610262565b80806001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610653575060408051601f3d908101601f1916820190925261065091810190610e63565b60015b61067b57604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610262565b600080516020610f6083398151915281146106ac57604051632a87526960e21b815260048101829052602401610262565b6001600160a01b03808516600090815260016020908152604080832093871683529290522060020154849084901561070a57604051634cc571cf60e01b81526001600160a01b03808416600483015282166024820152604401610262565b6001600160a01b038681166000818152600160208181526040808420958b16808552959091528083209182018054640100000000600160c01b031916336401000000008102919091179091554260029093019290925551909392917fe33956f8d60ae2b38d9860e46ec9b53d8fb58aa99a9404b1195b7ce35d2941dc91a45050505b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061081857507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661080c600080516020610f60833981519152546001600160a01b031690565b6001600160a01b031614155b156108365760405163703e46dd60e11b815260040160405180910390fd5b565b61084230826101ac565b50565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561089f575060408051601f3d908101601f1916820190925261089c91810190610e63565b60015b6108c757604051634c9c8ce360e01b81526001600160a01b0383166004820152602401610262565b600080516020610f6083398151915281146108f857604051632a87526960e21b815260048101829052602401610262565b61078c8383610a28565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146108365760405163703e46dd60e11b815260040160405180910390fd5b60008054604051636814b8e560e11b815282916001600160a01b03169063d02971ca9061097d90600190600401610e7c565b602060405180830381865afa15801561099a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109be9190610e8a565b6001600160a01b03808616600090815260016020818152604080842094891684529390529181209091015491925063ffffffff90911690610a0a610a03846006610eb0565b600a610a7e565b90508063ffffffff168263ffffffff16101593505050505b92915050565b610a3182610aa8565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115610a765761078c8282610b0d565b61018b610b83565b600081610a8c600185610ed8565b610a969190610ef5565b610aa1906001610f26565b9392505050565b806001600160a01b03163b600003610ade57604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610262565b600080516020610f6083398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b031684604051610b2a9190610f43565b600060405180830381855af49150503d8060008114610b65576040519150601f19603f3d011682016040523d82523d6000602084013e610b6a565b606091505b5091509150610b7a858383610ba2565b95945050505050565b34156108365760405163b398979f60e01b815260040160405180910390fd5b606082610bb757610bb282610bfe565b610aa1565b8151158015610bce57506001600160a01b0384163b155b15610bf757604051639996b31560e01b81526001600160a01b0385166004820152602401610262565b5092915050565b805115610c0e5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b0381168114610c3e57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060408385031215610c6c57600080fd5b610c7583610c27565b9150602083013567ffffffffffffffff80821115610c9257600080fd5b818501915085601f830112610ca657600080fd5b813581811115610cb857610cb8610c43565b604051601f8201601f19908116603f01168101908382118183101715610ce057610ce0610c43565b81604052828152886020848701011115610cf957600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60008060408385031215610d2e57600080fd5b610d3783610c27565b9150610d4560208401610c27565b90509250929050565b60005b83811015610d69578181015183820152602001610d51565b50506000910152565b6020815260008251806020840152610d91816040850160208701610d4e565b601f01601f19169190910160400192915050565b600060208284031215610db757600080fd5b610aa182610c27565b60048110610dde57634e487b7160e01b600052602160045260246000fd5b9052565b60408101610df08285610dc0565b6001600160a01b039290921660209190910152919050565b600060208284031215610e1a57600080fd5b81518015158114610aa157600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff808316818103610e5957610e59610e2a565b6001019392505050565b600060208284031215610e7557600080fd5b5051919050565b60208101610a228284610dc0565b600060208284031215610e9c57600080fd5b815163ffffffff81168114610aa157600080fd5b63ffffffff818116838216028082169190828114610ed057610ed0610e2a565b505092915050565b63ffffffff828116828216039080821115610bf757610bf7610e2a565b600063ffffffff80841680610f1a57634e487b7160e01b600052601260045260246000fd5b92169190910492915050565b63ffffffff818116838216019080821115610bf757610bf7610e2a565b60008251610f55818460208701610d4e565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca2646970667358221220e2a4e2c158ec7d38443cf09da5dacb8f5d2cef32752a3b7a150d8d9a0a5dc4f264736f6c63430008170033" }, + "0x0000000000000000000000000000000000003333": { + "comment": "Proxy: Smart contract to manage DIDs", + "balance": "0", + "code": "0x6080604052600a600c565b005b60186014601a565b6051565b565b6000604c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e808015606f573d6000f35b3d6000fdfea26469706673582212208de99705f21830b33bf2bd4a57ce70f27ec58ac48b2c88e1c96b59a11978ef8164736f6c63430008170033", + "storage": { + "0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000009999", + "f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00": "0x0000000000000000000000000000000000000000000000000000000000000001", + "360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000072731de66db3a6afdf484ae517bb6ac4b5e7b71" + } + }, + "0x072731de66db3a6afdf484ae517bb6ac4b5e7b71": { + "comment": "Implementation: Smart contract to manage DIDs", + "balance": "0", + "code": "0x60806040526004361061009c5760003560e01c8063ad3cb1cc11610064578063ad3cb1cc1461014f578063c041bd661461018d578063c4d66de8146101ad578063c6569381146101cd578063d066db54146101ed578063f59579441461020d57600080fd5b80631830eb5b146100a15780633f4f62b7146100d75780634f1ef286146100f957806352d1902d1461010c57806385e931351461012f575b600080fd5b3480156100ad57600080fd5b506100c16100bc366004611060565b61022d565b6040516100ce91906110cb565b60405180910390f35b3480156100e357600080fd5b506100f76100f236600461119b565b610399565b005b6100f7610107366004611229565b610443565b34801561011857600080fd5b50610121610462565b6040519081526020016100ce565b34801561013b57600080fd5b506100f761014a366004611060565b61047f565b34801561015b57600080fd5b50610180604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100ce91906112eb565b34801561019957600080fd5b506100f76101a83660046112fe565b61048c565b3480156101b957600080fd5b506100f76101c8366004611060565b61055f565b3480156101d957600080fd5b506100f76101e8366004611340565b610644565b3480156101f957600080fd5b506100f761020836600461119b565b610655565b34801561021957600080fd5b506100f7610228366004611340565b6106f6565b610235610fe0565b6001600160a01b0382166000908152600160205260408120600301548391036102815760405163431dc9ff60e11b81526001600160a01b03821660048201526024015b60405180910390fd5b6001600160a01b0383166000908152600160205260409081902081518083019092528054829082906102b290611393565b80601f01602080910402602001604051908101604052809291908181526020018280546102de90611393565b801561032b5780601f106103005761010080835404028352916020019161032b565b820191906000526020600020905b81548152906001019060200180831161030e57829003601f168201915b50505091835250506040805160c08101825260018401546001600160a01b039081168252600285015416602082810191909152600385015492820192909252600484015460608201526005840154608082015260069093015460ff16151560a0840152015291505b50919050565b6040516000906103bb90601960f81b90839030908b90889088906020016113c7565b60408051601f1981840301815282825280516020918201206000845290830180835281905260ff8916918301919091526060820187905260808201869052915061043a90889060019060a0016020604051602081039080840390855afa158015610429573d6000803e3d6000fd5b5050506020604051035185856106fe565b50505050505050565b61044b610840565b610454826108e7565b61045e8282610946565b5050565b600061046c610a03565b506000805160206115d183398151915290565b6104898133610a4c565b50565b604051601960f81b60208201526000602182018190526001600160601b031930606090811b8216602285015287901b1660368301526c19195858dd1a5d985d19511a59609a1b604a8301529060570160408051601f1981840301815282825280516020918201206000845290830180835281905260ff8716918301919091526060820185905260808201849052915061055890869060019060a0016020604051602081039080840390855afa158015610549573d6000803e3d6000fd5b50505060206040510351610a4c565b5050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460019190600160401b900460ff16806105a95750805467ffffffffffffffff808416911610155b156105c75760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff191667ffffffffffffffff831617600160401b1781556105f283610bde565b805468ff00000000000000001916815560405167ffffffffffffffff831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a1505050565b61065083338484610c08565b505050565b60405160009061067790601960f81b90839030908b9088908890602001611429565b60408051601f1981840301815282825280516020918201206000845290830180835281905260ff8916918301919091526060820187905260808201869052915061043a90889060019060a0016020604051602081039080840390855afa1580156106e5573d6000803e3d6000fd5b505050602060405103518585610c08565b610650833384845b6001600160a01b038416600090815260016020526040902060030154849015610745576040516305d68dff60e01b81526001600160a01b0382166004820152602401610278565b8484806001600160a01b0316826001600160a01b03161461078c576040516316343f1760e31b81526001600160a01b03808316600483015283166024820152604401610278565b6001600160a01b03871660009081526001602052604090206107af8587836114db565b506001600160a01b03871660008181526001602081815260409283902091820180546001600160a01b0319908116861790915560028301805490911633179055426003830181905560048301554360059092019190915590519182527f04ba3b3eaab06ab3e10d3d39ba7db30a9af06393b6574671b7a1000a5d4a0e3691015b60405180910390a150505050505050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806108c757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166108bb6000805160206115d1833981519152546001600160a01b031690565b6001600160a01b031614155b156108e55760405163703e46dd60e11b815260040160405180910390fd5b565b60005460405163574a81d760e01b81523060048201526001600160a01b0383811660248301529091169063574a81d79060440160006040518083038186803b15801561093257600080fd5b505afa158015610558573d6000803e3d6000fd5b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156109a0575060408051601f3d908101601f1916820190925261099d9181019061159b565b60015b6109c857604051634c9c8ce360e01b81526001600160a01b0383166004820152602401610278565b6000805160206115d183398151915281146109f957604051632a87526960e21b815260048101829052602401610278565b6106508383610dbf565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146108e55760405163703e46dd60e11b815260040160405180910390fd5b6001600160a01b038216600090815260016020526040812060030154839103610a935760405163431dc9ff60e11b81526001600160a01b0382166004820152602401610278565b6001600160a01b038316600090815260016020526040902060060154839060ff1615610add5760405163e9aeaecd60e01b81526001600160a01b0382166004820152602401610278565b8383806001600160a01b0316826001600160a01b031614610b24576040516316343f1760e31b81526001600160a01b03808316600483015283166024820152604401610278565b85336001600160a01b03821614801590610b5b57506001600160a01b03818116600090815260016020526040902060020154163314155b15610b7b57604051633fcc3f1760e01b8152336004820152602401610278565b6001600160a01b03871660008181526001602081815260409283902060068101805460ff19169093179092554360059092019190915590519182527f236b7a85392c62d219956b1f2d21f622daa26da228a7972f50caa2be59bf1706910161082f565b610be6610e15565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b038416600090815260016020526040812060030154859103610c4f5760405163431dc9ff60e11b81526001600160a01b0382166004820152602401610278565b6001600160a01b038516600090815260016020526040902060060154859060ff1615610c995760405163e9aeaecd60e01b81526001600160a01b0382166004820152602401610278565b8585806001600160a01b0316826001600160a01b031614610ce0576040516316343f1760e31b81526001600160a01b03808316600483015283166024820152604401610278565b87336001600160a01b03821614801590610d1757506001600160a01b03818116600090815260016020526040902060020154163314155b15610d3757604051633fcc3f1760e01b8152336004820152602401610278565b6001600160a01b0389166000908152600160205260409020610d5a8789836114db565b506001600160a01b0389166000818152600160209081526040918290204260048201554360059091015590519182527f90e3a0a6e9a465f47796c468fa4ba727e3aa2b9270bae4b93cd3dea9ac6e3452910160405180910390a1505050505050505050565b610dc882610e5e565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115610e0d576106508282610ec3565b61045e610f39565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff166108e557604051631afcd79f60e31b815260040160405180910390fd5b806001600160a01b03163b600003610e9457604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610278565b6000805160206115d183398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b031684604051610ee091906115b4565b600060405180830381855af49150503d8060008114610f1b576040519150601f19603f3d011682016040523d82523d6000602084013e610f20565b606091505b5091509150610f30858383610f58565b95945050505050565b34156108e55760405163b398979f60e01b815260040160405180910390fd5b606082610f6d57610f6882610fb7565b610fb0565b8151158015610f8457506001600160a01b0384163b155b15610fad57604051639996b31560e01b81526001600160a01b0385166004820152602401610278565b50805b9392505050565b805115610fc75780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b60405180604001604052806060815260200161103f6040518060c0016040528060006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000151581525090565b905290565b80356001600160a01b038116811461105b57600080fd5b919050565b60006020828403121561107257600080fd5b610fb082611044565b60005b8381101561109657818101518382015260200161107e565b50506000910152565b600081518084526110b781602086016020860161107b565b601f01601f19169290920160200192915050565b602081526000825160e060208401526110e861010084018261109f565b9050602084015160018060a01b038082511660408601528060208301511660608601525060408101516080850152606081015160a0850152608081015160c085015260a0810151151560e0850152508091505092915050565b803560ff8116811461105b57600080fd5b60008083601f84011261116457600080fd5b50813567ffffffffffffffff81111561117c57600080fd5b60208301915083602082850101111561119457600080fd5b9250929050565b60008060008060008060a087890312156111b457600080fd5b6111bd87611044565b95506111cb60208801611141565b94506040870135935060608701359250608087013567ffffffffffffffff8111156111f557600080fd5b61120189828a01611152565b979a9699509497509295939492505050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561123c57600080fd5b61124583611044565b9150602083013567ffffffffffffffff8082111561126257600080fd5b818501915085601f83011261127657600080fd5b81358181111561128857611288611213565b604051601f8201601f19908116603f011681019083821181831017156112b0576112b0611213565b816040528281528860208487010111156112c957600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b602081526000610fb0602083018461109f565b6000806000806080858703121561131457600080fd5b61131d85611044565b935061132b60208601611141565b93969395505050506040820135916060013590565b60008060006040848603121561135557600080fd5b61135e84611044565b9250602084013567ffffffffffffffff81111561137a57600080fd5b61138686828701611152565b9497909650939450505050565b600181811c908216806113a757607f821691505b60208210810361039357634e487b7160e01b600052602260045260246000fd5b6001600160f81b03198781168252861660018201526001600160601b0319606086811b8216600284015285901b1660168201526818dc99585d19511a5960ba1b602a820152600082846033840137506000910160330190815295945050505050565b6001600160f81b03198781168252861660018201526001600160601b0319606086811b8216600284015285901b166016820152681d5c19185d19511a5960ba1b602a820152600082846033840137506000910160330190815295945050505050565b601f821115610650576000816000526020600020601f850160051c810160208610156114b45750805b601f850160051c820191505b818110156114d3578281556001016114c0565b505050505050565b67ffffffffffffffff8311156114f3576114f3611213565b611507836115018354611393565b8361148b565b6000601f84116001811461153b57600085156115235750838201355b600019600387901b1c1916600186901b178355610558565b600083815260209020601f19861690835b8281101561156c578685013582556020948501946001909201910161154c565b50868210156115895760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6000602082840312156115ad57600080fd5b5051919050565b600082516115c681846020870161107b565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca26469706673582212207b11084ac1c6228f3917c7c9f50df951840ea85bf880de091f2c16e37538198664736f6c63430008170033" + }, "0x0000000000000000000000000000000000018888": { "comment": "Proxy: Ethereum registry for ERC-1056 ethr did methods", "balance": "0", "code": "0x6080604052600a600c565b005b60186014601a565b6051565b565b6000604c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e808015606f573d6000f35b3d6000fdfea26469706673582212208de99705f21830b33bf2bd4a57ce70f27ec58ac48b2c88e1c96b59a11978ef8164736f6c63430008170033", "storage": { + "0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000009999", "f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00": "0x0000000000000000000000000000000000000000000000000000000000000001", "360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000ef45dd3009cccced5304f337ebe64c56b6446e7c" } @@ -167,21 +183,38 @@ "balance": "0", "code": "0x60806040526004361061011e5760003560e01c806380b29f7c116100a0578063ad3cb1cc11610064578063ad3cb1cc14610369578063c4d66de8146103a7578063e476af5c146103c7578063f00d4b5d146103e7578063f96d0f9f1461040757600080fd5b806380b29f7c146102c95780638733d4e8146102e957806393072684146103095780639c2c1b2b14610329578063a7068d661461034957600080fd5b80634f1ef286116100e75780634f1ef2861461022457806352d1902d14610237578063622b2a3c1461024c57806370ae92d21461027c5780637ad4b0a4146102a957600080fd5b8062c023da14610123578063022914a7146101455780630d44625b14610198578063123b5e98146101e4578063240cf1fa14610204575b600080fd5b34801561012f57600080fd5b5061014361013e3660046113d9565b610434565b005b34801561015157600080fd5b5061017b610160366004611430565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156101a457600080fd5b506101d66101b336600461144b565b600160209081526000938452604080852082529284528284209052825290205481565b60405190815260200161018f565b3480156101f057600080fd5b506101436101ff366004611498565b610445565b34801561021057600080fd5b5061014361021f36600461151d565b6104d1565b610143610232366004611574565b61059c565b34801561024357600080fd5b506101d66105bb565b34801561025857600080fd5b5061026c61026736600461144b565b6105d8565b604051901515815260200161018f565b34801561028857600080fd5b506101d6610297366004611430565b60036020526000908152604090205481565b3480156102b557600080fd5b506101436102c43660046115c2565b61062b565b3480156102d557600080fd5b506101436102e436600461144b565b61063e565b3480156102f557600080fd5b5061017b610304366004611430565b61064a565b34801561031557600080fd5b50610143610324366004611621565b61067a565b34801561033557600080fd5b50610143610344366004611680565b610751565b34801561035557600080fd5b506101436103643660046116ea565b610828565b34801561037557600080fd5b5061039a604051806040016040528060058152602001640352e302e360dc1b81525081565b60405161018f919061177e565b3480156103b357600080fd5b506101436103c2366004611430565b610835565b3480156103d357600080fd5b506101436103e2366004611791565b61091a565b3480156103f357600080fd5b5061014361040236600461180b565b610999565b34801561041357600080fd5b506101d6610422366004611430565b60026020526000908152604090205481565b610440833384846109a4565b505050565b6000601960f81b813060038261045a8d61064a565b6001600160a01b03166001600160a01b03168152602001908152602001600020548b88888860405160200161049698979695949392919061183e565b6040516020818303038152906040528051906020012090506104c7886104bf8a8a8a8a87610a60565b868686610b4f565b5050505050505050565b6000601960f81b81306003826104e68b61064a565b6001600160a01b0316815260208082019290925260409081016000205481516001600160f81b0319968716818501529490951660218501526001600160601b0319606093841b8116602286015260368501959095528a831b851660568501526a31b430b733b2a7bbb732b960a91b606a8501529186901b90931660758301528051606981840301815260899092019052805191012090506105948661058e8188888887610a60565b84610c17565b505050505050565b6105a4610cdf565b6105ad82610d86565b6105b78282610ded565b5050565b60006105c5610eaa565b50600080516020611a0d83398151915290565b6001600160a01b03838116600090815260016020908152604080832081518084018890528251808203850181529083018352805190840120845282528083209385168352929052205442105b9392505050565b6106388433858585610b4f565b50505050565b61044083338484610ef3565b6001600160a01b0380821660009081526020819052604081205490911680156106735792915050565b5090919050565b6000601960f81b813060038261068f8c61064a565b6001600160a01b0316815260208082019290925260409081016000205481516001600160f81b0319968716818501529490951660218501526001600160601b0319606093841b8116602286015260368501959095528b831b851660568501526d7265766f6b6544656c656761746560901b606a850152607884018890529186901b90931660988301528051608c81840301815260ac909201905280519101209050610748876107418189898987610a60565b8585610ef3565b50505050505050565b6000601960f81b81306003826107668d61064a565b6001600160a01b0316815260208082019290925260409081016000205490516001600160f81b031995861692810192909252929093166021840152606090811b6001600160601b0319908116602285015260368401929092528a811b821660568401526a61646444656c656761746560a81b606a8401526075830187905285901b16609582015260a9810183905260c9016040516020818303038152906040528051906020012090506104c7886108208a8a8a8a87610a60565b868686610fd1565b6106388433858585610fd1565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460019190600160401b900460ff168061087f5750805467ffffffffffffffff808416911610155b1561089d5760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff191667ffffffffffffffff831617600160401b1781556108c8836110d0565b805468ff00000000000000001916815560405167ffffffffffffffff831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a1505050565b6000601960f81b813060038261092f8c61064a565b6001600160a01b03166001600160a01b03168152602001908152602001600020548a878760405160200161096997969594939291906118c4565b604051602081830303815290604052805190602001209050610748876109928989898987610a60565b85856109a4565b6105b7823383610c17565b83836109af8261064a565b6001600160a01b0316816001600160a01b0316146109e85760405162461bcd60e51b81526004016109df90611946565b60405180910390fd5b6001600160a01b0386166000818152600260205260408082205490517f18ab6b2ae3d64306c00ce663125f2bd680e441a098de1635bd7ad8b0d44965e492610a3592899289929190611969565b60405180910390a25050506001600160a01b0390921660009081526002602052604090204390555050565b6040805160008082526020820180845284905260ff8716928201929092526060810185905260808101849052819060019060a0016020604051602081039080840390855afa158015610ab6573d6000803e3d6000fd5b505050602060405103519050610acb8761064a565b6001600160a01b0316816001600160a01b031614610b1b5760405162461bcd60e51b815260206004820152600d60248201526c6261645f7369676e617475726560981b60448201526064016109df565b6001600160a01b0381166000908152600360205260408120805491610b3f836119ab565b9091555090979650505050505050565b8484610b5a8261064a565b6001600160a01b0316816001600160a01b031614610b8a5760405162461bcd60e51b81526004016109df90611946565b6001600160a01b0387167f18ab6b2ae3d64306c00ce663125f2bd680e441a098de1635bd7ad8b0d44965e48686610bc187426119c4565b6001600160a01b038c1660009081526002602052604090819020549051610beb9493929190611969565b60405180910390a25050506001600160a01b039093166000908152600260205260409020439055505050565b8282610c228261064a565b6001600160a01b0316816001600160a01b031614610c525760405162461bcd60e51b81526004016109df90611946565b6001600160a01b0385811660008181526020818152604080832080546001600160a01b031916958916958617905560028252918290205482519485529084015290917f38a5a6e68f30ed1ab45860a4afb34bcb2fc00f22ca462d249b8a8d40cda6f7a3910160405180910390a2505050506001600160a01b03166000908152600260205260409020439055565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480610d6657507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610d5a600080516020611a0d833981519152546001600160a01b031690565b6001600160a01b031614155b15610d845760405163703e46dd60e11b815260040160405180910390fd5b565b6004805460405163574a81d760e01b815230928101929092526001600160a01b038381166024840152169063574a81d79060440160006040518083038186803b158015610dd257600080fd5b505afa158015610de6573d6000803e3d6000fd5b5050505050565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610e47575060408051601f3d908101601f19168201909252610e44918101906119d7565b60015b610e6f57604051634c9c8ce360e01b81526001600160a01b03831660048201526024016109df565b600080516020611a0d8339815191528114610ea057604051632a87526960e21b8152600481018290526024016109df565b61044083836110fa565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610d845760405163703e46dd60e11b815260040160405180910390fd5b8383610efe8261064a565b6001600160a01b0316816001600160a01b031614610f2e5760405162461bcd60e51b81526004016109df90611946565b6001600160a01b03868116600081815260016020908152604080832081518084018b90528251808203850181528184018085528151918601919091208652918452828520968a16808652968452828520429081905586865260029094529190932054928990526060810194909452608084015260a0830152907f5a5084339536bcab65f20799fcc58724588145ca054bd2be626174b27ba156f79060c001610a35565b8484610fdc8261064a565b6001600160a01b0316816001600160a01b03161461100c5760405162461bcd60e51b81526004016109df90611946565b61101683426119c4565b6001600160a01b03888116600081815260016020908152604080832081518084018d9052825180820385018152908301835280519084012084528252808320948a16835293905291909120919091557f5a5084339536bcab65f20799fcc58724588145ca054bd2be626174b27ba156f7868661109287426119c4565b6001600160a01b038c811660009081526002602090815260409182902054825196875294909216918501919091528301526060820152608001610beb565b6110d8611150565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b61110382611199565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a28051156111485761044082826111fe565b6105b7611276565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16610d8457604051631afcd79f60e31b815260040160405180910390fd5b806001600160a01b03163b6000036111cf57604051634c9c8ce360e01b81526001600160a01b03821660048201526024016109df565b600080516020611a0d83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b03168460405161121b91906119f0565b600060405180830381855af49150503d8060008114611256576040519150601f19603f3d011682016040523d82523d6000602084013e61125b565b606091505b509150915061126b858383611295565b925050505b92915050565b3415610d845760405163b398979f60e01b815260040160405180910390fd5b6060826112aa576112a5826112f1565b610624565b81511580156112c157506001600160a01b0384163b155b156112ea57604051639996b31560e01b81526001600160a01b03851660048201526024016109df565b5080610624565b8051156113015780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b038116811461133157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261135d57600080fd5b813567ffffffffffffffff8082111561137857611378611336565b604051601f8301601f19908116603f011681019082821181831017156113a0576113a0611336565b816040528381528660208588010111156113b957600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156113ee57600080fd5b6113f78461131a565b925060208401359150604084013567ffffffffffffffff81111561141a57600080fd5b6114268682870161134c565b9150509250925092565b60006020828403121561144257600080fd5b6106248261131a565b60008060006060848603121561146057600080fd5b6114698461131a565b92506020840135915061147e6040850161131a565b90509250925092565b803560ff8116811461133157600080fd5b600080600080600080600060e0888a0312156114b357600080fd5b6114bc8861131a565b96506114ca60208901611487565b955060408801359450606088013593506080880135925060a088013567ffffffffffffffff8111156114fb57600080fd5b6115078a828b0161134c565b92505060c0880135905092959891949750929550565b600080600080600060a0868803121561153557600080fd5b61153e8661131a565b945061154c60208701611487565b935060408601359250606086013591506115686080870161131a565b90509295509295909350565b6000806040838503121561158757600080fd5b6115908361131a565b9150602083013567ffffffffffffffff8111156115ac57600080fd5b6115b88582860161134c565b9150509250929050565b600080600080608085870312156115d857600080fd5b6115e18561131a565b935060208501359250604085013567ffffffffffffffff81111561160457600080fd5b6116108782880161134c565b949793965093946060013593505050565b60008060008060008060c0878903121561163a57600080fd5b6116438761131a565b955061165160208801611487565b945060408701359350606087013592506080870135915061167460a0880161131a565b90509295509295509295565b600080600080600080600060e0888a03121561169b57600080fd5b6116a48861131a565b96506116b260208901611487565b95506040880135945060608801359350608088013592506116d560a0890161131a565b915060c0880135905092959891949750929550565b6000806000806080858703121561170057600080fd5b6117098561131a565b93506020850135925061171e6040860161131a565b9396929550929360600135925050565b60005b83811015611749578181015183820152602001611731565b50506000910152565b6000815180845261176a81602086016020860161172e565b601f01601f19169290920160200192915050565b6020815260006106246020830184611752565b60008060008060008060c087890312156117aa57600080fd5b6117b38761131a565b95506117c160208801611487565b945060408701359350606087013592506080870135915060a087013567ffffffffffffffff8111156117f257600080fd5b6117fe89828a0161134c565b9150509295509295509295565b6000806040838503121561181e57600080fd5b6118278361131a565b91506118356020840161131a565b90509250929050565b6001600160f81b03198981168252881660018201526001600160601b0319606088811b821660028401526016830188905286901b1660368201526b73657441747472696275746560a01b604a8201526056810184905282516000906118aa81607685016020880161172e565b607692019182019290925260960198975050505050505050565b6001600160f81b03198881168252871660018201526001600160601b0319606087811b821660028401526016830187905285901b1660368201526e7265766f6b6541747472696275746560881b604a82015260598101839052815160009061193381607985016020870161172e565b9190910160790198975050505050505050565b6020808252600990820152683130b22fb0b1ba37b960b91b604082015260600190565b8481526080602082015260006119826080830186611752565b6040830194909452506060015292915050565b634e487b7160e01b600052601160045260246000fd5b6000600182016119bd576119bd611995565b5060010190565b8082018082111561127057611270611995565b6000602082840312156119e957600080fd5b5051919050565b60008251611a0281846020870161172e565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca264697066735822122041023550f57b6c49d7a3e0c8c26d2ea4e06db2989abcb1738d1c2e4ccc19e8bb64736f6c63430008170033" }, + "0x000000000000000000000000000000000019999": { + "comment": "Proxy: Smart contract to resolve DIDs from various DID registries", + "balance": "0", + "code": "0x6080604052600a600c565b005b60186014601a565b6051565b565b6000604c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e808015606f573d6000f35b3d6000fdfea26469706673582212208de99705f21830b33bf2bd4a57ce70f27ec58ac48b2c88e1c96b59a11978ef8164736f6c63430008170033", + "storage": { + "0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000009999", + "0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000003333", + "0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000018888", + "f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00": "0x0000000000000000000000000000000000000000000000000000000000000001", + "360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000dcf8f229d50b2b10e9805936c8a395cc1fc1aabb" + } + }, + "0xdcf8f229d50b2b10e9805936c8a395cc1fc1aabb": { + "comment": "Implementation: Smart contract to resolve DIDs from various DID registries", + "balance": "0", + "code": "0x6080604052600436106100555760003560e01c806329181c6c1461005a5780634f1ef2861461009057806352d1902d146100a557806366874f25146100c8578063ad3cb1cc1461013f578063c0c53b8b14610170575b600080fd5b34801561006657600080fd5b5061007a6100753660046118f7565b610190565b60405161008791906119b8565b60405180910390f35b6100a361009e366004611a97565b6102e6565b005b3480156100b157600080fd5b506100ba610305565b604051908152602001610087565b3480156100d457600080fd5b506100e86100e33660046118f7565b610322565b604051610087919081516001600160a01b0390811682526020808401519091169082015260408083015190820152606080830151908201526080808301519082015260a09182015115159181019190915260c00190565b34801561014b57600080fd5b5061007a604051806040016040528060058152602001640352e302e360dc1b81525081565b34801561017c57600080fd5b506100a361018b366004611b29565b61055e565b606060006101d384848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061067292505050565b905060006101e482602001516107bd565b90506001600160a01b03811661021a578484604051631859e3bb60e11b8152600401610211929190611b74565b60405180910390fd5b8151610225906107f6565b156102a757600154604051631830eb5b60e01b81526001600160a01b03838116600483015290911690631830eb5b90602401600060405180830381865afa158015610274573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261029c9190810190611ba3565b5192506102e0915050565b81516040516102b99190602001611ccc565b60408051601f198184030181529082905263fdc1b5c360e01b825261021191600401611d1c565b92915050565b6102ee610833565b6102f7826108da565b6103018282610940565b5050565b600061030f610a02565b50600080516020611f3383398151915290565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152600061039584848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061067292505050565b905060006103a682602001516107bd565b90506001600160a01b0381166103d3578484604051631859e3bb60e11b8152600401610211929190611b74565b81516103de90610a4b565b15610496576002546040516310e67a9d60e31b81526001600160a01b0383811660048301526000921690638733d4e890602401602060405180830381865afa15801561042e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104529190611d70565b6040805160c0810182526001600160a01b039092168252600060208301819052908201819052606082018190526080820181905260a082015293506102e092505050565b81516104a1906107f6565b1561052557600154604051631830eb5b60e01b81526001600160a01b03838116600483015290911690631830eb5b90602401600060405180830381865afa1580156104f0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526105189190810190611ba3565b60200151925050506102e0565b81516040516105379190602001611ccc565b60408051601f198184030181529082905263fdc1b5c360e01b825261021191600401611d8d565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460019190600160401b900460ff16806105a7575080546001600160401b03808416911610155b156105c55760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff19166001600160401b03831617600160401b1781556105ef85610a75565b600180546001600160a01b038681166001600160a01b0319928316179092556002805492861692909116919091179055805468ff0000000000000000191681556040516001600160401b03831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15050505050565b6040805180820190915260608082526020820152600061069183610a9f565b905060006106b7604051806040016040528060018152602001601d60f91b815250610a9f565b90506000806106c68484610aaa565b95509250905080158061070457506107026106fb60405180604001604052806003815260200162191a5960ea1b815250610a9f565b8390610af8565b155b156107245785604051631859e3bb60e11b815260040161021191906119b8565b61072e8484610aaa565b955092509050806107545785604051631859e3bb60e11b815260040161021191906119b8565b604080518082019091526060808252602082015261077183610b0b565b81526040805180820190915260018152601d60f91b602082015261079f9061079890610a9f565b8690610b16565b94506107ae9150849050610b0b565b60208201529695505050505050565b600060166107c9835190565b036107d657506000919050565b60006107e183610b40565b90506107ec81611de1565b60601c9392505050565b60006102e061082460405180604001604052806008815260200167696e64796265737560c01b815250610a9f565b61082d84610a9f565b90610af8565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806108ba57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166108ae600080516020611f33833981519152546001600160a01b031690565b6001600160a01b031614155b156108d85760405163703e46dd60e11b815260040160405180910390fd5b565b60005460405163574a81d760e01b81523060048201526001600160a01b0383811660248301529091169063574a81d79060440160006040518083038186803b15801561092557600080fd5b505afa158015610939573d6000803e3d6000fd5b5050505050565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561099a575060408051601f3d908101601f1916820190925261099791810190611e1d565b60015b6109c257604051634c9c8ce360e01b81526001600160a01b0383166004820152602401610211565b600080516020611f3383398151915281146109f357604051632a87526960e21b815260048101829052602401610211565b6109fd8383610d32565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146108d85760405163703e46dd60e11b815260040160405180910390fd5b60006102e06108246040518060400160405280600481526020016332ba343960e11b815250610a9f565b610a7d610d88565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b60006102e082610dd1565b6000808080610ab98686610de5565b90506000198103610ad557600086600093509350935050610af1565b610ae986826001600160801b038816610ef0565b935093509350505b9250925092565b6000610b048383610f5d565b9392505050565b60606102e082610fa7565b6000808080610b25868661101e565b90506000198103610ad5576000808793509350935050610af1565b60606000610b4d83610a9f565b90506000610b7460405180604001604052806002815260200161060f60f31b815250610a9f565b9050610ba3610b9c60405180604001604052806002815260200161060f60f31b815250610a9f565b8390611110565b610bbe57505060408051602081019091526000815292915050565b610bd0610bcb838361111c565b610b0b565b93506000849050600060028251610be79190611e4c565b6001600160401b03811115610bfe57610bfe6119e0565b6040519080825280601f01601f191660200182016040528015610c28576020820181803683370190505b50905060005b8151811015610d2857600080610c6d85610c49856002611e6e565b81518110610c5957610c59611e85565b01602001516001600160f81b031916611128565b9150915080610c92575050604080516020810190915260008152979650505050505050565b600080610caf87610ca4876002611e6e565b610c49906001611e9b565b9150915080610cd65750506040805160208101909152600081529998505050505050505050565b81610ce2856010611eae565b610cec9190611ed1565b60f81b868681518110610d0157610d01611e85565b60200101906001600160f81b031916908160001a9053505060019093019250610c2e915050565b5095945050505050565b610d3b8261120e565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115610d80576109fd8282611273565b6103016112e9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff166108d857604051631afcd79f60e31b815260040160405180910390fd5b600080602083019050610b04818451611308565b60006001600160801b03838116908316808303610e07576000925050506102e0565b811580610e1357508181115b15610e2457600019925050506102e0565b6000610e308660801c90565b90506000610e3e8660801c90565b90506000610e4d825160001a90565b90505b6000610e5d848784611314565b90506000198103610e785760001996505050505050506102e0565b94859003949283019285851115610e995760001996505050505050506102e0565b84832085852003610ec557610eae8960801c90565b610eb89085611eea565b96505050505050506102e0565b85600103610edd5760001996505050505050506102e0565b6000199095019460019093019250610e50565b600080600080610f008760801c90565b90506001600160801b03871685870181811115610f30576040516365f4e9df60e01b815260040160405180910390fd5b6001996001600160801b03988916608085811b919091179a50928290039098169201901b17949350505050565b60006001600160801b038381169083168114610f7d5760009150506102e0565b610f9f610f8a8560801c90565b610f948560801c90565b839081902091201490565b949350505050565b60606001600160801b0382166001600160401b03811115610fca57610fca6119e0565b6040519080825280601f01601f191660200182016040528015610ff4576020820181803683370190505b50905060208101611018816110098560801c90565b6001600160801b0386166113dc565b50919050565b60006001600160801b03838116908316808303611040576000925050506102e0565b81158061104c57508181115b1561105d57600019925050506102e0565b60006110698660801c90565b905060006110778660801c90565b90506000611084876113ea565b905060001984015b600061109985888561142f565b905060001981036110b5576000199750505050505050506102e0565b808211156110ce576000199750505050505050506102e0565b8584208282038681018890209091036110f05797506102e09650505050505050565b81156110fe5750955061108c565b600019985050505050505050506102e0565b6000610b0483836114e3565b6000610b048383611530565b600080600360fc1b6001600160f81b03198416108015906111575750603960f81b6001600160f81b0319841611155b156111755761116b603060f885901c611efd565b9360019350915050565b604160f81b6001600160f81b03198416108015906111a15750602360f91b6001600160f81b0319841611155b156111c15760416111b760f885901c600a611ed1565b61116b9190611efd565b606160f81b6001600160f81b03198416108015906111ed5750603360f91b6001600160f81b0319841611155b156112035760616111b760f885901c600a611ed1565b506000928392509050565b806001600160a01b03163b60000361124457604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610211565b600080516020611f3383398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516112909190611f16565b600060405180830381855af49150503d80600081146112cb576040519150601f19603f3d011682016040523d82523d6000602084013e6112d0565b606091505b50915091506112e085838361158a565b95945050505050565b34156108d85760405163b398979f60e01b815260040160405180910390fd5b6000610b0483836115e6565b600060208311611330576113298484846115f2565b9050610b04565b83601f8416808503820160ff8516600080516020611f53833981519152025b81881015611391578751811861136481611703565b15611385578489036113788a60208a6115f2565b0195505050505050610b04565b6020890198505061134f565b826000036113a757600019945050505050610b04565b6113b28284886115f2565b945060001985036113cb57600019945050505050610b04565b509190910391909101949350505050565b8083828460045afa50505050565b60006001600160801b038216808203611416576040516365f4e9df60e01b815260040160405180910390fd5b610b04600182036114278560801c90565b015160001a90565b6000602083116114445761132984848461174e565b601f8316848401811561147c57819003600061146182848761174e565b9050600019811461147a5790869003019150610b049050565b505b60ff8416600080516020611f53833981519152025b868211156114d557601f19909101805190919081186114af81611703565b156114cf578783036114c38460208961174e565b01945050505050610b04565b50611491565b506000199695505050505050565b60006001600160801b0383811690831680821015611506576000925050506102e0565b848183111561151c576115198683611797565b90505b6115268186610f5d565b9695505050505050565b60006001600160801b03838116908316818111156115525784925050506102e0565b60008061155f87846117e2565b909250905061156e8287610f5d565b1561157e5793506102e092505050565b869450505050506102e0565b60608261159f5761159a82611865565b610b04565b81511580156115b657506001600160a01b0384163b155b156115df57604051639996b31560e01b81526001600160a01b0385166004820152602401610211565b5080610b04565b6000610b048383611891565b825160009081602085111561160657602094505b601285106116905760ff8416600080516020611f538339815191520282186116366001600160801b038217611703565b60000361166c5760109150601a86106116675761165b6001600160401b038217611703565b60000361166757601891505b61168a565b61167e6001600160c01b038217611703565b60000361168a57600891505b506116ce565b600a85106116ce5760ff8416600080516020611f538339815191520282186116c06001600160c01b038217611703565b6000036116cc57600891505b505b848110156116f65781811a60ff851681036116ed57509150610b049050565b506001016116ce565b5060001995945050505050565b7ffefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeff81019019167f80808080808080808080808080808080808080808080808080808080808080801690565b6000602083111561175e57602092505b83515b831561178b576000199093019280841a60ff84168103611785578492505050610b04565b50611761565b50600019949350505050565b60006001600160801b038316808311156117c4576040516365f4e9df60e01b815260040160405180910390fd5b610f9f6117d18560801c90565b60801b6001600160801b0385161790565b60008060006117f18560801c90565b90506001600160801b0385168085111561181e576040516365f4e9df60e01b815260040160405180910390fd5b608082901b6001600160801b0386161761185861183b8785611e9b565b6118458885611eea565b6001600160801b031660809190911b1790565b9350935050509250929050565b8051156118755780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b60006001600160801b038311156118bb5760405163fee7506f60e01b815260040160405180910390fd5b6001600160801b038211156118e357604051633b6b098d60e01b815260040160405180910390fd5b506001600160801b031660809190911b1790565b6000806020838503121561190a57600080fd5b82356001600160401b038082111561192157600080fd5b818501915085601f83011261193557600080fd5b81358181111561194457600080fd5b86602082850101111561195657600080fd5b60209290920196919550909350505050565b60005b8381101561198357818101518382015260200161196b565b50506000910152565b600081518084526119a4816020860160208601611968565b601f01601f19169290920160200192915050565b602081526000610b04602083018461198c565b6001600160a01b038116811461188e57600080fd5b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715611a1857611a186119e0565b60405290565b60405160c081016001600160401b0381118282101715611a1857611a186119e0565b604051601f8201601f191681016001600160401b0381118282101715611a6857611a686119e0565b604052919050565b60006001600160401b03821115611a8957611a896119e0565b50601f01601f191660200190565b60008060408385031215611aaa57600080fd5b8235611ab5816119cb565b915060208301356001600160401b03811115611ad057600080fd5b8301601f81018513611ae157600080fd5b8035611af4611aef82611a70565b611a40565b818152866020838501011115611b0957600080fd5b816020840160208301376000602083830101528093505050509250929050565b600080600060608486031215611b3e57600080fd5b8335611b49816119cb565b92506020840135611b59816119cb565b91506040840135611b69816119cb565b809150509250925092565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b60006020808385031215611bb657600080fd5b82516001600160401b0380821115611bcd57600080fd5b9084019081860360e0811215611be257600080fd5b611bea6119f6565b835183811115611bf957600080fd5b84019250601f83018813611c0c57600080fd5b8251611c1a611aef82611a70565b8181528987838701011115611c2e57600080fd5b611c3d82888301898801611968565b82525060c0601f1983011215611c5257600080fd5b611c5a611a1e565b9250848401519150611c6b826119cb565b908252604083015190611c7d826119cb565b8185840152606084015160408401526080840151606084015260a0840151608084015260c084015193508315158414611cb557600080fd5b60a083019390935250918101919091529392505050565b7f556e737570706f7274656420444944204d6574686f643a202700000000000000815260008251611d04816019850160208701611968565b602760f81b6019939091019283015250601a01919050565b60408152602460408201527f556e6976657273616c4469645265736f6c7665722e7265736f6c7665446f63756060820152631b595b9d60e21b608082015260a060208201526000610b0460a083018461198c565b600060208284031215611d8257600080fd5b8151610b04816119cb565b60408152602460408201527f556e6976657273616c4469645265736f6c7665722e7265736f6c76654d6574616060820152636461746160e01b608082015260a060208201526000610b0460a083018461198c565b805160208201516bffffffffffffffffffffffff198082169291906014831015611e155780818460140360031b1b83161693505b505050919050565b600060208284031215611e2f57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600082611e6957634e487b7160e01b600052601260045260246000fd5b500490565b80820281158282048414176102e0576102e0611e36565b634e487b7160e01b600052603260045260246000fd5b808201808211156102e0576102e0611e36565b60ff8181168382160290811690818114611eca57611eca611e36565b5092915050565b60ff81811683821601908111156102e0576102e0611e36565b818103818111156102e0576102e0611e36565b60ff82811682821603908111156102e0576102e0611e36565b60008251611f28818460208701611968565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc0101010101010101010101010101010101010101010101010101010101010101a26469706673582212200e55dd8b723b36c4da47f95d42d9fb6627f314bfba1841988b66e34431013e2b64736f6c63430008170033" + }, "0x0000000000000000000000000000000000005555": { "comment": "Proxy: Smart contract to manage schemas", "balance": "0", "code": "0x6080604052600a600c565b005b60186014601a565b6051565b565b6000604c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e808015606f573d6000f35b3d6000fdfea26469706673582212208de99705f21830b33bf2bd4a57ce70f27ec58ac48b2c88e1c96b59a11978ef8164736f6c63430008170033", "storage": { "0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000009999", - "0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000018888", + "0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000019999", "f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00": "0x0000000000000000000000000000000000000000000000000000000000000001", - "360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000000000000000000000002d8ef83a48caa0366b27021d47d8bb9f7d02016d" + "360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x00000000000000000000000056ce9ff2b588e7b79dd6defd4db942c2914b3720" } }, - "0x2d8ef83a48caa0366b27021d47d8bb9f7d02016d": { + "0x56ce9ff2b588e7b79dd6defd4db942c2914b3720": { "comment": "Implementation: Smart contract to manage schemas", "balance": "0", - "code": "0x6080604052600436106100705760003560e01c80635915b7681161004e5780635915b768146100d2578063ad3cb1cc146100f2578063bdd23ccb14610130578063eaa760c21461015057600080fd5b8063485cc955146100755780634f1ef2861461009757806352d1902d146100aa575b600080fd5b34801561008157600080fd5b5061009561009036600461099d565b61017d565b005b6100956100a53660046109ec565b61027e565b3480156100b657600080fd5b506100bf61029d565b6040519081526020015b60405180910390f35b3480156100de57600080fd5b506100956100ed366004610af9565b6102ba565b3480156100fe57600080fd5b50610123604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100c99190610b79565b34801561013c57600080fd5b5061009561014b366004610bac565b6102cd565b34801561015c57600080fd5b506100bf61016b366004610c38565b60026020526000908152604090205481565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460019190600160401b900460ff16806101c75750805467ffffffffffffffff808416911610155b156101e55760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff191667ffffffffffffffff831617600160401b1781556102108461032c565b600180546001600160a01b0319166001600160a01b038516179055805468ff00000000000000001916815560405167ffffffffffffffff831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a150505050565b610286610356565b61028f826103fd565b6102998282610463565b5050565b60006102a761052a565b50600080516020610d5683398151915290565b6102c78433858585610573565b50505050565b6040516000906102f190601960f81b90839030908c90899089908990602001610c51565b6040516020818303038152906040528051906020012090506103228861031a8a848b8b8b6106b3565b868686610573565b5050505050505050565b610334610764565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806103dd57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166103d1600080516020610d56833981519152546001600160a01b031690565b6001600160a01b031614155b156103fb5760405163703e46dd60e11b815260040160405180910390fd5b565b60005460405163574a81d760e01b81523060048201526001600160a01b0383811660248301529091169063574a81d79060440160006040518083038186803b15801561044857600080fd5b505afa15801561045c573d6000803e3d6000fd5b5050505050565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156104bd575060408051601f3d908101601f191682019092526104ba91810190610cc3565b60015b6104ea57604051634c9c8ce360e01b81526001600160a01b03831660048201526024015b60405180910390fd5b600080516020610d56833981519152811461051b57604051632a87526960e21b8152600481018290526024016104e1565b61052583836107ad565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103fb5760405163703e46dd60e11b815260040160405180910390fd5b6000838152600260205260409020548390156105a5576040516347f6332960e11b8152600481018290526024016104e1565b6001546040516310e67a9d60e31b81526001600160a01b03808916600483015288928892911690638733d4e890602401602060405180830381865afa1580156105f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106169190610cdc565b6001600160a01b0316816001600160a01b03161461065a5760405163cc41100960e01b81526001600160a01b038084166004830152821660248201526044016104e1565b600086815260026020526040908190204390555186907f3e21fe65ee16f151c8cda6e871883b2e0550f9c8511b4ea1d75c9c9e8d489f67906106a1908a9089908990610cf9565b60405180910390a25050505050505050565b6040805160008082526020820180845287905260ff8616928201929092526060810184905260808101839052819060019060a0016020604051602081039080840390855afa158015610709573d6000803e3d6000fd5b505050602060405103519050806001600160a01b0316876001600160a01b03161461075a5760405163cc41100960e01b81526001600160a01b038089166004830152821660248201526044016104e1565b9695505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff166103fb57604051631afcd79f60e31b815260040160405180910390fd5b6107b682610803565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a28051156107fb576105258282610868565b6102996108de565b806001600160a01b03163b60000361083957604051634c9c8ce360e01b81526001600160a01b03821660048201526024016104e1565b600080516020610d5683398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516108859190610d39565b600060405180830381855af49150503d80600081146108c0576040519150601f19603f3d011682016040523d82523d6000602084013e6108c5565b606091505b50915091506108d58583836108fd565b95945050505050565b34156103fb5760405163b398979f60e01b815260040160405180910390fd5b6060826109125761090d8261095c565b610955565b815115801561092957506001600160a01b0384163b155b1561095257604051639996b31560e01b81526001600160a01b03851660048201526024016104e1565b50805b9392505050565b80511561096c5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b6001600160a01b038116811461098557600080fd5b600080604083850312156109b057600080fd5b82356109bb81610988565b915060208301356109cb81610988565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156109ff57600080fd5b8235610a0a81610988565b9150602083013567ffffffffffffffff80821115610a2757600080fd5b818501915085601f830112610a3b57600080fd5b813581811115610a4d57610a4d6109d6565b604051601f8201601f19908116603f01168101908382118183101715610a7557610a756109d6565b81604052828152886020848701011115610a8e57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60008083601f840112610ac257600080fd5b50813567ffffffffffffffff811115610ada57600080fd5b602083019150836020828501011115610af257600080fd5b9250929050565b60008060008060608587031215610b0f57600080fd5b8435610b1a81610988565b935060208501359250604085013567ffffffffffffffff811115610b3d57600080fd5b610b4987828801610ab0565b95989497509550505050565b60005b83811015610b70578181015183820152602001610b58565b50506000910152565b6020815260008251806020840152610b98816040850160208701610b55565b601f01601f19169190910160400192915050565b600080600080600080600060c0888a031215610bc757600080fd5b8735610bd281610988565b9650602088013560ff81168114610be857600080fd5b955060408801359450606088013593506080880135925060a088013567ffffffffffffffff811115610c1957600080fd5b610c258a828b01610ab0565b989b979a50959850939692959293505050565b600060208284031215610c4a57600080fd5b5035919050565b6001600160f81b03198881168252871660018201526bffffffffffffffffffffffff19606087811b8216600284015286901b1660168201526b637265617465536368656d6160a01b602a8201526036810184905260008284605684013750600091016056019081529695505050505050565b600060208284031215610cd557600080fd5b5051919050565b600060208284031215610cee57600080fd5b815161095581610988565b6001600160a01b03841681526040602082018190528101829052818360608301376000818301606090810191909152601f909201601f1916010192915050565b60008251610d4b818460208701610b55565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca264697066735822122004327f7acb789b0212fc0886f4f174a5f4b4b46a13dbbb20db5383f95211b15d64736f6c63430008170033" + "code": "0x6080604052600436106100705760003560e01c806352d1902d1161004e57806352d1902d146100ca57806383d3fb3c146100f2578063ad3cb1cc14610112578063aebecb1c1461015057600080fd5b80634812cbf814610075578063485cc955146100975780634f1ef286146100b7575b600080fd5b34801561008157600080fd5b50610095610090366004610c36565b61017d565b005b3480156100a357600080fd5b506100956100b2366004610cf0565b610233565b6100956100c5366004610d70565b610334565b3480156100d657600080fd5b506100df610353565b6040519081526020015b60405180910390f35b3480156100fe57600080fd5b5061009561010d366004610e18565b610370565b34801561011e57600080fd5b50610143604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100e99190610ef4565b34801561015c57600080fd5b5061017061016b366004610f07565b610387565b6040516100e99190610f20565b6040516000906101a590601960f81b90839030908e908b908b908b908b908b90602001610f53565b60408051601f1981840301815282825280516020918201206000845290830180835281905260ff8c1691830191909152606082018a9052608082018990529150610227908b9060019060a0016020604051602081039080840390855afa158015610213573d6000803e3d6000fd5b505050602060405103518888888888610491565b50505050505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460019190600160401b900460ff168061027d5750805467ffffffffffffffff808416911610155b1561029b5760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff191667ffffffffffffffff831617600160401b1781556102c684610715565b600180546001600160a01b0319166001600160a01b038516179055805468ff00000000000000001916815560405167ffffffffffffffff831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a150505050565b61033c61073f565b610345826107e6565b61034f828261084c565b5050565b600061035d61090e565b5060008051602061124883398151915290565b61037f86338787878787610491565b505050505050565b61038f610bab565b6000828152600260205260408120600101548391036103c95760405163063de83560e21b8152600481018290526024015b60405180910390fd5b6000838152600260205260409081902081518083019092528054829082906103f090610fd9565b80601f016020809104026020016040519081016040528092919081815260200182805461041c90610fd9565b80156104695780601f1061043e57610100808354040283529160200191610469565b820191906000526020600020905b81548152906001019060200180831161044c57829003601f168201915b5050509183525050604080516020818101909252600193909301548352015291505b50919050565b6000858152600260205260409020600101548590156104c6576040516347f6332960e11b8152600481018290526024016103c0565b84848989806001600160a01b0316826001600160a01b03161461050f576040516316343f1760e31b81526001600160a01b038083166004830152831660248201526044016103c0565b6001546040516366874f2560e01b81526001600160a01b03909116906366874f2590610541908790879060040161100d565b60c060405180830381865afa92505050801561057a575060408051601f3d908101601f191682019092526105779181019061103c565b60015b610623573d8080156105a8576040519150601f19603f3d011682016040523d82523d6000602084013e6105ad565b606091505b506105bf8163431dc9ff60e11b610957565b156105e1578484604051634c92543b60e01b81526004016103c092919061100d565b6105f281631859e3bb60e11b610957565b1561061457848460405163046cb69560e21b81526004016103c092919061100d565b61061d8161097b565b5061068c565b80516001600160a01b03848116911614610663576040516316343f1760e31b81526001600160a01b038084166004830152841660248201526044016103c0565b8060a001511561068a5784846040516350943b5760e11b81526004016103c092919061100d565b505b60008a81526002602052604090206106a587898361111b565b5060008a8152600260205260409081902042600190910155517f45fee04f2246b5d68ef5c7ef25c36f53a681e27c076395d9c46b22af51e8b782906106ff908c908f909182526001600160a01b0316602082015260400190565b60405180910390a1505050505050505050505050565b61071d610987565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806107c657507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166107ba600080516020611248833981519152546001600160a01b031690565b6001600160a01b031614155b156107e45760405163703e46dd60e11b815260040160405180910390fd5b565b60005460405163574a81d760e01b81523060048201526001600160a01b0383811660248301529091169063574a81d79060440160006040518083038186803b15801561083157600080fd5b505afa158015610845573d6000803e3d6000fd5b5050505050565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156108a6575060408051601f3d908101601f191682019092526108a3918101906111db565b60015b6108ce57604051634c9c8ce360e01b81526001600160a01b03831660048201526024016103c0565b60008051602061124883398151915281146108ff57604051632a87526960e21b8152600481018290526024016103c0565b61090983836109d0565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146107e45760405163703e46dd60e11b815260040160405180910390fd5b600080610963846111f4565b6001600160e01b031984811691161491505092915050565b60208101815182018082fd5b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff166107e457604051631afcd79f60e31b815260040160405180910390fd5b6109d982610a26565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115610a1e576109098282610a8b565b61034f610b01565b806001600160a01b03163b600003610a5c57604051634c9c8ce360e01b81526001600160a01b03821660048201526024016103c0565b60008051602061124883398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b031684604051610aa8919061122b565b600060405180830381855af49150503d8060008114610ae3576040519150601f19603f3d011682016040523d82523d6000602084013e610ae8565b606091505b5091509150610af8858383610b20565b95945050505050565b34156107e45760405163b398979f60e01b815260040160405180910390fd5b606082610b3557610b3082610b7f565b610b78565b8151158015610b4c57506001600160a01b0384163b155b15610b7557604051639996b31560e01b81526001600160a01b03851660048201526024016103c0565b50805b9392505050565b805115610b8f5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b604051806040016040528060608152602001610bd36040518060200160405280600081525090565b905290565b6001600160a01b0381168114610ba857600080fd5b60008083601f840112610bff57600080fd5b50813567ffffffffffffffff811115610c1757600080fd5b602083019150836020828501011115610c2f57600080fd5b9250929050565b600080600080600080600080600060e08a8c031215610c5457600080fd5b8935610c5f81610bd8565b985060208a013560ff81168114610c7557600080fd5b975060408a0135965060608a0135955060808a0135945060a08a013567ffffffffffffffff80821115610ca757600080fd5b610cb38d838e01610bed565b909650945060c08c0135915080821115610ccc57600080fd5b50610cd98c828d01610bed565b915080935050809150509295985092959850929598565b60008060408385031215610d0357600080fd5b8235610d0e81610bd8565b91506020830135610d1e81610bd8565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610d6857610d68610d29565b604052919050565b60008060408385031215610d8357600080fd5b8235610d8e81610bd8565b915060208381013567ffffffffffffffff80821115610dac57600080fd5b818601915086601f830112610dc057600080fd5b813581811115610dd257610dd2610d29565b610de4601f8201601f19168501610d3f565b91508082528784828501011115610dfa57600080fd5b80848401858401376000848284010152508093505050509250929050565b60008060008060008060808789031215610e3157600080fd5b8635610e3c81610bd8565b955060208701359450604087013567ffffffffffffffff80821115610e6057600080fd5b610e6c8a838b01610bed565b90965094506060890135915080821115610e8557600080fd5b50610e9289828a01610bed565b979a9699509497509295939492505050565b60005b83811015610ebf578181015183820152602001610ea7565b50506000910152565b60008151808452610ee0816020860160208601610ea4565b601f01601f19169290920160200192915050565b602081526000610b786020830184610ec8565b600060208284031215610f1957600080fd5b5035919050565b602081526000825160406020840152610f3c6060840182610ec8565b905060208401515160408401528091505092915050565b6001600160f81b03198a81168252891660018201526bffffffffffffffffffffffff19606089811b8216600284015288901b1660168201526b637265617465536368656d6160a01b602a82015260368101869052600084866056840137848201605681016000815284868237506000930160560192835250909998505050505050505050565b600181811c90821680610fed57607f821691505b60208210810361048b57634e487b7160e01b600052602260045260246000fd5b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b600060c0828403121561104e57600080fd5b60405160c0810181811067ffffffffffffffff8211171561107157611071610d29565b604052825161107f81610bd8565b8152602083015161108f81610bd8565b8060208301525060408301516040820152606083015160608201526080830151608082015260a083015180151581146110c757600080fd5b60a08201529392505050565b601f821115610909576000816000526020600020601f850160051c810160208610156110fc5750805b601f850160051c820191505b8181101561037f57828155600101611108565b67ffffffffffffffff83111561113357611133610d29565b611147836111418354610fd9565b836110d3565b6000601f84116001811461117b57600085156111635750838201355b600019600387901b1c1916600186901b178355610845565b600083815260209020601f19861690835b828110156111ac578685013582556020948501946001909201910161118c565b50868210156111c95760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6000602082840312156111ed57600080fd5b5051919050565b805160208201516001600160e01b031980821692919060048310156112235780818460040360031b1b83161693505b505050919050565b6000825161123d818460208701610ea4565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca26469706673582212204533d1892132dfc1158c748769945aa2e7dd76a3999b140cbba9e26ed5e6d92264736f6c63430008170033" }, "0x0000000000000000000000000000000000004444": { "comment": "Proxy: Smart contract to manage credential definitions", @@ -189,16 +222,16 @@ "code": "0x6080604052600a600c565b005b60186014601a565b6051565b565b6000604c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e808015606f573d6000f35b3d6000fdfea26469706673582212208de99705f21830b33bf2bd4a57ce70f27ec58ac48b2c88e1c96b59a11978ef8164736f6c63430008170033", "storage": { "0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000009999", - "0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000018888", + "0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000019999", "0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000005555", "f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00": "0x0000000000000000000000000000000000000000000000000000000000000001", - "360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x00000000000000000000000097fa08cd747ea254194e6ed783126688b7b955d7" + "360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000000000000000000000007ee8b37410ba6b9d190cecad255ae43740d03da1" } }, - "0x97fa08cd747ea254194e6ed783126688b7b955d7": { + "0x7ee8b37410ba6b9d190cecad255ae43740d03da1": { "comment": "Implementation: Smart contract to manage credential definitions", "balance": "0", - "code": "0x6080604052600436106100705760003560e01c8063bbc742411161004e578063bbc74241146100f0578063c0c53b8b14610110578063eaa760c214610130578063f062236b1461015d57600080fd5b80634f1ef2861461007557806352d1902d1461008a578063ad3cb1cc146100b2575b600080fd5b610088610083366004610a5c565b61017d565b005b34801561009657600080fd5b5061009f61019c565b6040519081526020015b60405180910390f35b3480156100be57600080fd5b506100e3604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100a99190610b44565b3480156100fc57600080fd5b5061008861010b366004610bc0565b6101b9565b34801561011c57600080fd5b5061008861012b366004610c2a565b6101ce565b34801561013c57600080fd5b5061009f61014b366004610c75565b60036020526000908152604090205481565b34801561016957600080fd5b50610088610178366004610c8e565b6102e5565b610185610348565b61018e826103ef565b610198828261044e565b5050565b60006101a6610515565b50600080516020610e4183398151915290565b6101c785338686868661055e565b5050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460019190600160401b900460ff16806102185750805467ffffffffffffffff808416911610155b156102365760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff191667ffffffffffffffff831617600160401b17815561026185610732565b600180546001600160a01b038681166001600160a01b0319928316179092556002805492861692909116919091179055805468ff00000000000000001916815560405167ffffffffffffffff831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15050505050565b60405160009061030b90601960f81b90839030908d908a908a908a908a90602001610d23565b60405160208183030381529060405280519060200120905061033d896103348b848c8c8c61075c565b8787878761055e565b505050505050505050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806103cf57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166103c3600080516020610e41833981519152546001600160a01b031690565b6001600160a01b031614155b156103ed5760405163703e46dd60e11b815260040160405180910390fd5b565b60005460405163574a81d760e01b81523060048201526001600160a01b0383811660248301529091169063574a81d79060440160006040518083038186803b15801561043a57600080fd5b505afa1580156101c7573d6000803e3d6000fd5b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156104a8575060408051601f3d908101601f191682019092526104a591810190610dae565b60015b6104d557604051634c9c8ce360e01b81526001600160a01b03831660048201526024015b60405180910390fd5b600080516020610e41833981519152811461050657604051632a87526960e21b8152600481018290526024016104cc565b610510838361080d565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103ed5760405163703e46dd60e11b815260040160405180910390fd5b6000848152600360205260409020548490156105905760405163b1a7a2af60e01b8152600481018290526024016104cc565b6001546040516310e67a9d60e31b81526001600160a01b03808a16600483015289928992911690638733d4e890602401602060405180830381865afa1580156105dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106019190610dc7565b6001600160a01b0316816001600160a01b0316146106455760405163cc41100960e01b81526001600160a01b038084166004830152821660248201526044016104cc565b600254604051637553b06160e11b81526004810188905287916001600160a01b03169063eaa760c2906024016020604051808303816000875af1158015610690573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b49190610dae565b6000036106d75760405163063de83560e21b8152600481018290526024016104cc565b600088815260036020526040908190204390555188907fb244582b6218e1202021c674f5f9ba330f9393f8359101bb96445efeedff3db39061071e908c908a908a90610de4565b60405180910390a250505050505050505050565b61073a610863565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6040805160008082526020820180845287905260ff8616928201929092526060810184905260808101839052819060019060a0016020604051602081039080840390855afa1580156107b2573d6000803e3d6000fd5b505050602060405103519050806001600160a01b0316876001600160a01b0316146108035760405163cc41100960e01b81526001600160a01b038089166004830152821660248201526044016104cc565b9695505050505050565b610816826108ac565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a280511561085b576105108282610911565b610198610987565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff166103ed57604051631afcd79f60e31b815260040160405180910390fd5b806001600160a01b03163b6000036108e257604051634c9c8ce360e01b81526001600160a01b03821660048201526024016104cc565b600080516020610e4183398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b03168460405161092e9190610e24565b600060405180830381855af49150503d8060008114610969576040519150601f19603f3d011682016040523d82523d6000602084013e61096e565b606091505b509150915061097e8583836109a6565b95945050505050565b34156103ed5760405163b398979f60e01b815260040160405180910390fd5b6060826109bb576109b682610a05565b6109fe565b81511580156109d257506001600160a01b0384163b155b156109fb57604051639996b31560e01b81526001600160a01b03851660048201526024016104cc565b50805b9392505050565b805115610a155780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b6001600160a01b0381168114610a2e57600080fd5b634e487b7160e01b600052604160045260246000fd5b60008060408385031215610a6f57600080fd5b8235610a7a81610a31565b9150602083013567ffffffffffffffff80821115610a9757600080fd5b818501915085601f830112610aab57600080fd5b813581811115610abd57610abd610a46565b604051601f8201601f19908116603f01168101908382118183101715610ae557610ae5610a46565b81604052828152886020848701011115610afe57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b83811015610b3b578181015183820152602001610b23565b50506000910152565b6020815260008251806020840152610b63816040850160208701610b20565b601f01601f19169190910160400192915050565b60008083601f840112610b8957600080fd5b50813567ffffffffffffffff811115610ba157600080fd5b602083019150836020828501011115610bb957600080fd5b9250929050565b600080600080600060808688031215610bd857600080fd5b8535610be381610a31565b94506020860135935060408601359250606086013567ffffffffffffffff811115610c0d57600080fd5b610c1988828901610b77565b969995985093965092949392505050565b600080600060608486031215610c3f57600080fd5b8335610c4a81610a31565b92506020840135610c5a81610a31565b91506040840135610c6a81610a31565b809150509250925092565b600060208284031215610c8757600080fd5b5035919050565b60008060008060008060008060e0898b031215610caa57600080fd5b8835610cb581610a31565b9750602089013560ff81168114610ccb57600080fd5b965060408901359550606089013594506080890135935060a0890135925060c089013567ffffffffffffffff811115610d0357600080fd5b610d0f8b828c01610b77565b999c989b5096995094979396929594505050565b6001600160f81b03198981168252881660018201526bffffffffffffffffffffffff19606088811b8216600284015287901b1660168201527f63726561746543726564656e7469616c446566696e6974696f6e000000000000602a82015260448101859052606481018490526000828460848401375060009101608401908152979650505050505050565b600060208284031215610dc057600080fd5b5051919050565b600060208284031215610dd957600080fd5b81516109fe81610a31565b6001600160a01b03841681526040602082018190528101829052818360608301376000818301606090810191909152601f909201601f1916010192915050565b60008251610e36818460208701610b20565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca26469706673582212200e0babf8db311bee606a13b3bbbda0b81acf97f50dbe34a186627f036317833f64736f6c63430008170033" + "code": "0x6080604052600436106100705760003560e01c80639f889db51161004e5780639f889db5146100d2578063ad3cb1cc146100ff578063b6c409751461013d578063c0c53b8b1461015d57600080fd5b80631108cd7b146100755780634f1ef2861461009757806352d1902d146100aa575b600080fd5b34801561008157600080fd5b50610095610090366004610ccc565b61017d565b005b6100956100a5366004610e47565b610237565b3480156100b657600080fd5b506100bf610256565b6040519081526020015b60405180910390f35b3480156100de57600080fd5b506100f26100ed366004610ed9565b610273565b6040516100c99190610f42565b34801561010b57600080fd5b50610130604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100c99190610f75565b34801561014957600080fd5b50610095610158366004610f88565b61037d565b34801561016957600080fd5b5061009561017836600461101d565b610396565b6040516000906101a790601960f81b90839030908f908c908c908c908c908c908c90602001611068565b60408051601f1981840301815282825280516020918201206000845290830180835281905260ff8d1691830191909152606082018b9052608082018a9052915061022a908c9060019060a0016020604051602081039080840390855afa158015610215573d6000803e3d6000fd5b505050602060405103518989898989896104aa565b5050505050505050505050565b61023f6107ac565b61024882610853565b61025282826108b9565b5050565b600061026061097b565b5060008051602061144283398151915290565b61027b610c42565b6000828152600360205260408120600101548391036102b557604051634f4e6fe360e11b8152600481018290526024015b60405180910390fd5b6000838152600360205260409081902081518083019092528054829082906102dc90611100565b80601f016020809104026020016040519081016040528092919081815260200182805461030890611100565b80156103555780601f1061032a57610100808354040283529160200191610355565b820191906000526020600020905b81548152906001019060200180831161033857829003601f168201915b5050509183525050604080516020818101909252600193909301548352015291505b50919050565b61038d87338888888888886104aa565b50505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460019190600160401b900460ff16806103df575080546001600160401b03808416911610155b156103fd5760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff19166001600160401b03831617600160401b178155610427856109c4565b600180546001600160a01b038681166001600160a01b0319928316179092556002805492861692909116919091179055805468ff0000000000000000191681556040516001600160401b03831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15050505050565b6000868152600360205260409020600101548690156104df5760405163b1a7a2af60e01b8152600481018290526024016102ac565b85858a8a806001600160a01b0316826001600160a01b031614610528576040516316343f1760e31b81526001600160a01b038083166004830152831660248201526044016102ac565b6001546040516366874f2560e01b81526001600160a01b03909116906366874f259061055a9087908790600401611134565b60c060405180830381865afa925050508015610593575060408051601f3d908101601f1916820190925261059091810190611163565b60015b61063c573d8080156105c1576040519150601f19603f3d011682016040523d82523d6000602084013e6105c6565b606091505b506105d88163431dc9ff60e11b6109ee565b156105fa578484604051634c92543b60e01b81526004016102ac929190611134565b61060b81631859e3bb60e11b6109ee565b1561062d57848460405163046cb69560e21b81526004016102ac929190611134565b61063681610a12565b506106a5565b80516001600160a01b0384811691161461067c576040516316343f1760e31b81526001600160a01b038084166004830152841660248201526044016102ac565b8060a00151156106a35784846040516350943b5760e11b81526004016102ac929190611134565b505b600254604051632bafb2c760e21b8152600481018a905289916001600160a01b03169063aebecb1c906024016000604051808303816000875af11580156106f0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261071891908101906111f9565b5060008c8152600360205260409020610732888a83611316565b5042600360008e8152602001908152602001600020600101600001819055507f61a38b1ae2b65567a5f16692367ae7ac5760505f17b3b6e83e306795b9a83ffc8c8f6040516107949291909182526001600160a01b0316602082015260400190565b60405180910390a15050505050505050505050505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061083357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610827600080516020611442833981519152546001600160a01b031690565b6001600160a01b031614155b156108515760405163703e46dd60e11b815260040160405180910390fd5b565b60005460405163574a81d760e01b81523060048201526001600160a01b0383811660248301529091169063574a81d79060440160006040518083038186803b15801561089e57600080fd5b505afa1580156108b2573d6000803e3d6000fd5b5050505050565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610913575060408051601f3d908101601f19168201909252610910918101906113d5565b60015b61093b57604051634c9c8ce360e01b81526001600160a01b03831660048201526024016102ac565b600080516020611442833981519152811461096c57604051632a87526960e21b8152600481018290526024016102ac565b6109768383610a1e565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146108515760405163703e46dd60e11b815260040160405180910390fd5b6109cc610a74565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806109fa846113ee565b6001600160e01b031984811691161491505092915050565b60208101815182018082fd5b610a2782610abd565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115610a6c576109768282610b22565b610252610b98565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661085157604051631afcd79f60e31b815260040160405180910390fd5b806001600160a01b03163b600003610af357604051634c9c8ce360e01b81526001600160a01b03821660048201526024016102ac565b60008051602061144283398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b031684604051610b3f9190611425565b600060405180830381855af49150503d8060008114610b7a576040519150601f19603f3d011682016040523d82523d6000602084013e610b7f565b606091505b5091509150610b8f858383610bb7565b95945050505050565b34156108515760405163b398979f60e01b815260040160405180910390fd5b606082610bcc57610bc782610c16565b610c0f565b8151158015610be357506001600160a01b0384163b155b15610c0c57604051639996b31560e01b81526001600160a01b03851660048201526024016102ac565b50805b9392505050565b805115610c265780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b604051806040016040528060608152602001610c6a6040518060200160405280600081525090565b905290565b6001600160a01b0381168114610c3f57600080fd5b60008083601f840112610c9657600080fd5b5081356001600160401b03811115610cad57600080fd5b602083019150836020828501011115610cc557600080fd5b9250929050565b6000806000806000806000806000806101008b8d031215610cec57600080fd5b8a35610cf781610c6f565b995060208b013560ff81168114610d0d57600080fd5b985060408b0135975060608b0135965060808b0135955060a08b01356001600160401b0380821115610d3e57600080fd5b610d4a8e838f01610c84565b909750955060c08d0135945060e08d0135915080821115610d6a57600080fd5b50610d778d828e01610c84565b915080935050809150509295989b9194979a5092959850565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715610dc857610dc8610d90565b60405290565b604051602081016001600160401b0381118282101715610dc857610dc8610d90565b604051601f8201601f191681016001600160401b0381118282101715610e1857610e18610d90565b604052919050565b60006001600160401b03821115610e3957610e39610d90565b50601f01601f191660200190565b60008060408385031215610e5a57600080fd5b8235610e6581610c6f565b915060208301356001600160401b03811115610e8057600080fd5b8301601f81018513610e9157600080fd5b8035610ea4610e9f82610e20565b610df0565b818152866020838501011115610eb957600080fd5b816020840160208301376000602083830101528093505050509250929050565b600060208284031215610eeb57600080fd5b5035919050565b60005b83811015610f0d578181015183820152602001610ef5565b50506000910152565b60008151808452610f2e816020860160208601610ef2565b601f01601f19169290920160200192915050565b602081526000825160406020840152610f5e6060840182610f16565b905060208401515160408401528091505092915050565b602081526000610c0f6020830184610f16565b600080600080600080600060a0888a031215610fa357600080fd5b8735610fae81610c6f565b96506020880135955060408801356001600160401b0380821115610fd157600080fd5b610fdd8b838c01610c84565b909750955060608a0135945060808a0135915080821115610ffd57600080fd5b5061100a8a828b01610c84565b989b979a50959850939692959293505050565b60008060006060848603121561103257600080fd5b833561103d81610c6f565b9250602084013561104d81610c6f565b9150604084013561105d81610c6f565b809150509250925092565b6001600160f81b03198b811682528a1660018201526bffffffffffffffffffffffff1960608a811b8216600284015289901b1660168201527f63726561746543726564656e7469616c446566696e6974696f6e000000000000602a82015260448101879052600085876064840137858201856064820152838560848301376000930160840192835250909a9950505050505050505050565b600181811c9082168061111457607f821691505b60208210810361037757634e487b7160e01b600052602260045260246000fd5b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b600060c0828403121561117557600080fd5b60405160c081018181106001600160401b038211171561119757611197610d90565b60405282516111a581610c6f565b815260208301516111b581610c6f565b8060208301525060408301516040820152606083015160608201526080830151608082015260a083015180151581146111ed57600080fd5b60a08201529392505050565b6000602080838503121561120c57600080fd5b82516001600160401b038082111561122357600080fd5b90840190818603604081121561123857600080fd5b611240610da6565b83518381111561124f57600080fd5b84019250601f8301881361126257600080fd5b8251611270610e9f82610e20565b818152898783870101111561128457600080fd5b61129382888301898801610ef2565b825250601f1982018513156112a757600080fd5b6112af610dce565b938501518452938401929092525090949350505050565b601f821115610976576000816000526020600020601f850160051c810160208610156112ef5750805b601f850160051c820191505b8181101561130e578281556001016112fb565b505050505050565b6001600160401b0383111561132d5761132d610d90565b6113418361133b8354611100565b836112c6565b6000601f841160018114611375576000851561135d5750838201355b600019600387901b1c1916600186901b1783556108b2565b600083815260209020601f19861690835b828110156113a65786850135825560209485019460019092019101611386565b50868210156113c35760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6000602082840312156113e757600080fd5b5051919050565b805160208201516001600160e01b0319808216929190600483101561141d5780818460040360031b1b83161693505b505050919050565b60008251611437818460208701610ef2565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca2646970667358221220c96fc6e45fc35d5c60e3494e9c7ef987a34777e0916d4309e672d9aa11dae87664736f6c63430008170033" } } } diff --git a/network/config/nodes/validator5/key b/network/config/nodes/validator5/key index cc082ea6..17152833 100644 --- a/network/config/nodes/validator5/key +++ b/network/config/nodes/validator5/key @@ -1 +1 @@ -0xac6701921de0697f32539d9e95ffa85bbb846203ea2fce4cc19516c79ce578aa \ No newline at end of file +0x70f01ee7ca066302d6af3fd5fac6f07adf0b61ec8eb8c97d23cf72396090b15b \ No newline at end of file diff --git a/smart_contracts/README.md b/smart_contracts/README.md index ff1f593b..fe023d91 100644 --- a/smart_contracts/README.md +++ b/smart_contracts/README.md @@ -34,8 +34,10 @@ The following folders should be generated as the result: * [AccountControl TS contract wrapper class](./contracts-ts/AccountControl.ts) * [RoleControl](./contracts/auth/RoleControlInterface.sol) - contract to manage (assign/revoke) account roles. * [RoleControl TS contract wrapper class](./contracts-ts/RoleControl.ts) +* [IndyDidRegistry](./contracts/did/IndyDidRegistry.sol) - `indybesu` DID Registry + * [IndyDidRegistry TS contract wrapper class](./contracts-ts/IndyDidRegistry.ts) * [EthereumExtDidRegistry](./contracts/did/EthereumExtDidRegistry.sol) - [Ethereum DID Registry](https://github.com/uport-project/ethr-did-registry/tree/master) extended with permission checks - * [DidRegistry TS contract wrapper class](./contracts-ts/EthereumExtDidRegistry.ts) + * [DidRegistry TS contract wrapper class](./contracts-ts/EthereumDIDRegistry.ts) * [SchemaRegistry](./contracts/cl/SchemaRegistryInterface.sol) - contract to manage Schemas * [SchemaRegistry TS contract wrapper class](./contracts-ts/SchemaRegistry.ts) * [CredentialDefinitionRegistry](./contracts/cl/CredentialDefinitionRegistryInterface.sol) - contract to manage CL Credential Definitions @@ -53,10 +55,14 @@ You can find sample scripts demonstrating the usage of deployed contracts in the ``` > yarn demo/account ``` -* [Demo flow](./demos/flow.ts) - create/resolve DID/Schema/Credential Definition. +* [Demo flow](./demos/flow.ts) - create/resolve DID/Schema/Credential Definition using `did:indy2` method. ``` > yarn demo/flow ``` +* [Demo flow](./demos/flow-with-did-ethr.ts) - create/resolve DID/Schema/Credential Definition using `did:ethr` method. + ``` + > yarn demo/flow-with-did-ethr + ``` * [Roles management](./demos/role-control.ts) - get/assign/revoke role to/from account. ``` > yarn demo/roles @@ -85,12 +91,12 @@ You can find sample scripts demonstrating the usage of deployed contracts in the yarn solc-compile ``` - * `artifacts` and `compiled-contracts` folders with compiled contracts will be generated as the result of the execution. + * `artifacts` and `compiled-contracts` folders with compiled contracts will be generated as the result of the execution. 3. Execute script generating the contracts content for the network genesis file: > yarn genesis/generate - * `ContractsGenesis.json` file will be generated as the result + * `ContractsGenesis.json` file will be generated as the result 4. Put the whole block into the `alloc` section of the network genesis file. diff --git a/smart_contracts/contracts-ts/CredentialDefinitionRegistry.ts b/smart_contracts/contracts-ts/CredentialDefinitionRegistry.ts index cd86820d..fb2ae8ba 100644 --- a/smart_contracts/contracts-ts/CredentialDefinitionRegistry.ts +++ b/smart_contracts/contracts-ts/CredentialDefinitionRegistry.ts @@ -1,7 +1,13 @@ -import { getBytes, keccak256, Signature, toUtf8Bytes, toUtf8String } from 'ethers' -import { CredentialDefinitionCreatedEvent } from '../typechain-types/contracts/cl/CredentialDefinitionRegistry' +import { concat, getBytes, keccak256, Signature, toUtf8Bytes, toUtf8String } from 'ethers' +import { signEndorsementData } from '../test/utils/contract-helpers' +import { CredentialDefinitionMetadataStruct } from '../typechain-types/contracts/cl/CredentialDefinitionRegistry' import { Contract } from '../utils/contract' +export type CredentialDefinitionRecord = { + credDef: string + metadata: CredentialDefinitionMetadataStruct +} + export class CredentialDefinitionRegistry extends Contract { public static readonly defaultAddress = '0x0000000000000000000000000000000000004444' @@ -9,10 +15,17 @@ export class CredentialDefinitionRegistry extends Contract { super(CredentialDefinitionRegistry.name, sender) } - public async createCredentialDefinition(identity: string, id: string, schemaId: string, credDef: string) { + public async createCredentialDefinition( + identity: string, + id: string, + issuerId: string, + schemaId: string, + credDef: string, + ) { const tx = await this.instance.createCredentialDefinition( identity, keccak256(toUtf8Bytes(id)), + issuerId, keccak256(toUtf8Bytes(schemaId)), toUtf8Bytes(credDef), ) @@ -22,6 +35,7 @@ export class CredentialDefinitionRegistry extends Contract { public async createCredentialDefinitionSigned( identity: string, id: string, + issuerId: string, schemaId: string, credDef: string, signature: Signature, @@ -32,19 +46,41 @@ export class CredentialDefinitionRegistry extends Contract { signature.r, signature.s, keccak256(toUtf8Bytes(id)), + issuerId, keccak256(toUtf8Bytes(schemaId)), toUtf8Bytes(credDef), ) return tx.wait() } - public async created(id: string): Promise { - return this.instance.created(keccak256(toUtf8Bytes(id))) + public async resolveCredentialDefinition(id: string): Promise { + const record = await this.instance.resolveCredentialDefinition(keccak256(toUtf8Bytes(id))) + return { + credDef: toUtf8String(getBytes(record.credDef)), + metadata: { + created: record.metadata.created, + }, + } } - public async resolveCredentialDefinition(id: string): Promise { - const filer = await this.instance.filters.CredentialDefinitionCreated(keccak256(toUtf8Bytes(id))) - const events = await this.instance.queryFilter(filer) - return toUtf8String(getBytes(events[0].args[2])) + public signCreateCredDefEndorsementData( + identity: string, + privateKey: Uint8Array, + id: string, + issuerId: string, + schemaId: string, + credDef: string, + ) { + return this.signEndorsementData( + privateKey, + concat([ + identity, + toUtf8Bytes('createCredentialDefinition'), + getBytes(keccak256(toUtf8Bytes(id)), 'hex'), + toUtf8Bytes(issuerId), + getBytes(keccak256(toUtf8Bytes(schemaId)), 'hex'), + toUtf8Bytes(credDef), + ]), + ) } } diff --git a/smart_contracts/contracts-ts/EthereumExtDidRegistry.ts b/smart_contracts/contracts-ts/EthereumDIDRegistry.ts similarity index 100% rename from smart_contracts/contracts-ts/EthereumExtDidRegistry.ts rename to smart_contracts/contracts-ts/EthereumDIDRegistry.ts diff --git a/smart_contracts/contracts-ts/IndyDidRegistry.ts b/smart_contracts/contracts-ts/IndyDidRegistry.ts index 1e1c5a01..d8a2d8ee 100644 --- a/smart_contracts/contracts-ts/IndyDidRegistry.ts +++ b/smart_contracts/contracts-ts/IndyDidRegistry.ts @@ -1,5 +1,11 @@ +import { concat, getBytes, Signature, toUtf8Bytes, toUtf8String } from 'ethers' +import { DidMetadataStruct } from '../typechain-types/contracts/did/IndyDidRegistry' import { Contract } from '../utils/contract' -import { DidRecord, mapDidRecord } from './types' + +export type DidRecord = { + document: string + metadata: DidMetadataStruct +} export class IndyDidRegistry extends Contract { public static readonly defaultAddress = '0x0000000000000000000000000000000000003333' @@ -8,23 +14,72 @@ export class IndyDidRegistry extends Contract { super(IndyDidRegistry.name, sender) } - public async createDid(identity: string, did: string, document: string) { - const tx = await this.instance.createDid(identity, did, document) + public async createDid(identity: string, document: string) { + const tx = await this.instance.createDid(identity, toUtf8Bytes(document)) + return tx.wait() + } + + public async createDidSigned(identity: string, document: string, signature: Signature) { + const tx = await this.instance.createDidSigned( + identity, + signature.v, + signature.r, + signature.s, + toUtf8Bytes(document), + ) return tx.wait() } - public async updateDid(did: string, document: string) { - const tx = await this.instance.updateDid(did, document) + public async updateDid(identity: string, document: string) { + const tx = await this.instance.updateDid(identity, toUtf8Bytes(document)) return tx.wait() } - public async deactivateDid(did: string) { - const tx = await this.instance.deactivateDid(did) + public async updateDidSigned(identity: string, document: string, signature: Signature) { + const tx = await this.instance.updateDidSigned( + identity, + signature.v, + signature.r, + signature.s, + toUtf8Bytes(document), + ) return tx.wait() } - public async resolveDid(did: string): Promise { - const didRecord = await this.instance.resolveDid(did) - return mapDidRecord(didRecord) + public async deactivateDid(identity: string) { + const tx = await this.instance.deactivateDid(identity) + return tx.wait() + } + + public async deactivateDidSigned(identity: string, signature: Signature) { + const tx = await this.instance.deactivateDidSigned(identity, signature.v, signature.r, signature.s) + return tx.wait() + } + + public async resolveDid(identity: string): Promise { + const record = await this.instance.resolveDid(identity) + return { + document: toUtf8String(getBytes(record.document)), + metadata: { + owner: record.metadata.owner, + sender: record.metadata.sender, + created: record.metadata.created, + updated: record.metadata.updated, + versionId: record.metadata.versionId, + deactivated: record.metadata.deactivated, + }, + } + } + + public signCreateDidEndorsementData(identity: string, privateKey: Uint8Array, document: string) { + return this.signEndorsementData(privateKey, concat([identity, toUtf8Bytes('createDid'), toUtf8Bytes(document)])) + } + + public signUpdateDidEndorsementData(identity: string, privateKey: Uint8Array, document: string) { + return this.signEndorsementData(privateKey, concat([identity, toUtf8Bytes('updateDid'), toUtf8Bytes(document)])) + } + + public signDeactivateDidEndorsementData(identity: string, privateKey: Uint8Array) { + return this.signEndorsementData(privateKey, concat([identity, toUtf8Bytes('deactivateDid')])) } } diff --git a/smart_contracts/contracts-ts/SchemaRegistry.ts b/smart_contracts/contracts-ts/SchemaRegistry.ts index 41b5fba7..7ff4fac5 100644 --- a/smart_contracts/contracts-ts/SchemaRegistry.ts +++ b/smart_contracts/contracts-ts/SchemaRegistry.ts @@ -1,7 +1,12 @@ -import { getBytes, keccak256, Signature, toUtf8Bytes, toUtf8String } from 'ethers' -import { SchemaCreatedEvent } from '../typechain-types/contracts/cl/SchemaRegistryInterface' +import { concat, getBytes, keccak256, Signature, toUtf8Bytes, toUtf8String } from 'ethers' +import { SchemaMetadataStruct } from '../typechain-types/contracts/cl/SchemaRegistry' import { Contract } from '../utils/contract' +export type SchemaRecord = { + schema: string + metadata: SchemaMetadataStruct +} + export class SchemaRegistry extends Contract { public static readonly defaultAddress = '0x0000000000000000000000000000000000005555' @@ -9,30 +14,56 @@ export class SchemaRegistry extends Contract { super(SchemaRegistry.name, sender) } - public async createSchema(identity: string, id: string, schema: string) { - const tx = await this.instance.createSchema(identity, keccak256(toUtf8Bytes(id)), toUtf8Bytes(schema)) + public async createSchema(identity: string, id: string, issuerId: string, schema: string) { + const tx = await this.instance.createSchema(identity, keccak256(toUtf8Bytes(id)), issuerId, toUtf8Bytes(schema)) return tx.wait() } - public async createSchemaSigned(identity: string, id: string, schema: string, signature: Signature) { + public async createSchemaSigned( + identity: string, + id: string, + issuerId: string, + schema: string, + signature: Signature, + ) { const tx = await this.instance.createSchemaSigned( identity, signature.v, signature.r, signature.s, keccak256(toUtf8Bytes(id)), + issuerId, toUtf8Bytes(schema), ) return tx.wait() } - public async created(id: string): Promise { - return this.instance.created(keccak256(toUtf8Bytes(id))) + public async resolveSchema(id: string): Promise { + const record = await this.instance.resolveSchema(keccak256(toUtf8Bytes(id))) + return { + schema: toUtf8String(getBytes(record.schema)), + metadata: { + created: record.metadata.created, + }, + } } - public async resolveSchema(schemaId: string): Promise { - const filer = await this.instance.filters.SchemaCreated(keccak256(toUtf8Bytes(schemaId))) - const events = await this.instance.queryFilter(filer) - return toUtf8String(getBytes(events[0].args[2])) + public async signCreateSchemaEndorsementData( + identity: string, + privateKey: Uint8Array, + id: string, + issuerId: string, + schema: string, + ) { + return this.signEndorsementData( + privateKey, + concat([ + identity, + toUtf8Bytes('createSchema'), + getBytes(keccak256(toUtf8Bytes(id)), 'hex'), + toUtf8Bytes(issuerId), + toUtf8Bytes(schema), + ]), + ) } } diff --git a/smart_contracts/contracts-ts/UniversalDidReolver.ts b/smart_contracts/contracts-ts/UniversalDidReolver.ts index 0094cb48..b371ad35 100644 --- a/smart_contracts/contracts-ts/UniversalDidReolver.ts +++ b/smart_contracts/contracts-ts/UniversalDidReolver.ts @@ -1,5 +1,6 @@ +import { getBytes, toUtf8String } from 'ethers' +import { DidMetadataStruct } from '../typechain-types/contracts/did/IndyDidRegistry' import { Contract } from '../utils' -import { DidMetadata, mapDidMetadata } from './types' export class UniversalDidResolver extends Contract { public static readonly defaultAddress = '0x000000000000000000000000000000000019999' @@ -9,11 +10,17 @@ export class UniversalDidResolver extends Contract { } public async resolveDocument(id: string): Promise { - return this.instance.resolveDocument(id) + return toUtf8String(getBytes(await this.instance.resolveDocument(id))) } - public async resolveMetadata(id: string): Promise { + public async resolveMetadata(id: string): Promise { const metadata = await this.instance.resolveMetadata(id) - return mapDidMetadata(metadata) + return { + owner: metadata.owner, + sender: metadata.sender, + created: metadata.created, + updated: metadata.updated, + deactivated: metadata.deactivated, + } } } diff --git a/smart_contracts/contracts-ts/index.ts b/smart_contracts/contracts-ts/index.ts index 5666ab2c..5467b668 100644 --- a/smart_contracts/contracts-ts/index.ts +++ b/smart_contracts/contracts-ts/index.ts @@ -1,7 +1,9 @@ export * from './AccountControl' export * from './CredentialDefinitionRegistry' -export * from './EthereumExtDidRegistry' +export * from './IndyDidRegistry' +export * from './EthereumDIDRegistry' export * from './RoleControl' export * from './SchemaRegistry' +export * from './UniversalDidReolver' export * from './UpgradeControl' export * from './ValidatorControl' diff --git a/smart_contracts/contracts-ts/types/CredentialDefinition.ts b/smart_contracts/contracts-ts/types/CredentialDefinition.ts deleted file mode 100644 index 5cc049fc..00000000 --- a/smart_contracts/contracts-ts/types/CredentialDefinition.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { CredentialDefinitionRecordStruct } from '../../typechain-types/contracts/cl/CredentialDefinitionRegistryInterface' - -export type CredentialDefinitionRecord = CredentialDefinitionRecordStruct - -export function mapCredentialDefinitionRecord(data: CredentialDefinitionRecordStruct) { - return { - credDef: data.credDef, - metadata: { - created: data.metadata.created, - }, - } -} diff --git a/smart_contracts/contracts-ts/types/Did.ts b/smart_contracts/contracts-ts/types/Did.ts deleted file mode 100644 index 3b803657..00000000 --- a/smart_contracts/contracts-ts/types/Did.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { DidMetadataStruct, DidRecordStruct } from '../../typechain-types/contracts/did/IndyDidRegistry' - -export type DidRecord = DidRecordStruct -export type DidMetadata = DidMetadataStruct - -export function mapDidMetadata(metadata: DidMetadata) { - return { - owner: metadata.owner, - sender: metadata.sender, - created: metadata.created, - updated: metadata.updated, - deactivated: metadata.deactivated, - } -} - -export function mapDidRecord(record: DidRecord) { - return { - document: record.document, - metadata: mapDidMetadata(record.metadata), - } -} diff --git a/smart_contracts/contracts-ts/types/Schema.ts b/smart_contracts/contracts-ts/types/Schema.ts deleted file mode 100644 index a8d2dde3..00000000 --- a/smart_contracts/contracts-ts/types/Schema.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { SchemaRecordStruct } from '../../typechain-types/contracts/cl/SchemaRegistryInterface' - -export type SchemaRecord = SchemaRecordStruct - -export function mapSchemaRecord(record: SchemaRecord) { - return { - schema: record.schema, - metadata: { - created: record.metadata.created, - }, - } -} diff --git a/smart_contracts/contracts-ts/types/index.ts b/smart_contracts/contracts-ts/types/index.ts deleted file mode 100644 index c44ef121..00000000 --- a/smart_contracts/contracts-ts/types/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './Did' -export * from './CredentialDefinition' -export * from './Schema' diff --git a/smart_contracts/contracts/cl/CLRegistry.sol b/smart_contracts/contracts/cl/CLRegistry.sol index 5e098a6f..5e4db3fe 100644 --- a/smart_contracts/contracts/cl/CLRegistry.sol +++ b/smart_contracts/contracts/cl/CLRegistry.sol @@ -1,33 +1,50 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.20; -import { UnauthorizedIssuer } from "./ClErrors.sol"; -import { EthereumExtDidRegistry } from "../did/EthereumExtDidRegistry.sol"; +import { DidNotFound, IncorrectDid, NotIdentityOwner } from "../did/DidErrors.sol"; +import { DidMetadata } from "../did/DidTypes.sol"; +import { UniversalDidResolverInterface } from "../did/UniversalDidResolverInterface.sol"; +import { Errors } from "../utils/Errors.sol"; +import { InvalidIssuerId, IssuerHasBeenDeactivated, IssuerNotFound } from "./ClErrors.sol"; contract CLRegistry { /** - * @dev Reference to the DID registry contract + * @dev Reference to the contract that resolves DIDs */ - EthereumExtDidRegistry internal _didRegistry; + UniversalDidResolverInterface internal _didResolver; - modifier _validIssuer(address identity, address actor) { - if (actor != _didRegistry.identityOwner(identity)) { - revert UnauthorizedIssuer(identity, actor); - } + /** + * Checks that actor matches to the identity + */ + modifier _identityOwner(address identity, address actor) { + if (identity != actor) revert NotIdentityOwner(actor, identity); _; } - function _checkSignature( + /** + * @dev Check that the Issuer DID exist, authorized for actor, and active. + * @param did The Issuer's Account. + * @param identity The Issuer's DID. + * @param actor Actor identity address. + */ + modifier _validIssuer( + string calldata did, address identity, - bytes32 hash, - uint8 sigV, - bytes32 sigR, - bytes32 sigS - ) internal pure returns (address) { - address signer = ecrecover(hash, sigV, sigR, sigS); - if (identity != signer) { - revert UnauthorizedIssuer(identity, signer); + address actor + ) { + if (identity != actor) revert NotIdentityOwner(actor, identity); + + try _didResolver.resolveMetadata(did) returns (DidMetadata memory metadata) { + if (identity != metadata.owner) { + revert NotIdentityOwner(actor, identity); + } + if (metadata.deactivated) revert IssuerHasBeenDeactivated(did); + } catch (bytes memory reason) { + if (Errors.equals(reason, DidNotFound.selector)) revert IssuerNotFound(did); + if (Errors.equals(reason, IncorrectDid.selector)) revert InvalidIssuerId(did); + + Errors.rethrow(reason); } - return signer; + _; } } diff --git a/smart_contracts/contracts/cl/ClErrors.sol b/smart_contracts/contracts/cl/ClErrors.sol index d01b6324..9723d2f7 100644 --- a/smart_contracts/contracts/cl/ClErrors.sol +++ b/smart_contracts/contracts/cl/ClErrors.sol @@ -1,36 +1,50 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.20; +// Issuer errors + +/** + * @notice Error that occurs when the provided issuer is not found. + * @param did Issuer DID. + */ +error IssuerNotFound(string did); + +/** + * @notice Error that occurs when the provided issuer ID is invalid. + * @param did Issuer DID. + */ +error InvalidIssuerId(string did); + +/** + * @notice Error that occurs when attempting to perform an operation on behalf of a deactivated issuer. + * @param did Issuer DID. + */ +error IssuerHasBeenDeactivated(string did); + // Schema errors /** - * @notice Error that occurs when trying to create an already existing schema. - * @param id Schema ID. + * @notice Error that occurs when trying to create a schema with already existing schema identifier. + * @param id Keccak hash of Schema ID. */ error SchemaAlreadyExist(bytes32 id); /** * @notice Error that occurs when the specified schema is not found. - * @param id Schema ID. + * @param id Keccak hash of Schema ID. */ error SchemaNotFound(bytes32 id); // CredDef errors /** - * @notice Error that occurs when trying to create an existing credential definition. - * @param id Credential definition ID. + * @notice Error that occurs when trying to create a credential definition with already existing identifier. + * @param id Keccak hash of Credential definition ID. */ error CredentialDefinitionAlreadyExist(bytes32 id); /** * @notice Error that occurs when the specified credential definition is not found. - * @param id Credential definition ID. + * @param id Keccak hash of Credential definition ID. */ error CredentialDefinitionNotFound(bytes32 id); - -/** - * @notice Error that occurs when issuer DID of Schema or CredentialDefinition is not owned by sender. - * @param sender Sender account address. - */ -error UnauthorizedIssuer(address sender, address owner); diff --git a/smart_contracts/contracts/cl/CredentialDefinitionRegistry.sol b/smart_contracts/contracts/cl/CredentialDefinitionRegistry.sol index 5c03cb2f..6f848327 100644 --- a/smart_contracts/contracts/cl/CredentialDefinitionRegistry.sol +++ b/smart_contracts/contracts/cl/CredentialDefinitionRegistry.sol @@ -1,30 +1,39 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.20; +import { UniversalDidResolverInterface } from "../did/UniversalDidResolverInterface.sol"; import { ControlledUpgradeable } from "../upgrade/ControlledUpgradeable.sol"; +import { CredentialDefinitionRecord } from "./CredentialDefinitionTypes.sol"; import { CredentialDefinitionRegistryInterface } from "./CredentialDefinitionRegistryInterface.sol"; -import { CredentialDefinitionAlreadyExist, SchemaNotFound } from "./ClErrors.sol"; +import { CredentialDefinitionAlreadyExist, CredentialDefinitionNotFound } from "./ClErrors.sol"; import { CLRegistry } from "./CLRegistry.sol"; import { SchemaRegistryInterface } from "./SchemaRegistryInterface.sol"; -import { EthereumExtDidRegistry } from "../did/EthereumExtDidRegistry.sol"; contract CredentialDefinitionRegistry is CredentialDefinitionRegistryInterface, ControlledUpgradeable, CLRegistry { /** - * @dev Reference to the contract that manages anoncreds schemas + * @dev Reference to the contract that manages AnonCreds schemas */ SchemaRegistryInterface private _schemaRegistry; /** - * Mapping to track created credential definitions by their id to block number. + * Mapping Credential Definition ID to its Credential Definition Details and Metadata. */ - mapping(bytes32 id => uint block) public created; + mapping(bytes32 id => CredentialDefinitionRecord credentialDefinitionRecord) private _credDefs; /** * Checks the uniqueness of the credential definition ID */ modifier _uniqueCredDefId(bytes32 id) { - if (created[id] != 0) revert CredentialDefinitionAlreadyExist(id); + if (_credDefs[id].metadata.created != 0) revert CredentialDefinitionAlreadyExist(id); + _; + } + + /** + * Checks that the credential definition exist + */ + modifier _credDefExist(bytes32 id) { + if (_credDefs[id].metadata.created == 0) revert CredentialDefinitionNotFound(id); _; } @@ -32,17 +41,17 @@ contract CredentialDefinitionRegistry is CredentialDefinitionRegistryInterface, * Checks that the schema exist */ modifier _schemaExist(bytes32 id) { - if (_schemaRegistry.created(id) == 0) revert SchemaNotFound(id); + _schemaRegistry.resolveSchema(id); _; } function initialize( address upgradeControlAddress, - address ethereumExtDidRegistry, + address didResolverAddress, address schemaRegistryAddress ) public reinitializer(1) { _initializeUpgradeControl(upgradeControlAddress); - _didRegistry = EthereumExtDidRegistry(ethereumExtDidRegistry); + _didResolver = UniversalDidResolverInterface(didResolverAddress); _schemaRegistry = SchemaRegistryInterface(schemaRegistryAddress); } @@ -50,10 +59,11 @@ contract CredentialDefinitionRegistry is CredentialDefinitionRegistryInterface, function createCredentialDefinition( address identity, bytes32 id, + string calldata issuerId, bytes32 schemaId, bytes calldata credDef ) public virtual { - _createCredentialDefinition(identity, msg.sender, id, schemaId, credDef); + _createCredentialDefinition(identity, msg.sender, id, issuerId, schemaId, credDef); } /// @inheritdoc CredentialDefinitionRegistryInterface @@ -63,6 +73,7 @@ contract CredentialDefinitionRegistry is CredentialDefinitionRegistryInterface, bytes32 sigR, bytes32 sigS, bytes32 id, + string calldata issuerId, bytes32 schemaId, bytes calldata credDef ) public virtual { @@ -74,21 +85,32 @@ contract CredentialDefinitionRegistry is CredentialDefinitionRegistryInterface, identity, "createCredentialDefinition", id, + issuerId, schemaId, credDef ) ); - _createCredentialDefinition(identity, _checkSignature(identity, hash, sigV, sigR, sigS), id, schemaId, credDef); + _createCredentialDefinition(identity, ecrecover(hash, sigV, sigR, sigS), id, issuerId, schemaId, credDef); + } + + /// @inheritdoc CredentialDefinitionRegistryInterface + function resolveCredentialDefinition( + bytes32 id + ) public view virtual _credDefExist(id) returns (CredentialDefinitionRecord memory credentialDefinitionRecord) { + return _credDefs[id]; } function _createCredentialDefinition( address identity, address actor, bytes32 id, + string calldata issuerId, bytes32 schemaId, bytes calldata credDef - ) internal _uniqueCredDefId(id) _validIssuer(identity, actor) _schemaExist(schemaId) { - created[id] = block.number; - emit CredentialDefinitionCreated(id, actor, credDef); + ) internal _uniqueCredDefId(id) _validIssuer(issuerId, identity, actor) _schemaExist(schemaId) { + _credDefs[id].credDef = credDef; + _credDefs[id].metadata.created = block.timestamp; + + emit CredentialDefinitionCreated(id, identity); } } diff --git a/smart_contracts/contracts/cl/CredentialDefinitionRegistryInterface.sol b/smart_contracts/contracts/cl/CredentialDefinitionRegistryInterface.sol index 18e5248b..4d8c901e 100644 --- a/smart_contracts/contracts/cl/CredentialDefinitionRegistryInterface.sol +++ b/smart_contracts/contracts/cl/CredentialDefinitionRegistryInterface.sol @@ -1,57 +1,67 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.20; +import { CredentialDefinitionRecord } from "./CredentialDefinitionTypes.sol"; + interface CredentialDefinitionRegistryInterface { /** - * @dev Event that is sent when a Credential Definition is created. + * @dev Event that is sent when a Credential Definition is created * - * @param id KECCAK256 hash of credential definition id. - * @param identity Account address of credential definition issuer. - * @param credDef AnonCreds credential definition object as bytes. + * @param credentialDefinitionId Keccak hash of created credential definition id + * @param identity Issuer address */ - event CredentialDefinitionCreated(bytes32 indexed id, address identity, bytes credDef); + event CredentialDefinitionCreated(bytes32 credentialDefinitionId, address identity); /** * @dev Creates a new Credential Definition. * * Once the Credential Definition is created, this function emits a `CredentialDefinitionCreated` event - * with the new Credential Definition's ID. + * with the new Credential Definition's ID and issuer address. * * This function can revert with following errors: * - `CredentialDefinitionAlreadyExist`: Raised if Credential Definition with provided ID already exist. * - `SchemaNotFound`: Raised if the associated schema doesn't exist. - * - `UnauthorizedIssuer`: Raised when an issuer DID specified in CredentialDefinition is not owned by sender + * - `IssuerNotFound`: Raised if the associated issuer doesn't exist. + * - `InvalidIssuerId`: Raised if the provided issuer DID is invalid. + * - `IssuerHasBeenDeactivated`: Raised if the associated issuer is not active. + * - `NotIdentityOwner`: Raised when specified issuer DID is not owned by sender. * * @param identity Account address of credential definition issuer. - * @param id KECCAK256 hash of credential definition id to be created. - * @param schemaId KECCAK256 hash of schema id. - * @param credDef AnonCreds credential definition object as bytes. + * @param id Keccak hash of Credential Definition id to be created. + * @param issuerId DID of Credential Definition issuer. + * @param schemaId Keccak hash of Schema id. + * @param credDef AnonCreds Credential Definition JSON as bytes. */ function createCredentialDefinition( address identity, bytes32 id, + string calldata issuerId, bytes32 schemaId, bytes calldata credDef ) external; /** - * @dev Endorse a new Credential Definition. + * @dev Endorse a new Credential Definition (off-chain author signature). * * Once the Credential Definition is created, this function emits a `CredentialDefinitionCreated` event - * with the new Credential Definition's ID. + * with the new Credential Definition's ID and issuer address. * * This function can revert with following errors: * - `CredentialDefinitionAlreadyExist`: Raised if Credential Definition with provided ID already exist. * - `SchemaNotFound`: Raised if the associated schema doesn't exist. - * - `UnauthorizedIssuer`: Raised when an issuer DID specified in CredentialDefinition is not owned by sender + * - `IssuerNotFound`: Raised if the associated issuer doesn't exist. + * - `InvalidIssuerId`: Raised if the provided issuer DID is invalid. + * - `IssuerHasBeenDeactivated`: Raised if the associated issuer is not active. + * - `NotIdentityOwner`: Raised when specified issuer DID is not owned by signer * * @param identity Account address of credential definition issuer. * @param sigR Part of EcDSA signature. * @param sigV Part of EcDSA signature. * @param sigS Part of EcDSA signature. - * @param id KECCAK256 hash of credential definition id to be created. - * @param schemaId KECCAK256 hash of schema id. - * @param credDef AnonCreds credential definition object as bytes. + * @param id Keccak hash of Credential Definition id to be created. + * @param issuerId DID of Credential Definition issuer. + * @param schemaId Keccak hash of Schema id. + * @param credDef AnonCreds Credential Definition JSON as bytes. */ function createCredentialDefinitionSigned( address identity, @@ -59,14 +69,21 @@ interface CredentialDefinitionRegistryInterface { bytes32 sigR, bytes32 sigS, bytes32 id, + string calldata issuerId, bytes32 schemaId, bytes calldata credDef ) external; /** - * @dev Get the block number when a schema was created. + * @dev Resolve the Credential Definition associated with the given ID. + * + * If no matching Credential Definition is found, the function revert with `CredentialDefinitionNotFound` error + * + * @param id Keccak hash of the Credential Definition to be resolved. * - * @param id KECCAK256 hash of credential definition id. + * @return credentialDefinitionRecord Returns the credential definition with metadata. */ - function created(bytes32 id) external returns (uint256 block); + function resolveCredentialDefinition( + bytes32 id + ) external returns (CredentialDefinitionRecord memory credentialDefinitionRecord); } diff --git a/smart_contracts/contracts/cl/CredentialDefinitionTypes.sol b/smart_contracts/contracts/cl/CredentialDefinitionTypes.sol new file mode 100644 index 00000000..ceff5922 --- /dev/null +++ b/smart_contracts/contracts/cl/CredentialDefinitionTypes.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +/** + * @title CredentialDefinitionRecord + * @dev This struct holds the details of a credential definition + * and its associated metadata. + * + * @param credDef - Credential Definition JSON as bytes. + * @param metadata - Additional metadata associated with the credential definition. + */ +struct CredentialDefinitionRecord { + bytes credDef; + CredentialDefinitionMetadata metadata; +} + +/** + * @title CredentialDefinitionMetadata + * @dev This struct holds additional metadata for a credential definition. + * + * @param created - Timestamp indicating when the credential definition was created. + */ +struct CredentialDefinitionMetadata { + uint256 created; +} diff --git a/smart_contracts/contracts/cl/SchemaRegistry.sol b/smart_contracts/contracts/cl/SchemaRegistry.sol index dae52e7d..252b67a8 100644 --- a/smart_contracts/contracts/cl/SchemaRegistry.sol +++ b/smart_contracts/contracts/cl/SchemaRegistry.sol @@ -1,35 +1,49 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.20; +import { UniversalDidResolverInterface } from "../did/UniversalDidResolverInterface.sol"; import { ControlledUpgradeable } from "../upgrade/ControlledUpgradeable.sol"; -import { SchemaAlreadyExist } from "./ClErrors.sol"; +import { SchemaAlreadyExist, SchemaNotFound } from "./ClErrors.sol"; import { SchemaRegistryInterface } from "./SchemaRegistryInterface.sol"; +import { SchemaRecord } from "./SchemaTypes.sol"; import { CLRegistry } from "./CLRegistry.sol"; -import { EthereumExtDidRegistry } from "../did/EthereumExtDidRegistry.sol"; contract SchemaRegistry is SchemaRegistryInterface, ControlledUpgradeable, CLRegistry { /** - * Mapping to track created schemas by their id to the block number when it was created. + * Mapping Schema ID to its Schema Details and Metadata. */ - mapping(bytes32 id => uint block) public created; + mapping(bytes32 id => SchemaRecord SchemaRecord) private _schemas; /** * Checks the uniqueness of the Schema ID */ modifier _uniqueSchemaId(bytes32 id) { - if (created[id] != 0) revert SchemaAlreadyExist(id); + if (_schemas[id].metadata.created != 0) revert SchemaAlreadyExist(id); _; } - function initialize(address upgradeControlAddress, address ethereumExtDidRegistry) public reinitializer(1) { + /** + * Checks that the Schema exist + */ + modifier _schemaExist(bytes32 id) { + if (_schemas[id].metadata.created == 0) revert SchemaNotFound(id); + _; + } + + function initialize(address upgradeControlAddress, address didResolverAddress) public reinitializer(1) { _initializeUpgradeControl(upgradeControlAddress); - _didRegistry = EthereumExtDidRegistry(ethereumExtDidRegistry); + _didResolver = UniversalDidResolverInterface(didResolverAddress); } /// @inheritdoc SchemaRegistryInterface - function createSchema(address identity, bytes32 id, bytes calldata schema) public virtual { - _createSchema(identity, msg.sender, id, schema); + function createSchema( + address identity, + bytes32 id, + string calldata issuerId, + bytes calldata schema + ) public virtual { + _createSchema(identity, msg.sender, id, issuerId, schema); } /// @inheritdoc SchemaRegistryInterface @@ -39,21 +53,30 @@ contract SchemaRegistry is SchemaRegistryInterface, ControlledUpgradeable, CLReg bytes32 sigR, bytes32 sigS, bytes32 id, + string calldata issuerId, bytes calldata schema ) public virtual { bytes32 hash = keccak256( - abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createSchema", id, schema) + abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createSchema", id, issuerId, schema) ); - _createSchema(identity, _checkSignature(identity, hash, sigV, sigR, sigS), id, schema); + _createSchema(identity, ecrecover(hash, sigV, sigR, sigS), id, issuerId, schema); + } + + /// @inheritdoc SchemaRegistryInterface + function resolveSchema(bytes32 id) public view virtual _schemaExist(id) returns (SchemaRecord memory schemaRecord) { + return _schemas[id]; } function _createSchema( address identity, address actor, bytes32 id, + string calldata issuerId, bytes calldata schema - ) internal _uniqueSchemaId(id) _validIssuer(identity, actor) { - created[id] = block.number; - emit SchemaCreated(id, actor, schema); + ) internal _uniqueSchemaId(id) _validIssuer(issuerId, identity, actor) { + _schemas[id].schema = schema; + _schemas[id].metadata.created = block.timestamp; + + emit SchemaCreated(id, identity); } } diff --git a/smart_contracts/contracts/cl/SchemaRegistryInterface.sol b/smart_contracts/contracts/cl/SchemaRegistryInterface.sol index c1c8f5cf..0a310079 100644 --- a/smart_contracts/contracts/cl/SchemaRegistryInterface.sol +++ b/smart_contracts/contracts/cl/SchemaRegistryInterface.sol @@ -1,48 +1,57 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.20; +import { SchemaRecord } from "./SchemaTypes.sol"; + interface SchemaRegistryInterface { /** - * @dev Event that is sent when a Schema is created. + * @dev Event that is sent when a Schema is created * - * @param id KECCAK256 hash of created schema id. - * @param identity Account address of schema issuer . - * @param schema AnonCreds schema object as bytes. + * @param schemaId Keccak hash of created schema id + * @param identity Issuer address */ - event SchemaCreated(bytes32 indexed id, address identity, bytes schema); + event SchemaCreated(bytes32 schemaId, address identity); /** * @dev Creates a new Schema. * * Once the Schema is created, this function emits a `SchemaCreated` event - * with the new Schema ID. + * with the new Schema ID and issuer address. * * This function can revert with following errors: * - `SchemaAlreadyExist`: Raised if Schema with provided ID already exist. - * - `UnauthorizedIssuer`: Raised when an issuer DID specified in Schema is not owned by sender + * - `IssuerNotFound`: Raised if the associated issuer doesn't exist. + * - `InvalidIssuerId`: Raised if the provided issuer DID is invalid. + * - `IssuerHasBeenDeactivated`: Raised if the associated issuer is not active. + * - `NotIdentityOwner`: Raised when an issuer DID specified in Schema is not owned by sender * * @param identity Account address of schema issuer. - * @param id KECCAK256 hash of schema id to be created. - * @param schema AnonCreds schema object as bytes. + * @param id Keccak hash of Schema id to be created. + * @param issuerId DID of Schema issuer. + * @param schema AnonCreds schema JSON as bytes. */ - function createSchema(address identity, bytes32 id, bytes calldata schema) external; + function createSchema(address identity, bytes32 id, string calldata issuerId, bytes calldata schema) external; /** - * @dev Endorse a new Schema. + * @dev Endorse a new Schema (off-chain author signature).. * * Once the Schema is created, this function emits a `SchemaCreated` event - * with the new Schema ID. + * with the new Schema ID and issuer address. * * This function can revert with following errors: * - `SchemaAlreadyExist`: Raised if Schema with provided ID already exist. - * - `UnauthorizedIssuer`: Raised when an issuer DID specified in Schema is not owned by sender + * - `IssuerNotFound`: Raised if the associated issuer doesn't exist. + * - `InvalidIssuerId`: Raised if the provided issuer DID is invalid. + * - `IssuerHasBeenDeactivated`: Raised if the associated issuer is not active. + * - `NotIdentityOwner`: Raised when an issuer DID specified in Schema is not owned by signer * * @param identity Account address of schema issuer. * @param sigV Part of EcDSA signature. * @param sigR Part of EcDSA signature. * @param sigS Part of EcDSA signature. - * @param id KECCAK256 hash of schema id to be created. - * @param schema AnonCreds schema object as bytes. + * @param id Keccak hash of Schema id to be created. + * @param issuerId DID of Schema issuer. + * @param schema AnonCreds schema JSON as bytes. */ function createSchemaSigned( address identity, @@ -50,13 +59,18 @@ interface SchemaRegistryInterface { bytes32 sigR, bytes32 sigS, bytes32 id, + string calldata issuerId, bytes calldata schema ) external; /** - * @dev Get the block number when a schema was created. + * @dev Resolve the Schema associated with the given ID. + * + * If no matching Schema is found, the function revert with `SchemaNotFound` error + * + * @param id Keccak hash of Schema id to be resolved. * - * @param id KECCAK256 hash of schema id. + * @return schemaRecord Returns the Schema with Metadata. */ - function created(bytes32 id) external returns (uint256 block); + function resolveSchema(bytes32 id) external returns (SchemaRecord memory schemaRecord); } diff --git a/smart_contracts/contracts/cl/SchemaTypes.sol b/smart_contracts/contracts/cl/SchemaTypes.sol new file mode 100644 index 00000000..806d4b6e --- /dev/null +++ b/smart_contracts/contracts/cl/SchemaTypes.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +/** + * @title SchemaRecord + * @dev This struct holds the details of a schema + * and its associated metadata. + * + * @param schema - Schema JSON bytes. + * @param metadata - Additional metadata associated with the schema. + */ +struct SchemaRecord { + bytes schema; + SchemaMetadata metadata; +} + +/** + * @title SchemaMetadata + * @dev This struct holds additional metadata for a schema. + * + * @param created - Timestamp indicating when the schema was created. + */ +struct SchemaMetadata { + uint256 created; +} diff --git a/smart_contracts/contracts/did/DidErrors.sol b/smart_contracts/contracts/did/DidErrors.sol new file mode 100644 index 00000000..92e84968 --- /dev/null +++ b/smart_contracts/contracts/did/DidErrors.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +/** + * @dev Error that occurs when the specified DID is not found. + */ +error DidNotFound(address identity); + +/** + * @dev Error that occurs when trying to create an already existing DID. + */ +error DidAlreadyExist(address identity); + +/** + * @dev Error that occurs when trying to perform an operation with a deactivated DID. + */ +error DidHasBeenDeactivated(address identity); + +/** + * @dev Error that occurs when message sender address is nether DID owner or original creator. + */ +error UnauthorizedSender(address sender); + +/** + * @dev Error that occurs when the specified DID is incorrect. + */ +error IncorrectDid(string did); + +/** + * @notice Error that occurs when performed identity operation by not owned account. + */ +error NotIdentityOwner(address actor, address identity); diff --git a/smart_contracts/contracts/did/DidTypes.sol b/smart_contracts/contracts/did/DidTypes.sol new file mode 100644 index 00000000..7f0a3e4c --- /dev/null +++ b/smart_contracts/contracts/did/DidTypes.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +/** + * @dev DidRecord holds the DID Document and its associated metadata + */ +struct DidRecord { + bytes document; + DidMetadata metadata; +} + +/** + * @dev DidMetadata holds additional properties associated with the DID + */ +struct DidMetadata { + address owner; + address sender; + uint256 created; + uint256 updated; + uint256 versionId; + bool deactivated; +} diff --git a/smart_contracts/contracts/did/DidUtils.sol b/smart_contracts/contracts/did/DidUtils.sol new file mode 100644 index 00000000..5c63344e --- /dev/null +++ b/smart_contracts/contracts/did/DidUtils.sol @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import { StrSlice, toSlice } from "@dk1a/solidity-stringutils/src/StrSlice.sol"; +import { IncorrectDid } from "./DidErrors.sol"; +import { StringUtils } from "../utils/StringUtils.sol"; + +string constant DID_ETHR_METHOD = "ethr"; +string constant DID_INDY_BESU_METHOD = "indybesu"; + +struct ParsedDid { + string method; + string identifier; +} + +using { toSlice } for string; + +library DidUtils { + string private constant _DID_PREFIX = "did"; + string private constant _DID_DELIMETER = ":"; + uint16 private constant _ADDRESS_HEX_STRING_LENGTH = 22; + + /** + * @dev Parses a DID string and returns its components. + * @param did The DID string to be parsed. + * @return ParsedDid A struct containing the method and identifier of the DID. + */ + function parseDid(string memory did) internal view returns (ParsedDid memory) { + StrSlice didSlice = did.toSlice(); + StrSlice delimeterSlice = _DID_DELIMETER.toSlice(); + StrSlice component; + bool found; + + // Extract and check 'did' prefix. + (found, component, didSlice) = didSlice.splitOnce(delimeterSlice); + if (!found || !component.eq(_DID_PREFIX.toSlice())) revert IncorrectDid(did); + + // Extract the DID method. + (found, component, didSlice) = didSlice.splitOnce(delimeterSlice); + if (!found) revert IncorrectDid(did); + + ParsedDid memory parsedDid; + parsedDid.method = component.toString(); + + // Extract the DID identifier. + (, , component) = didSlice.rsplitOnce(_DID_DELIMETER.toSlice()); + parsedDid.identifier = component.toString(); + + return parsedDid; + } + + /** + * @dev Converts a given Ethereum identifier to an Ethereum address. + * @param identifier The Ethereum identifier to be converted. + * @return The Ethereum address derived from the identifier, or the zero address if the identifier is incorrect. + */ + function convertEthereumIdentifierToAddress(string memory identifier) internal view returns (address) { + if (!(StringUtils.length(identifier) != _ADDRESS_HEX_STRING_LENGTH)) return address(0); + + bytes memory identifierBytes = StringUtils.hexToBytes(identifier); + + return address(uint160(bytes20(identifierBytes))); + } + + /** + * @dev Checks if a given method string corresponds to the Ethereum method identifier. + * @param method The method string to check. + * @return Returns `true` if the method string matches the Ethereum method, `false` otherwise. + */ + function isEthereumMethod(string memory method) internal pure returns (bool) { + return method.toSlice().eq(DID_ETHR_METHOD.toSlice()); + } + + /** + * @dev Checks if a given method string corresponds to the Indy-Besu method. + * @param method The method string to check. + * @return Returns `true` if the method string matches the Indy-Besu method, `false` otherwise. + */ + function isIndyMethod(string memory method) internal pure returns (bool) { + return method.toSlice().eq(DID_INDY_BESU_METHOD.toSlice()); + } +} diff --git a/smart_contracts/contracts/did/IndyDidRegistry.sol b/smart_contracts/contracts/did/IndyDidRegistry.sol new file mode 100644 index 00000000..83cdf1ea --- /dev/null +++ b/smart_contracts/contracts/did/IndyDidRegistry.sol @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import { ControlledUpgradeable } from "../upgrade/ControlledUpgradeable.sol"; + +import { DidAlreadyExist, DidHasBeenDeactivated, DidNotFound, UnauthorizedSender, NotIdentityOwner } from "./DidErrors.sol"; +import { DidRecord } from "./DidTypes.sol"; +import { IndyDidRegistryInterface } from "./IndyDidRegistryInterface.sol"; + +contract IndyDidRegistry is IndyDidRegistryInterface, ControlledUpgradeable { + /** + * @dev Mapping DID to its corresponding DidRecord (Document/Metadata). + */ + mapping(address identity => DidRecord didRecord) private _dids; + + /** + * Checks that DID already exists + */ + modifier _didExist(address identity) { + if (_dids[identity].metadata.created == 0) revert DidNotFound(identity); + _; + } + + /** + * Checks that the DID has not yet been added + */ + modifier _didNotExist(address identity) { + if (_dids[identity].metadata.created != 0) revert DidAlreadyExist(identity); + _; + } + + /** + * Checks that the DID has not been deactivated + */ + modifier _didIsActive(address identity) { + if (_dids[identity].metadata.deactivated) revert DidHasBeenDeactivated(identity); + _; + } + + /** + * Checks that method was called either by did owner or sender + */ + modifier _senderIsAuthorized(address identity) { + // FIXME: once we add strict role and endorsement, the check here should be either owner or Trustee + if (msg.sender != identity && msg.sender != _dids[identity].metadata.sender) + revert UnauthorizedSender(msg.sender); + _; + } + + /** + * Checks that actor matches to the identity + */ + modifier _identityOwner(address identity, address actor) { + if (identity != actor) revert NotIdentityOwner(actor, identity); + _; + } + + function initialize(address upgradeControlAddress) public reinitializer(1) { + _initializeUpgradeControl(upgradeControlAddress); + } + + /// @inheritdoc IndyDidRegistryInterface + function createDid(address identity, bytes calldata document) public { + _createDid(identity, msg.sender, document); + } + + /// @inheritdoc IndyDidRegistryInterface + function createDidSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes calldata document) public { + bytes32 hash = keccak256( + abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createDid", document) + ); + _createDid(identity, ecrecover(hash, sigV, sigR, sigS), document); + } + + /// @inheritdoc IndyDidRegistryInterface + function updateDid(address identity, bytes calldata document) public { + _updateDid(identity, msg.sender, document); + } + + /// @inheritdoc IndyDidRegistryInterface + function updateDidSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes calldata document) public { + bytes32 hash = keccak256( + abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "updateDid", document) + ); + _updateDid(identity, ecrecover(hash, sigV, sigR, sigS), document); + } + + /// @inheritdoc IndyDidRegistryInterface + function deactivateDid(address identity) public { + _deactivateDid(identity, msg.sender); + } + + /// @inheritdoc IndyDidRegistryInterface + function deactivateDidSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS) public { + bytes32 hash = keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "deactivateDid")); + _deactivateDid(identity, ecrecover(hash, sigV, sigR, sigS)); + } + + /// @inheritdoc IndyDidRegistryInterface + function resolveDid(address identity) public view virtual _didExist(identity) returns (DidRecord memory didRecord) { + return _dids[identity]; + } + + function _createDid( + address identity, + address actor, + bytes calldata document + ) internal _didNotExist(identity) _identityOwner(identity, actor) { + _dids[identity].document = document; + _dids[identity].metadata.owner = identity; + _dids[identity].metadata.sender = msg.sender; + _dids[identity].metadata.created = block.timestamp; + _dids[identity].metadata.updated = block.timestamp; + _dids[identity].metadata.versionId = block.number; + + emit DIDCreated(identity); + } + + function _updateDid( + address identity, + address actor, + bytes calldata document + ) + internal + _didExist(identity) + _didIsActive(identity) + _identityOwner(identity, actor) + _senderIsAuthorized(identity) + { + _dids[identity].document = document; + _dids[identity].metadata.updated = block.timestamp; + _dids[identity].metadata.versionId = block.number; + + emit DIDUpdated(identity); + } + + function _deactivateDid( + address identity, + address actor + ) + internal + _didExist(identity) + _didIsActive(identity) + _identityOwner(identity, actor) + _senderIsAuthorized(identity) + { + _dids[identity].metadata.deactivated = true; + _dids[identity].metadata.versionId = block.number; + + emit DIDDeactivated(identity); + } +} diff --git a/smart_contracts/contracts/did/IndyDidRegistryInterface.sol b/smart_contracts/contracts/did/IndyDidRegistryInterface.sol new file mode 100644 index 00000000..a634431d --- /dev/null +++ b/smart_contracts/contracts/did/IndyDidRegistryInterface.sol @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import { DidRecord } from "./DidTypes.sol"; + +/** + * @dev The interface that defines functions for managing DID documents. + */ +interface IndyDidRegistryInterface { + /** + * @dev Event that is sent when a DID Document is created. + * + * @param identity Address of created DID Record. + */ + event DIDCreated(address identity); + + /** + * @dev Event that is sent when a DID Document is updated. + * + * @param identity Address of updated DID Record. + */ + event DIDUpdated(address identity); + + /** + * @dev Event that is sent when a DID Document is deactivated. + * + * @param identity Address of deactivated DID Record + */ + event DIDDeactivated(address identity); + + /** + * @dev Creates a new DID record. + * + * @param identity Address of DID identity owner. + * @param document DID Document JSON as bytes. + */ + function createDid(address identity, bytes calldata document) external; + + /** + * @dev Endorses a new DID record (off-chain author signature). + * + * @param identity Address of DID identity owner. + * @param sigV Part of EcDSA signature. + * @param sigR Part of EcDSA signature. + * @param sigS Part of EcDSA signature. + * @param document DID Document JSON as bytes. + */ + function createDidSigned( + address identity, + uint8 sigV, + bytes32 sigR, + bytes32 sigS, + bytes calldata document + ) external; + + /** + * @dev Updates an existing DID record. + * + * Restrictions: + * + * - DID must already exist; otherwise, will revert with a `DidNotFound` error. + * - DID must be active; otherwise, will revert with a `DidHasBeenDeactivated` error. + * - Sender address must be equal either to DID owner or creator; otherwise, will revert with a `UnauthorizedSender` error. + * - Sender address must be equal to passed identity address; otherwise, will revert with a `NotIdentityOwner` error. + * + * Events: + * - On successful DID update, will emit a `DIDUpdated` event. + * + * @param identity Address of the DID to update. + * @param document Updated DID Document JSON as bytes. + */ + function updateDid(address identity, bytes calldata document) external; + + /** + * @dev Endorses an updated DID document for an existing DID record (off-chain author signature). + * + * Restrictions: + * + * - DID must already exist; otherwise, will revert with a `DidNotFound` error. + * - DID must be active; otherwise, will revert with a `DidHasBeenDeactivated` error. + * - Sender address must be equal either to DID owner or creator; otherwise, will revert with a `UnauthorizedSender` error. + * - Signer address must be equal to passed identity address; otherwise, will revert with a `NotIdentityOwner` error. + * + * Events: + * - On successful DID update, will emit a `DIDUpdated` event. + * + * @param identity Address of the DID to update. + * @param sigV Part of EcDSA signature. + * @param sigR Part of EcDSA signature. + * @param sigS Part of EcDSA signature. + * @param document The updated DID Document as JSON string. + */ + function updateDidSigned( + address identity, + uint8 sigV, + bytes32 sigR, + bytes32 sigS, + bytes calldata document + ) external; + + /** + * @dev Deactivates an existing DID. + * + * Restrictions: + * - DID must be active; otherwise, will revert with a `DidHasBeenDeactivated` error. + * - DID must exist; otherwise, will revert with a `DidNotFound` error. + * - Sender address must be equal either to DID owner or creator; otherwise, will revert with a `UnauthorizedSender` error. + * - Sender address must be equal to passed identity address; otherwise, will revert with a `NotIdentityOwner` error. + * + * Events: + * - On successful DID deactivation, will emit a `DIDDeactivated` event. + * + * @param identity Address of the DID to be deactivated. + */ + function deactivateDid(address identity) external; + + /** + * @dev Endorses deactivation of an existing DID (off-chain author signature). + * + * Restrictions: + * - DID must be active; otherwise, will revert with a `DidHasBeenDeactivated` error. + * - DID must exist; otherwise, will revert with a `DidNotFound` error. + * - Sender address must be equal either to DID owner or creator; otherwise, will revert with a `UnauthorizedSender` error. + * - Signer address must be equal to passed identity address; otherwise, will revert with a `NotIdentityOwner` error. + * + * Events: + * - On successful DID deactivation, will emit a `DIDDeactivated` event. + * + * @param identity Address of the DID to be deactivated. + * @param sigV Part of EcDSA signature. + * @param sigR Part of EcDSA signature. + * @param sigS Part of EcDSA signature. + */ + function deactivateDidSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS) external; + + /** + * @dev Function to resolve DID Document for the given DID. + * + * Restrictions: + * - DID must exist; otherwise, will revert with a `DidNotFound` error. + * + * @param identity Address of the DID be resolved. + * + * @return didRecord The resolved DID record associated with provided DID identity address. + */ + function resolveDid(address identity) external view returns (DidRecord memory didRecord); +} diff --git a/smart_contracts/contracts/did/UniversalDidResolver.sol b/smart_contracts/contracts/did/UniversalDidResolver.sol new file mode 100644 index 00000000..d3bbc8e4 --- /dev/null +++ b/smart_contracts/contracts/did/UniversalDidResolver.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import { ControlledUpgradeable } from "../upgrade/ControlledUpgradeable.sol"; +import { UnsupportedOperation } from "../utils/Errors.sol"; + +import { IncorrectDid } from "./DidErrors.sol"; +import { DidMetadata } from "./DidTypes.sol"; +import { DidUtils, ParsedDid } from "./DidUtils.sol"; +import { EthereumExtDidRegistry } from "./EthereumExtDidRegistry.sol"; +import { IndyDidRegistryInterface } from "./IndyDidRegistryInterface.sol"; +import { UniversalDidResolverInterface } from "./UniversalDidResolverInterface.sol"; + +contract UniversalDidResolver is UniversalDidResolverInterface, ControlledUpgradeable { + IndyDidRegistryInterface internal _indyDidRegistry; + EthereumExtDidRegistry internal _ethereumDIDRegistry; + + function initialize( + address upgradeControlAddress, + address indyDidRegistry, + address ethereumDIDRegistryAddress + ) public reinitializer(1) { + _initializeUpgradeControl(upgradeControlAddress); + _indyDidRegistry = IndyDidRegistryInterface(indyDidRegistry); + _ethereumDIDRegistry = EthereumExtDidRegistry(ethereumDIDRegistryAddress); + } + + /// @inheritdoc UniversalDidResolverInterface + function resolveDocument(string calldata did) public view override returns (bytes memory document) { + ParsedDid memory parsedDid = DidUtils.parseDid(did); + address identity = DidUtils.convertEthereumIdentifierToAddress(parsedDid.identifier); + if (identity == address(0)) revert IncorrectDid(did); + + if (DidUtils.isIndyMethod(parsedDid.method)) { + return _indyDidRegistry.resolveDid(identity).document; + } else { + revert UnsupportedOperation( + "UniversalDidResolver.resolveDocument", + string.concat("Unsupported DID Method: '", parsedDid.method, "'") + ); + } + } + + /// @inheritdoc UniversalDidResolverInterface + function resolveMetadata(string calldata did) public view override returns (DidMetadata memory metadata) { + ParsedDid memory parsedDid = DidUtils.parseDid(did); + address identity = DidUtils.convertEthereumIdentifierToAddress(parsedDid.identifier); + if (identity == address(0)) revert IncorrectDid(did); + + if (DidUtils.isEthereumMethod(parsedDid.method)) { + address identityOwner = _ethereumDIDRegistry.identityOwner(identity); + return DidMetadata(identityOwner, address(0), 0, 0, 0, false); + } else if (DidUtils.isIndyMethod(parsedDid.method)) { + return _indyDidRegistry.resolveDid(identity).metadata; + } else { + revert UnsupportedOperation( + "UniversalDidResolver.resolveMetadata", + string.concat("Unsupported DID Method: '", parsedDid.method, "'") + ); + } + } +} diff --git a/smart_contracts/contracts/did/UniversalDidResolverInterface.sol b/smart_contracts/contracts/did/UniversalDidResolverInterface.sol new file mode 100644 index 00000000..d554fcfe --- /dev/null +++ b/smart_contracts/contracts/did/UniversalDidResolverInterface.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import { DidMetadata } from "./DidTypes.sol"; + +/** + * @title The interface that defines functions to resolve DID from various DID registries + */ +interface UniversalDidResolverInterface { + /** + * @dev Function to resolve DID Document for the given DID. + * + * Restrictions: + * - DID must exist; otherwise, will revert with a `DidNotFound` error. + * + * @param did The DID to be resolved. + * + * @return document The resolved DID document associated with provided DID. + */ + function resolveDocument(string calldata did) external view returns (bytes memory document); + + /** + * @dev Function to resolve DID Metadata for the given DID. + * + * Restrictions: + * - DID must exist; otherwise, will revert with a `DidNotFound` error. + * + * @param did The DID which metadata to be resolved. + * + * @return metadata The resolved DID metadata associated with provided DID. + */ + function resolveMetadata(string calldata did) external view returns (DidMetadata memory metadata); +} diff --git a/smart_contracts/contracts/utils/Errors.sol b/smart_contracts/contracts/utils/Errors.sol index 2fbb5bc7..a908b082 100644 --- a/smart_contracts/contracts/utils/Errors.sol +++ b/smart_contracts/contracts/utils/Errors.sol @@ -1,6 +1,25 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.20; +/** + * @dev Error that occurs when a required field is not provided. + * @param name The name of the required field. + */ +error FieldRequired(string name); + +/** + * @dev Error that occurs when provided two or more fields, which should not be provided together + * @param names Names of the conflicting fields + */ +error ConflictingFields(string names); + +/** + * @dev Error that occurs when the operation is not supported or cannot be performed. + * @param operation Name of the operation being performed + * @param description A brief error descriptiion + */ +error UnsupportedOperation(string operation, string description); + /** * @title Errors * @dev A library that provides utility functions for error handling. @@ -13,8 +32,8 @@ library Errors { * @return bool Returns true if the selectors match, indicating the errors are the same; otherwise, returns false. */ function equals(bytes memory reason, bytes4 errorSelector) internal pure returns (bool) { - bytes4 reasonSelector = abi.decode(reason, (bytes4)); - return reasonSelector == errorSelector; + bytes4 receivedSelector = bytes4(reason); + return errorSelector == receivedSelector; } /** diff --git a/smart_contracts/contracts/utils/StringUtils.sol b/smart_contracts/contracts/utils/StringUtils.sol index a03610c0..bfd4b99a 100644 --- a/smart_contracts/contracts/utils/StringUtils.sol +++ b/smart_contracts/contracts/utils/StringUtils.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.20; -import { toSlice } from "@dk1a/solidity-stringutils/src/StrSlice.sol"; +import { StrSlice, toSlice } from "@dk1a/solidity-stringutils/src/StrSlice.sol"; using { toSlice } for string; @@ -15,6 +15,33 @@ library StringUtils { string private constant _HEX_PREFIX = "0x"; bytes private constant _ZERO_BYTES = ""; + /** + * @dev Converts a hexadecimal string to bytes. + * @param hexString The hexadecimal string to be converted. + * @return The bytes represented by the hexadecimal string, or the zero bytes if the hex is incorrect. + */ + function hexToBytes(string memory hexString) internal view returns (bytes memory) { + StrSlice hexStringSlice = hexString.toSlice(); + StrSlice hexPrefixSlice = _HEX_PREFIX.toSlice(); + + // Check and remove hex prefix + if (!hexStringSlice.startsWith(_HEX_PREFIX.toSlice())) return _ZERO_BYTES; + hexString = hexStringSlice.stripPrefix(hexPrefixSlice).toString(); + + bytes memory hexStringBytes = bytes(hexString); + bytes memory resultBytes = new bytes(hexStringBytes.length / 2); + for (uint256 i = 0; i < resultBytes.length; i++) { + (uint8 firstByte, bool firstByteValid) = _hexCharToByte(hexStringBytes[2 * i]); + if (!firstByteValid) return _ZERO_BYTES; + + (uint8 secondByte, bool secondByteValid) = _hexCharToByte(hexStringBytes[2 * i + 1]); + if (!secondByteValid) return _ZERO_BYTES; + + resultBytes[i] = bytes1(firstByte * 16 + secondByte); + } + return resultBytes; + } + /** * @dev Checks if two strings are equal. * @param str First string to compare. @@ -51,4 +78,19 @@ library StringUtils { function hasHexPrefix(string memory str) internal pure returns (bool) { return str.toSlice().startsWith(_HEX_PREFIX.toSlice()); } + + /** + * Converts a single hexadecimal character to a byte + */ + function _hexCharToByte(bytes1 hexChar) private pure returns (uint8, bool) { + if (hexChar >= _ASCII_0 && hexChar <= _ASCII_9) { + return (uint8(hexChar) - uint8(_ASCII_0), true); + } else if (hexChar >= _ASCII_CAPITAL_A && hexChar <= _ASCII_CAPITAL_F) { + return (10 + uint8(hexChar) - uint8(_ASCII_CAPITAL_A), true); + } else if (hexChar >= _ASCII_SMALL_A && hexChar <= _ASCII_SMALL_F) { + return (10 + uint8(hexChar) - uint8(_ASCII_SMALL_A), true); + } else { + return (0, false); + } + } } diff --git a/smart_contracts/demos/flow-with-did-ethr.ts b/smart_contracts/demos/flow-with-did-ethr.ts new file mode 100644 index 00000000..978ed562 --- /dev/null +++ b/smart_contracts/demos/flow-with-did-ethr.ts @@ -0,0 +1,90 @@ +import environment from '../environment' +import { Actor } from './utils/actor' +import { ROLES } from '../contracts-ts' +import { createCredentialDefinitionObject, createSchemaObject } from '../utils' +import assert from 'assert' + +async function demo() { + let receipt: any + + const trustee = await new Actor(environment.accounts.account1).init() + const faber = await new Actor().init() + const alice = await new Actor().init() + const unauthorized = await new Actor().init() + + console.log('1. Trustee assign ENDORSER role to Faber') + receipt = await trustee.roleControl.assignRole(ROLES.ENDORSER, faber.address) + console.log(`Role ${ROLES.ENDORSER} assigned to account ${faber.address}. Receipt: ${JSON.stringify(receipt)}`) + + console.log('2. Try set service attribute to DID document by an unauthorized account') + await assert.rejects( + unauthorized.ethereumDIDRegistry.setAttribute( + unauthorized.address, + 'did/svc/did-communication', + 'https://example.com', + 86400, + ), + (err) => { + console.log(JSON.stringify(err)) + return true + }, + ) + + console.log('3. Faber sets service attribute to DID document (Optional)') + receipt = await faber.ethereumDIDRegistry.setAttribute( + faber.address, + 'did/svc/did-communication', + 'https://example.com', + 86400, + ) + console.log(`Attribute created for id ${faber.address}. Receipt: ${JSON.stringify(receipt)}`) + + console.log("4. Faber creates a Test Schema using the 'did:ethr' DID as the issuer") + const { id: schemaId, schema } = createSchemaObject({ issuerId: faber.didEthr }) + receipt = await faber.schemaRegistry.createSchema(faber.address, schemaId, faber.didEthr, schema) + console.log(`Schema created for id ${schemaId}. Receipt: ${JSON.stringify(receipt)}`) + + console.log('5. Faber resolves Test Schema to ensure its written') + const resolvedSchema = await faber.schemaRegistry.resolveSchema(schemaId) + console.log(`Schema resolved for ${schemaId}. Schema: ${resolvedSchema.schema}`) + + console.log("6. Faber create a Test Credential Definition using the 'did:ethr' DID as the issuer") + const { id: credentialDefinitionId, credDef: credentialDefinition } = createCredentialDefinitionObject({ + issuerId: faber.didEthr, + schemaId: schemaId, + }) + receipt = await faber.credentialDefinitionRegistry.createCredentialDefinition( + faber.address, + credentialDefinitionId, + faber.didEthr, + schemaId, + credentialDefinition, + ) + console.log(`Credential Definition created for id ${credentialDefinitionId}. Receipt: ${JSON.stringify(receipt)}`) + + console.log('7. Faber resolves Test Credential Definition to ensure its written') + const resolvedCredentialDefinition = await faber.credentialDefinitionRegistry.resolveCredentialDefinition( + credentialDefinitionId, + ) + console.log( + `Credential Definition resolved for ${credentialDefinitionId}. Credential Definition: ${resolvedCredentialDefinition.credDef}`, + ) + + console.log('8. Alice resolves Test Schema') + const testSchema = await alice.schemaRegistry.resolveSchema(schemaId) + console.log(`Schema resolved for ${schemaId}. Schema: ${testSchema.schema}`) + + console.log('9. Alice resolves Test Credential Definition') + const testCredentialDefinition = await alice.credentialDefinitionRegistry.resolveCredentialDefinition( + credentialDefinitionId, + ) + console.log( + `Credential Definition resolved for ${credentialDefinitionId}. Credential Definition: ${testCredentialDefinition.credDef}`, + ) +} + +if (require.main === module) { + demo() +} + +module.exports = exports = demo diff --git a/smart_contracts/demos/flow.ts b/smart_contracts/demos/flow.ts index b102a9ce..fd08f751 100644 --- a/smart_contracts/demos/flow.ts +++ b/smart_contracts/demos/flow.ts @@ -2,7 +2,6 @@ import environment from '../environment' import { Actor } from './utils/actor' import { ROLES } from '../contracts-ts' import { createCredentialDefinitionObject, createSchemaObject } from '../utils' -import assert from 'assert' async function demo() { let receipt: any @@ -10,71 +9,60 @@ async function demo() { const trustee = await new Actor(environment.accounts.account1).init() const faber = await new Actor().init() const alice = await new Actor().init() - const unauthorized = await new Actor().init() console.log('1. Trustee assign ENDORSER role to Faber') receipt = await trustee.roleControl.assignRole(ROLES.ENDORSER, faber.address) console.log(`Role ${ROLES.ENDORSER} assigned to account ${faber.address}. Receipt: ${JSON.stringify(receipt)}`) - console.log('2. Try set service attribute to DID document by an unauthorized account') - await assert.rejects( - unauthorized.ethereumDIDRegistry.setAttribute( - unauthorized.address, - 'did/svc/did-communication', - 'https://example.com', - 86400, - ), - (err) => { - console.log(JSON.stringify(err)) - return true - }, - ) + console.log('2. Faber creates DID Document') + receipt = await faber.didRegistry.createDid(faber.address, faber.didDocument) + console.log(`Did Document created for DID ${faber.did}. Receipt: ${JSON.stringify(receipt)}`) - console.log('3. Faber sets service attribute to DID document (Optional)') - receipt = await faber.ethereumDIDRegistry.setAttribute( - faber.address, - 'did/svc/did-communication', - 'https://example.com', - 86400, - ) - console.log(`Attribute created for id ${faber.address}. Receipt: ${JSON.stringify(receipt)}`) - - console.log("4. Faber creates a Test Schema using the 'did:ethr' DID as the issuer") - const { id: schemaId, schema } = createSchemaObject({ issuer: faber.address }) - receipt = await faber.schemaRegistry.createSchema(faber.address, schemaId, schema) + console.log('3. Faber creates Test Schema') + const { id: schemaId, schema } = createSchemaObject({ issuerId: faber.did }) + receipt = await faber.schemaRegistry.createSchema(faber.address, schemaId, faber.did, schema) console.log(`Schema created for id ${schemaId}. Receipt: ${JSON.stringify(receipt)}`) - console.log('5. Faber resolves Test Schema to ensure its written') - const resolvedSchema = await alice.schemaRegistry.resolveSchema(schemaId) - console.log(`Schema resolved for ${schemaId}. Schema: ${resolvedSchema}`) + console.log('4. Faber resolves Test Schema to ensure its written') + const resolvedSchema = await faber.schemaRegistry.resolveSchema(schemaId) + console.log(`Schema resolved for ${schemaId}. Schema: ${resolvedSchema.schema}`) - console.log("6. Faber create a Test Credential Definition using the 'did:ethr' DID as the issuer") + console.log('5. Faber create Test Credential Definition') const { id: credentialDefinitionId, credDef: credentialDefinition } = createCredentialDefinitionObject({ - issuer: faber.address, + issuerId: faber.did, schemaId: schemaId, }) receipt = await faber.credentialDefinitionRegistry.createCredentialDefinition( faber.address, credentialDefinitionId, + faber.did, schemaId, credentialDefinition, ) console.log(`Credential Definition created for id ${credentialDefinitionId}. Receipt: ${JSON.stringify(receipt)}`) - console.log('7. Faber resolves Test Credential Definition to ensure its written') - const resolvedCredDef = await faber.credentialDefinitionRegistry.resolveCredentialDefinition(credentialDefinitionId) - console.log(`Credential Definition resolved for ${credentialDefinitionId}. Credential Definition: ${resolvedCredDef}`) + console.log('6. Trustee resolves Test Credential Definition to ensure its written') + const resolvedCredentialDefinition = await faber.credentialDefinitionRegistry.resolveCredentialDefinition( + credentialDefinitionId, + ) + console.log( + `Credential Definition resolved for ${credentialDefinitionId}. Credential Definition: ${resolvedCredentialDefinition.credDef}`, + ) + + console.log("7. ALice resolves Faber's Did Document") + const faberDidDocument = await alice.didRegistry.resolveDid(faber.address) + console.log(`Did Document resolved for ${faber.did}. DID Document: ${faberDidDocument?.document}`) console.log('8. Alice resolves Test Schema') - const testResolvedSchema = await alice.schemaRegistry.resolveSchema(schemaId) - console.log(`Schema resolved for ${schemaId}. Schema: ${testResolvedSchema}`) + const testSchema = await alice.schemaRegistry.resolveSchema(schemaId) + console.log(`Schema resolved for ${schemaId}. Schema: ${testSchema.schema}`) console.log('9. Alice resolves Test Credential Definition') - const testResolvedCredDef = await alice.credentialDefinitionRegistry.resolveCredentialDefinition( + const testCredentialDefinition = await alice.credentialDefinitionRegistry.resolveCredentialDefinition( credentialDefinitionId, ) console.log( - `Credential Definition resolved for ${credentialDefinitionId}. Credential Definition: ${testResolvedCredDef}`, + `Credential Definition resolved for ${credentialDefinitionId}. Credential Definition: ${testCredentialDefinition.credDef}`, ) } diff --git a/smart_contracts/demos/utils/actor.ts b/smart_contracts/demos/utils/actor.ts index c1df3607..d9d2b8fe 100644 --- a/smart_contracts/demos/utils/actor.ts +++ b/smart_contracts/demos/utils/actor.ts @@ -1,5 +1,6 @@ import { RoleControl, + IndyDidRegistry, SchemaRegistry, CredentialDefinitionRegistry, ValidatorControl, @@ -12,6 +13,7 @@ export class Actor { public account: Account public roleControl!: RoleControl public validatorControl!: ValidatorControl + public didRegistry!: IndyDidRegistry public ethereumDIDRegistry!: EthereumExtDidRegistry public schemaRegistry!: SchemaRegistry public credentialDefinitionRegistry!: CredentialDefinitionRegistry @@ -24,6 +26,7 @@ export class Actor { public async init() { this.roleControl = await new RoleControl(this.account).getInstance(RoleControl.defaultAddress) this.validatorControl = await new ValidatorControl(this.account).getInstance(ValidatorControl.defaultAddress) + this.didRegistry = await new IndyDidRegistry(this.account).getInstance(IndyDidRegistry.defaultAddress) this.ethereumDIDRegistry = await new EthereumExtDidRegistry(this.account).getInstance( EthereumExtDidRegistry.defaultAddress, ) diff --git a/smart_contracts/environment.ts b/smart_contracts/environment.ts index 717b3747..79e0bc6d 100644 --- a/smart_contracts/environment.ts +++ b/smart_contracts/environment.ts @@ -56,7 +56,7 @@ export const environment = { name: 'testnet', }, did: { - method: 'indy2', + method: 'indybesu', }, } diff --git a/smart_contracts/package.json b/smart_contracts/package.json index f4e34834..03461d3c 100644 --- a/smart_contracts/package.json +++ b/smart_contracts/package.json @@ -18,6 +18,7 @@ "demo/roles": "yarn run-on-besu demos/role-control.ts", "demo/validators": "yarn run-on-besu demos/validator-control.ts", "demo/flow": "yarn run-on-besu demos/flow.ts", + "demo/flow-with-did-ethr": "yarn run-on-besu demos/flow-with-did-ethr.ts", "demo/account": "yarn run-on-besu demos/account-control.ts", "demo/upgrade": "yarn run-on-besu demos/upgrade-control.ts", "genesis/generate": "ts-node scripts/genesis/generate.ts", diff --git a/smart_contracts/scripts/genesis/config.ts b/smart_contracts/scripts/genesis/config.ts index 45974daf..2eedb1dd 100644 --- a/smart_contracts/scripts/genesis/config.ts +++ b/smart_contracts/scripts/genesis/config.ts @@ -2,11 +2,13 @@ import { AccountControlConfig, CredentialDefinitionsConfig, EthereumDidRegistryConfig, + IndyDidRegistryConfig, RolesConfig, SchemasConfig, + UniversalDidResolverConfig, + UpgradeControlConfig, ValidatorsConfig, } from './contracts' -import { UpgradeControlConfig } from './contracts/upgradeControl' export const compiledContractsFolder = 'compiled-contracts' export const inFile = 'config.json' @@ -15,21 +17,25 @@ export const outFile = 'ContractsGenesis.json' export interface Config { accountControl: AccountControlConfig credentialDefinitionRegistry: CredentialDefinitionsConfig + indyDidRegistry: IndyDidRegistryConfig ethereumDidRegistry: EthereumDidRegistryConfig roleControl: RolesConfig schemaRegistry: SchemasConfig + universalDidResolver: UniversalDidResolverConfig upgradeControl: UpgradeControlConfig validatorControl: ValidatorsConfig } const contractsAddresses = { + didRegistry: '0x0000000000000000000000000000000000003333', credentialDefinitionRegistry: '0x0000000000000000000000000000000000004444', schemas: '0x0000000000000000000000000000000000005555', roles: '0x0000000000000000000000000000000000006666', validators: '0x0000000000000000000000000000000000007777', accountControl: '0x0000000000000000000000000000000000008888', upgradeControl: '0x0000000000000000000000000000000000009999', - ethereumDidRegistry: '0x0000000000000000000000000000000000018888', + universalDidResolver: '0x000000000000000000000000000000000019999', + ethereumDIDRegistry: '0x0000000000000000000000000000000000018888', } export const config: Config = { @@ -47,16 +53,26 @@ export const config: Config = { address: contractsAddresses.credentialDefinitionRegistry, description: 'Smart contract to manage credential definitions', data: { - credentialDefinitions: [], - ethereumDidRegistry: contractsAddresses.ethereumDidRegistry, + universalDidResolverAddress: contractsAddresses.universalDidResolver, schemaRegistryAddress: contractsAddresses.schemas, upgradeControlAddress: contractsAddresses.upgradeControl, }, }, + indyDidRegistry: { + name: 'IndyDidRegistry', + address: contractsAddresses.didRegistry, + description: 'Smart contract to manage DIDs', + data: { + upgradeControlAddress: contractsAddresses.upgradeControl, + }, + }, ethereumDidRegistry: { name: 'EthereumExtDidRegistry', - address: contractsAddresses.ethereumDidRegistry, + address: contractsAddresses.ethereumDIDRegistry, description: 'Ethereum registry for ERC-1056 ethr did methods', + data: { + upgradeControlAddress: contractsAddresses.upgradeControl, + }, }, roleControl: { name: 'RoleControl', @@ -98,8 +114,17 @@ export const config: Config = { address: contractsAddresses.schemas, description: 'Smart contract to manage schemas', data: { - schemas: [], - ethereumDidRegistry: contractsAddresses.ethereumDidRegistry, + universalDidResolverAddress: contractsAddresses.universalDidResolver, + upgradeControlAddress: contractsAddresses.upgradeControl, + }, + }, + universalDidResolver: { + name: 'UniversalDidResolver', + address: contractsAddresses.universalDidResolver, + description: 'Smart contract to resolve DIDs from various DID registries', + data: { + etheriumDidRegistryAddress: contractsAddresses.ethereumDIDRegistry, + didRegistryAddress: contractsAddresses.didRegistry, upgradeControlAddress: contractsAddresses.upgradeControl, }, }, diff --git a/smart_contracts/scripts/genesis/contracts/credentialDefinitionRegistry.ts b/smart_contracts/scripts/genesis/contracts/credentialDefinitionRegistry.ts index bd3cd55a..71f31e51 100644 --- a/smart_contracts/scripts/genesis/contracts/credentialDefinitionRegistry.ts +++ b/smart_contracts/scripts/genesis/contracts/credentialDefinitionRegistry.ts @@ -5,8 +5,7 @@ import { buildProxySection, slots } from '../helpers' export interface CredentialDefinitionsConfig extends ContractConfig { data: { - credentialDefinitions: Array<{ id: string; data: { name: string } }> - ethereumDidRegistry: string + universalDidResolverAddress: string schemaRegistryAddress: string upgradeControlAddress: string } @@ -19,7 +18,7 @@ export function credentialDefinitionRegistry() { // address of upgrade control contact stored in slot 0 storage[slots['0']] = padLeft(data.upgradeControlAddress, 64) // address of DID registry contact stored in slot 1 - storage[slots['1']] = padLeft(data.ethereumDidRegistry, 64) + storage[slots['1']] = padLeft(data.universalDidResolverAddress, 64) // address of schema registry contact stored in slot 2 storage[slots['2']] = padLeft(data.schemaRegistryAddress, 64) return buildProxySection(name, address, description, storage) diff --git a/smart_contracts/scripts/genesis/contracts/ethereumDidRegistry.ts b/smart_contracts/scripts/genesis/contracts/ethereumDidRegistry.ts index 87e3f365..e47a2ad6 100644 --- a/smart_contracts/scripts/genesis/contracts/ethereumDidRegistry.ts +++ b/smart_contracts/scripts/genesis/contracts/ethereumDidRegistry.ts @@ -1,12 +1,18 @@ +import { padLeft } from 'web3-utils' import { config } from '../config' import { ContractConfig } from '../contractConfig' -import { buildProxySection } from '../helpers' +import { buildProxySection, slots } from '../helpers' -export interface EthereumDidRegistryConfig extends ContractConfig {} +export interface EthereumDidRegistryConfig extends ContractConfig { + data: { + upgradeControlAddress: string + } +} export function ethereumDidRegistry() { - const { name, address, description } = config.ethereumDidRegistry + const { name, address, description, data } = config.ethereumDidRegistry const storage: any = {} + storage[slots['0']] = padLeft(data.upgradeControlAddress, 64) return buildProxySection(name, address, description, storage) } diff --git a/smart_contracts/scripts/genesis/contracts/index.ts b/smart_contracts/scripts/genesis/contracts/index.ts index d9d9ba09..06edfd25 100644 --- a/smart_contracts/scripts/genesis/contracts/index.ts +++ b/smart_contracts/scripts/genesis/contracts/index.ts @@ -1,7 +1,9 @@ export * from './accountControl' export * from './credentialDefinitionRegistry' +export * from './indyDidRegistry' export * from './ethereumDidRegistry' export * from './roleControl' export * from './schemaRegistry' +export * from './universalDidResolver' export * from './upgradeControl' export * from './validatorControl' diff --git a/smart_contracts/scripts/genesis/contracts/indyDidRegistry.ts b/smart_contracts/scripts/genesis/contracts/indyDidRegistry.ts new file mode 100644 index 00000000..feae2a7e --- /dev/null +++ b/smart_contracts/scripts/genesis/contracts/indyDidRegistry.ts @@ -0,0 +1,18 @@ +import { padLeft } from 'web3-utils' +import { config } from '../config' +import { ContractConfig } from '../contractConfig' +import { buildProxySection, slots } from '../helpers' + +export interface IndyDidRegistryConfig extends ContractConfig { + data: { + upgradeControlAddress: string + } +} + +export function indyDidRegistry() { + const { name, address, description, data } = config.indyDidRegistry + const storage: any = {} + + storage[slots['0']] = padLeft(data.upgradeControlAddress, 64) + return buildProxySection(name, address, description, storage) +} diff --git a/smart_contracts/scripts/genesis/contracts/schemaRegistry.ts b/smart_contracts/scripts/genesis/contracts/schemaRegistry.ts index 187f2d9c..7446547b 100644 --- a/smart_contracts/scripts/genesis/contracts/schemaRegistry.ts +++ b/smart_contracts/scripts/genesis/contracts/schemaRegistry.ts @@ -5,8 +5,7 @@ import { buildProxySection, slots } from '../helpers' export interface SchemasConfig extends ContractConfig { data: { - schemas: Array<{ id: string; data: { name: string } }> - ethereumDidRegistry: string + universalDidResolverAddress: string upgradeControlAddress: string } } @@ -18,6 +17,6 @@ export function schemaRegistry() { // address of upgrade control contact stored in slot 0 storage[slots['0']] = padLeft(data.upgradeControlAddress, 64) // address of DID resolver contact stored in slot 1 - storage[slots['1']] = padLeft(data.ethereumDidRegistry, 64) + storage[slots['1']] = padLeft(data.universalDidResolverAddress, 64) return buildProxySection(name, address, description, storage) } diff --git a/smart_contracts/scripts/genesis/contracts/universalDidResolver.ts b/smart_contracts/scripts/genesis/contracts/universalDidResolver.ts new file mode 100644 index 00000000..9f9bcdb3 --- /dev/null +++ b/smart_contracts/scripts/genesis/contracts/universalDidResolver.ts @@ -0,0 +1,25 @@ +import { padLeft } from 'web3-utils' +import { config } from '../config' +import { ContractConfig } from '../contractConfig' +import { buildProxySection, slots } from '../helpers' + +export interface UniversalDidResolverConfig extends ContractConfig { + data: { + didRegistryAddress: string + etheriumDidRegistryAddress: string + upgradeControlAddress: string + } +} + +export function universalDidResolver() { + const { name, address, description, data } = config.universalDidResolver + const storage: any = {} + + // address of upgrade control contact stored in slot 0 + storage[slots['0']] = padLeft(data.upgradeControlAddress, 64) + // address of DID registry contact stored in slot 1 + storage[slots['1']] = padLeft(data.didRegistryAddress, 64) + // address of etherium DID registry contact stored in slot 2 + storage[slots['2']] = padLeft(data.etheriumDidRegistryAddress, 64) + return buildProxySection(name, address, description, storage) +} diff --git a/smart_contracts/scripts/genesis/generate.ts b/smart_contracts/scripts/genesis/generate.ts index 93d5737f..5582de82 100644 --- a/smart_contracts/scripts/genesis/generate.ts +++ b/smart_contracts/scripts/genesis/generate.ts @@ -4,8 +4,10 @@ import { accountControl, credentialDefinitionRegistry, ethereumDidRegistry, + indyDidRegistry, roleControl, schemaRegistry, + universalDidResolver, upgradeControl, validatorControl, } from './contracts' @@ -16,7 +18,9 @@ function main() { ...roleControl(), ...validatorControl(), ...upgradeControl(), + ...indyDidRegistry(), ...ethereumDidRegistry(), + ...universalDidResolver(), ...schemaRegistry(), ...credentialDefinitionRegistry(), } diff --git a/smart_contracts/test/cl/CredentialDefinitionRegistry.spec.ts b/smart_contracts/test/cl/CredentialDefinitionRegistry.spec.ts index 7faeb5b8..87558e71 100644 --- a/smart_contracts/test/cl/CredentialDefinitionRegistry.spec.ts +++ b/smart_contracts/test/cl/CredentialDefinitionRegistry.spec.ts @@ -1,46 +1,46 @@ import { expect } from 'chai' import { keccak256, toUtf8Bytes } from 'ethers' -import { EthereumExtDidRegistry } from '../../contracts-ts' +import { IndyDidRegistry } from '../../contracts-ts' import { createCredentialDefinitionObject } from '../../utils' import { createDid, + createDidSigned, createSchema, createSchemaSigned, deployCredentialDefinitionRegistry, - signCredDefEndorsementData, TestableCredentialDefinitionRegistry, TestableSchemaRegistry, testActorAddress, testActorPrivateKey, } from '../utils/contract-helpers' -import { ClErrors } from '../utils/errors' +import { ClErrors, DidError } from '../utils/errors' import { TestAccounts } from '../utils/test-entities' describe('CredentialDefinitionRegistry', function () { - let didRegistry: EthereumExtDidRegistry + let didRegistry: IndyDidRegistry let schemaRegistry: TestableSchemaRegistry let credentialDefinitionRegistry: TestableCredentialDefinitionRegistry let testAccounts: TestAccounts let schemaId: string - let issuer: string + let issuerAddress: string + let issuerId: string beforeEach(async function () { const { - didRegistry: didRegistryInit, + indyDidRegistry: didRegistryInit, schemaRegistry: schemaRegistryInit, credentialDefinitionRegistry: credentialDefinitionRegistryInit, testAccounts: testAccountsInit, } = await deployCredentialDefinitionRegistry() - issuer = testAccountsInit.trustee.account.address didRegistryInit.connect(testAccountsInit.trustee.account) schemaRegistryInit.connect(testAccountsInit.trustee.account) credentialDefinitionRegistryInit.connect(testAccountsInit.trustee.account) - const issuerId = `did:ethr:mainnet:${issuer}` - await createDid(didRegistryInit, testAccountsInit.trustee.account.address, issuerId) - - const { id } = await createSchema(schemaRegistryInit, issuer) + issuerAddress = testAccountsInit.trustee.account.address + issuerId = `did:indybesu:mainnet:${testAccountsInit.trustee.account.address}` + await createDid(didRegistryInit, issuerAddress, issuerId) + const { id } = await createSchema(schemaRegistryInit, issuerAddress, issuerId) didRegistry = didRegistryInit testAccounts = testAccountsInit @@ -50,28 +50,31 @@ describe('CredentialDefinitionRegistry', function () { }) describe('Add/Resolve Credential Definition', function () { - it('Should create Credential Definition', async function () { - const { id, credDef } = createCredentialDefinitionObject({ issuer, schemaId }) + it('Should create and resolve Credential Definition', async function () { + const { id, credDef } = createCredentialDefinitionObject({ issuerId, schemaId }) - await credentialDefinitionRegistry.createCredentialDefinition(issuer, id, schemaId, credDef) + await credentialDefinitionRegistry.createCredentialDefinition(issuerAddress, id, issuerId, schemaId, credDef) + const result = await credentialDefinitionRegistry.resolveCredentialDefinition(id) - const created = await credentialDefinitionRegistry.created(id) - expect(created).to.be.not.equal(0) + expect(result.credDef).to.be.deep.equal(credDef) }) - it('Should return zero created block a non-existing credential definition', async function () { - const { id } = createCredentialDefinitionObject({ issuer, schemaId }) + it('Should fail if resolving Credential Definition does not exist', async function () { + const { id } = createCredentialDefinitionObject({ issuerId, schemaId }) - const created = await credentialDefinitionRegistry.created(id) - expect(created).to.be.equal(0) + await expect(credentialDefinitionRegistry.resolveCredentialDefinition(id)) + .to.be.revertedWithCustomError(credentialDefinitionRegistry.baseInstance, ClErrors.CredentialDefinitionNotFound) + .withArgs(keccak256(toUtf8Bytes(id))) }) it('Should fail if Credential Definition is being already exists', async function () { - const { id, credDef } = createCredentialDefinitionObject({ issuer, schemaId }) + const { id, credDef } = createCredentialDefinitionObject({ issuerId, schemaId }) - await credentialDefinitionRegistry.createCredentialDefinition(issuer, id, schemaId, credDef) + await credentialDefinitionRegistry.createCredentialDefinition(issuerAddress, id, issuerId, schemaId, credDef) - await expect(credentialDefinitionRegistry.createCredentialDefinition(issuer, id, schemaId, credDef)) + await expect( + credentialDefinitionRegistry.createCredentialDefinition(issuerAddress, id, issuerId, schemaId, credDef), + ) .to.be.revertedWithCustomError( credentialDefinitionRegistry.baseInstance, ClErrors.CredentialDefinitionAlreadyExist, @@ -79,42 +82,145 @@ describe('CredentialDefinitionRegistry', function () { .withArgs(keccak256(toUtf8Bytes(id))) }) + it('Should fail if Credential Definition is being created with non-existing Issuer', async function () { + const unknownIssuerId = `did:indybesu:mainnet:${testAccounts.noRole.account.address}` + const { id, credDef } = createCredentialDefinitionObject({ issuerId: unknownIssuerId, schemaId }) + + credentialDefinitionRegistry.connect(testAccounts.noRole.account) + + await expect( + credentialDefinitionRegistry.createCredentialDefinition( + testAccounts.noRole.account.address, + id, + unknownIssuerId, + schemaId, + credDef, + ), + ) + .to.be.revertedWithCustomError(credentialDefinitionRegistry.baseInstance, ClErrors.IssuerNotFound) + .withArgs(unknownIssuerId) + }) + + it('Should fail if Credential Definition is being created with inactive Issuer', async function () { + await didRegistry.deactivateDid(issuerAddress) + + const { id, credDef } = createCredentialDefinitionObject({ issuerId, schemaId }) + + await expect( + credentialDefinitionRegistry.createCredentialDefinition(issuerAddress, id, issuerId, schemaId, credDef), + ) + .to.be.revertedWithCustomError(credentialDefinitionRegistry.baseInstance, ClErrors.IssuerHasBeenDeactivated) + .withArgs(issuerId) + }) + it('Should fail if Credential Definition is being created with non-existing Schema', async function () { - const unknownSchemaId = 'did:indy2:mainnet:SEp33q43PsdP7nDATyySSH/anoncreds/v0/SCHEMA/Test/1.0.0' - const { id, credDef } = createCredentialDefinitionObject({ issuer, schemaId: unknownSchemaId }) + const unknownSchemaId = `${issuerId}/anoncreds/v0/SCHEMA/Test/1.0.0` + const { id, credDef } = createCredentialDefinitionObject({ issuerId, schemaId: unknownSchemaId }) - await expect(credentialDefinitionRegistry.createCredentialDefinition(issuer, id, unknownSchemaId, credDef)) - .to.be.revertedWithCustomError(credentialDefinitionRegistry.baseInstance, ClErrors.SchemaNotFound) + await expect( + credentialDefinitionRegistry.createCredentialDefinition(issuerAddress, id, issuerId, unknownSchemaId, credDef), + ) + .to.be.revertedWithCustomError(schemaRegistry.baseInstance, ClErrors.SchemaNotFound) .withArgs(keccak256(toUtf8Bytes(unknownSchemaId))) }) it('Should fail if Credential Definition is being created with not owned Issuer DID', async function () { - const issuerId2 = 'did:indy2:mainnet:SEp33q43PsdP7nDATyyDDA' - const { id, credDef } = createCredentialDefinitionObject({ issuer, schemaId }) + const issuerId2 = `did:indybesu:mainnet:${testAccounts.trustee2.account}` + const { id, credDef } = createCredentialDefinitionObject({ issuerId, schemaId }) + didRegistry.connect(testAccounts.trustee2.account) + credentialDefinitionRegistry.connect(testAccounts.trustee2.account) + + await createDid(didRegistry, testAccounts.trustee2.account.address, issuerId2) await expect( credentialDefinitionRegistry.createCredentialDefinition( testAccounts.trustee2.account.address, id, + issuerId, schemaId, credDef, ), + ).to.be.revertedWithCustomError(credentialDefinitionRegistry.baseInstance, DidError.NotIdentityOwner) + }) + }) + + describe('Add/Resolve Credential Definition with did:ethr Issuer', function () { + it('Should create and resolve Credential Definition', async function () { + const ethrIssuerId = `did:ethr:${issuerAddress}` + const { id, credDef } = createCredentialDefinitionObject({ issuerId: ethrIssuerId, schemaId }) + + await credentialDefinitionRegistry.createCredentialDefinition(issuerAddress, id, ethrIssuerId, schemaId, credDef) + const result = await credentialDefinitionRegistry.resolveCredentialDefinition(id) + + expect(result.credDef).to.be.deep.equal(credDef) + }) + + it('Should fail if Credential Definition is being created with not owned Issuer DID', async function () { + const ethrIssuerId = `did:ethr:${testAccounts.trustee2.account.address}` + const { id, credDef } = createCredentialDefinitionObject({ issuerId: ethrIssuerId, schemaId }) + + await expect( + credentialDefinitionRegistry.createCredentialDefinition( + testAccounts.trustee2.account.address, + id, + ethrIssuerId, + schemaId, + credDef, + ), + ).to.be.revertedWithCustomError(credentialDefinitionRegistry.baseInstance, DidError.NotIdentityOwner) + }) + + it('Should fail if Credential Definition is being created with invalid Issuer ID', async function () { + const invalidIssuerId = 'did:ethr:ab$ddfgh354345' + const { id, credDef } = createCredentialDefinitionObject({ issuerId: invalidIssuerId, schemaId }) + + await expect( + credentialDefinitionRegistry.createCredentialDefinition(issuerAddress, id, invalidIssuerId, schemaId, credDef), ) - .to.be.revertedWithCustomError(credentialDefinitionRegistry.baseInstance, ClErrors.UnauthorizedIssuer) - .withArgs(testAccounts.trustee2.account.address, testAccounts.trustee.account.address) + .to.be.revertedWithCustomError(schemaRegistry.baseInstance, ClErrors.InvalidIssuerId) + .withArgs(invalidIssuerId) }) }) describe('Endorse/Resolve Credential Definition with did:ethr Issuer', function () { - it('Should endorse and resolve Credential Definition', async function () { - const { id: ethSchemaId } = await createSchemaSigned(schemaRegistry, testActorAddress) + it('Should endorse and resolve Credential Definition with did:ethr', async function () { + const authorDid = `did:ethr:${testActorAddress}` + const { id: ethSchemaId } = await createSchemaSigned(schemaRegistry, testActorAddress, authorDid) + + const { id, credDef } = createCredentialDefinitionObject({ issuerId: authorDid, schemaId: ethSchemaId }) + const signature = await credentialDefinitionRegistry.signCreateCredDefEndorsementData( + testActorAddress, + testActorPrivateKey, + id, + authorDid, + ethSchemaId, + credDef, + ) + + await credentialDefinitionRegistry.createCredentialDefinitionSigned( + testActorAddress, + id, + authorDid, + ethSchemaId, + credDef, + signature, + ) + + const result = await credentialDefinitionRegistry.resolveCredentialDefinition(id) + expect(result.credDef).to.be.deep.equal(credDef) + }) - const { id, credDef } = createCredentialDefinitionObject({ issuer: testActorAddress, schemaId: ethSchemaId }) - const signature = await signCredDefEndorsementData( - credentialDefinitionRegistry, + it('Should endorse and resolve Credential Definition with did:indybesu', async function () { + const authorDid = `did:indybesu:${testActorAddress}` + await createDidSigned(didRegistry, testActorAddress, authorDid) + const { id: ethSchemaId } = await createSchemaSigned(schemaRegistry, testActorAddress, authorDid) + + const { id, credDef } = createCredentialDefinitionObject({ issuerId: authorDid, schemaId: ethSchemaId }) + const signature = await credentialDefinitionRegistry.signCreateCredDefEndorsementData( testActorAddress, testActorPrivateKey, id, + authorDid, ethSchemaId, credDef, ) @@ -122,24 +228,27 @@ describe('CredentialDefinitionRegistry', function () { await credentialDefinitionRegistry.createCredentialDefinitionSigned( testActorAddress, id, + authorDid, ethSchemaId, credDef, signature, ) - const created = await credentialDefinitionRegistry.created(id) - expect(created).to.be.not.equal(0) + const result = await credentialDefinitionRegistry.resolveCredentialDefinition(id) + expect(result.credDef).to.be.deep.equal(credDef) }) it('Should fail if Credential Definition is being endorsed with not owned Issuer DID', async function () { - const { id: ethSchemaId } = await createSchemaSigned(schemaRegistry, testActorAddress) - const { id, credDef } = createCredentialDefinitionObject({ issuer: testActorAddress, schemaId: ethSchemaId }) + const authorDid = `did:ethr:${testActorAddress}` + const { id: ethSchemaId } = await createSchemaSigned(schemaRegistry, testActorAddress, authorDid) + + const { id, credDef } = createCredentialDefinitionObject({ issuerId: authorDid, schemaId: ethSchemaId }) - const signature = await signCredDefEndorsementData( - credentialDefinitionRegistry, + const signature = await credentialDefinitionRegistry.signCreateCredDefEndorsementData( testAccounts.trustee2.account.address, testActorPrivateKey, id, + authorDid, ethSchemaId, credDef, ) @@ -147,24 +256,25 @@ describe('CredentialDefinitionRegistry', function () { credentialDefinitionRegistry.createCredentialDefinitionSigned( testAccounts.trustee2.account.address, id, + authorDid, ethSchemaId, credDef, signature, ), - ) - .to.be.revertedWithCustomError(schemaRegistry.baseInstance, ClErrors.UnauthorizedIssuer) - .withArgs(testAccounts.trustee2.account.address, testActorAddress) + ).to.be.revertedWithCustomError(schemaRegistry.baseInstance, DidError.NotIdentityOwner) }) it('Should fail if Schema is being endorsed with invalid signature', async function () { - const { id: ethSchemaId } = await createSchemaSigned(schemaRegistry, testActorAddress) - const { id, credDef } = createCredentialDefinitionObject({ issuer: testActorAddress, schemaId: ethSchemaId }) + const authorDid = `did:ethr:${testActorAddress}` + const { id: ethSchemaId } = await createSchemaSigned(schemaRegistry, testActorAddress, authorDid) + + const { id, credDef } = createCredentialDefinitionObject({ issuerId: authorDid, schemaId: ethSchemaId }) - const signature = await signCredDefEndorsementData( - credentialDefinitionRegistry, + const signature = await credentialDefinitionRegistry.signCreateCredDefEndorsementData( testActorAddress, testActorPrivateKey, 'different id passed into signature', + authorDid, ethSchemaId, credDef, ) @@ -172,11 +282,12 @@ describe('CredentialDefinitionRegistry', function () { credentialDefinitionRegistry.createCredentialDefinitionSigned( testActorAddress, id, + authorDid, schemaId, credDef, signature, ), - ).to.be.revertedWithCustomError(schemaRegistry.baseInstance, ClErrors.UnauthorizedIssuer) + ).to.be.revertedWithCustomError(schemaRegistry.baseInstance, DidError.NotIdentityOwner) }) }) }) diff --git a/smart_contracts/test/cl/SchemaRegistry.spec.ts b/smart_contracts/test/cl/SchemaRegistry.spec.ts index 9a11f2a7..29eecc86 100644 --- a/smart_contracts/test/cl/SchemaRegistry.spec.ts +++ b/smart_contracts/test/cl/SchemaRegistry.spec.ts @@ -1,37 +1,38 @@ import { expect } from 'chai' import { keccak256, toUtf8Bytes } from 'ethers' -import { EthereumExtDidRegistry, SchemaRegistry } from '../../contracts-ts' +import { IndyDidRegistry, SchemaRegistry } from '../../contracts-ts' import { createSchemaObject } from '../../utils' import { createDid, + createDidSigned, deploySchemaRegistry, - signSchemaEndorsementData, TestableSchemaRegistry, testActorAddress, testActorPrivateKey, } from '../utils/contract-helpers' -import { ClErrors } from '../utils/errors' +import { ClErrors, DidError } from '../utils/errors' import { TestAccounts } from '../utils/test-entities' describe('SchemaRegistry', function () { - let didRegistry: EthereumExtDidRegistry + let didRegistry: IndyDidRegistry let schemaRegistry: TestableSchemaRegistry let testAccounts: TestAccounts - let issuer: string + let issuerAddress: string + let issuerId: string beforeEach(async function () { const { - didRegistry: didRegistryInit, + indyDidRegistry: didRegistryInit, schemaRegistry: schemaRegistryInit, testAccounts: testAccountsInit, } = await deploySchemaRegistry() - issuer = testAccountsInit.trustee.account.address didRegistryInit.connect(testAccountsInit.trustee.account) schemaRegistryInit.connect(testAccountsInit.trustee.account) - const issuerId = `did:ethr:mainnet:${issuer}` - await createDid(didRegistryInit, testAccountsInit.trustee.account.address, issuerId) + issuerAddress = testAccountsInit.trustee.account.address + issuerId = `did:indybesu:mainnet:${testAccountsInit.trustee.account.address}` + await createDid(didRegistryInit, issuerAddress, issuerId) didRegistry = didRegistryInit testAccounts = testAccountsInit @@ -39,81 +40,169 @@ describe('SchemaRegistry', function () { }) describe('Add/Resolve Schema', function () { - it('Should create Schema', async function () { - const { id, schema } = createSchemaObject({ issuer }) + it('Should create and resolve Schema', async function () { + const { id, schema } = createSchemaObject({ issuerId }) - await schemaRegistry.createSchema(issuer, id, schema) + await schemaRegistry.createSchema(issuerAddress, id, issuerId, schema) + const result = await schemaRegistry.resolveSchema(id) - const created = await schemaRegistry.created(id) - expect(created).to.be.not.equal(0) + expect(result.schema).to.be.equal(schema) }) - it('Should return zero created block a non-existing schema', async function () { - const { id } = createSchemaObject({ issuer }) + it('Should fail if resolving a non-existing schema', async function () { + const { id } = createSchemaObject({ issuerId }) - const created = await schemaRegistry.created(id) - expect(created).to.be.equal(0) + await expect(schemaRegistry.resolveSchema(id)) + .to.be.revertedWithCustomError(schemaRegistry.baseInstance, ClErrors.SchemaNotFound) + .withArgs(keccak256(toUtf8Bytes(id))) }) it('Should fail if Schema is being created already exists', async function () { - const { id, schema } = createSchemaObject({ issuer }) + const { id, schema } = createSchemaObject({ issuerId }) - await schemaRegistry.createSchema(issuer, id, schema) + await schemaRegistry.createSchema(issuerAddress, id, issuerId, schema) - await expect(schemaRegistry.createSchema(issuer, id, schema)) + await expect(schemaRegistry.createSchema(issuerAddress, id, issuerId, schema)) .to.be.revertedWithCustomError(schemaRegistry.baseInstance, ClErrors.SchemaAlreadyExist) .withArgs(keccak256(toUtf8Bytes(id))) }) + it('Should fail if Schema is being created with non-existing Issuer', async function () { + const identity = testAccounts.noRole.account.address + const unknownIssuerId = `did:indybesu:mainnet:${identity}` + const { id, schema } = createSchemaObject({ issuerId: unknownIssuerId }) + + schemaRegistry.connect(testAccounts.noRole.account) + + await expect(schemaRegistry.createSchema(identity, id, unknownIssuerId, schema)) + .to.be.revertedWithCustomError(schemaRegistry.baseInstance, ClErrors.IssuerNotFound) + .withArgs(unknownIssuerId) + }) + + it('Should fail if Schema is being created with inactive Issuer', async function () { + await didRegistry.deactivateDid(issuerAddress) + + const { id, schema } = createSchemaObject({ issuerId }) + + await expect(schemaRegistry.createSchema(issuerAddress, id, issuerId, schema)) + .to.be.revertedWithCustomError(schemaRegistry.baseInstance, ClErrors.IssuerHasBeenDeactivated) + .withArgs(issuerId) + }) + it('Should fail if Schema is being created with not owned Issuer DID', async function () { - const { id, schema } = createSchemaObject({ issuer }) + const issuerId2 = `did:indybesu:mainnet:${testAccounts.trustee2.account}` + const { id, schema } = createSchemaObject({ issuerId }) - await expect(schemaRegistry.createSchema(testAccounts.trustee2.account.address, id, schema)) - .to.be.revertedWithCustomError(schemaRegistry.baseInstance, ClErrors.UnauthorizedIssuer) - .withArgs(testAccounts.trustee2.account.address, testAccounts.trustee.account.address) + didRegistry.connect(testAccounts.trustee2.account) + schemaRegistry.connect(testAccounts.trustee2.account) + + await createDid(didRegistry, testAccounts.trustee2.account.address, issuerId2) + await expect( + schemaRegistry.createSchema(testAccounts.trustee2.account.address, id, issuerId, schema), + ).to.be.revertedWithCustomError(schemaRegistry.baseInstance, DidError.NotIdentityOwner) + }) + }) + + describe('Add/Resolve Schema with did:ethr Issuer', function () { + it('Should create and resolve Schema', async function () { + const ethrIssuerId = `did:ethr:${testAccounts.trustee.account.address}` + + const { id, schema } = createSchemaObject({ issuerId: ethrIssuerId }) + + await schemaRegistry.createSchema(issuerAddress, id, ethrIssuerId, schema) + const result = await schemaRegistry.resolveSchema(id) + + expect(result.schema).to.be.deep.equal(schema) + }) + + it('Should fail if Schema is being created with not owned Issuer DID', async function () { + const ethrIssuerId = `did:ethr:${testAccounts.trustee2.account.address}` + + const { id, schema } = createSchemaObject({ issuerId: ethrIssuerId }) + + await expect(schemaRegistry.createSchema(issuerAddress, id, ethrIssuerId, schema)).to.be.revertedWithCustomError( + schemaRegistry.baseInstance, + DidError.NotIdentityOwner, + ) + }) + + it('Should fail if Schema is being created with invalid Issuer ID', async function () { + const invalidIssuerId = 'did:ethr:ab$ddfgh354345' + const { id, schema } = createSchemaObject({ issuerId: invalidIssuerId }) + + await expect( + schemaRegistry.createSchema(issuerAddress, id, invalidIssuerId, schema), + ).to.be.revertedWithCustomError(schemaRegistry.baseInstance, ClErrors.InvalidIssuerId) }) }) describe('Endorse/Resolve Schema with did:ethr Issuer', function () { - it('Should endorse Schema', async function () { - const { id, schema } = createSchemaObject({ issuer: testActorAddress }) + it('Should endorse Schema with did:ethr', async function () { + const authorDid = `did:ethr:${testActorAddress}` + const { id, schema } = createSchemaObject({ issuerId: authorDid }) - const sig = await signSchemaEndorsementData(schemaRegistry, testActorAddress, testActorPrivateKey, id, schema) + const sig = await schemaRegistry.signCreateSchemaEndorsementData( + testActorAddress, + testActorPrivateKey, + id, + authorDid, + schema, + ) - await schemaRegistry.createSchemaSigned(testActorAddress, id, schema, sig) - const created = await schemaRegistry.created(id) - expect(created).to.be.not.equal(0) + await schemaRegistry.createSchemaSigned(testActorAddress, id, authorDid, schema, sig) + const result = await schemaRegistry.resolveSchema(id) + + expect(result.schema).to.be.equal(schema) + }) + + it('Should endorse Schema with did:indybesu', async function () { + const authorDid = `did:indybesu:${testActorAddress}` + await createDidSigned(didRegistry, testActorAddress, authorDid) + const { id, schema } = createSchemaObject({ issuerId: authorDid }) + + const sig = await schemaRegistry.signCreateSchemaEndorsementData( + testActorAddress, + testActorPrivateKey, + id, + authorDid, + schema, + ) + await schemaRegistry.createSchemaSigned(testActorAddress, id, authorDid, schema, sig) + const result = await schemaRegistry.resolveSchema(id) + + expect(result.schema).to.be.equal(schema) }) it('Should fail if Schema is being endorsed with not owned Issuer DID', async function () { - const { id, schema } = createSchemaObject({ issuer: testAccounts.trustee2.account.address }) + const authorDid = `did:ethr:${testAccounts.trustee2.account.address}` + const { id, schema } = createSchemaObject({ issuerId: authorDid }) - const sig = await signSchemaEndorsementData( - schemaRegistry, + const sig = await schemaRegistry.signCreateSchemaEndorsementData( testAccounts.trustee2.account.address, testActorPrivateKey, id, + authorDid, schema, ) - await expect(schemaRegistry.createSchemaSigned(testAccounts.trustee2.account.address, id, schema, sig)) - .to.be.revertedWithCustomError(schemaRegistry.baseInstance, ClErrors.UnauthorizedIssuer) - .withArgs(testAccounts.trustee2.account.address, testActorAddress) + await expect( + schemaRegistry.createSchemaSigned(testAccounts.trustee2.account.address, id, authorDid, schema, sig), + ).to.be.revertedWithCustomError(schemaRegistry.baseInstance, DidError.NotIdentityOwner) }) it('Should fail if Schema is being endorsed with invalid signature', async function () { - const { id, schema } = createSchemaObject({ issuer: testActorAddress }) + const authorDid = `did:ethr:${testActorAddress}` + const { id, schema } = createSchemaObject({ issuerId: authorDid }) - const sig = await signSchemaEndorsementData( - schemaRegistry, + const sig = await schemaRegistry.signCreateSchemaEndorsementData( testActorAddress, testActorPrivateKey, 'different id passed into signature', + authorDid, schema, ) - await expect(schemaRegistry.createSchemaSigned(testActorAddress, id, schema, sig)).to.be.revertedWithCustomError( - schemaRegistry.baseInstance, - ClErrors.UnauthorizedIssuer, - ) + await expect( + schemaRegistry.createSchemaSigned(testActorAddress, id, authorDid, schema, sig), + ).to.be.revertedWithCustomError(schemaRegistry.baseInstance, DidError.NotIdentityOwner) }) }) }) diff --git a/smart_contracts/test/did/DidRegistry.spec.ts b/smart_contracts/test/did/DidRegistry.spec.ts index 9a3aece3..a751e933 100644 --- a/smart_contracts/test/did/DidRegistry.spec.ts +++ b/smart_contracts/test/did/DidRegistry.spec.ts @@ -1,25 +1,154 @@ import { expect } from 'chai' -import { deployDidRegistry, TestableDidRegistry } from '../utils/contract-helpers' +import { createBaseDidDocument } from '../../utils/entity-factories' +import { + deployIndyDidRegistry, + TestableIndyDidRegistry, + testActorAddress, + testActorPrivateKey, +} from '../utils/contract-helpers' +import { DidError } from '../utils/errors' import { TestAccounts } from '../utils/test-entities' -describe('DIDContract', function () { - let didRegistry: TestableDidRegistry +describe('IndyDidRegistry', function () { + let didRegistry: TestableIndyDidRegistry let testAccounts: TestAccounts + let identity: string + let did: string + let didDocument: string beforeEach(async function () { - const { didRegistry: didRegistryInit, testAccounts: testAccountsInit } = await deployDidRegistry() + const { indyDidRegistry: didRegistryInit, testAccounts: testAccountsInit } = await deployIndyDidRegistry() didRegistry = didRegistryInit testAccounts = testAccountsInit + identity = testAccounts.trustee.account.address + did = `did:indybesu:testnet:${testAccounts.trustee.account}` + didDocument = createBaseDidDocument(did) + didRegistry.connect(testAccounts.trustee.account) }) describe('Create DID', function () { - it('Create DID Works', async function () { - // We do not need to cover DID Registry with tests as it's already done in the original contract - const changed = await didRegistry.changed(testAccounts.trustee.account.address) - expect(changed).to.be.equal(0) + it('Should create and resolve DID document', async function () { + await didRegistry.createDid(identity, didDocument) + + const { document } = await didRegistry.resolveDid(identity) + + expect(document).to.be.deep.equal(didDocument) + }) + + it('Should fail if resolving DID does not exist', async function () { + await expect(didRegistry.resolveDid(identity)) + .to.revertedWithCustomError(didRegistry.baseInstance, DidError.DidNotFound) + .withArgs(identity) + }) + + it('Should fail if the DID being created already exists', async function () { + await didRegistry.createDid(identity, didDocument) + + await expect(didRegistry.createDid(identity, didDocument)) + .to.be.revertedWithCustomError(didRegistry.baseInstance, DidError.DidAlreadyExist) + .withArgs(identity) + }) + }) + + describe('Update DID', function () { + it('Should update DID document', async function () { + await didRegistry.createDid(identity, didDocument) + + await didRegistry.updateDid(identity, didDocument) + + const { document } = await didRegistry.resolveDid(identity) + + expect(document).to.be.deep.equal(didDocument) + }) + + it('Should fail if the DID creator is not an update txn sender', async function () { + await didRegistry.createDid(identity, didDocument) + + didRegistry.connect(testAccounts.trustee2.account) + await expect(didRegistry.updateDid(identity, didDocument)).to.revertedWithCustomError( + didRegistry.baseInstance, + DidError.NotIdentityOwner, + ) + }) + + it('Should fail if the DID being updated does not exists', async function () { + await expect(didRegistry.updateDid(identity, didDocument)) + .to.revertedWithCustomError(didRegistry.baseInstance, DidError.DidNotFound) + .withArgs(identity) + }) + + it('Should fail if the DID being updated is deactivated', async function () { + await didRegistry.createDid(identity, didDocument) + await didRegistry.deactivateDid(identity) + + await expect(didRegistry.updateDid(identity, didDocument)) + .to.revertedWithCustomError(didRegistry.baseInstance, DidError.DidHasBeenDeactivated) + .withArgs(identity) + }) + }) + + describe('Deactivate DID', function () { + it('Should deactivate DID document', async function () { + await didRegistry.createDid(identity, didDocument) + await didRegistry.deactivateDid(identity) + + const didStorage = await didRegistry.resolveDid(identity) + + expect(didStorage.metadata.deactivated).is.true + }) + + it('Should fail if the DID has already been deactivated', async function () { + await didRegistry.createDid(identity, didDocument) + await didRegistry.deactivateDid(identity) + + await expect(didRegistry.deactivateDid(identity)) + .to.revertedWithCustomError(didRegistry.baseInstance, DidError.DidHasBeenDeactivated) + .withArgs(identity) + }) + + it('Should fail if the DID being deactivated does not exists', async function () { + await expect(didRegistry.deactivateDid(identity)) + .to.revertedWithCustomError(didRegistry.baseInstance, DidError.DidNotFound) + .withArgs(identity) + }) + + it('Should fail if the DID creator is not an deactivate txn sender', async function () { + await didRegistry.createDid(identity, didDocument) + + didRegistry.connect(testAccounts.trustee2.account) + await expect(didRegistry.deactivateDid(identity)).to.revertedWithCustomError( + didRegistry.baseInstance, + DidError.NotIdentityOwner, + ) + }) + }) + + describe('Endorse DID', function () { + it('Should endorse and resolve DID document', async function () { + const authorDid = `did:indybesu:testnet:${testActorAddress}` + const authorDidDocument = createBaseDidDocument(authorDid) + + let sig = await didRegistry.signCreateDidEndorsementData(testActorAddress, testActorPrivateKey, authorDidDocument) + await didRegistry.createDidSigned(testActorAddress, authorDidDocument, sig) + + let didRecord = await didRegistry.resolveDid(testActorAddress) + expect(didRecord.document).to.be.deep.equal(authorDidDocument) + + const updatedDidDocument = createBaseDidDocument(authorDid, { + id: 'kid', + type: 'Ed25519VerificationKey2018', + controller: authorDid, + publicKeyMultibase: 'key', + }) + + sig = await didRegistry.signUpdateDidEndorsementData(testActorAddress, testActorPrivateKey, updatedDidDocument) + await didRegistry.updateDidSigned(testActorAddress, updatedDidDocument, sig) + + didRecord = await didRegistry.resolveDid(testActorAddress) + expect(didRecord.document).to.be.deep.equal(updatedDidDocument) }) }) }) diff --git a/smart_contracts/test/did/UniversalDidResolver.spec.ts b/smart_contracts/test/did/UniversalDidResolver.spec.ts new file mode 100644 index 00000000..03e43db6 --- /dev/null +++ b/smart_contracts/test/did/UniversalDidResolver.spec.ts @@ -0,0 +1,78 @@ +import { loadFixture } from '@nomicfoundation/hardhat-network-helpers' +import { expect } from 'chai' +import { createBaseDidDocument } from '../../utils' +import { deployUniversalDidResolver, TestableUniversalDidResolver } from '../utils/contract-helpers' +import { DidError } from '../utils/errors' +import { TestAccounts } from '../utils/test-entities' + +describe('UniversalDidResolver', function () { + let did: string + let identity: string + let indybesuDidDocument: string + + let universalDidResolver: TestableUniversalDidResolver + let testAccounts: TestAccounts + + async function deployUniversalDidResolverFixture() { + const { + universalDidReolver: universalDidReolverInit, + indyDidRegistry, + testAccounts: testAccountsInit, + } = await deployUniversalDidResolver() + + identity = testAccountsInit.trustee.account.address + did = `did:indybesu:testnet:${identity}` + indybesuDidDocument = createBaseDidDocument(did) + + indyDidRegistry.connect(testAccountsInit.trustee.account) + await indyDidRegistry.createDid(identity, indybesuDidDocument) + + return { universalDidReolverInit, testAccountsInit } + } + + beforeEach(async function () { + const { universalDidReolverInit, testAccountsInit } = await loadFixture(deployUniversalDidResolverFixture) + + universalDidResolver = universalDidReolverInit + testAccounts = testAccountsInit + + universalDidResolver.connect(testAccounts.trustee.account) + }) + + describe('Resolve did:indybesu', function () { + it('Should resolve DID document', async function () { + const document = await universalDidResolver.resolveDocument(did) + + expect(document).to.be.deep.equal(indybesuDidDocument) + }) + + it('Should resolve DID metadata', async function () { + const metadata = await universalDidResolver.resolveMetadata(did) + + expect(metadata).to.contain({ + owner: testAccounts.trustee.account.address, + deactivated: false, + }) + }) + }) + + describe('Resolve did:ethr', function () { + it('Should resolve DID metadata', async function () { + const didEthr = `did:ethr:${testAccounts.trustee.account.address}` + const metadata = await universalDidResolver.resolveMetadata(didEthr) + + expect(metadata).to.contain({ + owner: testAccounts.trustee.account.address, + deactivated: false, + }) + }) + + it('Should fail if an incorrect DID method-specific-id is provided', async function () { + const incorrectDid = 'did:ethr:ab$ddfgh354345' + + await expect(universalDidResolver.resolveMetadata(incorrectDid)) + .revertedWithCustomError(universalDidResolver.baseInstance, DidError.IncorrectDid) + .withArgs(incorrectDid) + }) + }) +}) diff --git a/smart_contracts/test/utils/contract-helpers.ts b/smart_contracts/test/utils/contract-helpers.ts index 13927b0a..0bbad5c2 100644 --- a/smart_contracts/test/utils/contract-helpers.ts +++ b/smart_contracts/test/utils/contract-helpers.ts @@ -1,25 +1,32 @@ -import { concat, getAddress, getBytes, keccak256, SigningKey, toUtf8Bytes } from 'ethers' +import { concat, getAddress, getBytes, keccak256, SigningKey } from 'ethers' import { CredentialDefinitionRegistry, - EthereumExtDidRegistry, + IndyDidRegistry, RoleControl, SchemaRegistry, + UniversalDidResolver, UpgradeControl, ValidatorControl, } from '../../contracts-ts' -import { Contract, createSchemaObject } from '../../utils' +import { Contract, createBaseDidDocument, createSchemaObject } from '../../utils' import { getTestAccounts, ZERO_ADDRESS } from './test-entities' export const testActorAddress = '0x2036C6CD85692F0Fb2C26E6c6B2ECed9e4478Dfd' export const testActorPrivateKey = getBytes('0xa285ab66393c5fdda46d6fbad9e27fafd438254ab72ad5acb681a0e9f20f5d7b') +export class EthereumDIDRegistry extends testableContractMixin(Contract) { + constructor() { + super(EthereumDIDRegistry.name) + } +} + export class UpgradablePrototype extends testableContractMixin(Contract) { public get version(): Promise { return this.instance.getVersion() } } -export class TestableDidRegistry extends testableContractMixin(EthereumExtDidRegistry) {} +export class TestableIndyDidRegistry extends testableContractMixin(IndyDidRegistry) {} export class TestableSchemaRegistry extends testableContractMixin(SchemaRegistry) {} @@ -31,13 +38,7 @@ export class TestableValidatorControl extends testableContractMixin(ValidatorCon export class TestableUpgradeControl extends testableContractMixin(UpgradeControl) {} -function testableContractMixin Contract>(Base: T) { - return class extends Base { - public get baseInstance() { - return this.instance - } - } -} +export class TestableUniversalDidResolver extends testableContractMixin(UniversalDidResolver) {} export async function deployRoleControl() { const roleControl = await new RoleControl().deployProxy({ params: [ZERO_ADDRESS] }) @@ -46,88 +47,80 @@ export async function deployRoleControl() { return { roleControl, testAccounts } } -export async function deployDidRegistry() { +export async function deployIndyDidRegistry() { const { testAccounts } = await deployRoleControl() - const didRegistry = await new TestableDidRegistry().deployProxy({ + const indyDidRegistry = await new TestableIndyDidRegistry().deployProxy({ params: [ZERO_ADDRESS], }) - return { didRegistry, testAccounts } + return { indyDidRegistry, testAccounts } +} + +export async function deployUniversalDidResolver() { + const { indyDidRegistry, testAccounts } = await deployIndyDidRegistry() + const ethereumDIDRegistry = await new EthereumDIDRegistry().deploy() + + const universalDidReolver = await new TestableUniversalDidResolver().deployProxy({ + params: [ZERO_ADDRESS, indyDidRegistry.address, ethereumDIDRegistry.address], + }) + + return { universalDidReolver, ethereumDIDRegistry, indyDidRegistry, testAccounts } } export async function deploySchemaRegistry() { - const { didRegistry, testAccounts } = await deployDidRegistry() + const { universalDidReolver, indyDidRegistry, testAccounts } = await deployUniversalDidResolver() const schemaRegistry = await new TestableSchemaRegistry().deployProxy({ - params: [ZERO_ADDRESS, didRegistry.address], + params: [ZERO_ADDRESS, universalDidReolver.address], }) - return { didRegistry, schemaRegistry, testAccounts } + return { universalDidReolver, indyDidRegistry, schemaRegistry, testAccounts } } export async function deployCredentialDefinitionRegistry() { - const { didRegistry, schemaRegistry, testAccounts } = await deploySchemaRegistry() + const { universalDidReolver, indyDidRegistry, schemaRegistry, testAccounts } = await deploySchemaRegistry() const credentialDefinitionRegistry = await new TestableCredentialDefinitionRegistry().deployProxy({ - params: [ZERO_ADDRESS, didRegistry.address, schemaRegistry.address], + params: [ZERO_ADDRESS, universalDidReolver.address, schemaRegistry.address], }) - return { credentialDefinitionRegistry, didRegistry, schemaRegistry, testAccounts } + return { credentialDefinitionRegistry, universalDidReolver, indyDidRegistry, schemaRegistry, testAccounts } } -export async function createDid(didRegistry: EthereumExtDidRegistry, identity: string, did: string) { - // DID assume to be created by default - return did +export async function createDid(didRegistry: IndyDidRegistry, identity: string, did: string) { + const didDocument = createBaseDidDocument(did) + await didRegistry.createDid(identity, didDocument) + return didDocument } -export async function signEndorsementData(privateKey: Uint8Array, contract: string, data: string) { - const dataToSign = concat(['0x1900', getAddress(contract), data]) - return new SigningKey(privateKey).sign(keccak256(dataToSign)) +export async function createDidSigned(didRegistry: IndyDidRegistry, identity: string, did: string) { + const didDocument = createBaseDidDocument(did) + const sig = await didRegistry.signCreateDidEndorsementData(identity, testActorPrivateKey, didDocument) + await didRegistry.createDidSigned(identity, didDocument, sig) } -export async function signSchemaEndorsementData( - schemaRegistry: SchemaRegistry, - identity: string, - privateKey: Uint8Array, - id: string, - schema: string, -) { - return signEndorsementData( - privateKey, - schemaRegistry.address!, - concat([identity, toUtf8Bytes('createSchema'), getBytes(keccak256(toUtf8Bytes(id)), 'hex'), toUtf8Bytes(schema)]), - ) -} - -export async function createSchema(schemaRegistry: SchemaRegistry, issuer: string) { - const { id, schema } = createSchemaObject({ issuer }) - await schemaRegistry.createSchema(issuer, id, schema) +export async function createSchema(schemaRegistry: SchemaRegistry, identity: string, issuerId: string) { + const { id, schema } = createSchemaObject({ issuerId }) + await schemaRegistry.createSchema(identity, id, issuerId, schema) return { id, schema } } -export async function createSchemaSigned(schemaRegistry: SchemaRegistry, issuer: string) { - const { id, schema } = createSchemaObject({ issuer }) - const signature = await signSchemaEndorsementData(schemaRegistry, issuer, testActorPrivateKey, id, schema) - await schemaRegistry.createSchemaSigned(issuer, id, schema, signature) +export async function createSchemaSigned(schemaRegistry: SchemaRegistry, identity: string, issuerId: string) { + const { id, schema } = createSchemaObject({ issuerId }) + const signature = await schemaRegistry.signCreateSchemaEndorsementData( + identity, + testActorPrivateKey, + id, + issuerId, + schema, + ) + await schemaRegistry.createSchemaSigned(identity, id, issuerId, schema, signature) return { id, schema } } -export async function signCredDefEndorsementData( - credentialDefinitionRegistry: CredentialDefinitionRegistry, - identity: string, - privateKey: Uint8Array, - id: string, - schemaId: string, - credDef: string, -) { - return signEndorsementData( - privateKey, - credentialDefinitionRegistry.address!, - concat([ - identity, - toUtf8Bytes('createCredentialDefinition'), - getBytes(keccak256(toUtf8Bytes(id)), 'hex'), - getBytes(keccak256(toUtf8Bytes(schemaId)), 'hex'), - toUtf8Bytes(credDef), - ]), - ) +function testableContractMixin Contract>(Base: T) { + return class extends Base { + public get baseInstance() { + return this.instance + } + } } diff --git a/smart_contracts/test/utils/errors.ts b/smart_contracts/test/utils/errors.ts index 681f02c6..d5a1ed7a 100644 --- a/smart_contracts/test/utils/errors.ts +++ b/smart_contracts/test/utils/errors.ts @@ -1,14 +1,11 @@ -export namespace Errors { - export const ConflictingFields = 'ConflictingFields' - export const FieldRequired = 'FieldRequired' -} - export namespace AuthErrors { export const Unauthorized = 'Unauthorized' } export namespace ClErrors { - export const UnauthorizedIssuer = 'UnauthorizedIssuer' + export const IssuerNotFound = 'IssuerNotFound' + export const InvalidIssuerId = 'InvalidIssuerId' + export const IssuerHasBeenDeactivated = 'IssuerHasBeenDeactivated' // Schema errors export const SchemaAlreadyExist = 'SchemaAlreadyExist' @@ -19,6 +16,15 @@ export namespace ClErrors { export const CredentialDefinitionNotFound = 'CredentialDefinitionNotFound' } +export namespace DidError { + export const DidNotFound = 'DidNotFound' + export const DidAlreadyExist = 'DidAlreadyExist' + export const DidHasBeenDeactivated = 'DidHasBeenDeactivated' + export const UnauthorizedSender = 'UnauthorizedSender' + export const IncorrectDid = 'IncorrectDid' + export const NotIdentityOwner = 'NotIdentityOwner' +} + export namespace ProxyError { export const ERC1967InvalidImplementation = 'ERC1967InvalidImplementation' } diff --git a/smart_contracts/utils/account.ts b/smart_contracts/utils/account.ts index e69bd994..73dbbdc7 100644 --- a/smart_contracts/utils/account.ts +++ b/smart_contracts/utils/account.ts @@ -1,6 +1,6 @@ -import { encodeBase58, Signer } from 'ethers' +import { Signer } from 'ethers' import { ethers } from 'hardhat' -import { environment, host, web3 } from '../environment' +import { host, web3 } from '../environment' import { createBaseDidDocument } from './entity-factories' export interface AccountInfo { @@ -28,13 +28,7 @@ export class Account { } public get did() { - const method = environment.did.method - const network = environment.network.name - // TODO: The DID's method-specefic-id is not generated according to the specification. - // It needs to be adjusted to match the specification: Base58(Truncate_msb(16(SHA256(publicKey)))) - const methodSpeceficId = encodeBase58(this.address).substring(0, 22) - - return `did:${method}:${network}:${methodSpeceficId}` + return `did:indybesu:${this.address}` } public get didEthr() { diff --git a/smart_contracts/utils/contract.ts b/smart_contracts/utils/contract.ts index 0b60425e..bb545915 100644 --- a/smart_contracts/utils/contract.ts +++ b/smart_contracts/utils/contract.ts @@ -1,13 +1,13 @@ -import { Signer } from 'ethers' +import { concat, getAddress, keccak256, Signer, SigningKey } from 'ethers' import { ethers, upgrades } from 'hardhat' import { host } from '../environment' export class Contract { public address?: string - public instance: any protected readonly name: string protected readonly signer?: Signer + protected instance: any constructor(name: string, sender?: any) { this.name = name @@ -70,4 +70,9 @@ export class Contract { return acc }, {}) } + + protected signEndorsementData(privateKey: Uint8Array, data: string) { + const dataToSign = concat(['0x1900', getAddress(this.address!), data]) + return new SigningKey(privateKey).sign(keccak256(dataToSign)) + } } diff --git a/smart_contracts/utils/entity-factories.ts b/smart_contracts/utils/entity-factories.ts index 6065054d..25067ada 100644 --- a/smart_contracts/utils/entity-factories.ts +++ b/smart_contracts/utils/entity-factories.ts @@ -1,11 +1,11 @@ -export function createBaseDidDocument(did: string) { +export function createBaseDidDocument(did: string, key?: any) { const kid = `${did}#KEY-1` return JSON.stringify({ '@context': ['https://www.w3.org/ns/did/v1'], id: did, controller: [did], verificationMethod: [ - { + key || { id: kid, type: 'Ed25519VerificationKey2018', controller: did, @@ -23,19 +23,18 @@ export function createBaseDidDocument(did: string) { } interface CreateSchemaParams { - issuer: string + issuerId: string name?: string version?: string attrNames?: string[] } export function createSchemaObject({ - issuer, + issuerId, name = 'BasicIdentity', version = '1.0.0', attrNames = ['First Name', 'Last Name'], }: CreateSchemaParams) { - const issuerId = `did:ethr:${issuer}` const id = `${issuerId}/anoncreds/v0/SCHEMA/${name}/${version}` return { id, @@ -50,7 +49,7 @@ export function createSchemaObject({ } interface CreateCredentialDefinitionParams { - issuer: string + issuerId: string schemaId: string credDefType?: string tag?: string @@ -58,7 +57,7 @@ interface CreateCredentialDefinitionParams { } export function createCredentialDefinitionObject({ - issuer, + issuerId, schemaId, credDefType = 'CL', tag = 'BasicIdentity', @@ -69,7 +68,6 @@ export function createCredentialDefinitionObject({ z: '632...005', }, }: CreateCredentialDefinitionParams) { - const issuerId = `did:ethr:${issuer}` const id = `${issuerId}/anoncreds/v0/CLAIM_DEF/${schemaId}/${tag}` return { id, diff --git a/vdr/src/client/client.rs b/vdr/src/client/client.rs index 091ed6b7..f9f39386 100644 --- a/vdr/src/client/client.rs +++ b/vdr/src/client/client.rs @@ -220,6 +220,7 @@ pub mod test { pub const CHAIN_ID: u64 = 1337; pub const CONTRACTS_SPEC_BASE_PATH: &str = "../smart_contracts/artifacts/contracts/"; + pub const INDY_DID_REGISTRY_PATH: &str = "did/IndyDidRegistry.sol/IndyDidRegistry.json"; pub const SCHEMA_REGISTRY_SPEC_PATH: &str = "cl/SchemaRegistry.sol/SchemaRegistry.json"; pub const CRED_DEF_REGISTRY_SPEC_PATH: &str = "cl/CredentialDefinitionRegistry.sol/CredentialDefinitionRegistry.json"; @@ -236,6 +237,9 @@ pub mod test { ]; pub const DEFAULT_NONCE: u64 = 0; + pub static INDY_REGISTRY_ADDRESS: Lazy
= + Lazy::new(|| Address::from("0x0000000000000000000000000000000000003333")); + pub static SCHEMA_REGISTRY_ADDRESS: Lazy
= Lazy::new(|| Address::from("0x0000000000000000000000000000000000005555")); @@ -295,6 +299,11 @@ pub mod test { spec_path: Some(build_contract_path(ETHR_DID_REGISTRY_PATH)), spec: None, }, + ContractConfig { + address: INDY_REGISTRY_ADDRESS.to_string(), + spec_path: Some(build_contract_path(INDY_DID_REGISTRY_PATH)), + spec: None, + }, ] } diff --git a/vdr/src/contracts/cl/credential_definition_registry.rs b/vdr/src/contracts/cl/credential_definition_registry.rs index f624c169..d480c7f2 100644 --- a/vdr/src/contracts/cl/credential_definition_registry.rs +++ b/vdr/src/contracts/cl/credential_definition_registry.rs @@ -3,22 +3,21 @@ use log_derive::{logfn, logfn_inputs}; use crate::{ client::LedgerClient, contracts::cl::types::{ - credential_definition::{CredentialDefinition, CredentialDefinitionCreatedEvent}, + credential_definition::{CredentialDefinition, CredentialDefinitionRecord}, credential_definition_id::CredentialDefinitionId, }, error::VdrResult, types::{ - Address, EventParser, EventQueryBuilder, MethodParam, Transaction, TransactionBuilder, + Address, MethodStringParam, Transaction, TransactionBuilder, TransactionEndorsingDataBuilder, TransactionParser, TransactionType, }, - Block, EventLog, EventQuery, SignatureData, TransactionEndorsingData, VdrError, + SignatureData, TransactionEndorsingData, VdrError, }; const CONTRACT_NAME: &str = "CredentialDefinitionRegistry"; const METHOD_CREATE_CREDENTIAL_DEFINITION: &str = "createCredentialDefinition"; const METHOD_CREATE_CREDENTIAL_DEFINITION_SIGNED: &str = "createCredentialDefinitionSigned"; -const METHOD_CREDENTIAL_DEFINITION_CREATED: &str = "created"; -const EVENT_CREDENTIAL_DEFINITION_CREATED: &str = "CredentialDefinitionCreated"; +const METHOD_RESOLVE_CREDENTIAL_DEFINITION: &str = "resolveCredentialDefinition"; /// Build transaction to execute CredentialDefinitionRegistry.createCredentialDefinition contract /// method to create a new Credential Definition @@ -26,7 +25,6 @@ const EVENT_CREDENTIAL_DEFINITION_CREATED: &str = "CredentialDefinitionCreated"; /// # Params /// - `client` client connected to the network where contract will be executed /// - `from` transaction sender account address -/// - `id` id of credential definition to be created /// - `credential_definition` Credential Definition object matching to the specification - https://hyperledger.github.io/anoncreds-spec/#term:credential-definition /// /// # Returns @@ -36,16 +34,17 @@ const EVENT_CREDENTIAL_DEFINITION_CREATED: &str = "CredentialDefinitionCreated"; pub async fn build_create_credential_definition_transaction( client: &LedgerClient, from: &Address, - id: &CredentialDefinitionId, credential_definition: &CredentialDefinition, ) -> VdrResult { // TODO: validate credential definition let identity = Address::try_from(&credential_definition.issuer_id)?; + let id = credential_definition.id(); TransactionBuilder::new() .set_contract(CONTRACT_NAME) .set_method(METHOD_CREATE_CREDENTIAL_DEFINITION) .add_param(&identity)? - .add_param(id)? + .add_param(&id)? + .add_param(&credential_definition.issuer_id)? .add_param(&credential_definition.schema_id)? .add_param(credential_definition)? .set_type(TransactionType::Write) @@ -58,7 +57,6 @@ pub async fn build_create_credential_definition_transaction( /// /// #Params /// - `client` client connected to the network where contract will be executed -/// - `id` id of credential definition to be created /// - `credential_definition` Credential Definition object matching to the specification - https://hyperledger.github.io/anoncreds-spec/#term:credential-definition /// /// #Returns @@ -67,16 +65,19 @@ pub async fn build_create_credential_definition_transaction( #[logfn_inputs(Debug)] pub async fn build_create_credential_definition_endorsing_data( client: &LedgerClient, - id: &CredentialDefinitionId, credential_definition: &CredentialDefinition, ) -> VdrResult { let identity = Address::try_from(&credential_definition.issuer_id)?; + let id = credential_definition.id(); TransactionEndorsingDataBuilder::new() .set_contract(CONTRACT_NAME) .set_identity(&identity) .add_param(&identity)? - .add_param(MethodParam::from(METHOD_CREATE_CREDENTIAL_DEFINITION))? - .add_param(id)? + .add_param(&MethodStringParam::from( + METHOD_CREATE_CREDENTIAL_DEFINITION, + ))? + .add_param(&id)? + .add_param(&credential_definition.issuer_id)? .add_param(&credential_definition.schema_id)? .add_param(credential_definition)? .build(client) @@ -89,7 +90,6 @@ pub async fn build_create_credential_definition_endorsing_data( /// /// #Params /// - `client` client connected to the network where contract will be executed -/// - `id` id of credential definition to be created /// - `credential_definition` Credential Definition object matching to the specification - https://hyperledger.github.io/anoncreds-spec/#term:credential-definition /// - `signature` signature of schema issuer /// @@ -100,20 +100,21 @@ pub async fn build_create_credential_definition_endorsing_data( pub async fn build_create_credential_definition_signed_transaction( client: &LedgerClient, from: &Address, - id: &CredentialDefinitionId, credential_definition: &CredentialDefinition, signature: &SignatureData, ) -> VdrResult { // TODO: validate credential definition let identity = Address::try_from(&credential_definition.issuer_id)?; + let id = credential_definition.id(); TransactionBuilder::new() .set_contract(CONTRACT_NAME) .set_method(METHOD_CREATE_CREDENTIAL_DEFINITION_SIGNED) .add_param(&identity)? - .add_param(signature.v())? - .add_param(signature.r())? - .add_param(signature.s())? - .add_param(id)? + .add_param(&signature.v())? + .add_param(&signature.r())? + .add_param(&signature.s())? + .add_param(&id)? + .add_param(&credential_definition.issuer_id)? .add_param(&credential_definition.schema_id)? .add_param(credential_definition)? .set_type(TransactionType::Write) @@ -122,133 +123,75 @@ pub async fn build_create_credential_definition_signed_transaction( .await } -/// Build transaction to execute CredentialDefinitionRegistry.credDefs contract method to get -/// block number when a Credential Definition was created +/// Build transaction to execute CredentialDefinitionRegistry.resolveCredentialDefinition contract +/// method to retrieve an existing Credential Definition by the given id /// -/// #Params -/// - `client` client connected to the network where contract will be executed -/// - `id` identifier of target credential definition +/// # Params +/// - `client` client connected to the network where contract will be executed +/// - `id` id of Credential Definition to resolve /// -/// #Returns -/// transaction: Transaction - prepared read transaction object to submit +/// # Returns +/// Read transaction to submit #[logfn(Info)] #[logfn_inputs(Debug)] -pub async fn build_get_credential_definition_created_transaction( +pub async fn build_resolve_credential_definition_transaction( client: &LedgerClient, id: &CredentialDefinitionId, ) -> VdrResult { + // TODO: validate credential definition TransactionBuilder::new() .set_contract(CONTRACT_NAME) - .set_method(METHOD_CREDENTIAL_DEFINITION_CREATED) + .set_method(METHOD_RESOLVE_CREDENTIAL_DEFINITION) .add_param(id)? .set_type(TransactionType::Read) .build(client) .await } -/// Build event query to get CredentialDefinitionRegistry.CredentialDefinitionCreated event from the ledger -/// -/// #Params -/// - `client` client connected to the network where contract will be executed -/// - `id` identifier of target credential definition -/// - `from_block` start block -/// - `to_block` finish block -/// -/// #Returns -/// query: EventQuery - prepared event query to send -#[logfn(Info)] -#[logfn_inputs(Debug)] -pub async fn build_get_credential_definition_query( - client: &LedgerClient, - id: &CredentialDefinitionId, - from_block: Option<&Block>, - to_block: Option<&Block>, -) -> VdrResult { - EventQueryBuilder::new() - .set_contract(CONTRACT_NAME) - .set_from_block(from_block.cloned()) - .set_to_block(to_block.cloned()) - .set_event_filer(id.to_filter()) - .build(client) -} - -/// Parse the result of execution CredentialDefinitionRegistry.credDefs contract method to receive -/// block number when a credential definition was created +/// Parse the result of execution CredentialDefinitionRegistry.resolveCredentialDefinition contract +/// method to receive a Credential Definition associated with the id /// /// # Params /// - `client` client connected to the network where contract will be executed /// - `bytes` result bytes returned from the ledger /// /// # Returns -/// Block when the credential definition was created +/// parsed Credential Definition #[logfn(Info)] #[logfn_inputs(Debug)] -pub fn parse_credential_definition_created_result( +pub fn parse_resolve_credential_definition_result( client: &LedgerClient, bytes: &[u8], -) -> VdrResult { +) -> VdrResult { + // TODO: validate credential definition TransactionParser::new() .set_contract(CONTRACT_NAME) - .set_method(METHOD_CREDENTIAL_DEFINITION_CREATED) - .parse::(client, bytes) -} - -/// Parse CredentialDefinitionRegistry.CredentialDefinitionCreated from the event log. -/// -/// # Params -/// - `client` client connected to the network where contract will be executed -/// - `bytes` result bytes returned from the ledger -/// -/// # Returns -/// Parsed Credential Definition event object -#[logfn(Info)] -#[logfn_inputs(Debug)] -pub fn parse_credential_definition_created_event( - client: &LedgerClient, - log: &EventLog, -) -> VdrResult { - // TODO: validate schema - EventParser::new() - .set_contract(CONTRACT_NAME) - .set_event(EVENT_CREDENTIAL_DEFINITION_CREATED) - .parse(client, log) + .set_method(METHOD_RESOLVE_CREDENTIAL_DEFINITION) + .parse::(client, bytes) } /// Single step function to resolve a Credential Definition for the given ID /// /// # Params /// - `client` client connected to the network where contract will be executed -/// - `id` id of schema to resolve +/// - `id` id of credential definition to resolve /// /// # Returns /// Resolved Credential Definition object -#[logfn(Info)] -#[logfn_inputs(Debug)] pub async fn resolve_credential_definition( client: &LedgerClient, id: &CredentialDefinitionId, ) -> VdrResult { - let transaction = build_get_credential_definition_created_transaction(client, id).await?; + let transaction = build_resolve_credential_definition_transaction(client, id).await?; let response = client.submit_transaction(&transaction).await?; - let created_block = parse_credential_definition_created_result(client, &response)?; - - let schema_query = build_get_credential_definition_query( - client, - id, - Some(&created_block), - Some(&created_block), - ) - .await?; - let events = client.query_events(&schema_query).await?; - - if events.len() != 1 { - return Err(VdrError::ClientInvalidResponse( - format!("Unable to resolve schema: Unexpected amout of schema created events received for id: {:?}", id) - )); + if response.is_empty() { + return Err(VdrError::ClientInvalidResponse(format!( + "Credential Definition not found for id: {:?}", + id + ))); } - - let cred_def = parse_credential_definition_created_event(client, &events[0])?.cred_def; - Ok(cred_def) + let cred_def_record = parse_resolve_credential_definition_result(client, &response)?; + Ok(cred_def_record.credential_definition) } #[cfg(test)] @@ -277,19 +220,15 @@ pub mod test { async fn build_create_credential_definition_transaction_test() { init_env_logger(); let client = mock_client(); - let (id, cred_def) = credential_definition( + let cred_def = credential_definition( &DID::from(ISSUER_ID), &SchemaId::from(SCHEMA_ID), Some(CREDENTIAL_DEFINITION_TAG), ); - let transaction = build_create_credential_definition_transaction( - &client, - &TRUSTEE_ACC, - &id, - &cred_def, - ) - .await - .unwrap(); + let transaction = + build_create_credential_definition_transaction(&client, &TRUSTEE_ACC, &cred_def) + .await + .unwrap(); let expected_transaction = Transaction { type_: TransactionType::Write, from: Some(TRUSTEE_ACC.clone()), @@ -297,32 +236,38 @@ pub mod test { nonce: Some(DEFAULT_NONCE.clone()), chain_id: CHAIN_ID, data: vec![ - 187, 199, 66, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 226, 219, 108, 141, + 182, 196, 9, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 226, 219, 108, 141, 198, 198, 129, 187, 93, 106, 209, 33, 161, 7, 243, 0, 233, 178, 181, 109, 71, 26, 149, 232, 163, 135, 235, 109, 104, 137, 85, 62, 141, 209, 156, 9, 33, 105, - 94, 200, 254, 71, 119, 190, 195, 248, 17, 17, 141, 239, 177, 34, 27, 23, 130, - 143, 227, 3, 94, 147, 14, 185, 63, 10, 50, 145, 115, 71, 104, 106, 145, 232, - 190, 123, 84, 240, 64, 217, 94, 167, 52, 119, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, + 94, 200, 254, 71, 119, 190, 195, 248, 17, 17, 141, 239, 177, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, + 34, 27, 23, 130, 143, 227, 3, 94, 147, 14, 185, 63, 10, 50, 145, 115, 71, 104, + 106, 145, 232, 190, 123, 84, 240, 64, 217, 94, 167, 52, 119, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 42, 123, 34, 105, 115, 115, 117, 101, 114, 73, 100, 34, 58, 34, 100, 105, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 59, 100, 105, 100, 58, 101, 116, 104, 114, 58, 116, 101, + 115, 116, 110, 101, 116, 58, 48, 120, 102, 48, 101, 50, 100, 98, 54, 99, 56, + 100, 99, 54, 99, 54, 56, 49, 98, 98, 53, 100, 54, 97, 100, 49, 50, 49, 97, 49, + 48, 55, 102, 51, 48, 48, 101, 57, 98, 50, 98, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 42, 123, 34, 105, 115, 115, 117, 101, 114, 73, 100, 34, 58, 34, 100, 105, 100, + 58, 101, 116, 104, 114, 58, 116, 101, 115, 116, 110, 101, 116, 58, 48, 120, + 102, 48, 101, 50, 100, 98, 54, 99, 56, 100, 99, 54, 99, 54, 56, 49, 98, 98, 53, + 100, 54, 97, 100, 49, 50, 49, 97, 49, 48, 55, 102, 51, 48, 48, 101, 57, 98, 50, + 98, 53, 34, 44, 34, 115, 99, 104, 101, 109, 97, 73, 100, 34, 58, 34, 100, 105, 100, 58, 101, 116, 104, 114, 58, 116, 101, 115, 116, 110, 101, 116, 58, 48, 120, 102, 48, 101, 50, 100, 98, 54, 99, 56, 100, 99, 54, 99, 54, 56, 49, 98, 98, 53, 100, 54, 97, 100, 49, 50, 49, 97, 49, 48, 55, 102, 51, 48, 48, 101, 57, - 98, 50, 98, 53, 34, 44, 34, 115, 99, 104, 101, 109, 97, 73, 100, 34, 58, 34, - 100, 105, 100, 58, 101, 116, 104, 114, 58, 116, 101, 115, 116, 110, 101, 116, - 58, 48, 120, 102, 48, 101, 50, 100, 98, 54, 99, 56, 100, 99, 54, 99, 54, 56, - 49, 98, 98, 53, 100, 54, 97, 100, 49, 50, 49, 97, 49, 48, 55, 102, 51, 48, 48, - 101, 57, 98, 50, 98, 53, 47, 97, 110, 111, 110, 99, 114, 101, 100, 115, 47, - 118, 48, 47, 83, 67, 72, 69, 77, 65, 47, 70, 49, 68, 67, 108, 97, 70, 69, 122, - 105, 51, 116, 47, 49, 46, 48, 46, 48, 34, 44, 34, 99, 114, 101, 100, 68, 101, - 102, 84, 121, 112, 101, 34, 58, 34, 67, 76, 34, 44, 34, 116, 97, 103, 34, 58, - 34, 100, 101, 102, 97, 117, 108, 116, 34, 44, 34, 118, 97, 108, 117, 101, 34, - 58, 123, 34, 110, 34, 58, 34, 55, 55, 57, 46, 46, 46, 51, 57, 55, 34, 44, 34, - 114, 99, 116, 120, 116, 34, 58, 34, 55, 55, 52, 46, 46, 46, 57, 55, 55, 34, 44, - 34, 115, 34, 58, 34, 55, 53, 48, 46, 46, 56, 57, 51, 34, 44, 34, 122, 34, 58, - 34, 54, 51, 50, 46, 46, 46, 48, 48, 53, 34, 125, 125, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 98, 50, 98, 53, 47, 97, 110, 111, 110, 99, 114, 101, 100, 115, 47, 118, 48, 47, + 83, 67, 72, 69, 77, 65, 47, 70, 49, 68, 67, 108, 97, 70, 69, 122, 105, 51, 116, + 47, 49, 46, 48, 46, 48, 34, 44, 34, 99, 114, 101, 100, 68, 101, 102, 84, 121, + 112, 101, 34, 58, 34, 67, 76, 34, 44, 34, 116, 97, 103, 34, 58, 34, 100, 101, + 102, 97, 117, 108, 116, 34, 44, 34, 118, 97, 108, 117, 101, 34, 58, 123, 34, + 110, 34, 58, 34, 55, 55, 57, 46, 46, 46, 51, 57, 55, 34, 44, 34, 114, 99, 116, + 120, 116, 34, 58, 34, 55, 55, 52, 46, 46, 46, 57, 55, 55, 34, 44, 34, 115, 34, + 58, 34, 55, 53, 48, 46, 46, 56, 57, 51, 34, 44, 34, 122, 34, 58, 34, 54, 51, + 50, 46, 46, 46, 48, 48, 53, 34, 125, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], signature: RwLock::new(None), hash: None, @@ -335,27 +280,33 @@ pub mod test { use super::*; #[async_std::test] - async fn build_get_credential_definition_query_test() { + async fn build_resolve_credential_definition_transaction_test() { init_env_logger(); let client = mock_client(); - let (id, _) = credential_definition( + let cred_def = credential_definition( &DID::from(ISSUER_ID), &SchemaId::from(SCHEMA_ID), Some(CREDENTIAL_DEFINITION_TAG), ); - let query = build_get_credential_definition_query(&client, &id, None, None) - .await - .unwrap(); - let expected_query = EventQuery { - address: CRED_DEF_REGISTRY_ADDRESS.clone(), - from_block: None, - to_block: None, - event_signature: None, - event_filter: Some( - "6d471a95e8a387eb6d6889553e8dd19c0921695ec8fe4777bec3f811118defb1".to_string(), - ), + let transaction = + build_resolve_credential_definition_transaction(&client, &cred_def.id()) + .await + .unwrap(); + let expected_transaction = Transaction { + type_: TransactionType::Read, + from: None, + to: CRED_DEF_REGISTRY_ADDRESS.clone(), + nonce: None, + chain_id: CHAIN_ID, + data: vec![ + 159, 136, 157, 181, 109, 71, 26, 149, 232, 163, 135, 235, 109, 104, 137, 85, + 62, 141, 209, 156, 9, 33, 105, 94, 200, 254, 71, 119, 190, 195, 248, 17, 17, + 141, 239, 177, + ], + signature: RwLock::new(None), + hash: None, }; - assert_eq!(expected_query, query); + assert_eq!(expected_transaction, transaction); } } diff --git a/vdr/src/contracts/cl/mod.rs b/vdr/src/contracts/cl/mod.rs index c7603490..cedf4949 100644 --- a/vdr/src/contracts/cl/mod.rs +++ b/vdr/src/contracts/cl/mod.rs @@ -2,12 +2,8 @@ pub mod credential_definition_registry; pub mod schema_registry; pub mod types; -pub use types::{ - schema::{Schema, SchemaCreatedEvent}, - schema_id::SchemaId, -}; +pub use types::{schema::Schema, schema_id::SchemaId}; pub use types::{ - credential_definition::{CredentialDefinition, CredentialDefinitionCreatedEvent}, - credential_definition_id::CredentialDefinitionId, + credential_definition::CredentialDefinition, credential_definition_id::CredentialDefinitionId, }; diff --git a/vdr/src/contracts/cl/schema_registry.rs b/vdr/src/contracts/cl/schema_registry.rs index cd4abedb..f154e785 100644 --- a/vdr/src/contracts/cl/schema_registry.rs +++ b/vdr/src/contracts/cl/schema_registry.rs @@ -3,29 +3,27 @@ use log_derive::{logfn, logfn_inputs}; use crate::{ client::LedgerClient, contracts::cl::types::{ - schema::{Schema, SchemaCreatedEvent}, + schema::{Schema, SchemaRecord}, schema_id::SchemaId, }, error::VdrResult, types::{ - Address, EventParser, EventQueryBuilder, MethodParam, Transaction, TransactionBuilder, + Address, MethodStringParam, Transaction, TransactionBuilder, TransactionEndorsingDataBuilder, TransactionParser, TransactionType, }, - Block, EventLog, EventQuery, SignatureData, TransactionEndorsingData, VdrError, + SignatureData, TransactionEndorsingData, VdrError, }; const CONTRACT_NAME: &str = "SchemaRegistry"; const METHOD_CREATE_SCHEMA: &str = "createSchema"; const METHOD_CREATE_SCHEMA_SIGNED: &str = "createSchemaSigned"; -const METHOD_SCHEMA_CREATED: &str = "created"; -const EVENT_SCHEMA_CREATED: &str = "SchemaCreated"; +const METHOD_RESOLVE_SCHEMA: &str = "resolveSchema"; /// Build transaction to execute SchemaRegistry.createSchema contract method to create a new Schema /// /// # Params /// - `client` client connected to the network where contract will be executed /// - `from` transaction sender account address -/// - `id` id of schema to be created /// - `schema` Schema object matching to the specification - https://hyperledger.github.io/anoncreds-spec/#term:schema /// /// # Returns @@ -35,16 +33,17 @@ const EVENT_SCHEMA_CREATED: &str = "SchemaCreated"; pub async fn build_create_schema_transaction( client: &LedgerClient, from: &Address, - id: &SchemaId, schema: &Schema, ) -> VdrResult { // TODO: validate schema let identity = Address::try_from(&schema.issuer_id)?; + let id = schema.id(); TransactionBuilder::new() .set_contract(CONTRACT_NAME) .set_method(METHOD_CREATE_SCHEMA) .add_param(&identity)? - .add_param(id)? + .add_param(&id)? + .add_param(&schema.issuer_id)? .add_param(schema)? .set_type(TransactionType::Write) .set_from(from) @@ -56,7 +55,6 @@ pub async fn build_create_schema_transaction( /// /// #Params /// - `client` client connected to the network where contract will be executed -/// - `id` id of schema to be created /// - `schema` Schema object matching to the specification - https://hyperledger.github.io/anoncreds-spec/#term:schema /// /// #Returns @@ -65,16 +63,17 @@ pub async fn build_create_schema_transaction( #[logfn_inputs(Debug)] pub async fn build_create_schema_endorsing_data( client: &LedgerClient, - id: &SchemaId, schema: &Schema, ) -> VdrResult { let identity = Address::try_from(&schema.issuer_id)?; + let id = schema.id(); TransactionEndorsingDataBuilder::new() .set_contract(CONTRACT_NAME) .set_identity(&identity) .add_param(&identity)? - .add_param(MethodParam::from(METHOD_CREATE_SCHEMA))? - .add_param(id)? + .add_param(&MethodStringParam::from(METHOD_CREATE_SCHEMA))? + .add_param(&id)? + .add_param(&schema.issuer_id)? .add_param(schema)? .build(client) .await @@ -86,7 +85,6 @@ pub async fn build_create_schema_endorsing_data( /// /// #Params /// - `client` client connected to the network where contract will be executed -/// - `id` id of schema to be created /// - `schema` Schema object matching to the specification - https://hyperledger.github.io/anoncreds-spec/#term:schema /// - `signature` signature of schema issuer /// @@ -97,19 +95,20 @@ pub async fn build_create_schema_endorsing_data( pub async fn build_create_schema_signed_transaction( client: &LedgerClient, sender: &Address, - id: &SchemaId, schema: &Schema, signature: &SignatureData, ) -> VdrResult { let identity = Address::try_from(&schema.issuer_id)?; + let id = schema.id(); TransactionBuilder::new() .set_contract(CONTRACT_NAME) .set_method(METHOD_CREATE_SCHEMA_SIGNED) .add_param(&identity)? - .add_param(signature.v())? - .add_param(signature.r())? - .add_param(signature.s())? - .add_param(id)? + .add_param(&signature.v())? + .add_param(&signature.r())? + .add_param(&signature.s())? + .add_param(&id)? + .add_param(&schema.issuer_id)? .add_param(schema)? .set_type(TransactionType::Write) .set_from(sender) @@ -117,93 +116,45 @@ pub async fn build_create_schema_signed_transaction( .await } -/// Build transaction to execute SchemaRegistry.schemasCreated contract method to get -/// block number when Schema was created +/// Build transaction to execute SchemaRegistry.resolveSchema contract method to retrieve an existing Schema by the given id /// -/// #Params -/// - `client` client connected to the network where contract will be executed -/// - `id` identifier of target schema +/// # Params +/// - `client` client connected to the network where contract will be executed +/// - `id` id of Schema to resolve /// -/// #Returns -/// transaction: Transaction - prepared read transaction object to submit +/// # Returns +/// Read transaction to submit #[logfn(Info)] #[logfn_inputs(Debug)] -pub async fn build_get_schema_created_transaction( +pub async fn build_resolve_schema_transaction( client: &LedgerClient, id: &SchemaId, ) -> VdrResult { TransactionBuilder::new() .set_contract(CONTRACT_NAME) - .set_method(METHOD_SCHEMA_CREATED) + .set_method(METHOD_RESOLVE_SCHEMA) .add_param(id)? .set_type(TransactionType::Read) .build(client) .await } -/// Build event query to get SchemaRegistry.SchemaCreated event from the ledger -/// -/// #Params -/// - `client` client connected to the network where contract will be executed -/// - `id` identifier of target schema -/// - `from_block` start block -/// - `to_block` finish block -/// -/// #Returns -/// query: EventQuery - prepared event query to send -#[logfn(Info)] -#[logfn_inputs(Debug)] -pub async fn build_get_schema_query( - client: &LedgerClient, - id: &SchemaId, - from_block: Option<&Block>, - to_block: Option<&Block>, -) -> VdrResult { - EventQueryBuilder::new() - .set_contract(CONTRACT_NAME) - .set_from_block(from_block.cloned()) - .set_to_block(to_block.cloned()) - .set_event_filer(id.to_filter()) - .build(client) -} - -/// Parse the result of execution SchemaRegistry.schemas contract method to receive -/// block number when a schema was created -/// -/// # Params -/// - `client` client connected to the network where contract will be executed -/// - `bytes` result bytes returned from the ledger -/// -/// # Returns -/// Block when the schema was created -#[logfn(Info)] -#[logfn_inputs(Debug)] -pub fn parse_schema_created_result(client: &LedgerClient, bytes: &[u8]) -> VdrResult { - TransactionParser::new() - .set_contract(CONTRACT_NAME) - .set_method(METHOD_SCHEMA_CREATED) - .parse::(client, bytes) -} - -/// Parse SchemaRegistry.SchemaCreated from the event log. +/// Parse the result of execution SchemaRegistry.resolveSchema contract method to receive a Schema associated with the id /// /// # Params /// - `client` client connected to the network where contract will be executed /// - `bytes` result bytes returned from the ledger /// /// # Returns -/// Parsed Schema object +/// parsed Schema #[logfn(Info)] #[logfn_inputs(Debug)] -pub fn parse_schema_created_event( - client: &LedgerClient, - log: &EventLog, -) -> VdrResult { +pub fn parse_resolve_schema_result(client: &LedgerClient, bytes: &[u8]) -> VdrResult { // TODO: validate schema - EventParser::new() + TransactionParser::new() .set_contract(CONTRACT_NAME) - .set_event(EVENT_SCHEMA_CREATED) - .parse(client, log) + .set_method(METHOD_RESOLVE_SCHEMA) + .parse::(client, bytes) } /// Single step function to resolve a Schema for the given ID @@ -217,30 +168,16 @@ pub fn parse_schema_created_event( #[logfn(Info)] #[logfn_inputs(Debug)] pub async fn resolve_schema(client: &LedgerClient, id: &SchemaId) -> VdrResult { - let transaction = build_get_schema_created_transaction(client, id).await?; + let transaction = build_resolve_schema_transaction(client, id).await?; let response = client.submit_transaction(&transaction).await?; - let created_block = parse_schema_created_result(client, &response)?; - - let schema_query = - build_get_schema_query(client, id, Some(&created_block), Some(&created_block)).await?; - let events = client.query_events(&schema_query).await?; - - if events.is_empty() { + if response.is_empty() { return Err(VdrError::ClientInvalidResponse(format!( "Schema not found for id: {:?}", id ))); } - - if events.len() > 1 { - return Err(VdrError::ClientInvalidResponse(format!( - "More then one schema resolved for the given id: {:?}", - id - ))); - } - - let schema = parse_schema_created_event(client, &events[0])?.schema; - Ok(schema) + let schema_record = parse_resolve_schema_result(client, &response)?; + Ok(schema_record.schema) } #[cfg(test)] @@ -265,8 +202,8 @@ pub mod test { async fn build_create_schema_transaction_test() { init_env_logger(); let client = mock_client(); - let (id, schema) = schema(&DID::from(ISSUER_ID), Some(SCHEMA_NAME)); - let transaction = build_create_schema_transaction(&client, &TRUSTEE_ACC, &id, &schema) + let schema = schema(&DID::from(ISSUER_ID), Some(SCHEMA_NAME)); + let transaction = build_create_schema_transaction(&client, &TRUSTEE_ACC, &schema) .await .unwrap(); let expected_transaction = Transaction { @@ -276,22 +213,27 @@ pub mod test { nonce: Some(DEFAULT_NONCE.clone()), chain_id: CHAIN_ID, data: vec![ - 89, 21, 183, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 226, 219, 108, 141, + 131, 211, 251, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 226, 219, 108, 141, 198, 198, 129, 187, 93, 106, 209, 33, 161, 7, 243, 0, 233, 178, 181, 34, 27, 23, 130, 143, 227, 3, 94, 147, 14, 185, 63, 10, 50, 145, 115, 71, 104, 106, 145, 232, 190, 123, 84, 240, 64, 217, 94, 167, 52, 119, 152, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 100, 105, 100, 58, 101, 116, 104, 114, 58, + 116, 101, 115, 116, 110, 101, 116, 58, 48, 120, 102, 48, 101, 50, 100, 98, 54, + 99, 56, 100, 99, 54, 99, 54, 56, 49, 98, 98, 53, 100, 54, 97, 100, 49, 50, 49, + 97, 49, 48, 55, 102, 51, 48, 48, 101, 57, 98, 50, 98, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 153, 123, 34, 105, 115, 115, 117, 101, 114, 73, 100, 34, 58, 34, - 100, 105, 100, 58, 101, 116, 104, 114, 58, 116, 101, 115, 116, 110, 101, 116, - 58, 48, 120, 102, 48, 101, 50, 100, 98, 54, 99, 56, 100, 99, 54, 99, 54, 56, - 49, 98, 98, 53, 100, 54, 97, 100, 49, 50, 49, 97, 49, 48, 55, 102, 51, 48, 48, - 101, 57, 98, 50, 98, 53, 34, 44, 34, 110, 97, 109, 101, 34, 58, 34, 70, 49, 68, - 67, 108, 97, 70, 69, 122, 105, 51, 116, 34, 44, 34, 118, 101, 114, 115, 105, - 111, 110, 34, 58, 34, 49, 46, 48, 46, 48, 34, 44, 34, 97, 116, 116, 114, 78, - 97, 109, 101, 115, 34, 58, 91, 34, 76, 97, 115, 116, 32, 78, 97, 109, 101, 34, - 44, 34, 70, 105, 114, 115, 116, 32, 78, 97, 109, 101, 34, 93, 125, 0, 0, 0, 0, - 0, 0, 0, + 0, 0, 0, 141, 123, 34, 105, 115, 115, 117, 101, 114, 73, 100, 34, 58, 34, 100, + 105, 100, 58, 101, 116, 104, 114, 58, 116, 101, 115, 116, 110, 101, 116, 58, + 48, 120, 102, 48, 101, 50, 100, 98, 54, 99, 56, 100, 99, 54, 99, 54, 56, 49, + 98, 98, 53, 100, 54, 97, 100, 49, 50, 49, 97, 49, 48, 55, 102, 51, 48, 48, 101, + 57, 98, 50, 98, 53, 34, 44, 34, 110, 97, 109, 101, 34, 58, 34, 70, 49, 68, 67, + 108, 97, 70, 69, 122, 105, 51, 116, 34, 44, 34, 118, 101, 114, 115, 105, 111, + 110, 34, 58, 34, 49, 46, 48, 46, 48, 34, 44, 34, 97, 116, 116, 114, 78, 97, + 109, 101, 115, 34, 58, 91, 34, 70, 105, 114, 115, 116, 32, 78, 97, 109, 101, + 34, 93, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], signature: RwLock::new(None), hash: None, @@ -300,30 +242,35 @@ pub mod test { } } - mod build_get_schema_query { + mod build_resolve_schema_transaction { use super::*; #[async_std::test] - async fn build_get_schema_query_test() { + async fn build_resolve_schema_transaction_test() { init_env_logger(); let client = mock_client(); - let (id, _) = schema(&DID::from(ISSUER_ID), Some(SCHEMA_NAME)); - let query = build_get_schema_query(&client, &id, None, None) + let schema = schema(&DID::from(ISSUER_ID), Some(SCHEMA_NAME)); + let transaction = build_resolve_schema_transaction(&client, &schema.id()) .await .unwrap(); - let expected_query = EventQuery { - address: SCHEMA_REGISTRY_ADDRESS.clone(), - from_block: None, - to_block: None, - event_signature: None, - event_filter: Some( - "221b17828fe3035e930eb93f0a32917347686a91e8be7b54f040d95ea7347798".to_string(), - ), + let expected_transaction = Transaction { + type_: TransactionType::Read, + from: None, + to: SCHEMA_REGISTRY_ADDRESS.clone(), + nonce: None, + chain_id: CHAIN_ID, + data: vec![ + 174, 190, 203, 28, 34, 27, 23, 130, 143, 227, 3, 94, 147, 14, 185, 63, 10, 50, + 145, 115, 71, 104, 106, 145, 232, 190, 123, 84, 240, 64, 217, 94, 167, 52, 119, + 152, + ], + signature: RwLock::new(None), + hash: None, }; - assert_eq!(expected_query, query); + assert_eq!(expected_transaction, transaction); } } - // + // mod parse_resolve_schema_result { // use super::*; // use crate::contracts::did::types::did::DID; @@ -349,8 +296,8 @@ pub mod test { // 0, 0, 0, // ]; // let parsed_schema = parse_resolve_schema_result(&client, &data).unwrap(); - // let (_, expected_schema) = schema(&DID::from(ISSUER_ID), Some(SCHEMA_NAME)); - // assert_eq!(expected_schema, parsed_schema); + // let expected_schema = schema(&DID::from(ISSUER_ID), Some(SCHEMA_NAME)); + // assert_eq!(expected_schema, parsed_schema.schema); // } // } } diff --git a/vdr/src/contracts/cl/types/credential_definition.rs b/vdr/src/contracts/cl/types/credential_definition.rs index f64fcd95..8d93b8b7 100644 --- a/vdr/src/contracts/cl/types/credential_definition.rs +++ b/vdr/src/contracts/cl/types/credential_definition.rs @@ -1,11 +1,19 @@ -use crate::{error::VdrError, types::ContractParam, Address}; - use crate::{ - contracts::{cl::types::schema_id::SchemaId, did::types::did::DID}, - types::ContractEvent, + error::VdrError, + types::{ContractOutput, ContractParam}, + CredentialDefinitionId, }; + +use crate::contracts::{cl::types::schema_id::SchemaId, did::types::did::DID}; use serde_derive::{Deserialize, Serialize}; +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct CredentialDefinitionRecord { + pub credential_definition: CredentialDefinition, + pub metadata: CredentialDefinitionMetadata, +} + pub use indy_data_types::anoncreds::cred_def::SignatureType; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -20,6 +28,17 @@ pub struct CredentialDefinition { pub value: serde_json::Value, } +impl CredentialDefinition { + pub fn id(&self) -> CredentialDefinitionId { + CredentialDefinitionId::build(&self.issuer_id, &self.schema_id, &self.tag) + } +} + +#[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize)] +pub struct CredentialDefinitionMetadata { + pub created: u64, +} + impl TryFrom<&CredentialDefinition> for ContractParam { type Error = VdrError; @@ -30,45 +49,52 @@ impl TryFrom<&CredentialDefinition> for ContractParam { } } -#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] -pub struct CredentialDefinitionCreatedEvent { - pub id_hash: String, - pub identity: Address, - pub cred_def: CredentialDefinition, -} - -impl TryFrom for CredentialDefinitionCreatedEvent { +impl TryFrom<&ContractOutput> for CredentialDefinition { type Error = VdrError; - fn try_from(log: ContractEvent) -> Result { - let id = log.get_fixed_bytes(0)?; - let identity = log.get_address(1)?; - let schema_bytes = log.get_bytes(2)?; - let cred_def = serde_json::from_slice(&schema_bytes).map_err(|err| { + fn try_from(value: &ContractOutput) -> Result { + serde_json::from_slice(&value.get_bytes(0)?).map_err(|err| { VdrError::ContractInvalidResponseData(format!( - "Unable to parse credential definition from contract event. Err: {:?}", + "Unable to parse CredentialDefinition from the response. Err: {:?}", err )) - })?; - - Ok(CredentialDefinitionCreatedEvent { - id_hash: hex::encode(id), - identity, - cred_def, }) } } +impl TryFrom for CredentialDefinitionMetadata { + type Error = VdrError; + + fn try_from(value: ContractOutput) -> Result { + let created = value.get_u128(0)?; + let cred_def_metadata = CredentialDefinitionMetadata { + created: created as u64, + }; + Ok(cred_def_metadata) + } +} + +impl TryFrom for CredentialDefinitionRecord { + type Error = VdrError; + + fn try_from(value: ContractOutput) -> Result { + let output_tuple = value.get_tuple(0)?; + let credential_definition = CredentialDefinition::try_from(&output_tuple)?; + let metadata = output_tuple.get_tuple(1)?; + + let cred_def_with_metadata = CredentialDefinitionRecord { + credential_definition, + metadata: CredentialDefinitionMetadata::try_from(metadata)?, + }; + Ok(cred_def_with_metadata) + } +} + #[cfg(test)] pub mod test { use super::*; use crate::{ - contracts::{ - cl::types::{ - credential_definition_id::CredentialDefinitionId, schema::test::SCHEMA_ID, - }, - did::types::did_doc::test::ISSUER_ID, - }, + contracts::{cl::types::schema::test::SCHEMA_ID, did::types::did_doc::test::ISSUER_ID}, utils::rand_string, }; use serde_json::json; @@ -76,14 +102,6 @@ pub mod test { pub const _CREDENTIAL_DEFINITION_ID: &str = "did:ethr:testnet:0xf0e2db6c8dc6c681bb5d6ad121a107f300e9b2b5/anoncreds/v0/CLAIM_DEF/did:ethr:testnet:0xf0e2db6c8dc6c681bb5d6ad121a107f300e9b2b5/anoncreds/v0/SCHEMA/F1DClaFEzi3t/1.0.0/default"; pub const CREDENTIAL_DEFINITION_TAG: &str = "default"; - pub fn credential_definition_id( - issuer_id: &DID, - schema_id: &SchemaId, - tag: &str, - ) -> CredentialDefinitionId { - CredentialDefinitionId::build(issuer_id, schema_id.as_ref(), tag) - } - fn credential_definition_value() -> serde_json::Value { json!({ "n": "779...397", @@ -98,21 +116,19 @@ pub mod test { issuer_id: &DID, schema_id: &SchemaId, tag: Option<&str>, - ) -> (CredentialDefinitionId, CredentialDefinition) { + ) -> CredentialDefinition { let tag = tag.map(String::from).unwrap_or_else(rand_string); - let id = credential_definition_id(issuer_id, schema_id, tag.as_str()); - let cred_def = CredentialDefinition { + CredentialDefinition { issuer_id: issuer_id.clone(), schema_id: SchemaId::from(schema_id.as_ref()), cred_def_type: SignatureType::CL, tag: tag.to_string(), value: credential_definition_value(), - }; - (id, cred_def) + } } fn cred_def_param() -> ContractParam { - let (_, cred_def) = credential_definition( + let cred_def = credential_definition( &DID::from(ISSUER_ID), &SchemaId::from(SCHEMA_ID), Some(CREDENTIAL_DEFINITION_TAG), @@ -125,7 +141,7 @@ pub mod test { #[test] fn convert_cred_def_into_contract_param_test() { - let (_, credential_definition) = credential_definition( + let credential_definition = credential_definition( &DID::from(ISSUER_ID), &SchemaId::from(SCHEMA_ID), Some(CREDENTIAL_DEFINITION_TAG), @@ -134,4 +150,20 @@ pub mod test { assert_eq!(cred_def_param(), param); } } + + mod convert_into_object { + use super::*; + + #[test] + fn convert_contract_output_into_cred_def() { + let data = ContractOutput::new(vec![cred_def_param()]); + let converted = CredentialDefinition::try_from(&data).unwrap(); + let credential_definition = credential_definition( + &DID::from(ISSUER_ID), + &SchemaId::from(SCHEMA_ID), + Some(CREDENTIAL_DEFINITION_TAG), + ); + assert_eq!(credential_definition, converted); + } + } } diff --git a/vdr/src/contracts/cl/types/credential_definition_id.rs b/vdr/src/contracts/cl/types/credential_definition_id.rs index 6c95e9fd..a4be4b1d 100644 --- a/vdr/src/contracts/cl/types/credential_definition_id.rs +++ b/vdr/src/contracts/cl/types/credential_definition_id.rs @@ -1,4 +1,4 @@ -use crate::{contracts::did::types::did::DID, types::ContractParam, VdrError}; +use crate::{contracts::did::types::did::DID, types::ContractParam, SchemaId, VdrError}; use serde_derive::{Deserialize, Serialize}; use sha3::Digest; @@ -9,13 +9,13 @@ pub struct CredentialDefinitionId(String); impl CredentialDefinitionId { const ID_PATH: &'static str = "anoncreds/v0/CLAIM_DEF"; - pub fn build(issuer_id: &DID, schema_id: &str, tag: &str) -> CredentialDefinitionId { + pub fn build(issuer_id: &DID, schema_id: &SchemaId, tag: &str) -> CredentialDefinitionId { CredentialDefinitionId::from( format!( "{}/{}/{}/{}", issuer_id.as_ref(), Self::ID_PATH, - schema_id, + schema_id.as_ref(), tag ) .as_str(), @@ -25,10 +25,6 @@ impl CredentialDefinitionId { pub fn hash(&self) -> Vec { sha3::Keccak256::digest(self.0.as_bytes()).to_vec() } - - pub(crate) fn to_filter(&self) -> String { - hex::encode(self.hash()) - } } impl TryFrom<&CredentialDefinitionId> for ContractParam { diff --git a/vdr/src/contracts/cl/types/schema.rs b/vdr/src/contracts/cl/types/schema.rs index b0595893..7f0a6b65 100644 --- a/vdr/src/contracts/cl/types/schema.rs +++ b/vdr/src/contracts/cl/types/schema.rs @@ -1,13 +1,20 @@ use crate::{ error::VdrError, types::{ContractOutput, ContractParam}, - Address, + SchemaId, }; use std::collections::HashSet; -use crate::{contracts::did::types::did::DID, types::ContractEvent}; +use crate::contracts::did::types::did::DID; use serde_derive::{Deserialize, Serialize}; +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct SchemaRecord { + pub schema: Schema, + pub metadata: SchemaMetadata, +} + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Schema { #[serde(rename = "issuerId")] @@ -18,6 +25,17 @@ pub struct Schema { pub attr_names: HashSet, } +impl Schema { + pub fn id(&self) -> SchemaId { + SchemaId::build(&self.issuer_id, &self.name, &self.version) + } +} + +#[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize)] +pub struct SchemaMetadata { + pub created: u64, +} + impl TryFrom<&Schema> for ContractParam { type Error = VdrError; @@ -32,7 +50,7 @@ impl TryFrom<&ContractOutput> for Schema { type Error = VdrError; fn try_from(value: &ContractOutput) -> Result { - serde_json::from_str(&value.get_string(0)?).map_err(|err| { + serde_json::from_slice(&value.get_bytes(0)?).map_err(|err| { VdrError::ContractInvalidResponseData(format!( "Unable to parse Schema from the response. Err: {:?}", err @@ -41,72 +59,60 @@ impl TryFrom<&ContractOutput> for Schema { } } -#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] -pub struct SchemaCreatedEvent { - pub id_hash: String, - pub identity: Address, - pub schema: Schema, +impl TryFrom for SchemaMetadata { + type Error = VdrError; + + fn try_from(value: ContractOutput) -> Result { + let created = value.get_u128(0)?; + let schema_metadata = SchemaMetadata { + created: created as u64, + }; + Ok(schema_metadata) + } } -impl TryFrom for SchemaCreatedEvent { +impl TryFrom for SchemaRecord { type Error = VdrError; - fn try_from(log: ContractEvent) -> Result { - let id = log.get_fixed_bytes(0)?; - let identity = log.get_address(1)?; - let schema_bytes = log.get_bytes(2)?; - let schema = serde_json::from_slice(&schema_bytes).map_err(|err| { - VdrError::ContractInvalidResponseData(format!( - "Unable to parse schema from contract event. Err: {:?}", - err - )) - })?; + fn try_from(value: ContractOutput) -> Result { + let output_tuple = value.get_tuple(0)?; + let schema = Schema::try_from(&output_tuple)?; + let metadata = output_tuple.get_tuple(1)?; - Ok(SchemaCreatedEvent { - id_hash: hex::encode(id), - identity, + let schema_with_meta = SchemaRecord { schema, - }) + metadata: SchemaMetadata::try_from(metadata)?, + }; + Ok(schema_with_meta) } } #[cfg(test)] pub mod test { use super::*; - use crate::{ - contracts::{cl::types::schema_id::SchemaId, did::types::did_doc::test::ISSUER_ID}, - utils::rand_string, - }; + use crate::{contracts::did::types::did_doc::test::ISSUER_ID, utils::rand_string}; pub const SCHEMA_ID: &str = "did:ethr:testnet:0xf0e2db6c8dc6c681bb5d6ad121a107f300e9b2b5/anoncreds/v0/SCHEMA/F1DClaFEzi3t/1.0.0"; pub const SCHEMA_NAME: &str = "F1DClaFEzi3t"; pub const SCHEMA_VERSION: &str = "1.0.0"; pub const SCHEMA_ATTRIBUTE_FIRST_NAME: &str = "First Name"; - pub const SCHEMA_ATTRIBUTE_LAST_NAME: &str = "Last Name"; - - pub fn schema_id(issuer_id: &DID, name: &str) -> SchemaId { - SchemaId::build(issuer_id, name, SCHEMA_VERSION) - } - pub fn schema(issuer_id: &DID, name: Option<&str>) -> (SchemaId, Schema) { + pub fn schema(issuer_id: &DID, name: Option<&str>) -> Schema { let name = name.map(String::from).unwrap_or_else(rand_string); - let id = schema_id(issuer_id, name.as_str()); let mut attr_names: HashSet = HashSet::new(); attr_names.insert(SCHEMA_ATTRIBUTE_FIRST_NAME.to_string()); - attr_names.insert(SCHEMA_ATTRIBUTE_LAST_NAME.to_string()); - let schema = Schema { + Schema { issuer_id: issuer_id.clone(), name, version: SCHEMA_VERSION.to_string(), attr_names, - }; - (id, schema) + } } fn schema_param() -> ContractParam { - let (_, schema) = schema(&DID::from(ISSUER_ID), Some(SCHEMA_NAME)); + let schema = schema(&DID::from(ISSUER_ID), Some(SCHEMA_NAME)); ContractParam::Bytes(serde_json::to_vec(&schema).unwrap()) } @@ -115,9 +121,21 @@ pub mod test { #[test] fn convert_schema_into_contract_param_test() { - let (_, schema) = schema(&DID::from(ISSUER_ID), Some(SCHEMA_NAME)); + let schema = schema(&DID::from(ISSUER_ID), Some(SCHEMA_NAME)); let param: ContractParam = (&schema).try_into().unwrap(); assert_eq!(schema_param(), param); } } + + mod convert_into_object { + use super::*; + + #[test] + fn convert_contract_output_into_schema() { + let data = ContractOutput::new(vec![schema_param()]); + let converted = Schema::try_from(&data).unwrap(); + let schema = schema(&DID::from(ISSUER_ID), Some(SCHEMA_NAME)); + assert_eq!(schema, converted); + } + } } diff --git a/vdr/src/contracts/cl/types/schema_id.rs b/vdr/src/contracts/cl/types/schema_id.rs index 0a1dfc48..9e86a18b 100644 --- a/vdr/src/contracts/cl/types/schema_id.rs +++ b/vdr/src/contracts/cl/types/schema_id.rs @@ -25,10 +25,6 @@ impl SchemaId { pub fn hash(&self) -> Vec { sha3::Keccak256::digest(self.0.as_bytes()).to_vec() } - - pub(crate) fn to_filter(&self) -> String { - hex::encode(self.hash()) - } } impl TryFrom<&SchemaId> for ContractParam { diff --git a/vdr/src/contracts/did/did_ethr_registry.rs b/vdr/src/contracts/did/did_ethr_registry.rs index 055f4a3f..481795e9 100644 --- a/vdr/src/contracts/did/did_ethr_registry.rs +++ b/vdr/src/contracts/did/did_ethr_registry.rs @@ -2,22 +2,15 @@ use log_derive::{logfn, logfn_inputs}; use crate::{ client::LedgerClient, - contracts::{ - did::{ - did_ethr_resolver, - types::{ - did_doc_attribute::{DelegateType, DidDocAttribute, Validity}, - did_events::{DidAttributeChanged, DidDelegateChanged, DidEvents, DidOwnerChanged}, - }, - DidResolutionOptions, - }, - DidDocumentWithMeta, + contracts::did::types::{ + did_doc_attribute::{DelegateType, DidDocAttribute, Validity}, + did_events::{DidAttributeChanged, DidDelegateChanged, DidEvents, DidOwnerChanged}, }, error::VdrResult, types::{ - Address, EventLog, EventParser, EventQuery, EventQueryBuilder, MethodParam, Transaction, - TransactionBuilder, TransactionEndorsingDataBuilder, TransactionParser, TransactionType, - UintBytesParam, + Address, EventLog, EventParser, EventQuery, EventQueryBuilder, MethodStringParam, + MethodUintBytesParam, Transaction, TransactionBuilder, TransactionEndorsingDataBuilder, + TransactionParser, TransactionType, }, Block, Nonce, SignatureData, TransactionEndorsingData, VdrError, DID, }; @@ -101,7 +94,7 @@ pub async fn build_did_change_owner_endorsing_data( .set_identity(&identity) .add_param(&nonce)? .add_param(&identity)? - .add_param(MethodParam::from(METHOD_CHANGE_OWNER))? + .add_param(&MethodStringParam::from(METHOD_CHANGE_OWNER))? .add_param(new_owner)? .build(client) .await @@ -134,9 +127,9 @@ pub async fn build_did_change_owner_signed_transaction( .set_contract(CONTRACT_NAME) .set_method(METHOD_CHANGE_OWNER_SIGNED) .add_param(&identity)? - .add_param(signature.v())? - .add_param(signature.r())? - .add_param(signature.s())? + .add_param(&signature.v())? + .add_param(&signature.r())? + .add_param(&signature.s())? .add_param(new_owner)? .set_type(TransactionType::Write) .set_from(sender) @@ -208,10 +201,10 @@ pub async fn build_did_add_delegate_endorsing_data( .set_identity(&identity) .add_param(&nonce)? .add_param(&identity)? - .add_param(MethodParam::from(METHOD_ADD_DELEGATE))? + .add_param(&MethodStringParam::from(METHOD_ADD_DELEGATE))? .add_param(delegate_type)? .add_param(delegate)? - .add_param(UintBytesParam::from(validity.0))? + .add_param(&MethodUintBytesParam::from(validity.0))? .build(client) .await } @@ -248,9 +241,9 @@ pub async fn build_did_add_delegate_signed_transaction( .set_contract(CONTRACT_NAME) .set_method(METHOD_ADD_DELEGATE_SIGNED) .add_param(&identity)? - .add_param(signature.v())? - .add_param(signature.r())? - .add_param(signature.s())? + .add_param(&signature.v())? + .add_param(&signature.r())? + .add_param(&signature.s())? .add_param(delegate_type)? .add_param(delegate)? .add_param(validity)? @@ -319,7 +312,7 @@ pub async fn build_did_revoke_delegate_endorsing_data( .set_identity(&identity) .add_param(&nonce)? .add_param(&identity)? - .add_param(MethodParam::from(METHOD_REVOKE_DELEGATE))? + .add_param(&MethodStringParam::from(METHOD_REVOKE_DELEGATE))? .add_param(delegate_type)? .add_param(delegate)? .build(client) @@ -356,9 +349,9 @@ pub async fn build_did_revoke_delegate_signed_transaction( .set_contract(CONTRACT_NAME) .set_method(METHOD_REVOKE_DELEGATE_SIGNED) .add_param(&identity)? - .add_param(signature.v())? - .add_param(signature.r())? - .add_param(signature.s())? + .add_param(&signature.v())? + .add_param(&signature.r())? + .add_param(&signature.s())? .add_param(delegate_type)? .add_param(delegate)? .set_type(TransactionType::Write) @@ -429,10 +422,10 @@ pub async fn build_did_set_attribute_endorsing_data( .set_identity(&identity) .add_param(&nonce)? .add_param(&identity)? - .add_param(MethodParam::from(METHOD_SET_ATTRIBUTE))? + .add_param(&MethodStringParam::from(METHOD_SET_ATTRIBUTE))? .add_param(&attribute.name()?)? .add_param(&attribute.value()?)? - .add_param(UintBytesParam::from(validity.0))? + .add_param(&MethodUintBytesParam::from(validity.0))? .build(client) .await } @@ -469,9 +462,9 @@ pub async fn build_did_set_attribute_signed_transaction( .set_contract(CONTRACT_NAME) .set_method(METHOD_SET_ATTRIBUTE_SIGNED) .add_param(&identity)? - .add_param(signature.v())? - .add_param(signature.r())? - .add_param(signature.s())? + .add_param(&signature.v())? + .add_param(&signature.r())? + .add_param(&signature.s())? .add_param(&attribute.name()?)? .add_param(&attribute.value()?)? .add_param(validity)? @@ -538,7 +531,7 @@ pub async fn build_did_revoke_attribute_endorsing_data( .set_identity(&identity) .add_param(&nonce)? .add_param(&identity)? - .add_param(MethodParam::from(METHOD_REVOKE_ATTRIBUTE))? + .add_param(&MethodStringParam::from(METHOD_REVOKE_ATTRIBUTE))? .add_param(&attribute.name()?)? .add_param(&attribute.value()?)? .build(client) @@ -575,9 +568,9 @@ pub async fn build_did_revoke_attribute_signed_transaction( .set_contract(CONTRACT_NAME) .set_method(METHOD_REVOKE_ATTRIBUTE_SIGNED) .add_param(&identity)? - .add_param(signature.v())? - .add_param(signature.r())? - .add_param(signature.s())? + .add_param(&signature.v())? + .add_param(&signature.r())? + .add_param(&signature.s())? .add_param(&attribute.name()?)? .add_param(&attribute.value()?)? .set_type(TransactionType::Write) @@ -852,25 +845,6 @@ pub async fn resolve_identity_nonce(client: &LedgerClient, identity: &Address) - parse_did_nonce_result(client, &response) } -/// Single step function to resolve a DidDocument with metadata for the given DID -/// -/// # Params -/// - `client` client connected to the network where contract will be executed -/// - `did` DID to get a DID Document and metadata -/// - `options` Resolution options -/// -/// # Returns -/// Parsed DID event object -#[logfn(Info)] -#[logfn_inputs(Debug)] -pub async fn resolve_did( - client: &LedgerClient, - did: &DID, - options: Option<&DidResolutionOptions>, -) -> VdrResult { - did_ethr_resolver::resolve_did(client, did, options).await -} - #[cfg(test)] pub mod test { use super::*; diff --git a/vdr/src/contracts/did/did_ethr_resolver.rs b/vdr/src/contracts/did/did_ethr_resolver.rs deleted file mode 100644 index 5f438ab2..00000000 --- a/vdr/src/contracts/did/did_ethr_resolver.rs +++ /dev/null @@ -1,398 +0,0 @@ -use chrono::Utc; -use log_derive::{logfn, logfn_inputs}; - -use crate::{ - contracts::{ - did::{types::did_doc_attribute::PublicKeyPurpose, DidResolutionError}, - types::did::ParsedDid, - DidDocumentWithMeta, DidMetadata, DidResolutionMetadata, DID_RESOLUTION_FORMAT, - }, - did_ethr_registry::{ - build_get_did_changed_transaction, build_get_did_events_query, parse_did_changed_result, - parse_did_event_response, ETHR_DID_METHOD, - }, - Block, DelegateType, DidAttributeChanged, DidDelegateChanged, DidDocAttribute, DidDocument, - DidDocumentBuilder, DidEvents, DidOwnerChanged, DidResolutionOptions, LedgerClient, VdrResult, - VerificationKeyType, DID, -}; - -#[logfn(Info)] -#[logfn_inputs(Debug)] -pub(crate) async fn resolve_did( - client: &LedgerClient, - did: &DID, - options: Option<&DidResolutionOptions>, -) -> VdrResult { - // Parse DID - let parsed_did = match ParsedDid::try_from(did) { - Ok(did) => did, - Err(_) => { - return Ok(DidDocumentWithMeta { - did_document: None, - did_document_metadata: DidMetadata::default(), - did_resolution_metadata: DidResolutionMetadata { - content_type: None, - error: Some(DidResolutionError::InvalidDid), - message: Some(format!("Not a valid did: {}", did.as_ref())), - }, - }); - } - }; - if parsed_did.method != ETHR_DID_METHOD { - return Ok(DidDocumentWithMeta { - did_document: None, - did_document_metadata: DidMetadata::default(), - did_resolution_metadata: DidResolutionMetadata { - content_type: None, - error: Some(DidResolutionError::MethodNotSupported), - message: Some(format!( - "DID Method is not supported: {}", - parsed_did.method - )), - }, - }); - } - - let did = parsed_did.as_short_did(); - - let block_tag = options.and_then(|options| options.block_tag.as_ref()); - let accept = options.and_then(|options| options.accept.as_deref()); - - match accept.as_deref() { - Some(DID_RESOLUTION_FORMAT) | None => { - // ok - } - Some(accept) => { - return Ok(DidDocumentWithMeta { - did_document: None, - did_document_metadata: DidMetadata::default(), - did_resolution_metadata: DidResolutionMetadata { - content_type: None, - error: Some(DidResolutionError::RepresentationNotSupported), - message: Some(format!( - "VDR does not support the requested 'accept' format: {}", - accept - )), - }, - }); - } - } - - match _resolve_did(client, &did, block_tag).await { - Ok((did_document, did_metadata)) => Ok(DidDocumentWithMeta { - did_document: Some(did_document), - did_document_metadata: did_metadata, - did_resolution_metadata: DidResolutionMetadata { - content_type: accept.map(String::from), - error: None, - message: None, - }, - }), - Err(err) => Ok(DidDocumentWithMeta { - did_document: None, - did_document_metadata: DidMetadata::default(), - did_resolution_metadata: DidResolutionMetadata { - content_type: None, - error: Some(DidResolutionError::NotFound), - message: Some(err.to_string()), - }, - }), - } -} - -#[logfn(Trace)] -#[logfn_inputs(Trace)] -pub(crate) async fn _resolve_did( - client: &LedgerClient, - did: &DID, - block: Option<&Block>, -) -> VdrResult<(DidDocument, DidMetadata)> { - // Build base DID document for ethr DID - let mut did_doc_builder = DidDocumentBuilder::base_for_did(did, client.chain_id())?; - - // TODO: support the case when DID identifier is public key - - // Query block number when DID was changed last time - let did_changed_block = get_did_changed_block(client, did).await?; - - // if DID has not been ever changed, we do not need to query events and just return base did document - if did_changed_block.is_none() { - let did_document = did_doc_builder.build(); - return Ok((did_document, DidMetadata::default())); - } - - let mut version_id: Option = None; - let mut next_version_id: Option = None; - - // time in seconds for attributes validity check - let now = match block { - Some(block) => { - // request block time if the resolution happens for specific block - client.get_block(Some(block)).await?.timestamp - } - None => { - // else current time - Utc::now().timestamp() as u64 - } - }; - - // request events for a specific block until previous exists - let did_history = receive_did_history(client, did, did_changed_block).await?; - - // assemble Did Document from the history events - // iterate in the reverse order -> oldest to newest - for (event_block, event) in did_history.into_iter().rev() { - match block { - // if we resolve DID for specific block we need to skip all blocks higher - Some(block) if event_block.value() > block.value() => { - if next_version_id.is_none() { - next_version_id = Some(event_block) - } - continue; - } - _ => { - version_id = Some(event_block); - } - } - - // handle event - handle_did_event(&mut did_doc_builder, &event, client, now)?; - - // break for deactivate DID -> minimal DID Document will be returned - if did_doc_builder.deactivated() { - break; - } - } - - let did_document_metadata = build_did_metadata( - client, - did_doc_builder.deactivated(), - version_id.as_ref(), - next_version_id.as_ref(), - ) - .await?; - let did_document = did_doc_builder.build(); - Ok((did_document, did_document_metadata)) -} - -#[logfn(Trace)] -#[logfn_inputs(Trace)] -async fn get_did_changed_block(client: &LedgerClient, did: &DID) -> VdrResult { - let transaction = build_get_did_changed_transaction(client, did).await?; - let response = client.submit_transaction(&transaction).await?; - parse_did_changed_result(client, &response) -} - -#[logfn(Trace)] -#[logfn_inputs(Trace)] -async fn receive_did_history( - client: &LedgerClient, - did: &DID, - first_block: Block, -) -> VdrResult> { - let mut history: Vec<(Block, DidEvents)> = Vec::new(); - let mut previous_block: Option = Some(first_block); - while previous_block.is_some() { - let transaction = build_get_did_events_query( - client, - did, - previous_block.as_ref(), - previous_block.as_ref(), - ) - .await?; - let logs = client.query_events(&transaction).await?; - - // if no logs, break the loop as nothing to add to the change history - if logs.is_empty() { - break; - } - - // parse events - for log in logs { - let event = parse_did_event_response(client, &log)?; - previous_block = Some(event.previous_change()); - history.push((log.block, event)); - } - } - Ok(history) -} - -#[logfn(Trace)] -#[logfn_inputs(Trace)] -fn handle_did_owner_changed( - did_doc_builder: &mut DidDocumentBuilder, - event: &DidOwnerChanged, -) -> VdrResult<()> { - if event.owner.is_null() { - // DID is considered to be deactivated - did_doc_builder.deactivate(); - return Ok(()); - } - - let controller = DID::build(ETHR_DID_METHOD, None, event.owner.as_ref()); - did_doc_builder.set_controller(controller.as_ref()); - Ok(()) -} - -#[logfn(Trace)] -#[logfn_inputs(Trace)] -fn handle_did_delegate_changed( - did_doc_builder: &mut DidDocumentBuilder, - event: &DidDelegateChanged, - now: u64, - client: &LedgerClient, -) -> VdrResult<()> { - let event_index = event.key(); - let delegate_type = DelegateType::try_from(event.delegate_type.as_slice())?; - - if event.valid_to > now { - did_doc_builder.add_delegate_key( - &event_index, - &VerificationKeyType::EcdsaSecp256k1RecoveryMethod2020, - Some(event.delegate.as_blockchain_id(client.chain_id()).as_str()), - None, - None, - None, - None, - ); - - match delegate_type { - DelegateType::VeriKey => { - did_doc_builder.add_assertion_method_reference(&event_index)?; - } - DelegateType::SigAuth => { - did_doc_builder.add_authentication_reference(&event_index)?; - } - } - } else { - // delegate expired - did_doc_builder.remove_delegate_key(&event_index)?; - match delegate_type { - DelegateType::VeriKey => { - did_doc_builder.remove_assertion_method_reference(&event_index)?; - } - DelegateType::SigAuth => { - did_doc_builder.remove_authentication_reference(&event_index)?; - } - } - }; - Ok(()) -} - -#[logfn(Trace)] -#[logfn_inputs(Trace)] -fn handle_did_attribute_changed( - did_doc_builder: &mut DidDocumentBuilder, - event: &DidAttributeChanged, - now: u64, -) -> VdrResult<()> { - let event_index = event.key(); - let attribute = DidDocAttribute::try_from(event)?; - - match attribute { - DidDocAttribute::PublicKey(key) => { - if event.valid_to > now { - did_doc_builder.add_delegate_key( - &event_index, - &key.type_.into(), - None, - None, - key.public_key_hex.as_deref(), - key.public_key_base58.as_deref(), - key.public_key_base64.as_deref(), - ); - - match key.purpose { - PublicKeyPurpose::VeriKey => { - did_doc_builder.add_assertion_method_reference(&event_index)?; - } - PublicKeyPurpose::SigAuth => { - did_doc_builder.add_authentication_reference(&event_index)?; - } - PublicKeyPurpose::Enc => { - did_doc_builder.add_key_agreement_reference(&event_index)?; - } - } - } else { - // key expired - did_doc_builder.remove_delegate_key(&event_index)?; - match key.purpose { - PublicKeyPurpose::VeriKey => { - did_doc_builder.remove_assertion_method_reference(&event_index)?; - } - PublicKeyPurpose::SigAuth => { - did_doc_builder.remove_authentication_reference(&event_index)?; - } - PublicKeyPurpose::Enc => { - did_doc_builder.remove_key_agreement_reference(&event_index)?; - } - } - } - } - DidDocAttribute::Service(service) => { - if event.valid_to > now { - did_doc_builder.add_service( - &event_index, - None, - &service.type_, - &service.service_endpoint, - ); - } else { - did_doc_builder.remove_service(&event_index)?; - } - } - }; - Ok(()) -} - -#[logfn(Trace)] -#[logfn_inputs(Trace)] -fn handle_did_event( - did_doc_builder: &mut DidDocumentBuilder, - event: &DidEvents, - client: &LedgerClient, - now: u64, -) -> VdrResult<()> { - match event { - DidEvents::OwnerChanged(event) => handle_did_owner_changed(did_doc_builder, event), - DidEvents::DelegateChanged(event) => { - handle_did_delegate_changed(did_doc_builder, event, now, client) - } - DidEvents::AttributeChangedEvent(event) => { - handle_did_attribute_changed(did_doc_builder, event, now) - } - } -} - -#[logfn(Trace)] -#[logfn_inputs(Trace)] -async fn build_did_metadata( - client: &LedgerClient, - deactivated: bool, - version_id: Option<&Block>, - next_version_id: Option<&Block>, -) -> VdrResult { - let (updated, version_id) = match version_id { - Some(version_id) => { - let block = client.get_block(Some(version_id)).await?; - (Some(block.timestamp), Some(block.number)) - } - None => (None, None), - }; - - let (next_update, next_version_id) = match next_version_id { - Some(next_version_id) => { - let block = client.get_block(Some(next_version_id)).await?; - (Some(block.timestamp), Some(block.number)) - } - None => (None, None), - }; - - Ok(DidMetadata { - deactivated: Some(deactivated), - updated, - version_id, - next_update, - next_version_id, - }) -} diff --git a/vdr/src/contracts/did/did_indy_registry.rs b/vdr/src/contracts/did/did_indy_registry.rs new file mode 100644 index 00000000..95ad17bd --- /dev/null +++ b/vdr/src/contracts/did/did_indy_registry.rs @@ -0,0 +1,494 @@ +use log_derive::{logfn, logfn_inputs}; + +use crate::{ + client::LedgerClient, + contracts::did::types::{ + did::DID, + did_doc::{DidDocument, DidRecord}, + }, + error::VdrResult, + types::{ + Address, MethodStringParam, Transaction, TransactionBuilder, + TransactionEndorsingDataBuilder, TransactionParser, TransactionType, + }, + SignatureData, TransactionEndorsingData, +}; + +const CONTRACT_NAME: &str = "IndyDidRegistry"; +const METHOD_CREATE_DID: &str = "createDid"; +const METHOD_CREATE_DID_SIGNED: &str = "createDidSigned"; +const METHOD_UPDATE_DID: &str = "updateDid"; +const METHOD_UPDATE_DID_SIGNED: &str = "updateDidSigned"; +const METHOD_DEACTIVATE_DID: &str = "deactivateDid"; +const METHOD_DEACTIVATE_DID_SIGNED: &str = "deactivateDidSigned"; +const METHOD_RESOLVE_DID: &str = "resolveDid"; + +pub const INDYBESU_DID_METHOD: &str = "indybesu"; + +/// Build transaction to execute IndyDidRegistry.createDid contract method to create a new DID +/// +/// # Params +/// - `client` client connected to the network where contract will be executed +/// - `from` transaction sender account address +/// - `did` DID to create. +/// - `did_doc` DID Document matching to the specification: https://www.w3.org/TR/did-core/ +/// +/// # Returns +/// Write transaction to sign and submit +#[logfn(Info)] +#[logfn_inputs(Debug)] +pub async fn build_create_did_transaction( + client: &LedgerClient, + from: &Address, + did: &DID, + did_doc: &DidDocument, +) -> VdrResult { + let identity = Address::try_from(did)?; + TransactionBuilder::new() + .set_contract(CONTRACT_NAME) + .set_method(METHOD_CREATE_DID) + .add_param(&identity)? + .add_param(did_doc)? + .set_type(TransactionType::Write) + .set_from(from) + .build(client) + .await +} + +/// Prepared data for endorsing IndyDidRegistry.createDid contract method +/// +/// #Params +/// - `did` DID to create. +/// - `did_doc` DID Document matching to the specification: https://www.w3.org/TR/did-core/ +/// +/// #Returns +/// data: TransactionEndorsingData - transaction endorsement data to sign +#[logfn(Info)] +#[logfn_inputs(Debug)] +pub async fn build_create_did_endorsing_data( + client: &LedgerClient, + did: &DID, + did_doc: &DidDocument, +) -> VdrResult { + let identity = Address::try_from(did)?; + TransactionEndorsingDataBuilder::new() + .set_contract(CONTRACT_NAME) + .set_identity(&identity) + .add_param(&identity)? + .add_param(&MethodStringParam::from(METHOD_CREATE_DID))? + .add_param(did_doc)? + .build(client) + .await +} + +/// Build transaction to execute IndyDidRegistry.createDidSigned contract method to endorse a new DID +/// Endorsing version of the method - sender is not identity owner +/// +/// # Params +/// - `client` client connected to the network where contract will be executed +/// - `from` transaction sender account address +/// - `did` DID to create. +/// - `did_doc` DID Document matching to the specification: https://www.w3.org/TR/did-core/ +/// - `signature` signature of DID identity owner +/// +/// # Returns +/// Write transaction to sign and submit +#[logfn(Info)] +#[logfn_inputs(Debug)] +pub async fn build_create_did_signed_transaction( + client: &LedgerClient, + from: &Address, + did: &DID, + did_doc: &DidDocument, + signature: &SignatureData, +) -> VdrResult { + let identity = Address::try_from(did)?; + TransactionBuilder::new() + .set_contract(CONTRACT_NAME) + .set_method(METHOD_CREATE_DID_SIGNED) + .add_param(&identity)? + .add_param(&signature.v())? + .add_param(&signature.r())? + .add_param(&signature.s())? + .add_param(did_doc)? + .set_type(TransactionType::Write) + .set_from(from) + .build(client) + .await +} + +/// Build transaction to execute IndyDidRegistry.updateDid contract method to update DID document for an existing DID +/// +/// # Params +/// - `client` client connected to the network where contract will be executed +/// - `from` transaction sender account address +/// - `did` DID to update. +/// - `did_doc` DID Document matching to the specification: https://www.w3.org/TR/did-core/ +/// +/// # Returns +/// Write transaction to sign and submit +#[logfn(Info)] +#[logfn_inputs(Debug)] +pub async fn build_update_did_transaction( + client: &LedgerClient, + from: &Address, + did: &DID, + did_doc: &DidDocument, +) -> VdrResult { + let identity = Address::try_from(did)?; + TransactionBuilder::new() + .set_contract(CONTRACT_NAME) + .set_method(METHOD_UPDATE_DID) + .add_param(&identity)? + .add_param(did_doc)? + .set_type(TransactionType::Write) + .set_from(from) + .build(client) + .await +} + +/// Prepared data for endorsing IndyDidRegistry.updateDid contract method +/// +/// #Params +/// - `did` DID to create. +/// - `did_doc` DID Document matching to the specification: https://www.w3.org/TR/did-core/ +/// +/// #Returns +/// data: TransactionEndorsingData - transaction endorsement data to sign +#[logfn(Info)] +#[logfn_inputs(Debug)] +pub async fn build_update_did_endorsing_data( + client: &LedgerClient, + did: &DID, + did_doc: &DidDocument, +) -> VdrResult { + let identity = Address::try_from(did)?; + TransactionEndorsingDataBuilder::new() + .set_contract(CONTRACT_NAME) + .set_identity(&identity) + .add_param(&identity)? + .add_param(&MethodStringParam::from(METHOD_UPDATE_DID))? + .add_param(did_doc)? + .build(client) + .await +} + +/// Build transaction to execute IndyDidRegistry.updateDidSigned contract method to update DID document for an existing DID +/// Endorsing version of the method - sender is not identity owner +/// +/// # Params +/// - `client` client connected to the network where contract will be executed +/// - `from` transaction sender account address +/// - `did` DID to create. +/// - `did_doc` DID Document matching to the specification: https://www.w3.org/TR/did-core/ +/// - `signature` signature of DID identity owner +/// +/// # Returns +/// Write transaction to sign and submit +#[logfn(Info)] +#[logfn_inputs(Debug)] +pub async fn build_update_did_signed_transaction( + client: &LedgerClient, + from: &Address, + did: &DID, + did_doc: &DidDocument, + signature: &SignatureData, +) -> VdrResult { + let identity = Address::try_from(did)?; + TransactionBuilder::new() + .set_contract(CONTRACT_NAME) + .set_method(METHOD_UPDATE_DID_SIGNED) + .add_param(&identity)? + .add_param(&signature.v())? + .add_param(&signature.r())? + .add_param(&signature.s())? + .add_param(did_doc)? + .set_type(TransactionType::Write) + .set_from(from) + .build(client) + .await +} + +/// Build transaction to execute IndyDidRegistry.deactivateDid contract method to deactivate an existing DID +/// +/// # Params +/// - `client` client connected to the network where contract will be executed +/// - `from` transaction sender account address +/// - `did` DID to deactivate. +/// +/// # Returns +/// Write transaction to sign and submit +#[logfn(Info)] +#[logfn_inputs(Debug)] +pub async fn build_deactivate_did_transaction( + client: &LedgerClient, + from: &Address, + did: &DID, +) -> VdrResult { + let identity = Address::try_from(did)?; + TransactionBuilder::new() + .set_contract(CONTRACT_NAME) + .set_method(METHOD_DEACTIVATE_DID) + .add_param(&identity)? + .set_type(TransactionType::Write) + .set_from(from) + .build(client) + .await +} + +/// Build transaction to execute IndyDidRegistry.deactivateDid contract method to deactivate an existing DID +/// +/// #Params +/// - `did` DID to create. +/// - `did_doc` DID Document matching to the specification: https://www.w3.org/TR/did-core/ +/// +/// #Returns +/// data: TransactionEndorsingData - transaction endorsement data to sign +#[logfn(Info)] +#[logfn_inputs(Debug)] +pub async fn build_deactivate_did_endorsing_data( + client: &LedgerClient, + did: &DID, +) -> VdrResult { + let identity = Address::try_from(did)?; + TransactionEndorsingDataBuilder::new() + .set_contract(CONTRACT_NAME) + .set_identity(&identity) + .add_param(&identity)? + .add_param(&MethodStringParam::from(METHOD_DEACTIVATE_DID))? + .build(client) + .await +} + +/// Build transaction to execute IndyDidRegistry.deactivateDidSigned contract method to deactivate an existing DID +/// Endorsing version of the method - sender is not identity owner +/// +/// # Params +/// - `client` client connected to the network where contract will be executed +/// - `from` transaction sender account address +/// - `did` DID to create. +/// - `did_doc` DID Document matching to the specification: https://www.w3.org/TR/did-core/ +/// - `signature` signature of DID identity owner +/// +/// # Returns +/// Write transaction to sign and submit +#[logfn(Info)] +#[logfn_inputs(Debug)] +pub async fn build_deactivate_did_signed_transaction( + client: &LedgerClient, + from: &Address, + did: &DID, + signature: &SignatureData, +) -> VdrResult { + let identity = Address::try_from(did)?; + TransactionBuilder::new() + .set_contract(CONTRACT_NAME) + .set_method(METHOD_DEACTIVATE_DID_SIGNED) + .add_param(&identity)? + .add_param(&signature.v())? + .add_param(&signature.r())? + .add_param(&signature.s())? + .set_type(TransactionType::Write) + .set_from(from) + .build(client) + .await +} + +/// Build transaction to execute IndyDidRegistry.resolveDid contract method to receive a DID Document associated with the DID +/// +/// # Params +/// - `client` client connected to the network where contract will be executed +/// - `did` DID to resolve. +/// +/// # Returns +/// Read transaction to submit +#[logfn(Info)] +#[logfn_inputs(Debug)] +pub async fn build_resolve_did_transaction( + client: &LedgerClient, + did: &DID, +) -> VdrResult { + let identity = Address::try_from(did)?; + TransactionBuilder::new() + .set_contract(CONTRACT_NAME) + .set_method(METHOD_RESOLVE_DID) + .add_param(&identity)? + .set_type(TransactionType::Read) + .build(client) + .await +} + +/// Parse the result of execution IndyDidRegistry.resolveDid contract method to receive a DID Document associated with the DID +/// +/// # Params +/// - `client` client connected to the network where contract will be executed +/// - `bytes` result bytes returned from the ledger +/// +/// # Returns +/// parsed DID Record +#[logfn(Info)] +#[logfn_inputs(Debug)] +pub fn parse_resolve_did_result(client: &LedgerClient, bytes: &[u8]) -> VdrResult { + TransactionParser::new() + .set_contract(CONTRACT_NAME) + .set_method(METHOD_RESOLVE_DID) + .parse::(client, bytes) +} + +#[cfg(test)] +pub mod test { + use super::*; + use crate::{ + client::client::test::{ + mock_client, CHAIN_ID, DEFAULT_NONCE, INDY_REGISTRY_ADDRESS, TRUSTEE_ACC, + }, + contracts::did::types::{ + did::DID, + did_doc::test::{did_doc, ISSUER_ID}, + }, + utils::init_env_logger, + }; + use std::sync::RwLock; + + mod build_create_did_transaction { + use super::*; + use crate::client::client::test::mock_client; + + #[async_std::test] + async fn build_create_did_transaction_test() { + init_env_logger(); + let client = mock_client(); + let did = DID::from(ISSUER_ID); + let did_doc = did_doc(ISSUER_ID); + let transaction = build_create_did_transaction(&client, &TRUSTEE_ACC, &did, &did_doc) + .await + .unwrap(); + let expected_transaction = Transaction { + type_: TransactionType::Write, + from: Some(TRUSTEE_ACC.clone()), + to: INDY_REGISTRY_ADDRESS.clone(), + nonce: Some(DEFAULT_NONCE.clone()), + chain_id: CHAIN_ID, + data: vec![ + 245, 149, 121, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 226, 219, 108, 141, + 198, 198, 129, 187, 93, 106, 209, 33, 161, 7, 243, 0, 233, 178, 181, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 22, 123, 34, 64, 99, 111, 110, 116, 101, 120, 116, 34, + 58, 91, 34, 104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119, 46, 119, 51, + 46, 111, 114, 103, 47, 110, 115, 47, 100, 105, 100, 47, 118, 49, 34, 93, 44, + 34, 105, 100, 34, 58, 34, 100, 105, 100, 58, 105, 110, 100, 121, 98, 101, 115, + 117, 58, 100, 105, 100, 58, 101, 116, 104, 114, 58, 116, 101, 115, 116, 110, + 101, 116, 58, 48, 120, 102, 48, 101, 50, 100, 98, 54, 99, 56, 100, 99, 54, 99, + 54, 56, 49, 98, 98, 53, 100, 54, 97, 100, 49, 50, 49, 97, 49, 48, 55, 102, 51, + 48, 48, 101, 57, 98, 50, 98, 53, 34, 44, 34, 118, 101, 114, 105, 102, 105, 99, + 97, 116, 105, 111, 110, 77, 101, 116, 104, 111, 100, 34, 58, 91, 123, 34, 105, + 100, 34, 58, 34, 100, 105, 100, 58, 105, 110, 100, 121, 98, 101, 115, 117, 58, + 100, 105, 100, 58, 101, 116, 104, 114, 58, 116, 101, 115, 116, 110, 101, 116, + 58, 48, 120, 102, 48, 101, 50, 100, 98, 54, 99, 56, 100, 99, 54, 99, 54, 56, + 49, 98, 98, 53, 100, 54, 97, 100, 49, 50, 49, 97, 49, 48, 55, 102, 51, 48, 48, + 101, 57, 98, 50, 98, 53, 35, 75, 69, 89, 45, 49, 34, 44, 34, 116, 121, 112, + 101, 34, 58, 34, 69, 100, 50, 53, 53, 49, 57, 86, 101, 114, 105, 102, 105, 99, + 97, 116, 105, 111, 110, 75, 101, 121, 50, 48, 49, 56, 34, 44, 34, 99, 111, 110, + 116, 114, 111, 108, 108, 101, 114, 34, 58, 34, 100, 105, 100, 58, 105, 110, + 100, 121, 98, 101, 115, 117, 58, 100, 105, 100, 58, 101, 116, 104, 114, 58, + 116, 101, 115, 116, 110, 101, 116, 58, 48, 120, 102, 48, 101, 50, 100, 98, 54, + 99, 56, 100, 99, 54, 99, 54, 56, 49, 98, 98, 53, 100, 54, 97, 100, 49, 50, 49, + 97, 49, 48, 55, 102, 51, 48, 48, 101, 57, 98, 50, 98, 53, 35, 75, 69, 89, 45, + 49, 34, 44, 34, 112, 117, 98, 108, 105, 99, 75, 101, 121, 77, 117, 108, 116, + 105, 98, 97, 115, 101, 34, 58, 34, 122, 65, 75, 74, 80, 51, 102, 55, 66, 68, + 54, 87, 52, 105, 87, 69, 81, 57, 106, 119, 110, 100, 86, 84, 67, 66, 113, 56, + 117, 97, 50, 85, 116, 116, 56, 69, 69, 106, 74, 54, 86, 120, 115, 102, 34, 125, + 93, 44, 34, 97, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, + 34, 58, 91, 34, 100, 105, 100, 58, 105, 110, 100, 121, 98, 101, 115, 117, 58, + 100, 105, 100, 58, 101, 116, 104, 114, 58, 116, 101, 115, 116, 110, 101, 116, + 58, 48, 120, 102, 48, 101, 50, 100, 98, 54, 99, 56, 100, 99, 54, 99, 54, 56, + 49, 98, 98, 53, 100, 54, 97, 100, 49, 50, 49, 97, 49, 48, 55, 102, 51, 48, 48, + 101, 57, 98, 50, 98, 53, 35, 75, 69, 89, 45, 49, 34, 93, 125, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + ], + signature: RwLock::new(None), + hash: None, + }; + assert_eq!(expected_transaction, transaction); + } + } + + mod build_resolve_did_transaction { + use super::*; + + #[async_std::test] + async fn build_resolve_did_transaction_test() { + init_env_logger(); + let client = mock_client(); + let transaction = build_resolve_did_transaction(&client, &DID::from(ISSUER_ID)) + .await + .unwrap(); + let expected_transaction = Transaction { + type_: TransactionType::Read, + from: None, + to: INDY_REGISTRY_ADDRESS.clone(), + nonce: None, + chain_id: CHAIN_ID, + data: vec![ + 24, 48, 235, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 226, 219, 108, 141, + 198, 198, 129, 187, 93, 106, 209, 33, 161, 7, 243, 0, 233, 178, 181, + ], + signature: RwLock::new(None), + hash: None, + }; + assert_eq!(expected_transaction, transaction); + } + } + + // mod parse_resolve_did_result { + // use super::*; + // + // #[test] + // fn parse_resolve_did_result_with_metadata_test() { + // init_env_logger(); + // let client = mock_client(); + // let issuer_did = "did:indybesu:testnet:Q6Wvnm4v6ENzRC2mkUPkYR"; + // + // let data = vec![ + // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 5, 148, 0, + // 220, 208, 81, 88, 255, 216, 202, 9, 41, 55, 152, 157, 210, 123, 59, 220, 0, 0, 0, + // 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 226, 219, 108, 141, 198, 198, 129, 187, 93, 106, + // 209, 33, 161, 7, 243, 0, 233, 178, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 176, 160, 37, 0, 0, 0, 0, 0, 0, 0, + // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 176, 160, 37, + // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // 0, 0, 0, 0, 0, 0, 1, 161, 123, 34, 64, 99, 111, 110, 116, 101, 120, 116, 34, 58, + // 91, 34, 104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119, 46, 119, 51, 46, 111, + // 114, 103, 47, 110, 115, 47, 100, 105, 100, 47, 118, 49, 34, 93, 44, 34, 97, 108, + // 115, 111, 75, 110, 111, 119, 110, 65, 115, 34, 58, 91, 93, 44, 34, 97, 117, 116, + // 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 34, 58, 91, 34, 100, 105, 100, + // 58, 105, 110, 100, 121, 50, 58, 116, 101, 115, 116, 110, 101, 116, 58, 81, 54, 87, + // 118, 110, 109, 52, 118, 54, 69, 78, 122, 82, 67, 50, 109, 107, 85, 80, 107, 89, 82, + // 35, 75, 69, 89, 45, 49, 34, 93, 44, 34, 105, 100, 34, 58, 34, 100, 105, 100, 58, + // 105, 110, 100, 121, 50, 58, 116, 101, 115, 116, 110, 101, 116, 58, 81, 54, 87, 118, + // 110, 109, 52, 118, 54, 69, 78, 122, 82, 67, 50, 109, 107, 85, 80, 107, 89, 82, 34, + // 44, 34, 118, 101, 114, 105, 102, 105, 99, 97, 116, 105, 111, 110, 77, 101, 116, + // 104, 111, 100, 34, 58, 91, 123, 34, 99, 111, 110, 116, 114, 111, 108, 108, 101, + // 114, 34, 58, 34, 100, 105, 100, 58, 105, 110, 100, 121, 50, 58, 116, 101, 115, 116, + // 110, 101, 116, 58, 81, 54, 87, 118, 110, 109, 52, 118, 54, 69, 78, 122, 82, 67, 50, + // 109, 107, 85, 80, 107, 89, 82, 34, 44, 34, 105, 100, 34, 58, 34, 100, 105, 100, 58, + // 105, 110, 100, 121, 50, 58, 116, 101, 115, 116, 110, 101, 116, 58, 81, 54, 87, 118, + // 110, 109, 52, 118, 54, 69, 78, 122, 82, 67, 50, 109, 107, 85, 80, 107, 89, 82, 35, + // 75, 69, 89, 45, 49, 34, 44, 34, 112, 117, 98, 108, 105, 99, 75, 101, 121, 77, 117, + // 108, 116, 105, 98, 97, 115, 101, 34, 58, 34, 122, 65, 75, 74, 80, 51, 102, 55, 66, + // 68, 54, 87, 52, 105, 87, 69, 81, 57, 106, 119, 110, 100, 86, 84, 67, 66, 113, 56, + // 117, 97, 50, 85, 116, 116, 56, 69, 69, 106, 74, 54, 86, 120, 115, 102, 34, 44, 34, + // 116, 121, 112, 101, 34, 58, 34, 69, 100, 50, 53, 53, 49, 57, 86, 101, 114, 105, + // 102, 105, 99, 97, 116, 105, 111, 110, 75, 101, 121, 50, 48, 49, 56, 34, 125, 93, + // 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // 0, 0, 0, 0, 0, + // ]; + // let parsed_did_doc = parse_resolve_did_result(&client, &data).unwrap(); + // assert_eq!(did_doc(issuer_did), parsed_did_doc.document); + // } + // } +} diff --git a/vdr/src/contracts/did/did_resolver.rs b/vdr/src/contracts/did/did_resolver.rs new file mode 100644 index 00000000..ce1aaca0 --- /dev/null +++ b/vdr/src/contracts/did/did_resolver.rs @@ -0,0 +1,443 @@ +use chrono::Utc; +use log_derive::{logfn, logfn_inputs}; + +use crate::{ + contracts::{ + did::{types::did_doc_attribute::PublicKeyPurpose, DidResolutionError}, + types::did::ParsedDid, + DidDocumentWithMeta, DidMetadata, DidRecord, DidResolutionMetadata, DID_RESOLUTION_FORMAT, + }, + did_ethr_registry::{ + build_get_did_changed_transaction, build_get_did_events_query, parse_did_changed_result, + parse_did_event_response, ETHR_DID_METHOD, + }, + did_indy_registry::{ + build_resolve_did_transaction, parse_resolve_did_result, INDYBESU_DID_METHOD, + }, + Block, DelegateType, DidAttributeChanged, DidDelegateChanged, DidDocAttribute, + DidDocumentBuilder, DidEvents, DidOwnerChanged, DidResolutionOptions, LedgerClient, VdrError, + VdrResult, VerificationKeyType, DID, +}; + +/// Single step function to resolve a DidDocument with metadata for the given DID +/// +/// # Params +/// - `client` client connected to the network where contract will be executed +/// - `did` DID to get a DID Document and metadata +/// - `options` Resolution options +/// +/// # Returns +/// Parsed DID event object +#[logfn(Info)] +#[logfn_inputs(Debug)] +pub async fn resolve_did( + client: &LedgerClient, + did: &DID, + options: Option<&DidResolutionOptions>, +) -> VdrResult { + // Parse DID + let parsed_did = match ParsedDid::try_from(did) { + Ok(did) => did, + Err(_) => { + return Ok(DidDocumentWithMeta { + did_document: None, + did_document_metadata: DidMetadata::default(), + did_resolution_metadata: DidResolutionMetadata { + content_type: None, + error: Some(DidResolutionError::InvalidDid), + message: Some(format!("Not a valid did: {}", did.as_ref())), + }, + }); + } + }; + + let accept = options.and_then(|options| options.accept.as_deref()); + let block_tag = options.and_then(|options| options.block_tag.as_ref()); + + match accept { + Some(DID_RESOLUTION_FORMAT) | None => { + // ok + } + Some(accept) => { + return Ok(DidDocumentWithMeta { + did_document: None, + did_document_metadata: DidMetadata::default(), + did_resolution_metadata: DidResolutionMetadata { + content_type: None, + error: Some(DidResolutionError::RepresentationNotSupported), + message: Some(format!( + "VDR does not support the requested 'accept' format: {}", + accept + )), + }, + }); + } + } + + let did = parsed_did.as_short_did(); + + let resolve_result = match parsed_did.method.as_str() { + INDYBESU_DID_METHOD => indybesu::resolve(client, &did).await, + ETHR_DID_METHOD => ethr::resolve(client, &did, block_tag).await, + _ => { + return Ok(DidDocumentWithMeta { + did_document: None, + did_document_metadata: DidMetadata::default(), + did_resolution_metadata: DidResolutionMetadata { + content_type: None, + error: Some(DidResolutionError::MethodNotSupported), + message: Some(format!( + "DID Method is not supported: {}", + parsed_did.method + )), + }, + }); + } + }; + + match resolve_result { + Ok(did_record) => Ok(DidDocumentWithMeta { + did_document: Some(did_record.document), + did_document_metadata: did_record.metadata, + did_resolution_metadata: DidResolutionMetadata { + content_type: accept.map(String::from), + error: None, + message: None, + }, + }), + Err(err) => Ok(DidDocumentWithMeta { + did_document: None, + did_document_metadata: DidMetadata::default(), + did_resolution_metadata: DidResolutionMetadata { + content_type: None, + error: Some(DidResolutionError::NotFound), + message: Some(err.to_string()), + }, + }), + } +} + +mod indybesu { + use super::*; + + #[logfn(Trace)] + #[logfn_inputs(Trace)] + pub(crate) async fn resolve(client: &LedgerClient, did: &DID) -> VdrResult { + let transaction = build_resolve_did_transaction(client, did).await?; + let response = client.submit_transaction(&transaction).await?; + if response.is_empty() { + return Err(VdrError::ClientInvalidResponse(format!( + "DID not found: {:?}", + did + ))); + } + parse_resolve_did_result(client, &response) + } +} + +mod ethr { + use super::*; + + #[logfn(Trace)] + #[logfn_inputs(Trace)] + pub(crate) async fn resolve( + client: &LedgerClient, + did: &DID, + block: Option<&Block>, + ) -> VdrResult { + // Build base DID document for ethr DID + let mut did_doc_builder = DidDocumentBuilder::base_for_did(did, client.chain_id())?; + + // TODO: support the case when DID identifier is public key + + // Query block number when DID was changed last time + let did_changed_block = get_did_changed_block(client, did).await?; + + // if DID has not been ever changed, we do not need to query events and just return base did document + if did_changed_block.is_none() { + let document = did_doc_builder.build(); + return Ok(DidRecord { + document, + metadata: DidMetadata::default(), + }); + } + + let mut version_id: Option = None; + let mut next_version_id: Option = None; + + // time in seconds for attributes validity check + let now = match block { + Some(block) => { + // request block time if the resolution happens for specific block + client.get_block(Some(block)).await?.timestamp + } + None => { + // else current time + Utc::now().timestamp() as u64 + } + }; + + // request events for a specific block until previous exists + let did_history = receive_did_history(client, did, did_changed_block).await?; + + // assemble Did Document from the history events + // iterate in the reverse order -> oldest to newest + for (event_block, event) in did_history.into_iter().rev() { + match block { + // if we resolve DID for specific block we need to skip all blocks higher + Some(block) if event_block.value() > block.value() => { + if next_version_id.is_none() { + next_version_id = Some(event_block) + } + continue; + } + _ => { + version_id = Some(event_block); + } + } + + // handle event + handle_did_event(&mut did_doc_builder, &event, client, now)?; + + // break for deactivate DID -> minimal DID Document will be returned + if did_doc_builder.deactivated() { + break; + } + } + + let metadata = build_did_metadata( + client, + did_doc_builder.deactivated(), + version_id.as_ref(), + next_version_id.as_ref(), + ) + .await?; + Ok(DidRecord { + document: did_doc_builder.build(), + metadata, + }) + } + + #[logfn(Trace)] + #[logfn_inputs(Trace)] + async fn get_did_changed_block(client: &LedgerClient, did: &DID) -> VdrResult { + let transaction = build_get_did_changed_transaction(client, did).await?; + let response = client.submit_transaction(&transaction).await?; + parse_did_changed_result(client, &response) + } + + #[logfn(Trace)] + #[logfn_inputs(Trace)] + async fn receive_did_history( + client: &LedgerClient, + did: &DID, + first_block: Block, + ) -> VdrResult> { + let mut history: Vec<(Block, DidEvents)> = Vec::new(); + let mut previous_block: Option = Some(first_block); + while previous_block.is_some() { + let transaction = build_get_did_events_query( + client, + did, + previous_block.as_ref(), + previous_block.as_ref(), + ) + .await?; + let logs = client.query_events(&transaction).await?; + + // if no logs, break the loop as nothing to add to the change history + if logs.is_empty() { + break; + } + + // parse events + for log in logs { + let event = parse_did_event_response(client, &log)?; + previous_block = Some(event.previous_change()); + history.push((log.block, event)); + } + } + Ok(history) + } + + #[logfn(Trace)] + #[logfn_inputs(Trace)] + fn handle_did_owner_changed( + did_doc_builder: &mut DidDocumentBuilder, + event: &DidOwnerChanged, + ) -> VdrResult<()> { + if event.owner.is_null() { + // DID is considered to be deactivated + did_doc_builder.deactivate(); + return Ok(()); + } + + let controller = DID::build(ETHR_DID_METHOD, None, event.owner.as_ref()); + did_doc_builder.set_controller(controller.as_ref()); + Ok(()) + } + + #[logfn(Trace)] + #[logfn_inputs(Trace)] + fn handle_did_delegate_changed( + did_doc_builder: &mut DidDocumentBuilder, + event: &DidDelegateChanged, + now: u64, + client: &LedgerClient, + ) -> VdrResult<()> { + let event_index = event.key(); + let delegate_type = DelegateType::try_from(event.delegate_type.as_slice())?; + + if event.valid_to > now { + did_doc_builder.add_delegate_key( + &event_index, + &VerificationKeyType::EcdsaSecp256k1RecoveryMethod2020, + Some(event.delegate.as_blockchain_id(client.chain_id()).as_str()), + None, + None, + None, + None, + ); + + match delegate_type { + DelegateType::VeriKey => { + did_doc_builder.add_assertion_method_reference(&event_index)?; + } + DelegateType::SigAuth => { + did_doc_builder.add_authentication_reference(&event_index)?; + } + } + } else { + // delegate expired + did_doc_builder.remove_delegate_key(&event_index)?; + match delegate_type { + DelegateType::VeriKey => { + did_doc_builder.remove_assertion_method_reference(&event_index)?; + } + DelegateType::SigAuth => { + did_doc_builder.remove_authentication_reference(&event_index)?; + } + } + }; + Ok(()) + } + + #[logfn(Trace)] + #[logfn_inputs(Trace)] + fn handle_did_attribute_changed( + did_doc_builder: &mut DidDocumentBuilder, + event: &DidAttributeChanged, + now: u64, + ) -> VdrResult<()> { + let event_index = event.key(); + let attribute = DidDocAttribute::try_from(event)?; + + match attribute { + DidDocAttribute::PublicKey(key) => { + if event.valid_to > now { + did_doc_builder.add_delegate_key( + &event_index, + &key.type_.into(), + None, + None, + key.public_key_hex.as_deref(), + key.public_key_base58.as_deref(), + key.public_key_base64.as_deref(), + ); + + match key.purpose { + PublicKeyPurpose::VeriKey => { + did_doc_builder.add_assertion_method_reference(&event_index)?; + } + PublicKeyPurpose::SigAuth => { + did_doc_builder.add_authentication_reference(&event_index)?; + } + PublicKeyPurpose::Enc => { + did_doc_builder.add_key_agreement_reference(&event_index)?; + } + } + } else { + // key expired + did_doc_builder.remove_delegate_key(&event_index)?; + match key.purpose { + PublicKeyPurpose::VeriKey => { + did_doc_builder.remove_assertion_method_reference(&event_index)?; + } + PublicKeyPurpose::SigAuth => { + did_doc_builder.remove_authentication_reference(&event_index)?; + } + PublicKeyPurpose::Enc => { + did_doc_builder.remove_key_agreement_reference(&event_index)?; + } + } + } + } + DidDocAttribute::Service(service) => { + if event.valid_to > now { + did_doc_builder.add_service( + &event_index, + None, + &service.type_, + &service.service_endpoint, + ); + } else { + did_doc_builder.remove_service(&event_index)?; + } + } + }; + Ok(()) + } + + #[logfn(Trace)] + #[logfn_inputs(Trace)] + fn handle_did_event( + did_doc_builder: &mut DidDocumentBuilder, + event: &DidEvents, + client: &LedgerClient, + now: u64, + ) -> VdrResult<()> { + match event { + DidEvents::OwnerChanged(event) => handle_did_owner_changed(did_doc_builder, event), + DidEvents::DelegateChanged(event) => { + handle_did_delegate_changed(did_doc_builder, event, now, client) + } + DidEvents::AttributeChangedEvent(event) => { + handle_did_attribute_changed(did_doc_builder, event, now) + } + } + } + + #[logfn(Trace)] + #[logfn_inputs(Trace)] + async fn build_did_metadata( + client: &LedgerClient, + deactivated: bool, + version_id: Option<&Block>, + next_version_id: Option<&Block>, + ) -> VdrResult { + let (updated, version_id) = match version_id { + Some(version_id) => { + let block = client.get_block(Some(version_id)).await?; + (Some(block.timestamp), Some(block.number)) + } + None => (None, None), + }; + + let (next_update, next_version_id) = match next_version_id { + Some(next_version_id) => { + let block = client.get_block(Some(next_version_id)).await?; + (Some(block.timestamp), Some(block.number)) + } + None => (None, None), + }; + + Ok(DidMetadata { + created: None, + deactivated: Some(deactivated), + updated, + version_id, + next_update, + next_version_id, + }) + } +} diff --git a/vdr/src/contracts/did/mod.rs b/vdr/src/contracts/did/mod.rs index 93b6289c..4fbe41f9 100644 --- a/vdr/src/contracts/did/mod.rs +++ b/vdr/src/contracts/did/mod.rs @@ -1,7 +1,8 @@ pub mod did_ethr_registry; +pub mod did_indy_registry; +pub mod did_resolver; pub mod types; -pub(crate) mod did_ethr_resolver; - pub use did_ethr_registry::*; +pub use did_indy_registry::*; pub use types::{did::DID, did_doc::*, did_doc_attribute::*}; diff --git a/vdr/src/contracts/did/types/did_doc.rs b/vdr/src/contracts/did/types/did_doc.rs index 2f1d990c..f05d17f1 100644 --- a/vdr/src/contracts/did/types/did_doc.rs +++ b/vdr/src/contracts/did/types/did_doc.rs @@ -1,4 +1,8 @@ -use crate::{error::VdrError, Block}; +use crate::{ + error::VdrError, + types::{ContractOutput, ContractParam}, + Block, +}; use crate::contracts::did::types::did::DID; use log::warn; @@ -42,8 +46,10 @@ pub struct DidDocument { #[serde(skip_serializing_if = "Option::is_none")] pub controller: Option, pub verification_method: Vec, + #[serde(skip_serializing_if = "Vec::is_empty")] #[serde(default)] pub authentication: Vec, + #[serde(skip_serializing_if = "Vec::is_empty")] #[serde(default)] pub assertion_method: Vec, #[serde(skip_serializing_if = "Vec::is_empty")] @@ -62,9 +68,18 @@ pub struct DidDocument { pub also_known_as: Option>, } +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct DidRecord { + pub document: DidDocument, + pub metadata: DidMetadata, +} + #[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct DidMetadata { + #[serde(skip_serializing_if = "Option::is_none")] + pub created: Option, #[serde(skip_serializing_if = "Option::is_none")] pub deactivated: Option, #[serde(skip_serializing_if = "Option::is_none")] @@ -214,6 +229,66 @@ impl Default for StringOrVector { } } +impl TryFrom<&DidDocument> for ContractParam { + type Error = VdrError; + + fn try_from(value: &DidDocument) -> Result { + serde_json::to_vec(value) + .map(ContractParam::Bytes) + .map_err(|_| VdrError::ContractInvalidInputData) + } +} + +impl TryFrom<&ContractOutput> for DidDocument { + type Error = VdrError; + + fn try_from(value: &ContractOutput) -> Result { + serde_json::from_slice(&value.get_bytes(0)?).map_err(|err| { + VdrError::ContractInvalidResponseData(format!( + "Unable to parse DID Document from the response. Err: {:?}", + err + )) + }) + } +} + +impl TryFrom for DidMetadata { + type Error = VdrError; + + fn try_from(value: ContractOutput) -> Result { + let _owner = value.get_address(0)?; + let _sender = value.get_address(1)?; + let created = value.get_u128(2)? as u64; + let updated = value.get_u128(3)? as u64; + let version_id = value.get_u128(4)? as u64; + let deactivated = value.get_bool(5)?; + let did_metadata = DidMetadata { + deactivated: Some(deactivated), + created: Some(created), + version_id: Some(version_id), + updated: Some(updated), + next_version_id: None, + next_update: None, + }; + Ok(did_metadata) + } +} + +impl TryFrom for DidRecord { + type Error = VdrError; + + fn try_from(value: ContractOutput) -> Result { + let output_tuple = value.get_tuple(0)?; + let did_document = DidDocument::try_from(&output_tuple)?; + let metadata = output_tuple.get_tuple(1)?; + let did_doc_with_metadata = DidRecord { + document: did_document, + metadata: DidMetadata::try_from(metadata)?, + }; + Ok(did_doc_with_metadata) + } +} + #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub enum DidResolutionError { /* @@ -248,12 +323,17 @@ pub enum DidResolutionError { #[cfg(test)] pub mod test { use super::*; - use serde_json::json; + use crate::{contracts::ETHR_DID_METHOD, did_indy_registry::INDYBESU_DID_METHOD}; - pub const TEST_DID_ETHR: &str = "did:ethr:0xb9c5714089478a327f09197987f16f9e5d936e8a"; - pub const ISSUER_ID: &str = "did:ethr:testnet:0xf0e2db6c8dc6c681bb5d6ad121a107f300e9b2b5"; + pub const _TEST_INDYBESU_DID: &str = + "did:indybesu:testnet:0xf0e2db6c8dc6c681bb5d6ad121a107f300e9b2b5"; + pub const TEST_ACCOUNT: &str = "0xb9c5714089478a327f09197987f16f9e5d936e8a"; + pub const TEST_ETHR_DID: &str = "did:ethr:0xb9c5714089478a327f09197987f16f9e5d936e8a"; pub const SERVICE_ENDPOINT: &str = "http://example.com"; pub const SERVICE_TYPE: &str = "Service"; + pub const MULTIBASE_KEY: &'static str = "zAKJP3f7BD6W4iWEQ9jwndVTCBq8ua2Utt8EEjJ6Vxsf"; + pub const KEY_1: &'static str = "KEY-1"; + pub const ISSUER_ID: &str = "did:ethr:testnet:0xf0e2db6c8dc6c681bb5d6ad121a107f300e9b2b5"; pub fn _service(id: &str) -> Service { Service { @@ -263,34 +343,96 @@ pub mod test { } } - pub fn default_ethr_did_document(chain_id: Option) -> DidDocument { + pub fn verification_method(id: &str) -> VerificationMethod { + VerificationMethod { + id: id.to_string(), + type_: VerificationKeyType::Ed25519VerificationKey2018, + controller: id.to_string(), + blockchain_account_id: None, + public_key_multibase: Some(MULTIBASE_KEY.to_string()), + public_key_hex: None, + public_key_base58: None, + public_key_base64: None, + } + } + + pub fn verification_relationship(id: &str) -> VerificationMethodOrReference { + VerificationMethodOrReference::String(id.to_string()) + } + + pub fn did_doc(identity: &str) -> DidDocument { + let id = DID::build(INDYBESU_DID_METHOD, None, identity); + let kid = format!("{}#{}", id.as_ref(), KEY_1); + DidDocument { + context: StringOrVector::Vector(vec![BASE_CONTEXT.to_string()]), + id: id.clone(), + controller: None, + verification_method: vec![verification_method(&kid)], + authentication: vec![verification_relationship(&kid)], + assertion_method: vec![], + capability_invocation: vec![], + capability_delegation: vec![], + key_agreement: vec![], + service: vec![], + also_known_as: None, + } + } + + pub fn default_ethr_did_document(identity: &str, chain_id: Option) -> DidDocument { + let id = DID::build(ETHR_DID_METHOD, None, identity); let chain_id = chain_id.unwrap_or(1); - let blockchain_account_id = format!( - "eip155:{}:0xb9c5714089478a327f09197987f16f9e5d936e8a", - chain_id - ); - serde_json::from_value(json!({ - "@context": [ - "https://www.w3.org/ns/did/v1", - "https://w3id.org/security/suites/secp256k1recovery-2020/v2", - "https://w3id.org/security/v3-unstable" - ], - "id": "did:ethr:0xb9c5714089478a327f09197987f16f9e5d936e8a", - "verificationMethod": [ - { - "id": "did:ethr:0xb9c5714089478a327f09197987f16f9e5d936e8a#controller", - "type": "EcdsaSecp256k1RecoveryMethod2020", - "controller": "did:ethr:0xb9c5714089478a327f09197987f16f9e5d936e8a", - "blockchainAccountId": blockchain_account_id - } - ], - "authentication": [ - "did:ethr:0xb9c5714089478a327f09197987f16f9e5d936e8a#controller" - ], - "assertionMethod": [ - "did:ethr:0xb9c5714089478a327f09197987f16f9e5d936e8a#controller" - ] - })) - .unwrap() + let blockchain_account_id = format!("eip155:{}:{}", chain_id, identity); + let kid = format!("{}#controller", id.as_ref()); + DidDocument { + context: StringOrVector::Vector(vec![ + BASE_CONTEXT.to_string(), + SECPK_CONTEXT.to_string(), + KEYS_CONTEXT.to_string(), + ]), + id: id.clone(), + controller: None, + verification_method: vec![VerificationMethod { + id: kid.clone(), + type_: VerificationKeyType::EcdsaSecp256k1RecoveryMethod2020, + controller: id.to_string(), + blockchain_account_id: Some(blockchain_account_id), + public_key_multibase: None, + public_key_hex: None, + public_key_base58: None, + public_key_base64: None, + }], + authentication: vec![verification_relationship(&kid)], + assertion_method: vec![verification_relationship(&kid)], + capability_invocation: vec![], + capability_delegation: vec![], + key_agreement: vec![], + service: vec![], + also_known_as: None, + } + } + + fn did_doc_param() -> ContractParam { + ContractParam::Bytes(serde_json::to_vec(&did_doc(ISSUER_ID)).unwrap()) + } + + mod convert_into_contract_param { + use super::*; + + #[test] + fn convert_did_doc_into_contract_param_test() { + let param: ContractParam = (&did_doc(ISSUER_ID)).try_into().unwrap(); + assert_eq!(did_doc_param(), param); + } + } + + mod convert_into_object { + use super::*; + + #[test] + fn convert_contract_output_into_did_doc() { + let data = ContractOutput::new(vec![did_doc_param()]); + let converted = DidDocument::try_from(&data).unwrap(); + assert_eq!(did_doc(ISSUER_ID), converted); + } } } diff --git a/vdr/src/contracts/did/types/did_doc_builder.rs b/vdr/src/contracts/did/types/did_doc_builder.rs index 34860cb6..b69c3c6e 100644 --- a/vdr/src/contracts/did/types/did_doc_builder.rs +++ b/vdr/src/contracts/did/types/did_doc_builder.rs @@ -387,9 +387,8 @@ impl DidDocumentBuilder { pub mod test { use super::*; use crate::contracts::types::did_doc::test::{ - default_ethr_did_document, SERVICE_ENDPOINT, SERVICE_TYPE, TEST_DID_ETHR, + default_ethr_did_document, SERVICE_ENDPOINT, SERVICE_TYPE, TEST_ACCOUNT, TEST_ETHR_DID, }; - use serde_json::json; const KEY_1_INDEX: &str = "KEY_1"; const KEY_2_INDEX: &str = "KEY_2"; @@ -398,15 +397,15 @@ pub mod test { #[test] fn build_base_ethr_did_document_test() { - let did_document = DidDocumentBuilder::base_for_did(&DID::from(TEST_DID_ETHR), 1) + let did_document = DidDocumentBuilder::base_for_did(&DID::from(TEST_ETHR_DID), 1) .unwrap() .build(); - assert_eq!(default_ethr_did_document(None), did_document); + assert_eq!(default_ethr_did_document(TEST_ACCOUNT, None), did_document); } #[test] fn build_did_document_test() { - let mut builder = DidDocumentBuilder::base_for_did(&DID::from(TEST_DID_ETHR), 1).unwrap(); + let mut builder = DidDocumentBuilder::base_for_did(&DID::from(TEST_ETHR_DID), 1).unwrap(); builder.add_delegate_key( KEY_1_INDEX, &VerificationKeyType::EcdsaSecp256k1RecoveryMethod2020, @@ -446,7 +445,6 @@ pub mod test { &ServiceEndpoint::String(SERVICE_ENDPOINT.to_string()), ); let did_document = builder.build(); - println!("{}", json!(did_document).to_string()); assert_eq!(4, did_document.verification_method.len()); assert_eq!(3, did_document.assertion_method.len()); @@ -455,23 +453,23 @@ pub mod test { assert_eq!(1, did_document.service.len()); assert_eq!( - format!("{}#controller", TEST_DID_ETHR), + format!("{}#controller", TEST_ETHR_DID), did_document.verification_method[0].id ); assert_eq!( - format!("{}#delegate-1", TEST_DID_ETHR), + format!("{}#delegate-1", TEST_ETHR_DID), did_document.verification_method[1].id ); assert_eq!( - format!("{}#delegate-2", TEST_DID_ETHR), + format!("{}#delegate-2", TEST_ETHR_DID), did_document.verification_method[2].id ); assert_eq!( - format!("{}#delegate-3", TEST_DID_ETHR), + format!("{}#delegate-3", TEST_ETHR_DID), did_document.verification_method[3].id ); assert_eq!( - format!("{}#service-1", TEST_DID_ETHR), + format!("{}#service-1", TEST_ETHR_DID), did_document.service[0].id ); } diff --git a/vdr/src/lib.rs b/vdr/src/lib.rs index 25ce9072..93fdf31a 100644 --- a/vdr/src/lib.rs +++ b/vdr/src/lib.rs @@ -21,14 +21,12 @@ pub use contracts::{ cl::{ credential_definition_registry, schema_registry, types::{ - credential_definition::{CredentialDefinition, CredentialDefinitionCreatedEvent}, - credential_definition_id::CredentialDefinitionId, - schema::{Schema, SchemaCreatedEvent}, - schema_id::SchemaId, + credential_definition::CredentialDefinition, + credential_definition_id::CredentialDefinitionId, schema::Schema, schema_id::SchemaId, }, }, did::{ - did_ethr_registry, + did_ethr_registry, did_indy_registry, did_resolver, types::{ did::DID, did_doc::{ diff --git a/vdr/src/migration/credential_definition.rs b/vdr/src/migration/credential_definition.rs index 3952167c..69886ca1 100644 --- a/vdr/src/migration/credential_definition.rs +++ b/vdr/src/migration/credential_definition.rs @@ -55,7 +55,11 @@ impl CredentialDefinitionId { })?; let issuer_did = DID::build(DID_METHOD, Some(NETWORK), id); - let cred_def_id = CredentialDefinitionId::build(&issuer_did, schema_id, tag); + let cred_def_id = CredentialDefinitionId::build( + &issuer_did, + &SchemaId::from(schema_id.to_string().as_str()), + tag, + ); Ok(cred_def_id) } } diff --git a/vdr/src/test.rs b/vdr/src/test.rs index 64647cd4..9a4445c4 100644 --- a/vdr/src/test.rs +++ b/vdr/src/test.rs @@ -1,11 +1,10 @@ use crate::{ client::client::test::client, contracts::{ - auth::Role, + auth::{role_control, Role}, cl::types::{credential_definition::test::credential_definition, schema::test::schema}, - did::{DID, ETHR_DID_METHOD}, + did::{did_indy_registry, types::did_doc::test::did_doc, DidRecord, DID, ETHR_DID_METHOD}, }, - error::VdrResult, signer::basic_signer::{ test::{basic_signer, TRUSTEE_ACC}, BasicSigner, @@ -14,45 +13,171 @@ use crate::{ LedgerClient, TransactionEndorsingData, }; -fn did(address: &Address) -> DID { - DID::build(ETHR_DID_METHOD, None, address.as_ref()) -} +mod helpers { + use super::*; + use crate::{Address, LedgerClient}; + + pub async fn sign_and_submit_transaction( + client: &LedgerClient, + transaction: Transaction, + signer: &BasicSigner, + ) -> String { + let sign_bytes = transaction.get_signing_bytes().unwrap(); + let from = transaction.from.as_ref().unwrap(); + let signature = signer.sign(&sign_bytes, from.as_ref()).unwrap(); + transaction.set_signature(signature); + let block_hash = client.submit_transaction(&transaction).await.unwrap(); + client.get_receipt(&block_hash).await.unwrap() + } + + pub fn sign_endorsing_data( + data: &TransactionEndorsingData, + signer: &BasicSigner, + ) -> SignatureData { + signer + .sign(&data.get_signing_bytes().unwrap(), data.from.as_ref()) + .unwrap() + } + + pub async fn assign_role( + client: &LedgerClient, + assignee_account: &Address, + role_to_assign: &Role, + signer: &BasicSigner, + ) -> String { + let transaction = role_control::build_assign_role_transaction( + client, + &TRUSTEE_ACC, + role_to_assign, + assignee_account, + ) + .await + .unwrap(); + sign_and_submit_transaction(client, transaction, signer).await + } -async fn sign_and_submit_transaction( - client: &LedgerClient, - transaction: Transaction, - signer: &BasicSigner, -) -> String { - let sign_bytes = transaction.get_signing_bytes().unwrap(); - let signature = signer.sign(&sign_bytes, TRUSTEE_ACC.as_ref()).unwrap(); - transaction.set_signature(signature); - let block_hash = client.submit_transaction(&transaction).await.unwrap(); - client.get_receipt(&block_hash).await.unwrap() + pub async fn create_trustee(signer: &mut BasicSigner, client: &LedgerClient) -> Address { + let (identity, _) = signer.create_key(None).unwrap(); + assign_role(&client, &identity, &Role::Trustee, &signer).await; + identity + } } -fn sign_endorsing_data(data: &TransactionEndorsingData, signer: &BasicSigner) -> SignatureData { - signer - .sign(&data.get_signing_bytes().unwrap(), data.from.as_ref()) - .unwrap() +mod did_indy { + use super::*; + + async fn resolve_did(client: &LedgerClient, did: &DID) -> DidRecord { + let transaction = did_indy_registry::build_resolve_did_transaction(client, did) + .await + .unwrap(); + let result = client.submit_transaction(&transaction).await.unwrap(); + did_indy_registry::parse_resolve_did_result(client, &result).unwrap() + } + + #[async_std::test] + async fn create_did_test() { + let mut signer = basic_signer(); + let client = client(); + let identity = super::helpers::create_trustee(&mut signer, &client).await; + + // create + let did_doc = did_doc(identity.as_ref()); + let transaction = did_indy_registry::build_create_did_transaction( + &client, + &identity, + &did_doc.id, + &did_doc, + ) + .await + .unwrap(); + super::helpers::sign_and_submit_transaction(&client, transaction, &signer).await; + + // read + let resolved_did_record = resolve_did(&client, &did_doc.id).await; + assert_eq!(did_doc, resolved_did_record.document); + } + + #[async_std::test] + async fn create_and_deactivate_test() { + let mut signer = basic_signer(); + let client = client(); + let identity = super::helpers::create_trustee(&mut signer, &client).await; + + // create + let did_doc = did_doc(identity.as_ref()); + let transaction = did_indy_registry::build_create_did_transaction( + &client, + &identity, + &did_doc.id, + &did_doc, + ) + .await + .unwrap(); + super::helpers::sign_and_submit_transaction(&client, transaction, &signer).await; + + // deactivate + let transaction = + did_indy_registry::build_deactivate_did_transaction(&client, &identity, &did_doc.id) + .await + .unwrap(); + super::helpers::sign_and_submit_transaction(&client, transaction, &signer).await; + + // read + let resolved_did_record = resolve_did(&client, &did_doc.id).await; + assert_eq!(true, resolved_did_record.metadata.deactivated.unwrap()); + } + + #[async_std::test] + async fn endorse_did_test() { + let mut signer = basic_signer(); + let client = client(); + let (identity, _) = signer.create_key(None).unwrap(); + + // create + let did_doc = did_doc(identity.as_ref()); + let endorsement_data = + did_indy_registry::build_create_did_endorsing_data(&client, &did_doc.id, &did_doc) + .await + .unwrap(); + + let signature = super::helpers::sign_endorsing_data(&endorsement_data, &signer); + + let transaction = did_indy_registry::build_create_did_signed_transaction( + &client, + &TRUSTEE_ACC, + &did_doc.id, + &did_doc, + &signature, + ) + .await + .unwrap(); + + super::helpers::sign_and_submit_transaction(&client, transaction, &signer).await; + + // read + let resolved_did_record = resolve_did(&client, &did_doc.id).await; + assert_eq!(did_doc, resolved_did_record.document); + } } -mod did { +mod did_ethr { use super::*; use crate::{ contracts::{ did::{ did_ethr_registry, did_ethr_registry::test::{public_key, service, validity}, + did_resolver, types::{ - did_doc::test::{default_ethr_did_document, TEST_DID_ETHR}, - did_doc_attribute::DidDocAttribute, + did_doc::test::default_ethr_did_document, did_doc_attribute::DidDocAttribute, }, DID, }, types::did::ParsedDid, + ETHR_DID_METHOD, }, did_ethr_registry::test::{public_key_2, public_key_3}, - Address, LedgerClient, Validity, VdrResult, + Address, LedgerClient, Validity, }; async fn endorse_set_did_attribute( @@ -68,7 +193,7 @@ mod did { .await .unwrap(); - let signature = sign_endorsing_data(&transaction_endorsing_data, signer); + let signature = super::helpers::sign_endorsing_data(&transaction_endorsing_data, signer); let transaction = did_ethr_registry::build_did_set_attribute_signed_transaction( client, @@ -81,7 +206,7 @@ mod did { .await .unwrap(); - sign_and_submit_transaction(&client, transaction, &signer).await; + super::helpers::sign_and_submit_transaction(&client, transaction, &signer).await; } async fn endorse_revoke_did_attribute( @@ -95,7 +220,7 @@ mod did { .await .unwrap(); - let signature = sign_endorsing_data(&transaction_endorsing_data, signer); + let signature = super::helpers::sign_endorsing_data(&transaction_endorsing_data, signer); let transaction = did_ethr_registry::build_did_revoke_attribute_signed_transaction( client, @@ -106,15 +231,16 @@ mod did { ) .await .unwrap(); - sign_and_submit_transaction(&client, transaction, &signer).await + super::helpers::sign_and_submit_transaction(&client, transaction, &signer).await } #[async_std::test] - async fn demo_create_did_ethr() -> VdrResult<()> { - let signer = basic_signer(); + async fn demo_create_did_ethr() { + let mut signer = basic_signer(); let client = client(); + let identity = super::helpers::create_trustee(&mut signer, &client).await; - let did = super::did(&TRUSTEE_ACC.clone()); + let did = DID::build(ETHR_DID_METHOD, None, identity.as_ref()); // read DID changed block -> it must be none let transaction = did_ethr_registry::build_get_did_changed_transaction(&client, &did) @@ -127,14 +253,14 @@ mod did { // add service attribute to DID let transaction = did_ethr_registry::build_did_set_attribute_transaction( &client, - &TRUSTEE_ACC, + &identity, &did, &service(), &validity(), ) .await .unwrap(); - sign_and_submit_transaction(&client, transaction, &signer).await; + super::helpers::sign_and_submit_transaction(&client, transaction, &signer).await; // Read DID events let transaction = did_ethr_registry::build_get_did_events_query(&client, &did, None, None) @@ -156,17 +282,17 @@ mod did { // add service key to DID let transaction = did_ethr_registry::build_did_set_attribute_transaction( &client, - &TRUSTEE_ACC, + &identity, &did, &public_key(), &validity(), ) .await .unwrap(); - sign_and_submit_transaction(&client, transaction, &signer).await; + super::helpers::sign_and_submit_transaction(&client, transaction, &signer).await; // resolve DID document - let did_doc_with_meta = did_ethr_registry::resolve_did(&client, &did, None) + let did_doc_with_meta = did_resolver::resolve_did(&client, &did, None) .await .unwrap(); let did_document = did_doc_with_meta.did_document.unwrap(); @@ -176,17 +302,14 @@ mod did { false, did_doc_with_meta.did_document_metadata.deactivated.unwrap() ); - - Ok(()) } #[async_std::test] - async fn demo_endorse_did_ethr() -> VdrResult<()> { + async fn demo_endorse_did_ethr() { let mut signer = basic_signer(); let client = client(); - let (identity, _) = signer.create_key(None)?; - - let did = super::did(&identity); + let (identity, _) = signer.create_key(None).unwrap(); + let did = DID::build(ETHR_DID_METHOD, None, identity.as_ref()); // endorse service attribute endorse_set_did_attribute(&client, &did, &service(), &validity(), &signer).await; @@ -195,23 +318,21 @@ mod did { endorse_set_did_attribute(&client, &did, &public_key(), &validity(), &signer).await; // resolve DID document - let did_doc_with_meta = did_ethr_registry::resolve_did(&client, &did, None) + let did_doc_with_meta = did_resolver::resolve_did(&client, &did, None) .await .unwrap(); let did_document = did_doc_with_meta.did_document.unwrap(); assert_eq!(1, did_document.service.len()); assert_eq!(2, did_document.verification_method.len()); - - Ok(()) } #[async_std::test] - async fn demo_did_ethr_deactivate() -> VdrResult<()> { + async fn demo_did_ethr_deactivate() { let mut signer = basic_signer(); let client = client(); - let (identity, _) = signer.create_key(None)?; + let (identity, _) = signer.create_key(None).unwrap(); - let did = super::did(&identity); + let did = DID::build(ETHR_DID_METHOD, None, identity.as_ref()); // add service attribute let service = service(); @@ -225,7 +346,7 @@ mod did { .await .unwrap(); - let signature = sign_endorsing_data(&transaction_endorsing_data, &signer); + let signature = super::helpers::sign_endorsing_data(&transaction_endorsing_data, &signer); let transaction = did_ethr_registry::build_did_change_owner_signed_transaction( &client, @@ -236,10 +357,10 @@ mod did { ) .await .unwrap(); - sign_and_submit_transaction(&client, transaction, &signer).await; + super::helpers::sign_and_submit_transaction(&client, transaction, &signer).await; // Resole DID document - let did_doc_with_meta = did_ethr_registry::resolve_did(&client, &did, None) + let did_doc_with_meta = did_resolver::resolve_did(&client, &did, None) .await .unwrap(); let did_document = did_doc_with_meta.did_document.unwrap(); @@ -254,17 +375,15 @@ mod did { assert_eq!(0, did_document.verification_method.len()); assert_eq!(0, did_document.authentication.len()); assert_eq!(0, did_document.assertion_method.len()); - - Ok(()) } #[async_std::test] - async fn demo_did_add_remove_attribute() -> VdrResult<()> { + async fn demo_did_ethr_add_remove_attribute() { let mut signer = basic_signer(); let client = client(); - let (identity, _) = signer.create_key(None)?; + let (identity, _) = signer.create_key(None).unwrap(); - let did = super::did(&identity); + let did = DID::build(ETHR_DID_METHOD, None, identity.as_ref()); // set service attribute let service = service(); @@ -280,7 +399,7 @@ mod did { endorse_set_did_attribute(&client, &did, &public_key_2, &validity, &signer).await; // resolve DID document - let did_doc_with_meta = did_ethr_registry::resolve_did(&client, &did, None) + let did_doc_with_meta = did_resolver::resolve_did(&client, &did, None) .await .unwrap(); let did_document_before_remove = did_doc_with_meta.did_document.unwrap(); @@ -295,7 +414,7 @@ mod did { endorse_revoke_did_attribute(&client, &did, &service, &signer).await; // resolve DID document - let did_doc_with_meta = did_ethr_registry::resolve_did(&client, &did, None) + let did_doc_with_meta = did_resolver::resolve_did(&client, &did, None) .await .unwrap(); let did_document_after_remove = did_doc_with_meta.did_document.unwrap(); @@ -310,7 +429,7 @@ mod did { endorse_set_did_attribute(&client, &did, &public_key_3, &validity, &signer).await; // resolve DID document - let did_doc_with_meta = did_ethr_registry::resolve_did(&client, &did, None) + let did_doc_with_meta = did_resolver::resolve_did(&client, &did, None) .await .unwrap(); let did_document_after_add = did_doc_with_meta.did_document.unwrap(); @@ -319,110 +438,103 @@ mod did { assert_eq!(1, did_document_after_add.key_agreement.len()); assert_eq!(1, did_document_after_add.authentication.len()); assert_eq!(2, did_document_after_add.assertion_method.len()); - - Ok(()) } #[async_std::test] - async fn demo_resolve_offchain_did() -> VdrResult<()> { + async fn demo_resolve_offchain_did() { + let mut signer = basic_signer(); let client = client(); + let (identity, _) = signer.create_key(None).unwrap(); - let did = DID::from(TEST_DID_ETHR); + let did = DID::build(ETHR_DID_METHOD,None, identity.as_ref()); // Resole DID document - let did_doc_with_meta = did_ethr_registry::resolve_did(&client, &did, None) + let did_doc_with_meta = did_resolver::resolve_did(&client, &did, None) .await .unwrap(); + println!("{:?}", did_doc_with_meta); let did_document = did_doc_with_meta.did_document.unwrap(); // DID Document is empty assert_eq!( - default_ethr_did_document(Some(client.chain_id())), + default_ethr_did_document(identity.as_ref(), Some(client.chain_id())), did_document ); - - Ok(()) } } mod schema { use super::*; - use crate::{schema_registry, LedgerClient, Schema, SchemaId, DID}; + use crate::{schema_registry, Schema}; pub(crate) async fn endorse_schema( client: &LedgerClient, did: &DID, signer: &BasicSigner, - ) -> (SchemaId, Schema) { - let (schema_id, schema) = schema(did, None); + ) -> Schema { + let schema = schema(did, None); let transaction_endorsing_data = - schema_registry::build_create_schema_endorsing_data(client, &schema_id, &schema) + schema_registry::build_create_schema_endorsing_data(client, &schema) .await .unwrap(); - let signature = sign_endorsing_data(&transaction_endorsing_data, signer); + let signature = super::helpers::sign_endorsing_data(&transaction_endorsing_data, signer); let transaction = schema_registry::build_create_schema_signed_transaction( client, &TRUSTEE_ACC.clone(), - &schema_id, &schema, &signature, ) .await .unwrap(); - sign_and_submit_transaction(client, transaction, signer).await; - (schema_id, schema) + super::helpers::sign_and_submit_transaction(client, transaction, signer).await; + schema } #[async_std::test] - async fn demo_create_schema() -> VdrResult<()> { + async fn demo_create_schema() { let signer = basic_signer(); let client = client(); // create DID - let did = super::did(&TRUSTEE_ACC.clone()); + let did = DID::build(ETHR_DID_METHOD, None, TRUSTEE_ACC.as_ref()); // write - let (schema_id, schema) = schema(&did, None); + let schema = schema(&did, None); let transaction = schema_registry::build_create_schema_transaction( &client, &TRUSTEE_ACC.clone(), - &schema_id, &schema, ) .await .unwrap(); - sign_and_submit_transaction(&client, transaction, &signer).await; + super::helpers::sign_and_submit_transaction(&client, transaction, &signer).await; // read - let resolved_schema = schema_registry::resolve_schema(&client, &schema_id) + let resolved_schema = schema_registry::resolve_schema(&client, &schema.id()) .await .unwrap(); assert_eq!(schema, resolved_schema); - - Ok(()) } #[async_std::test] - async fn demo_endorse_schema() -> VdrResult<()> { + async fn demo_endorse_schema() { let mut signer = basic_signer(); let client = client(); - let (identity, _) = signer.create_key(None)?; + let (identity, _) = signer.create_key(None).unwrap(); // create DID - let did = super::did(&identity); + let did = DID::build(ETHR_DID_METHOD, None, identity.as_ref()); // endorse schema - let (schema_id, schema) = endorse_schema(&client, &did, &signer).await; + let schema = endorse_schema(&client, &did, &signer).await; // read - let resolved_schema = schema_registry::resolve_schema(&client, &schema_id) + let resolved_schema = schema_registry::resolve_schema(&client, &schema.id()) .await .unwrap(); assert_eq!(schema, resolved_schema); - - Ok(()) } } @@ -431,101 +543,88 @@ mod credential_definition { use crate::{credential_definition_registry, schema_registry}; #[async_std::test] - async fn demo_create_credential_definition() -> VdrResult<()> { + async fn demo_create_credential_definition() { let signer = basic_signer(); let client = client(); // create DID - let did = super::did(&TRUSTEE_ACC.clone()); + let did = DID::build(ETHR_DID_METHOD, None, TRUSTEE_ACC.as_ref()); // create Schema - let (schema_id, schema) = schema(&did, None); - let transaction = schema_registry::build_create_schema_transaction( - &client, - &TRUSTEE_ACC, - &schema_id, - &schema, - ) - .await - .unwrap(); - sign_and_submit_transaction(&client, transaction, &signer).await; + let schema = schema(&did, None); + let transaction = + schema_registry::build_create_schema_transaction(&client, &TRUSTEE_ACC, &schema) + .await + .unwrap(); + super::helpers::sign_and_submit_transaction(&client, transaction, &signer).await; // write - let (credential_definition_id, credential_definition) = - credential_definition(&did, &schema_id, None); + let credential_definition = credential_definition(&did, &schema.id(), None); let transaction = credential_definition_registry::build_create_credential_definition_transaction( &client, &TRUSTEE_ACC, - &credential_definition_id, &credential_definition, ) .await .unwrap(); - sign_and_submit_transaction(&client, transaction, &signer).await; + super::helpers::sign_and_submit_transaction(&client, transaction, &signer).await; // read let resolved_credential_definition = credential_definition_registry::resolve_credential_definition( &client, - &credential_definition_id, + &credential_definition.id(), ) .await .unwrap(); assert_eq!(credential_definition, resolved_credential_definition); - - Ok(()) } #[async_std::test] - async fn demo_endorse_credential_definition() -> VdrResult<()> { + async fn demo_endorse_credential_definition() { let mut signer = basic_signer(); let client = client(); - let (identity, _) = signer.create_key(None)?; + let (identity, _) = signer.create_key(None).unwrap(); // create DID Document - let did = super::did(&identity); + let did = DID::build(ETHR_DID_METHOD, None, identity.as_ref()); // create Schema - let (schema_id, _) = super::schema::endorse_schema(&client, &did, &signer).await; + let schema = super::schema::endorse_schema(&client, &did, &signer).await; // write - let (credential_definition_id, credential_definition) = - credential_definition(&did, &schema_id, None); + let credential_definition = credential_definition(&did, &schema.id(), None); let transaction_endorsing_data = credential_definition_registry::build_create_credential_definition_endorsing_data( &client, - &credential_definition_id, &credential_definition, ) .await .unwrap(); - let signature = sign_endorsing_data(&transaction_endorsing_data, &signer); + let signature = super::helpers::sign_endorsing_data(&transaction_endorsing_data, &signer); let transaction = credential_definition_registry::build_create_credential_definition_signed_transaction( &client, &TRUSTEE_ACC.clone(), - &credential_definition_id, &credential_definition, &signature, ) .await .unwrap(); - sign_and_submit_transaction(&client, transaction, &signer).await; + super::helpers::sign_and_submit_transaction(&client, transaction, &signer).await; // read let resolved_credential_definition = credential_definition_registry::resolve_credential_definition( &client, - &credential_definition_id, + &credential_definition.id(), ) .await .unwrap(); assert_eq!(credential_definition, resolved_credential_definition); - - Ok(()) } } @@ -533,24 +632,7 @@ mod role { use super::*; use crate::role_control; - pub(crate) async fn build_and_submit_assign_role_transaction( - client: &LedgerClient, - assignee_account: &Address, - role_to_assign: &Role, - signer: &BasicSigner, - ) -> String { - let transaction = role_control::build_assign_role_transaction( - client, - &TRUSTEE_ACC, - role_to_assign, - assignee_account, - ) - .await - .unwrap(); - sign_and_submit_transaction(client, transaction, signer).await - } - - async fn build_and_submit_revoke_role_transaction( + async fn revoke_role( client: &LedgerClient, revokee_account: &Address, role_to_revoke: &Role, @@ -598,37 +680,23 @@ mod role { } #[async_std::test] - async fn demo_build_and_submit_assign_and_remove_role_transactions_test() -> VdrResult<()> { + async fn demo_build_and_submit_assign_and_remove_role_transactions_test() { let signer = basic_signer(); let (assignee_account, _) = signer.create_account(None).unwrap(); let client = client(); let role_to_assign = Role::Endorser; - build_and_submit_assign_role_transaction( - &client, - &assignee_account, - &role_to_assign, - &signer, - ) - .await; + super::helpers::assign_role(&client, &assignee_account, &role_to_assign, &signer).await; let assigned_role = build_and_submit_get_role_transaction(&client, &assignee_account).await; assert_eq!(role_to_assign, assigned_role); - build_and_submit_revoke_role_transaction( - &client, - &assignee_account, - &role_to_assign, - &signer, - ) - .await; + revoke_role(&client, &assignee_account, &role_to_assign, &signer).await; let has_role = build_and_submit_has_role_transaction(&client, &role_to_assign, &assignee_account) .await; assert!(!has_role); - - Ok(()) } } @@ -663,7 +731,7 @@ mod validator { ) .await .unwrap(); - sign_and_submit_transaction(client, transaction, signer).await + super::helpers::sign_and_submit_transaction(client, transaction, signer).await } async fn build_and_submit_remove_validator_transaction( @@ -679,21 +747,15 @@ mod validator { ) .await .unwrap(); - sign_and_submit_transaction(client, transaction, signer).await + super::helpers::sign_and_submit_transaction(client, transaction, signer).await } #[async_std::test] - async fn demo_build_and_submit_transaction_test() -> VdrResult<()> { + async fn demo_build_and_submit_transaction_test() { let signer = basic_signer(); let (new_validator_address, _) = signer.create_account(None).unwrap(); let client = client(); - role::build_and_submit_assign_role_transaction( - &client, - &TRUSTEE_ACC, - &Role::Steward, - &signer, - ) - .await; + super::helpers::assign_role(&client, &TRUSTEE_ACC, &Role::Steward, &signer).await; build_and_submit_add_validator_transaction(&client, &new_validator_address, &signer).await; @@ -707,7 +769,5 @@ mod validator { let validator_list = build_and_submit_get_validators_transaction(&client).await; assert_eq!(validator_list.len(), 4); assert!(!validator_list.contains(&new_validator_address)); - - Ok(()) } } diff --git a/vdr/src/types/contract.rs b/vdr/src/types/contract.rs index ff1f822b..85b87826 100644 --- a/vdr/src/types/contract.rs +++ b/vdr/src/types/contract.rs @@ -89,10 +89,10 @@ impl ContractOutput { .map(ContractOutput) } - pub fn get_string(&self, index: usize) -> VdrResult { - self.get_item(index)?.into_string().ok_or_else(|| { - VdrError::ContractInvalidResponseData("Missing string value".to_string()) - }) + pub fn get_bytes(&self, index: usize) -> VdrResult> { + self.get_item(index)? + .into_bytes() + .ok_or_else(|| VdrError::ContractInvalidResponseData("Missing bytes value".to_string())) } pub fn get_address(&self, index: usize) -> VdrResult
{ @@ -123,6 +123,14 @@ impl ContractOutput { .as_u64()) } + pub fn get_u128(&self, index: usize) -> VdrResult { + Ok(self + .get_item(index)? + .into_uint() + .ok_or_else(|| VdrError::ContractInvalidResponseData("Missing uint value".to_string()))? + .as_u128()) + } + pub fn get_address_array(&self, index: usize) -> VdrResult> { Ok(self .get_item(index)? @@ -208,18 +216,18 @@ impl From for ContractEvent { } #[derive(Debug)] -pub(crate) struct UintBytesParam(u64); +pub(crate) struct MethodUintBytesParam(u64); -impl From for UintBytesParam { +impl From for MethodUintBytesParam { fn from(value: u64) -> Self { - UintBytesParam(value) + MethodUintBytesParam(value) } } -impl TryFrom for ContractParam { +impl TryFrom<&MethodUintBytesParam> for ContractParam { type Error = VdrError; - fn try_from(value: UintBytesParam) -> Result { + fn try_from(value: &MethodUintBytesParam) -> Result { Ok(ContractParam::FixedBytes( format_bytes32(value.0.to_be_bytes().as_slice())?.to_vec(), )) @@ -227,18 +235,18 @@ impl TryFrom for ContractParam { } #[derive(Debug)] -pub(crate) struct MethodParam(&'static str); +pub(crate) struct MethodStringParam(&'static str); -impl From<&'static str> for MethodParam { +impl From<&'static str> for MethodStringParam { fn from(value: &'static str) -> Self { - MethodParam(value) + MethodStringParam(value) } } -impl TryFrom for ContractParam { +impl TryFrom<&MethodStringParam> for ContractParam { type Error = VdrError; - fn try_from(value: MethodParam) -> Result { + fn try_from(value: &MethodStringParam) -> Result { Ok(ContractParam::String(value.0.to_string())) } } diff --git a/vdr/src/types/mod.rs b/vdr/src/types/mod.rs index ff618a10..d27f412c 100644 --- a/vdr/src/types/mod.rs +++ b/vdr/src/types/mod.rs @@ -16,7 +16,7 @@ pub use transaction::{ }; pub(crate) use contract::{ - ContractEvent, ContractOutput, ContractParam, MethodParam, UintBytesParam, + ContractEvent, ContractOutput, ContractParam, MethodStringParam, MethodUintBytesParam, }; pub(crate) use event_query::{EventParser, EventQueryBuilder}; pub(crate) use transaction::{ diff --git a/vdr/src/types/signature.rs b/vdr/src/types/signature.rs index 4903c53c..f6830b0c 100644 --- a/vdr/src/types/signature.rs +++ b/vdr/src/types/signature.rs @@ -26,10 +26,10 @@ impl SignatureData { #[derive(Debug)] pub(crate) struct SignatureV(pub u64); -impl TryFrom for ContractParam { +impl TryFrom<&SignatureV> for ContractParam { type Error = VdrError; - fn try_from(value: SignatureV) -> Result { + fn try_from(value: &SignatureV) -> Result { Ok(ContractParam::Uint((value.0 + 27).into())) } } @@ -37,21 +37,21 @@ impl TryFrom for ContractParam { #[derive(Debug)] pub(crate) struct SignatureR(pub Vec); -impl TryFrom for ContractParam { +impl TryFrom<&SignatureR> for ContractParam { type Error = VdrError; - fn try_from(value: SignatureR) -> Result { - Ok(ContractParam::FixedBytes(value.0)) + fn try_from(value: &SignatureR) -> Result { + Ok(ContractParam::FixedBytes(value.0.to_vec())) } } #[derive(Debug)] pub(crate) struct SignatureS(pub Vec); -impl TryFrom for ContractParam { +impl TryFrom<&SignatureS> for ContractParam { type Error = VdrError; - fn try_from(value: SignatureS) -> Result { - Ok(ContractParam::FixedBytes(value.0)) + fn try_from(value: &SignatureS) -> Result { + Ok(ContractParam::FixedBytes(value.0.to_vec())) } } diff --git a/vdr/src/types/transaction.rs b/vdr/src/types/transaction.rs index 0d81add3..a287f4a1 100644 --- a/vdr/src/types/transaction.rs +++ b/vdr/src/types/transaction.rs @@ -14,7 +14,7 @@ use crate::{ client::{GAS_LIMIT, GAS_PRICE}, error::{VdrError, VdrResult}, types::{ - contract::UintBytesParam, signature::SignatureData, Address, ContractOutput, ContractParam, + signature::SignatureData, Address, ContractOutput, ContractParam, MethodUintBytesParam, }, LedgerClient, }; @@ -486,7 +486,7 @@ impl TryFrom<&Nonce> for ContractParam { type Error = VdrError; fn try_from(value: &Nonce) -> Result { - UintBytesParam::from(value.0).try_into() + (&MethodUintBytesParam::from(value.0)).try_into() } } diff --git a/vdr/uniffi.toml b/vdr/uniffi.toml deleted file mode 100644 index 2048895e..00000000 --- a/vdr/uniffi.toml +++ /dev/null @@ -1,2 +0,0 @@ -[bindings.kotlin] -cdylib_name = "indy_besu_vdr_uniffi" \ No newline at end of file diff --git a/vdr/uniffi/src/ffi/contracts/credential_definition_registry.rs b/vdr/uniffi/src/ffi/contracts/credential_definition_registry.rs index 6f2f5009..e7829c71 100644 --- a/vdr/uniffi/src/ffi/contracts/credential_definition_registry.rs +++ b/vdr/uniffi/src/ffi/contracts/credential_definition_registry.rs @@ -1,18 +1,16 @@ use crate::ffi::{ client::LedgerClient, error::{VdrError, VdrResult}, - event_query::{EventLog, EventQuery}, transaction::{Transaction, TransactionEndorsingData}, types::SignatureData, }; -use indy_besu_vdr::{credential_definition_registry, Address, Block, CredentialDefinitionId}; +use indy_besu_vdr::{credential_definition_registry, Address, CredentialDefinitionId}; use serde_json::json; #[uniffi::export(async_runtime = "tokio")] pub async fn build_create_credential_definition_transaction( client: &LedgerClient, from: &str, - id: &str, credential_definition: &str, ) -> VdrResult { let credential_definition = @@ -23,7 +21,6 @@ pub async fn build_create_credential_definition_transaction( credential_definition_registry::build_create_credential_definition_transaction( &client.client, &Address::from(from), - &CredentialDefinitionId::from(id), &credential_definition, ) .await?; @@ -33,7 +30,6 @@ pub async fn build_create_credential_definition_transaction( #[uniffi::export(async_runtime = "tokio")] pub async fn build_create_credential_definition_endorsing_data( client: &LedgerClient, - id: &str, credential_definition: &str, ) -> VdrResult { let credential_definition = @@ -42,7 +38,6 @@ pub async fn build_create_credential_definition_endorsing_data( })?; credential_definition_registry::build_create_credential_definition_endorsing_data( &client.client, - &CredentialDefinitionId::from(id), &credential_definition, ) .await @@ -54,7 +49,6 @@ pub async fn build_create_credential_definition_endorsing_data( pub async fn build_create_credential_definition_signed_transaction( client: &LedgerClient, from: &str, - id: &str, credential_definition: &str, signature: SignatureData, ) -> VdrResult { @@ -65,7 +59,6 @@ pub async fn build_create_credential_definition_signed_transaction( credential_definition_registry::build_create_credential_definition_signed_transaction( &client.client, &Address::from(from), - &CredentialDefinitionId::from(id), &credential_definition, &signature.into(), ) @@ -75,67 +68,37 @@ pub async fn build_create_credential_definition_signed_transaction( } #[uniffi::export(async_runtime = "tokio")] -pub async fn build_get_credential_definition_created_transaction( +pub async fn build_resolve_credential_definition_transaction( client: &LedgerClient, id: &str, ) -> VdrResult { - credential_definition_registry::build_get_credential_definition_created_transaction( - &client.client, - &CredentialDefinitionId::from(id), - ) - .await - .map(Transaction::from) - .map_err(VdrError::from) -} - -#[uniffi::export(async_runtime = "tokio")] -pub async fn build_get_credential_definition_query( - client: &LedgerClient, - id: &str, - from_block: Option, - to_block: Option, -) -> VdrResult { - credential_definition_registry::build_get_credential_definition_query( - &client.client, - &CredentialDefinitionId::from(id), - from_block.map(Block::from).as_ref(), - to_block.map(Block::from).as_ref(), - ) - .await - .map(EventQuery::from) - .map_err(VdrError::from) + let transaction = + credential_definition_registry::build_resolve_credential_definition_transaction( + &client.client, + &CredentialDefinitionId::from(id), + ) + .await?; + Ok(Transaction { transaction }) } #[uniffi::export] -pub fn parse_credential_definition_created_result( +pub fn parse_resolve_credential_definition_result( client: &LedgerClient, bytes: Vec, -) -> VdrResult { - let create = credential_definition_registry::parse_credential_definition_created_result( - &client.client, - &bytes, - )?; - Ok(create.value()) -} - -#[uniffi::export] -pub fn parse_credential_definition_created_event( - client: &LedgerClient, - log: EventLog, ) -> VdrResult { - let event = credential_definition_registry::parse_credential_definition_created_event( + let cred_def = credential_definition_registry::parse_resolve_credential_definition_result( &client.client, - &log.into(), + &bytes, )?; - Ok(json!(event).to_string()) + Ok(json!(cred_def).to_string()) } #[uniffi::export(async_runtime = "tokio")] pub async fn resolve_credential_definition(client: &LedgerClient, id: &str) -> VdrResult { - let cred_def = credential_definition_registry::resolve_credential_definition( + let schema = credential_definition_registry::resolve_credential_definition( &client.client, &CredentialDefinitionId::from(id), ) .await?; - Ok(json!(cred_def).to_string()) + Ok(json!(schema).to_string()) } diff --git a/vdr/uniffi/src/ffi/contracts/did_ethr_registry.rs b/vdr/uniffi/src/ffi/contracts/did_ethr_registry.rs index 2710bb1e..8c5bfff5 100644 --- a/vdr/uniffi/src/ffi/contracts/did_ethr_registry.rs +++ b/vdr/uniffi/src/ffi/contracts/did_ethr_registry.rs @@ -1,17 +1,17 @@ -use crate::ffi::{ - client::LedgerClient, - error::{VdrError, VdrResult}, - event_query::{EventLog, EventQuery}, - transaction::{Transaction, TransactionEndorsingData}, - types::SignatureData, +use crate::{ + ffi::{ + client::LedgerClient, + error::{VdrError, VdrResult}, + transaction::{Transaction, TransactionEndorsingData}, + types::SignatureData, + }, + EventLog, EventQuery, }; use indy_besu_vdr::{ did_ethr_registry, Address, Block, DelegateType, DidAttributeChanged as DidAttributeChanged_, DidDelegateChanged as DidDelegateChanged_, DidDocAttribute, DidEvents as DidEvents_, - DidOwnerChanged as DidOwnerChanged_, - DidResolutionOptions as DidResolutionOptions_, Validity, DID, + DidOwnerChanged as DidOwnerChanged_, Validity, DID, }; -use serde_json::json; #[uniffi::export(async_runtime = "tokio")] pub async fn build_did_change_owner_transaction( @@ -397,6 +397,12 @@ pub fn parse_did_changed_result(client: &LedgerClient, bytes: Vec) -> VdrRes Ok(block.value()) } +#[uniffi::export] +pub fn parse_did_nonce_result(client: &LedgerClient, bytes: Vec) -> VdrResult { + let block = did_ethr_registry::parse_did_nonce_result(&client.client, &bytes)?; + Ok(block.value()) +} + #[uniffi::export] pub fn parse_did_owner_result(client: &LedgerClient, bytes: Vec) -> VdrResult { let address = did_ethr_registry::parse_did_owner_result(&client.client, &bytes)?; @@ -440,21 +446,6 @@ pub fn parse_did_event_response(client: &LedgerClient, log: EventLog) -> VdrResu .map_err(VdrError::from) } -#[uniffi::export(async_runtime = "tokio")] -pub async fn resolve_did( - client: &LedgerClient, - did: &str, - options: Option, -) -> VdrResult { - let options = match options { - Some(options) => Some(DidResolutionOptions_::try_from(options)?), - None => None, - }; - let did_with_meta = - did_ethr_registry::resolve_did(&client.client, &DID::from(did), options.as_ref()).await?; - Ok(json!(did_with_meta).to_string()) -} - #[derive(uniffi::Record)] pub struct DidAttributeChanged { pub identity: String, @@ -536,20 +527,3 @@ impl From for DidEvents { } } } - -#[derive(uniffi::Record)] -pub struct DidResolutionOptions { - pub accept: Option, - pub block_tag: Option, -} - -impl TryFrom for DidResolutionOptions_ { - type Error = VdrError; - - fn try_from(value: DidResolutionOptions) -> Result { - Ok(DidResolutionOptions_ { - accept: value.accept, - block_tag: value.block_tag.map(|block_tag| Block::from(block_tag)), - }) - } -} diff --git a/vdr/uniffi/src/ffi/contracts/did_indy_registry.rs b/vdr/uniffi/src/ffi/contracts/did_indy_registry.rs new file mode 100644 index 00000000..ecfa9ff4 --- /dev/null +++ b/vdr/uniffi/src/ffi/contracts/did_indy_registry.rs @@ -0,0 +1,184 @@ +use crate::ffi::{ + client::LedgerClient, + error::{VdrError, VdrResult}, + transaction::{Transaction, TransactionEndorsingData}, + types::SignatureData, +}; +use indy_besu_vdr::{did_indy_registry, Address, DID}; +use serde_json::json; + +#[uniffi::export(async_runtime = "tokio")] +pub async fn build_create_did_transaction( + client: &LedgerClient, + from: &str, + did: &str, + did_doc: &str, +) -> VdrResult { + let did_doc = serde_json::from_str(did_doc).map_err(|err| VdrError::CommonInvalidData { + msg: format!("Unable to parse DID DDocument. Err: {:?}", err), + })?; + let transaction = did_indy_registry::build_create_did_transaction( + &client.client, + &Address::from(from), + &DID::from(did), + &did_doc, + ) + .await?; + Ok(Transaction { transaction }) +} + +#[uniffi::export(async_runtime = "tokio")] +pub async fn build_create_did_endorsing_data( + client: &LedgerClient, + did: &str, + did_doc: &str, +) -> VdrResult { + let did_doc = serde_json::from_str(did_doc).map_err(|err| VdrError::CommonInvalidData { + msg: format!("Unable to parse DID Document. Err: {:?}", err), + })?; + did_indy_registry::build_create_did_endorsing_data(&client.client, &DID::from(did), &did_doc) + .await + .map(TransactionEndorsingData::from) + .map_err(VdrError::from) +} + +#[uniffi::export(async_runtime = "tokio")] +pub async fn build_create_did_signed_transaction( + client: &LedgerClient, + from: &str, + did: &str, + did_doc: &str, + signature: SignatureData, +) -> VdrResult { + let did_doc = serde_json::from_str(did_doc).map_err(|err| VdrError::CommonInvalidData { + msg: format!("Unable to parse DID Document. Err: {:?}", err), + })?; + did_indy_registry::build_create_did_signed_transaction( + &client.client, + &Address::from(from), + &DID::from(did), + &did_doc, + &signature.into(), + ) + .await + .map(Transaction::from) + .map_err(VdrError::from) +} + +#[uniffi::export(async_runtime = "tokio")] +pub async fn build_update_did_transaction( + client: &LedgerClient, + from: &str, + did: &str, + did_doc: &str, +) -> VdrResult { + let did_doc = serde_json::from_str(did_doc).map_err(|err| VdrError::CommonInvalidData { + msg: format!("Unable to parse DID DDocument. Err: {:?}", err), + })?; + let transaction = did_indy_registry::build_update_did_transaction( + &client.client, + &Address::from(from), + &DID::from(did), + &did_doc, + ) + .await?; + Ok(Transaction { transaction }) +} + +#[uniffi::export(async_runtime = "tokio")] +pub async fn build_update_did_endorsing_data( + client: &LedgerClient, + did: &str, + did_doc: &str, +) -> VdrResult { + let did_doc = serde_json::from_str(did_doc).map_err(|err| VdrError::CommonInvalidData { + msg: format!("Unable to parse DID Document. Err: {:?}", err), + })?; + did_indy_registry::build_update_did_endorsing_data(&client.client, &DID::from(did), &did_doc) + .await + .map(TransactionEndorsingData::from) + .map_err(VdrError::from) +} + +#[uniffi::export(async_runtime = "tokio")] +pub async fn build_update_did_signed_transaction( + client: &LedgerClient, + from: &str, + did: &str, + did_doc: &str, + signature: SignatureData, +) -> VdrResult { + let did_doc = serde_json::from_str(did_doc).map_err(|err| VdrError::CommonInvalidData { + msg: format!("Unable to parse DID Document. Err: {:?}", err), + })?; + did_indy_registry::build_update_did_signed_transaction( + &client.client, + &Address::from(from), + &DID::from(did), + &did_doc, + &signature.into(), + ) + .await + .map(Transaction::from) + .map_err(VdrError::from) +} + +#[uniffi::export(async_runtime = "tokio")] +pub async fn build_deactivate_did_transaction( + client: &LedgerClient, + from: &str, + did: &str, +) -> VdrResult { + let transaction = did_indy_registry::build_deactivate_did_transaction( + &client.client, + &Address::from(from), + &DID::from(did), + ) + .await?; + Ok(Transaction { transaction }) +} + +#[uniffi::export(async_runtime = "tokio")] +pub async fn build_deactivate_did_endorsing_data( + client: &LedgerClient, + did: &str, +) -> VdrResult { + did_indy_registry::build_deactivate_did_endorsing_data(&client.client, &DID::from(did)) + .await + .map(TransactionEndorsingData::from) + .map_err(VdrError::from) +} + +#[uniffi::export(async_runtime = "tokio")] +pub async fn build_deactivate_did_signed_transaction( + client: &LedgerClient, + from: &str, + did: &str, + signature: SignatureData, +) -> VdrResult { + did_indy_registry::build_deactivate_did_signed_transaction( + &client.client, + &Address::from(from), + &DID::from(did), + &signature.into(), + ) + .await + .map(Transaction::from) + .map_err(VdrError::from) +} + +#[uniffi::export(async_runtime = "tokio")] +pub async fn build_resolve_did_transaction( + client: &LedgerClient, + did: &str, +) -> VdrResult { + let transaction = + did_indy_registry::build_resolve_did_transaction(&client.client, &DID::from(did)).await?; + Ok(Transaction { transaction }) +} + +#[uniffi::export] +pub fn parse_resolve_did_result(client: &LedgerClient, bytes: Vec) -> VdrResult { + let did_record = did_indy_registry::parse_resolve_did_result(&client.client, &bytes)?; + Ok(json!(did_record).to_string()) +} diff --git a/vdr/uniffi/src/ffi/contracts/did_resolver.rs b/vdr/uniffi/src/ffi/contracts/did_resolver.rs new file mode 100644 index 00000000..e56d95f8 --- /dev/null +++ b/vdr/uniffi/src/ffi/contracts/did_resolver.rs @@ -0,0 +1,36 @@ +use crate::{LedgerClient, VdrError, VdrResult}; +use serde_json::json; + +use indy_besu_vdr::{did_resolver, Block, DidResolutionOptions as DidResolutionOptions_, DID}; + +#[uniffi::export(async_runtime = "tokio")] +pub async fn resolve_did( + client: &LedgerClient, + did: &str, + options: Option, +) -> VdrResult { + let options = match options { + Some(options) => Some(DidResolutionOptions_::try_from(options)?), + None => None, + }; + let did_with_meta = + did_resolver::resolve_did(&client.client, &DID::from(did), options.as_ref()).await?; + Ok(json!(did_with_meta).to_string()) +} + +#[derive(uniffi::Record)] +pub struct DidResolutionOptions { + pub accept: Option, + pub block_tag: Option, +} + +impl TryFrom for DidResolutionOptions_ { + type Error = VdrError; + + fn try_from(value: DidResolutionOptions) -> Result { + Ok(DidResolutionOptions_ { + accept: value.accept, + block_tag: value.block_tag.map(|block_tag| Block::from(block_tag)), + }) + } +} diff --git a/vdr/uniffi/src/ffi/contracts/mod.rs b/vdr/uniffi/src/ffi/contracts/mod.rs index f7e7e433..a3f01d23 100644 --- a/vdr/uniffi/src/ffi/contracts/mod.rs +++ b/vdr/uniffi/src/ffi/contracts/mod.rs @@ -1,5 +1,7 @@ pub mod credential_definition_registry; pub mod did_ethr_registry; +pub mod did_indy_registry; +pub mod did_resolver; pub mod role_control; pub mod schema_registry; pub mod validator_control; diff --git a/vdr/uniffi/src/ffi/contracts/schema_registry.rs b/vdr/uniffi/src/ffi/contracts/schema_registry.rs index 16f7befd..c479611f 100644 --- a/vdr/uniffi/src/ffi/contracts/schema_registry.rs +++ b/vdr/uniffi/src/ffi/contracts/schema_registry.rs @@ -1,18 +1,16 @@ use crate::ffi::{ client::LedgerClient, error::{VdrError, VdrResult}, - event_query::{EventLog, EventQuery}, transaction::{Transaction, TransactionEndorsingData}, types::SignatureData, }; -use indy_besu_vdr::{schema_registry, Address, Block, SchemaId}; +use indy_besu_vdr::{schema_registry, Address, SchemaId}; use serde_json::json; #[uniffi::export(async_runtime = "tokio")] pub async fn build_create_schema_transaction( client: &LedgerClient, from: &str, - id: &str, schema: &str, ) -> VdrResult { let schema = serde_json::from_str(schema).map_err(|err| VdrError::CommonInvalidData { @@ -21,7 +19,6 @@ pub async fn build_create_schema_transaction( let transaction = schema_registry::build_create_schema_transaction( &client.client, &Address::from(from), - &SchemaId::from(id), &schema, ) .await?; @@ -31,27 +28,21 @@ pub async fn build_create_schema_transaction( #[uniffi::export(async_runtime = "tokio")] pub async fn build_create_schema_endorsing_data( client: &LedgerClient, - id: &str, schema: &str, ) -> VdrResult { let schema = serde_json::from_str(schema).map_err(|err| VdrError::CommonInvalidData { msg: format!("Unable to parse credential definition. Err: {:?}", err), })?; - schema_registry::build_create_schema_endorsing_data( - &client.client, - &SchemaId::from(id), - &schema, - ) - .await - .map(TransactionEndorsingData::from) - .map_err(VdrError::from) + schema_registry::build_create_schema_endorsing_data(&client.client, &schema) + .await + .map(TransactionEndorsingData::from) + .map_err(VdrError::from) } #[uniffi::export(async_runtime = "tokio")] pub async fn build_create_schema_signed_transaction( client: &LedgerClient, from: &str, - id: &str, schema: &str, signature: SignatureData, ) -> VdrResult { @@ -61,7 +52,6 @@ pub async fn build_create_schema_signed_transaction( schema_registry::build_create_schema_signed_transaction( &client.client, &Address::from(from), - &SchemaId::from(id), &schema, &signature.into(), ) @@ -71,44 +61,20 @@ pub async fn build_create_schema_signed_transaction( } #[uniffi::export(async_runtime = "tokio")] -pub async fn build_get_schema_created_transaction( +pub async fn build_resolve_schema_transaction( client: &LedgerClient, id: &str, ) -> VdrResult { - schema_registry::build_get_schema_created_transaction(&client.client, &SchemaId::from(id)) - .await - .map(Transaction::from) - .map_err(VdrError::from) -} - -#[uniffi::export(async_runtime = "tokio")] -pub async fn build_get_schema_query( - client: &LedgerClient, - id: &str, - from_block: Option, - to_block: Option, -) -> VdrResult { - schema_registry::build_get_schema_query( - &client.client, - &SchemaId::from(id), - from_block.map(Block::from).as_ref(), - to_block.map(Block::from).as_ref(), - ) - .await - .map(EventQuery::from) - .map_err(VdrError::from) -} - -#[uniffi::export] -pub fn parse_schema_created_result(client: &LedgerClient, bytes: Vec) -> VdrResult { - let create = schema_registry::parse_schema_created_result(&client.client, &bytes)?; - Ok(create.value()) + let transaction = + schema_registry::build_resolve_schema_transaction(&client.client, &SchemaId::from(id)) + .await?; + Ok(Transaction { transaction }) } #[uniffi::export] -pub fn parse_schema_created_event(client: &LedgerClient, log: EventLog) -> VdrResult { - let event = schema_registry::parse_schema_created_event(&client.client, &log.into())?; - Ok(json!(event).to_string()) +pub fn parse_resolve_schema_result(client: &LedgerClient, bytes: Vec) -> VdrResult { + let schema = schema_registry::parse_resolve_schema_result(&client.client, &bytes)?; + Ok(json!(schema).to_string()) } #[uniffi::export(async_runtime = "tokio")] diff --git a/vdr/uniffi/src/mod.rs b/vdr/uniffi/src/mod.rs deleted file mode 100644 index e69de29b..00000000 diff --git a/vdr/wasm/demo/node/src/main.ts b/vdr/wasm/demo/node/src/main.ts index 993598dd..e46a0427 100644 --- a/vdr/wasm/demo/node/src/main.ts +++ b/vdr/wasm/demo/node/src/main.ts @@ -1,7 +1,7 @@ import fs from "fs"; import secp256k1 from "secp256k1"; -import { LedgerClient, EthrDidRegistry, SchemaRegistry } from "indy-besu-vdr"; +import { LedgerClient, EthrDidRegistry, DidResolver, SchemaRegistry } from "indy-besu-vdr"; const chainId = 1337 const nodeAddress = 'http://127.0.0.1:8545' @@ -52,9 +52,10 @@ async function demo() { console.log('2. Publish and Modify DID') const did = 'did:ethr:' + identity.address const serviceAttribute = {"serviceEndpoint":"http://10.0.0.2","type":"TestService"} - let endorsingData = await EthrDidRegistry.buildDidSetAttributeEndorsingData(client, did, serviceAttribute, BigInt(100000)) + const validity = BigInt(1000) + let endorsingData = await EthrDidRegistry.buildDidSetAttributeEndorsingData(client, did, serviceAttribute, validity) let authorSignature = sign(endorsingData.getSigningBytes(), identity.secret) - let transaction = await EthrDidRegistry.buildDidSetAttributeSignedTransaction(client, trustee.address, did, serviceAttribute, BigInt(100000), authorSignature) + let transaction = await EthrDidRegistry.buildDidSetAttributeSignedTransaction(client, trustee.address, did, serviceAttribute, validity, authorSignature) let transactionSignature = sign(transaction.getSigningBytes(), trustee.secret) transaction.setSignature(transactionSignature) let txnHash = await client.submitTransaction(transaction) @@ -62,21 +63,21 @@ async function demo() { console.log('Transaction receipt: ' + receipt) console.log('3. Resolve DID Document') - const didWithMeta = await EthrDidRegistry.resolveDid(client, did, null) + const didWithMeta = await DidResolver.resolveDid(client, did, null) console.log('Resolved DID Document: ' + JSON.stringify(didWithMeta, null, 2)) console.log('4. Publish Schema') const name = (Math.random() + 1).toString(36).substring(7) - const schemaId = `did:ethr:test:${identity.address}/anoncreds/v0/SCHEMA/${name}/1.0.0` + const schemaId = `${did}/anoncreds/v0/SCHEMA/${name}/1.0.0` const schema = { "attrNames": [ "First Name", "Last Name" ], - "issuerId": `did:ethr:test:${identity.address}`, + "issuerId": did, "name": name, "version": "1.0.0" } - let schemaEndorsingData = await SchemaRegistry.buildCreateSchemaEndorsingData(client, schemaId, schema) + let schemaEndorsingData = await SchemaRegistry.buildCreateSchemaEndorsingData(client, schema) authorSignature = sign(schemaEndorsingData.getSigningBytes(), identity.secret) - transaction = await SchemaRegistry.buildCreateSchemaSignedTransaction(client, trustee.address, schemaId, schema, authorSignature) + transaction = await SchemaRegistry.buildCreateSchemaSignedTransaction(client, trustee.address, schema, authorSignature) transactionSignature = sign(transaction.getSigningBytes(), trustee.secret) transaction.setSignature(transactionSignature) txnHash = await client.submitTransaction(transaction) diff --git a/vdr/wasm/src/contracts/credential_definition_registry.rs b/vdr/wasm/src/contracts/credential_definition_registry.rs index d1bca190..ef6de449 100644 --- a/vdr/wasm/src/contracts/credential_definition_registry.rs +++ b/vdr/wasm/src/contracts/credential_definition_registry.rs @@ -1,6 +1,6 @@ use indy_besu_vdr::{ - credential_definition_registry, Address, Block, CredentialDefinition, CredentialDefinitionId, - EventLog, SignatureData, + credential_definition_registry, Address, CredentialDefinition, CredentialDefinitionId, + SignatureData, }; use std::rc::Rc; use wasm_bindgen::prelude::*; @@ -8,7 +8,6 @@ use wasm_bindgen::prelude::*; use crate::{ client::LedgerClientWrapper, error::{JsResult, Result}, - event_query::EventQueryWrapper, transaction::{TransactionEndorsingDataWrapper, TransactionWrapper}, }; @@ -21,33 +20,29 @@ impl CredentialDefinitionRegistry { pub async fn build_create_credential_definition_transaction( client: &LedgerClientWrapper, from: &str, - id: &str, cred_def: JsValue, ) -> Result { let client = client.0.clone(); let cred_def: CredentialDefinition = serde_wasm_bindgen::from_value(cred_def)?; let address = Address::from(from); - let id = CredentialDefinitionId::from(id); let transaction = credential_definition_registry::build_create_credential_definition_transaction( - &client, &address, &id, &cred_def, + &client, &address, &cred_def, ) .await .as_js()?; Ok(TransactionWrapper(Rc::new(transaction))) } - #[wasm_bindgen(js_name = buildCreateSchemaEndorsingData)] - pub async fn build_create_schema_endorsing_data( + #[wasm_bindgen(js_name = buildCreateCredentialDefinitionEndorsingData)] + pub async fn build_create_credential_definition_endorsing_data( client: &LedgerClientWrapper, - id: &str, cred_def: JsValue, ) -> Result { let cred_def: CredentialDefinition = serde_wasm_bindgen::from_value(cred_def)?; - let id = CredentialDefinitionId::from(id); let data = credential_definition_registry::build_create_credential_definition_endorsing_data( - &client.0, &id, &cred_def, + &client.0, &cred_def, ) .await .as_js()?; @@ -58,20 +53,17 @@ impl CredentialDefinitionRegistry { pub async fn build_create_credential_definition_signed_transaction( client: &LedgerClientWrapper, from: &str, - id: &str, cred_def: JsValue, signature_data: JsValue, ) -> Result { let client = client.0.clone(); let cred_def: CredentialDefinition = serde_wasm_bindgen::from_value(cred_def)?; let address = Address::from(from); - let id = CredentialDefinitionId::from(id); let signature_data: SignatureData = serde_wasm_bindgen::from_value(signature_data)?; let transaction = credential_definition_registry::build_create_credential_definition_signed_transaction( &client, &address, - &id, &cred_def, &signature_data, ) @@ -80,14 +72,14 @@ impl CredentialDefinitionRegistry { Ok(TransactionWrapper(Rc::new(transaction))) } - #[wasm_bindgen(js_name = buildGetCredentialDefinitionCreatedTransaction)] - pub async fn build_get_credential_definition_created_transaction( + #[wasm_bindgen(js_name = buildResolveCredentialDefinitionTransaction)] + pub async fn build_resolve_credential_definition_transaction( client: &LedgerClientWrapper, id: &str, ) -> Result { let id = CredentialDefinitionId::from(id); let transaction = - credential_definition_registry::build_get_credential_definition_created_transaction( + credential_definition_registry::build_resolve_credential_definition_transaction( &client.0, &id, ) .await @@ -95,50 +87,16 @@ impl CredentialDefinitionRegistry { Ok(TransactionWrapper(Rc::new(transaction))) } - #[wasm_bindgen(js_name = buildGetCredentialDefinitionQuery)] - pub async fn build_get_credential_definition_query( - client: &LedgerClientWrapper, - id: &str, - from_block: Option, - to_block: Option, - ) -> Result { - let id = CredentialDefinitionId::from(id); - let from_block = from_block.map(Block::from); - let to_block = to_block.map(Block::from); - let query = credential_definition_registry::build_get_credential_definition_query( - &client.0, - &id, - from_block.as_ref(), - to_block.as_ref(), - ) - .await - .as_js()?; - Ok(EventQueryWrapper(Rc::new(query))) - } - - #[wasm_bindgen(js_name = parseCredentialDefinitionCreatedResult)] - pub fn parse_credential_definition_created_result( + #[wasm_bindgen(js_name = parseResolveCredentialDefinitionResult)] + pub fn parse_resolve_credential_definition_result( client: &LedgerClientWrapper, bytes: Vec, - ) -> Result { - let block = credential_definition_registry::parse_credential_definition_created_result( - &client.0, &bytes, - ) - .as_js()?; - Ok(block.value()) - } - - #[wasm_bindgen(js_name = parseCredentialDefinitionCreatedEvent)] - pub fn parse_credential_definition_created_event( - client: &LedgerClientWrapper, - log: JsValue, ) -> Result { - let log: EventLog = serde_wasm_bindgen::from_value(log)?; - let event = credential_definition_registry::parse_credential_definition_created_event( - &client.0, &log, + let cred_def = credential_definition_registry::parse_resolve_credential_definition_result( + &client.0, &bytes, ) .as_js()?; - let result: JsValue = serde_wasm_bindgen::to_value(&event)?; + let result: JsValue = serde_wasm_bindgen::to_value(&cred_def)?; Ok(result) } diff --git a/vdr/wasm/src/contracts/did_ethr_registry.rs b/vdr/wasm/src/contracts/did_ethr_registry.rs index 5eef7241..4e72a8c3 100644 --- a/vdr/wasm/src/contracts/did_ethr_registry.rs +++ b/vdr/wasm/src/contracts/did_ethr_registry.rs @@ -1,6 +1,6 @@ use indy_besu_vdr::{ - did_ethr_registry, Address, Block, DelegateType, DidDocAttribute, DidResolutionOptions, - EventLog, SignatureData, Validity, DID, + did_ethr_registry, Address, Block, DelegateType, DidDocAttribute, EventLog, SignatureData, + Validity, DID, }; use std::rc::Rc; use wasm_bindgen::prelude::*; @@ -475,19 +475,4 @@ impl EthrDidRegistry { let result: JsValue = serde_wasm_bindgen::to_value(&event)?; Ok(result) } - - #[wasm_bindgen(js_name = resolveDid)] - pub async fn resolve_did( - client: &LedgerClientWrapper, - did: &str, - options: JsValue, - ) -> Result { - let did = DID::from(did); - let options: Option = serde_wasm_bindgen::from_value(options).ok(); - let did_with_meta = did_ethr_registry::resolve_did(&client.0, &did, options.as_ref()) - .await - .as_js()?; - let result: JsValue = serde_wasm_bindgen::to_value(&did_with_meta)?; - Ok(result) - } } diff --git a/vdr/wasm/src/contracts/did_indy_registry.rs b/vdr/wasm/src/contracts/did_indy_registry.rs new file mode 100644 index 00000000..69f6a279 --- /dev/null +++ b/vdr/wasm/src/contracts/did_indy_registry.rs @@ -0,0 +1,195 @@ +use indy_besu_vdr::{did_indy_registry, Address, DidDocument, SignatureData, DID}; +use std::rc::Rc; +use wasm_bindgen::prelude::*; + +use crate::{ + client::LedgerClientWrapper, + error::{JsResult, Result}, + transaction::{TransactionEndorsingDataWrapper, TransactionWrapper}, +}; + +#[wasm_bindgen(js_name = IndyDidRegistry)] +pub struct IndyDidRegistry; + +#[wasm_bindgen(js_class = IndyDidRegistry)] +impl IndyDidRegistry { + #[wasm_bindgen(js_name = buildCreateDidTransaction)] + pub async fn build_create_did_transaction( + client: &LedgerClientWrapper, + from: &str, + did: &str, + did_doc: JsValue, + ) -> Result { + let did_doc: DidDocument = serde_wasm_bindgen::from_value(did_doc)?; + let address = Address::from(from); + let did = DID::from(did); + let transaction = + did_indy_registry::build_create_did_transaction(&client.0, &address, &did, &did_doc) + .await + .as_js()?; + Ok(TransactionWrapper(Rc::new(transaction))) + } + + #[wasm_bindgen(js_name = buildCreateDidEndorsingData)] + pub async fn build_create_did_endorsing_data( + client: &LedgerClientWrapper, + did: &str, + did_doc: JsValue, + ) -> Result { + let did_doc: DidDocument = serde_wasm_bindgen::from_value(did_doc)?; + let did = DID::from(did); + let data = did_indy_registry::build_create_did_endorsing_data(&client.0, &did, &did_doc) + .await + .as_js()?; + Ok(TransactionEndorsingDataWrapper(Rc::new(data))) + } + + #[wasm_bindgen(js_name = buildCreateDidSignedTransaction)] + pub async fn build_create_did_signed_transaction( + client: &LedgerClientWrapper, + from: &str, + did: &str, + did_doc: JsValue, + signature_data: JsValue, + ) -> Result { + let from = Address::from(from); + let did_doc: DidDocument = serde_wasm_bindgen::from_value(did_doc)?; + let did = DID::from(did); + let signature_data: SignatureData = serde_wasm_bindgen::from_value(signature_data)?; + let transaction = did_indy_registry::build_create_did_signed_transaction( + &client.0, + &from, + &did, + &did_doc, + &signature_data, + ) + .await + .as_js()?; + Ok(TransactionWrapper(Rc::new(transaction))) + } + + #[wasm_bindgen(js_name = buildUpdateDidTransaction)] + pub async fn build_update_did_transaction( + client: &LedgerClientWrapper, + from: &str, + did: &str, + did_doc: JsValue, + ) -> Result { + let from = Address::from(from); + let did = DID::from(did); + let did_doc: DidDocument = serde_wasm_bindgen::from_value(did_doc)?; + let transaction = + did_indy_registry::build_update_did_transaction(&client.0, &from, &did, &did_doc) + .await + .as_js()?; + Ok(TransactionWrapper(Rc::new(transaction))) + } + + #[wasm_bindgen(js_name = buildUpdateDidEndorsingData)] + pub async fn build_update_did_endorsing_data( + client: &LedgerClientWrapper, + did: &str, + did_doc: JsValue, + ) -> Result { + let did_doc: DidDocument = serde_wasm_bindgen::from_value(did_doc)?; + let did = DID::from(did); + let data = did_indy_registry::build_update_did_endorsing_data(&client.0, &did, &did_doc) + .await + .as_js()?; + Ok(TransactionEndorsingDataWrapper(Rc::new(data))) + } + + #[wasm_bindgen(js_name = buildUpdateDidSignedTransaction)] + pub async fn build_update_did_signed_transaction( + client: &LedgerClientWrapper, + from: &str, + did: &str, + did_doc: JsValue, + signature_data: JsValue, + ) -> Result { + let from = Address::from(from); + let did_doc: DidDocument = serde_wasm_bindgen::from_value(did_doc)?; + let did = DID::from(did); + let signature_data: SignatureData = serde_wasm_bindgen::from_value(signature_data)?; + let transaction = did_indy_registry::build_update_did_signed_transaction( + &client.0, + &from, + &did, + &did_doc, + &signature_data, + ) + .await + .as_js()?; + Ok(TransactionWrapper(Rc::new(transaction))) + } + + #[wasm_bindgen(js_name = buildDeactivateDidTransaction)] + pub async fn build_deactivate_did_transaction( + client: &LedgerClientWrapper, + from: &str, + did: &str, + ) -> Result { + let address = Address::from(from); + let did = DID::from(did); + let transaction = + did_indy_registry::build_deactivate_did_transaction(&client.0, &address, &did) + .await + .as_js()?; + Ok(TransactionWrapper(Rc::new(transaction))) + } + + #[wasm_bindgen(js_name = buildDeactivateDidEndorsingData)] + pub async fn build_deactivate_did_endorsing_data( + client: &LedgerClientWrapper, + did: &str, + ) -> Result { + let did = DID::from(did); + let data = did_indy_registry::build_deactivate_did_endorsing_data(&client.0, &did) + .await + .as_js()?; + Ok(TransactionEndorsingDataWrapper(Rc::new(data))) + } + + #[wasm_bindgen(js_name = buildDeactivateDidSignedTransaction)] + pub async fn build_deactivate_did_signed_transaction( + client: &LedgerClientWrapper, + from: &str, + did: &str, + signature_data: JsValue, + ) -> Result { + let from = Address::from(from); + let did = DID::from(did); + let signature_data: SignatureData = serde_wasm_bindgen::from_value(signature_data)?; + let transaction = did_indy_registry::build_deactivate_did_signed_transaction( + &client.0, + &from, + &did, + &signature_data, + ) + .await + .as_js()?; + Ok(TransactionWrapper(Rc::new(transaction))) + } + + #[wasm_bindgen(js_name = buildResolveDidTransaction)] + pub async fn build_resolve_did_transaction( + client: &LedgerClientWrapper, + did: &str, + ) -> Result { + let did = DID::from(did); + let transaction = did_indy_registry::build_resolve_did_transaction(&client.0, &did) + .await + .as_js()?; + Ok(TransactionWrapper(Rc::new(transaction))) + } + + #[wasm_bindgen(js_name = parseResolveDidResult)] + pub fn parse_resolve_did_result( + client: &LedgerClientWrapper, + bytes: Vec, + ) -> Result { + let did_doc = did_indy_registry::parse_resolve_did_result(&client.0, &bytes).as_js()?; + let result: JsValue = serde_wasm_bindgen::to_value(&did_doc)?; + Ok(result) + } +} diff --git a/vdr/wasm/src/contracts/did_resolver.rs b/vdr/wasm/src/contracts/did_resolver.rs new file mode 100644 index 00000000..ce5c4dc6 --- /dev/null +++ b/vdr/wasm/src/contracts/did_resolver.rs @@ -0,0 +1,28 @@ +use indy_besu_vdr::{did_resolver, Address, DidDocument, DID, DidResolutionOptions}; +use wasm_bindgen::prelude::*; + +use crate::{ + client::LedgerClientWrapper, + error::{JsResult, Result}, +}; + +#[wasm_bindgen(js_name = DidResolver)] +pub struct DidResolver; + +#[wasm_bindgen(js_class = DidResolver)] +impl DidResolver { + #[wasm_bindgen(js_name = resolveDid)] + pub async fn resolve_did( + client: &LedgerClientWrapper, + did: &str, + options: JsValue, + ) -> Result { + let did = DID::from(did); + let options: Option = serde_wasm_bindgen::from_value(options).ok(); + let did_with_meta = did_resolver::resolve_did(&client.0, &did, options.as_ref()) + .await + .as_js()?; + let result: JsValue = serde_wasm_bindgen::to_value(&did_with_meta)?; + Ok(result) + } +} diff --git a/vdr/wasm/src/contracts/mod.rs b/vdr/wasm/src/contracts/mod.rs index f7e7e433..a3f01d23 100644 --- a/vdr/wasm/src/contracts/mod.rs +++ b/vdr/wasm/src/contracts/mod.rs @@ -1,5 +1,7 @@ pub mod credential_definition_registry; pub mod did_ethr_registry; +pub mod did_indy_registry; +pub mod did_resolver; pub mod role_control; pub mod schema_registry; pub mod validator_control; diff --git a/vdr/wasm/src/contracts/schema_registry.rs b/vdr/wasm/src/contracts/schema_registry.rs index e103ffaa..c010e3a7 100644 --- a/vdr/wasm/src/contracts/schema_registry.rs +++ b/vdr/wasm/src/contracts/schema_registry.rs @@ -1,11 +1,10 @@ -use indy_besu_vdr::{schema_registry, Address, Block, EventLog, Schema, SchemaId, SignatureData}; +use indy_besu_vdr::{schema_registry, Address, Schema, SchemaId, SignatureData}; use std::rc::Rc; use wasm_bindgen::prelude::*; use crate::{ client::LedgerClientWrapper, error::{JsResult, Result}, - event_query::EventQueryWrapper, transaction::{TransactionEndorsingDataWrapper, TransactionWrapper}, }; @@ -18,14 +17,12 @@ impl SchemaRegistry { pub async fn build_create_schema_transaction( client: &LedgerClientWrapper, from: &str, - id: &str, schema: JsValue, ) -> Result { let schema: Schema = serde_wasm_bindgen::from_value(schema)?; let address = Address::from(from); - let id = SchemaId::from(id); let transaction = - schema_registry::build_create_schema_transaction(&client.0, &address, &id, &schema) + schema_registry::build_create_schema_transaction(&client.0, &address, &schema) .await .as_js()?; Ok(TransactionWrapper(Rc::new(transaction))) @@ -34,12 +31,10 @@ impl SchemaRegistry { #[wasm_bindgen(js_name = buildCreateSchemaEndorsingData)] pub async fn build_create_schema_endorsing_data( client: &LedgerClientWrapper, - id: &str, schema: JsValue, ) -> Result { let schema: Schema = serde_wasm_bindgen::from_value(schema)?; - let id = SchemaId::from(id); - let data = schema_registry::build_create_schema_endorsing_data(&client.0, &id, &schema) + let data = schema_registry::build_create_schema_endorsing_data(&client.0, &schema) .await .as_js()?; Ok(TransactionEndorsingDataWrapper(Rc::new(data))) @@ -49,18 +44,15 @@ impl SchemaRegistry { pub async fn build_create_schema_signed_transaction( client: &LedgerClientWrapper, from: &str, - id: &str, schema: JsValue, signature_data: JsValue, ) -> Result { let schema: Schema = serde_wasm_bindgen::from_value(schema)?; let address = Address::from(from); - let id = SchemaId::from(id); let signature_data: SignatureData = serde_wasm_bindgen::from_value(signature_data)?; let transaction = schema_registry::build_create_schema_signed_transaction( &client.0, &address, - &id, &schema, &signature_data, ) @@ -69,56 +61,25 @@ impl SchemaRegistry { Ok(TransactionWrapper(Rc::new(transaction))) } - #[wasm_bindgen(js_name = buildGetSchemaCreatedTransaction)] - pub async fn build_get_schema_created_transaction( + #[wasm_bindgen(js_name = buildResolveSchemaTransaction)] + pub async fn build_resolve_schema_transaction( client: &LedgerClientWrapper, id: &str, ) -> Result { let id = SchemaId::from(id); - let transaction = schema_registry::build_get_schema_created_transaction(&client.0, &id) + let transaction = schema_registry::build_resolve_schema_transaction(&client.0, &id) .await .as_js()?; Ok(TransactionWrapper(Rc::new(transaction))) } - #[wasm_bindgen(js_name = buildGetSchemaQuery)] - pub async fn build_get_schema_query( - client: &LedgerClientWrapper, - id: &str, - from_block: Option, - to_block: Option, - ) -> Result { - let id = SchemaId::from(id); - let from_block = from_block.map(Block::from); - let to_block = to_block.map(Block::from); - let query = schema_registry::build_get_schema_query( - &client.0, - &id, - from_block.as_ref(), - to_block.as_ref(), - ) - .await - .as_js()?; - Ok(EventQueryWrapper(Rc::new(query))) - } - - #[wasm_bindgen(js_name = parseSchemaCreatedResult)] - pub fn parse_schema_created_result( + #[wasm_bindgen(js_name = parseResolveSchemaResult)] + pub fn parse_resolve_schema_result( client: &LedgerClientWrapper, bytes: Vec, - ) -> Result { - let block = schema_registry::parse_schema_created_result(&client.0, &bytes).as_js()?; - Ok(block.value()) - } - - #[wasm_bindgen(js_name = parseSchemaCreatedEvent)] - pub fn parse_schema_created_event( - client: &LedgerClientWrapper, - log: JsValue, ) -> Result { - let log: EventLog = serde_wasm_bindgen::from_value(log)?; - let event = schema_registry::parse_schema_created_event(&client.0, &log).as_js()?; - let result: JsValue = serde_wasm_bindgen::to_value(&event)?; + let schema = schema_registry::parse_resolve_schema_result(&client.0, &bytes).as_js()?; + let result: JsValue = serde_wasm_bindgen::to_value(&schema)?; Ok(result) } diff --git a/vdr/wrappers/python/demo/test.py b/vdr/wrappers/python/demo/test.py index d41a0abd..34b40663 100644 --- a/vdr/wrappers/python/demo/test.py +++ b/vdr/wrappers/python/demo/test.py @@ -65,16 +65,17 @@ async def demo(): print("4. Publish Schema") name = ''.join(secrets.choice(string.ascii_uppercase + string.digits) for _ in range(6)) - schema_id = 'did:ethr:test:' + identity["address"] + '/anoncreds/v0/SCHEMA/' + name + '/1.0.0' + schema_id = did + '/anoncreds/v0/SCHEMA/' + name + '/1.0.0' schema = { "attrNames": ["First Name", "Last Name"], - "issuerId": 'did:ethr:test:' + identity["address"], + "issuerId": did, "name": name, "version": "1.0.0" } - endorsing_data = await build_create_schema_endorsing_data(client, schema_id, json.dumps(schema)) + endorsing_data = await build_create_schema_endorsing_data(client, json.dumps(schema)) identity_signature = sign(identity["secret"], endorsing_data.get_signing_bytes()) - transaction = await build_create_schema_signed_transaction(client, trustee["address"], schema_id, + transaction = await build_create_schema_signed_transaction(client, + trustee["address"], json.dumps(schema), identity_signature) trustee_signature = sign(trustee["secret"], transaction.get_signing_bytes()) diff --git a/vdr/wrappers/python/indy_besu_vdr/__init__.py b/vdr/wrappers/python/indy_besu_vdr/__init__.py index 5c18d229..a2213b3a 100644 --- a/vdr/wrappers/python/indy_besu_vdr/__init__.py +++ b/vdr/wrappers/python/indy_besu_vdr/__init__.py @@ -24,15 +24,19 @@ build_add_validator_transaction, build_assign_role_transaction, build_create_credential_definition_transaction, + build_create_did_transaction, + build_create_did_endorsing_data, + build_create_did_signed_transaction, + build_create_did_signed_transaction, build_did_change_owner_transaction, - build_did_change_owner_signed_transaction, build_did_change_owner_endorsing_data, + build_did_change_owner_signed_transaction, build_did_add_delegate_transaction, - build_did_add_delegate_signed_transaction, build_did_add_delegate_endorsing_data, + build_did_add_delegate_signed_transaction, build_did_revoke_delegate_transaction, - build_did_revoke_delegate_signed_transaction, build_did_revoke_delegate_endorsing_data, + build_did_revoke_delegate_signed_transaction, build_did_set_attribute_transaction, build_did_set_attribute_endorsing_data, build_did_set_attribute_signed_transaction, @@ -45,35 +49,49 @@ build_get_did_events_query, parse_did_changed_result, parse_did_owner_result, + parse_did_nonce_result, parse_did_attribute_changed_event_response, parse_did_delegate_changed_event_response, parse_did_owner_changed_event_response, parse_did_event_response, + build_create_did_transaction, + build_update_did_transaction, + build_update_did_endorsing_data, + build_update_did_signed_transaction, + build_deactivate_did_transaction, + build_deactivate_did_endorsing_data, + build_deactivate_did_signed_transaction, + build_resolve_did_transaction, + parse_resolve_did_result, resolve_did, build_create_schema_transaction, build_create_schema_endorsing_data, build_create_schema_signed_transaction, - build_get_schema_created_transaction, - build_get_schema_query, - parse_schema_created_result, - parse_schema_created_event, + build_resolve_schema_transaction, + parse_resolve_schema_result, resolve_schema, build_create_credential_definition_transaction, build_create_credential_definition_endorsing_data, build_create_credential_definition_signed_transaction, - build_get_credential_definition_created_transaction, - build_get_credential_definition_query, - parse_credential_definition_created_result, - parse_credential_definition_created_event, + build_resolve_credential_definition_transaction, + parse_resolve_credential_definition_result, resolve_credential_definition, build_get_role_transaction, build_get_validators_transaction, build_has_role_transaction, build_remove_validator_transaction, + build_resolve_did_transaction, + build_resolve_schema_transaction, + resolve_schema, build_revoke_role_transaction, + build_update_did_transaction, parse_get_role_result, parse_get_validators_result, parse_has_role_result, + parse_resolve_credential_definition_result, + resolve_credential_definition, + parse_resolve_did_result, + parse_resolve_schema_result ) __all__ = ( @@ -101,6 +119,11 @@ "build_add_validator_transaction", "build_assign_role_transaction", "build_create_credential_definition_transaction", + "build_create_credential_definition_endorsing_data", + "build_create_credential_definition_signed_transaction", + "build_create_did_transaction", + "build_create_did_endorsing_data", + "build_create_did_signed_transaction", "build_did_change_owner_transaction", "build_did_change_owner_signed_transaction", "build_did_change_owner_endorsing_data", @@ -122,33 +145,35 @@ "build_get_did_events_query", "parse_did_changed_result", "parse_did_owner_result", + "parse_did_nonce_result", "parse_did_attribute_changed_event_response", "parse_did_delegate_changed_event_response", "parse_did_owner_changed_event_response", "parse_did_event_response", "resolve_did", + "resolve_schema", + "resolve_credential_definition", "build_create_schema_transaction", "build_create_schema_endorsing_data", "build_create_schema_signed_transaction", - "build_get_schema_created_transaction", - "build_get_schema_query", - "parse_schema_created_result", - "parse_schema_created_event", - "resolve_schema", - "build_create_credential_definition_transaction", - "build_create_credential_definition_endorsing_data", - "build_create_credential_definition_signed_transaction", - "build_get_credential_definition_created_transaction", - "build_get_credential_definition_query", - "parse_credential_definition_created_result", - "parse_credential_definition_created_event", - "resolve_credential_definition", + "build_deactivate_did_transaction", + "build_deactivate_did_endorsing_data", + "build_deactivate_did_signed_transaction", "build_get_role_transaction", "build_get_validators_transaction", "build_has_role_transaction", "build_remove_validator_transaction", + "build_resolve_credential_definition_transaction", + "build_resolve_did_transaction", + "build_resolve_schema_transaction", "build_revoke_role_transaction", + "build_update_did_transaction", + "build_update_did_endorsing_data", + "build_update_did_signed_transaction", "parse_get_role_result", "parse_get_validators_result", "parse_has_role_result", + "parse_resolve_credential_definition_result", + "parse_resolve_did_result", + "parse_resolve_schema_result" ) diff --git a/vdr/wrappers/python/indy_besu_vdr/indy_besu_vdr.py b/vdr/wrappers/python/indy_besu_vdr/indy_besu_vdr.py index 9679731a..489be7a7 100644 --- a/vdr/wrappers/python/indy_besu_vdr/indy_besu_vdr.py +++ b/vdr/wrappers/python/indy_besu_vdr/indy_besu_vdr.py @@ -491,17 +491,29 @@ def _uniffi_check_api_checksums(lib): raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_assign_role_transaction() != 13494: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_credential_definition_endorsing_data() != 59949: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_credential_definition_endorsing_data() != 55676: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_credential_definition_signed_transaction() != 6216: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_credential_definition_signed_transaction() != 38063: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_credential_definition_transaction() != 59923: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_credential_definition_transaction() != 27654: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_schema_endorsing_data() != 3325: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_did_endorsing_data() != 54516: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_schema_signed_transaction() != 56271: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_did_signed_transaction() != 40911: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_schema_transaction() != 6657: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_did_transaction() != 55435: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_schema_endorsing_data() != 53121: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_schema_signed_transaction() != 19440: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_schema_transaction() != 31018: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_deactivate_did_endorsing_data() != 24992: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_deactivate_did_signed_transaction() != 50123: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_deactivate_did_transaction() != 52099: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_add_delegate_endorsing_data() != 21660: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") @@ -533,10 +545,6 @@ def _uniffi_check_api_checksums(lib): raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_set_attribute_transaction() != 65451: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_credential_definition_created_transaction() != 55886: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_credential_definition_query() != 15375: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_did_changed_transaction() != 41555: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_did_events_query() != 35752: @@ -547,21 +555,25 @@ def _uniffi_check_api_checksums(lib): raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_role_transaction() != 34920: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_schema_created_transaction() != 11928: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_schema_query() != 36622: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_validators_transaction() != 16117: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_has_role_transaction() != 35189: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_remove_validator_transaction() != 23482: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_resolve_credential_definition_transaction() != 50274: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_resolve_did_transaction() != 13420: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_resolve_schema_transaction() != 25036: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_revoke_role_transaction() != 41767: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_credential_definition_created_event() != 43712: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_update_did_endorsing_data() != 47376: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_credential_definition_created_result() != 43952: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_update_did_signed_transaction() != 42885: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_update_did_transaction() != 9871: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_attribute_changed_event_response() != 27285: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") @@ -571,6 +583,8 @@ def _uniffi_check_api_checksums(lib): raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_event_response() != 5583: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_nonce_result() != 38919: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_owner_changed_event_response() != 45369: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_owner_result() != 11739: @@ -581,9 +595,11 @@ def _uniffi_check_api_checksums(lib): raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_has_role_result() != 16372: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_schema_created_event() != 39931: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_resolve_credential_definition_result() != 30087: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_resolve_did_result() != 15878: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_schema_created_result() != 64564: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_resolve_schema_result() != 15793: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_resolve_credential_definition() != 411: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") @@ -744,7 +760,6 @@ def _uniffi_check_api_checksums(lib): _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_credential_definition_endorsing_data.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, - _UniffiRustBuffer, ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_credential_definition_endorsing_data.restype = ctypes.c_void_p _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_credential_definition_signed_transaction.argtypes = ( @@ -752,20 +767,38 @@ def _uniffi_check_api_checksums(lib): _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, - _UniffiRustBuffer, ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_credential_definition_signed_transaction.restype = ctypes.c_void_p _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_credential_definition_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, - _UniffiRustBuffer, ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_credential_definition_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_schema_endorsing_data.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_did_endorsing_data.argtypes = ( + ctypes.c_void_p, + _UniffiRustBuffer, + _UniffiRustBuffer, +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_did_endorsing_data.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_did_signed_transaction.argtypes = ( + ctypes.c_void_p, + _UniffiRustBuffer, + _UniffiRustBuffer, + _UniffiRustBuffer, + _UniffiRustBuffer, +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_did_signed_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_did_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, + _UniffiRustBuffer, +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_did_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_schema_endorsing_data.argtypes = ( + ctypes.c_void_p, + _UniffiRustBuffer, ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_schema_endorsing_data.restype = ctypes.c_void_p _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_schema_signed_transaction.argtypes = ( @@ -773,16 +806,32 @@ def _uniffi_check_api_checksums(lib): _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, - _UniffiRustBuffer, ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_schema_signed_transaction.restype = ctypes.c_void_p _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_schema_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, - _UniffiRustBuffer, ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_schema_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_deactivate_did_endorsing_data.argtypes = ( + ctypes.c_void_p, + _UniffiRustBuffer, +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_deactivate_did_endorsing_data.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_deactivate_did_signed_transaction.argtypes = ( + ctypes.c_void_p, + _UniffiRustBuffer, + _UniffiRustBuffer, + _UniffiRustBuffer, +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_deactivate_did_signed_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_deactivate_did_transaction.argtypes = ( + ctypes.c_void_p, + _UniffiRustBuffer, + _UniffiRustBuffer, +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_deactivate_did_transaction.restype = ctypes.c_void_p _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_add_delegate_endorsing_data.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, @@ -900,18 +949,6 @@ def _uniffi_check_api_checksums(lib): ctypes.c_uint64, ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_set_attribute_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_credential_definition_created_transaction.argtypes = ( - ctypes.c_void_p, - _UniffiRustBuffer, -) -_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_credential_definition_created_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_credential_definition_query.argtypes = ( - ctypes.c_void_p, - _UniffiRustBuffer, - _UniffiRustBuffer, - _UniffiRustBuffer, -) -_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_credential_definition_query.restype = ctypes.c_void_p _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_did_changed_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, @@ -939,18 +976,6 @@ def _uniffi_check_api_checksums(lib): _UniffiRustBuffer, ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_role_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_schema_created_transaction.argtypes = ( - ctypes.c_void_p, - _UniffiRustBuffer, -) -_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_schema_created_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_schema_query.argtypes = ( - ctypes.c_void_p, - _UniffiRustBuffer, - _UniffiRustBuffer, - _UniffiRustBuffer, -) -_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_schema_query.restype = ctypes.c_void_p _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_validators_transaction.argtypes = ( ctypes.c_void_p, ) @@ -967,6 +992,21 @@ def _uniffi_check_api_checksums(lib): _UniffiRustBuffer, ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_remove_validator_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_resolve_credential_definition_transaction.argtypes = ( + ctypes.c_void_p, + _UniffiRustBuffer, +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_resolve_credential_definition_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_resolve_did_transaction.argtypes = ( + ctypes.c_void_p, + _UniffiRustBuffer, +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_resolve_did_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_resolve_schema_transaction.argtypes = ( + ctypes.c_void_p, + _UniffiRustBuffer, +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_resolve_schema_transaction.restype = ctypes.c_void_p _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_revoke_role_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, @@ -974,18 +1014,27 @@ def _uniffi_check_api_checksums(lib): _UniffiRustBuffer, ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_revoke_role_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_credential_definition_created_event.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_update_did_endorsing_data.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, - ctypes.POINTER(_UniffiRustCallStatus), + _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_credential_definition_created_event.restype = _UniffiRustBuffer -_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_credential_definition_created_result.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_update_did_endorsing_data.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_update_did_signed_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, - ctypes.POINTER(_UniffiRustCallStatus), + _UniffiRustBuffer, + _UniffiRustBuffer, + _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_credential_definition_created_result.restype = ctypes.c_uint64 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_update_did_signed_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_update_did_transaction.argtypes = ( + ctypes.c_void_p, + _UniffiRustBuffer, + _UniffiRustBuffer, + _UniffiRustBuffer, +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_update_did_transaction.restype = ctypes.c_void_p _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_attribute_changed_event_response.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, @@ -1010,6 +1059,12 @@ def _uniffi_check_api_checksums(lib): ctypes.POINTER(_UniffiRustCallStatus), ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_event_response.restype = _UniffiRustBuffer +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_nonce_result.argtypes = ( + ctypes.c_void_p, + _UniffiRustBuffer, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_nonce_result.restype = ctypes.c_uint64 _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_owner_changed_event_response.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, @@ -1040,18 +1095,24 @@ def _uniffi_check_api_checksums(lib): ctypes.POINTER(_UniffiRustCallStatus), ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_has_role_result.restype = ctypes.c_int8 -_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_schema_created_event.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_resolve_credential_definition_result.argtypes = ( + ctypes.c_void_p, + _UniffiRustBuffer, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_resolve_credential_definition_result.restype = _UniffiRustBuffer +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_resolve_did_result.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_schema_created_event.restype = _UniffiRustBuffer -_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_schema_created_result.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_resolve_did_result.restype = _UniffiRustBuffer +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_resolve_schema_result.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_schema_created_result.restype = ctypes.c_uint64 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_resolve_schema_result.restype = _UniffiRustBuffer _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_resolve_credential_definition.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, @@ -1351,6 +1412,15 @@ def _uniffi_check_api_checksums(lib): _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_credential_definition_transaction.argtypes = ( ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_credential_definition_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_did_endorsing_data.argtypes = ( +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_did_endorsing_data.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_did_signed_transaction.argtypes = ( +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_did_signed_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_did_transaction.argtypes = ( +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_did_transaction.restype = ctypes.c_uint16 _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_schema_endorsing_data.argtypes = ( ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_schema_endorsing_data.restype = ctypes.c_uint16 @@ -1360,6 +1430,15 @@ def _uniffi_check_api_checksums(lib): _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_schema_transaction.argtypes = ( ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_schema_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_deactivate_did_endorsing_data.argtypes = ( +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_deactivate_did_endorsing_data.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_deactivate_did_signed_transaction.argtypes = ( +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_deactivate_did_signed_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_deactivate_did_transaction.argtypes = ( +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_deactivate_did_transaction.restype = ctypes.c_uint16 _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_add_delegate_endorsing_data.argtypes = ( ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_add_delegate_endorsing_data.restype = ctypes.c_uint16 @@ -1405,12 +1484,6 @@ def _uniffi_check_api_checksums(lib): _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_set_attribute_transaction.argtypes = ( ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_set_attribute_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_credential_definition_created_transaction.argtypes = ( -) -_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_credential_definition_created_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_credential_definition_query.argtypes = ( -) -_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_credential_definition_query.restype = ctypes.c_uint16 _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_did_changed_transaction.argtypes = ( ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_did_changed_transaction.restype = ctypes.c_uint16 @@ -1426,12 +1499,6 @@ def _uniffi_check_api_checksums(lib): _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_role_transaction.argtypes = ( ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_role_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_schema_created_transaction.argtypes = ( -) -_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_schema_created_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_schema_query.argtypes = ( -) -_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_schema_query.restype = ctypes.c_uint16 _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_validators_transaction.argtypes = ( ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_validators_transaction.restype = ctypes.c_uint16 @@ -1441,15 +1508,27 @@ def _uniffi_check_api_checksums(lib): _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_remove_validator_transaction.argtypes = ( ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_remove_validator_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_resolve_credential_definition_transaction.argtypes = ( +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_resolve_credential_definition_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_resolve_did_transaction.argtypes = ( +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_resolve_did_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_resolve_schema_transaction.argtypes = ( +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_resolve_schema_transaction.restype = ctypes.c_uint16 _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_revoke_role_transaction.argtypes = ( ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_revoke_role_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_credential_definition_created_event.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_update_did_endorsing_data.argtypes = ( +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_update_did_endorsing_data.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_update_did_signed_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_credential_definition_created_event.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_credential_definition_created_result.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_update_did_signed_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_update_did_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_credential_definition_created_result.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_update_did_transaction.restype = ctypes.c_uint16 _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_attribute_changed_event_response.argtypes = ( ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_attribute_changed_event_response.restype = ctypes.c_uint16 @@ -1462,6 +1541,9 @@ def _uniffi_check_api_checksums(lib): _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_event_response.argtypes = ( ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_event_response.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_nonce_result.argtypes = ( +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_nonce_result.restype = ctypes.c_uint16 _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_owner_changed_event_response.argtypes = ( ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_owner_changed_event_response.restype = ctypes.c_uint16 @@ -1477,12 +1559,15 @@ def _uniffi_check_api_checksums(lib): _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_has_role_result.argtypes = ( ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_has_role_result.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_schema_created_event.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_resolve_credential_definition_result.argtypes = ( +) +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_resolve_credential_definition_result.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_resolve_did_result.argtypes = ( ) -_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_schema_created_event.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_schema_created_result.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_resolve_did_result.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_resolve_schema_result.argtypes = ( ) -_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_schema_created_result.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_resolve_schema_result.restype = ctypes.c_uint16 _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_resolve_credential_definition.argtypes = ( ) _UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_resolve_credential_definition.restype = ctypes.c_uint16 @@ -2313,10 +2398,10 @@ def write(value, buf): class DidResolutionOptions: - accept: "str" + accept: "typing.Optional[str]" block_tag: "typing.Optional[int]" @typing.no_type_check - def __init__(self, accept: "str", block_tag: "typing.Optional[int]"): + def __init__(self, accept: "typing.Optional[str]", block_tag: "typing.Optional[int]"): self.accept = accept self.block_tag = block_tag @@ -2334,18 +2419,18 @@ class _UniffiConverterTypeDidResolutionOptions(_UniffiConverterRustBuffer): @staticmethod def read(buf): return DidResolutionOptions( - accept=_UniffiConverterString.read(buf), + accept=_UniffiConverterOptionalString.read(buf), block_tag=_UniffiConverterOptionalUInt64.read(buf), ) @staticmethod def check_lower(value): - _UniffiConverterString.check_lower(value.accept) + _UniffiConverterOptionalString.check_lower(value.accept) _UniffiConverterOptionalUInt64.check_lower(value.block_tag) @staticmethod def write(value, buf): - _UniffiConverterString.write(value.accept, buf) + _UniffiConverterOptionalString.write(value.accept, buf) _UniffiConverterOptionalUInt64.write(value.block_tag, buf) @@ -3530,17 +3615,14 @@ def build_assign_role_transaction(client: "LedgerClient",_from: "str",role: "int _UniffiConverterTypeVdrError, ) -def build_create_credential_definition_endorsing_data(client: "LedgerClient",id: "str",credential_definition: "str"): +def build_create_credential_definition_endorsing_data(client: "LedgerClient",credential_definition: "str"): _UniffiConverterTypeLedgerClient.check_lower(client) - _UniffiConverterString.check_lower(id) - _UniffiConverterString.check_lower(credential_definition) return _uniffi_rust_call_async( _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_credential_definition_endorsing_data( _UniffiConverterTypeLedgerClient.lower(client), - _UniffiConverterString.lower(id), _UniffiConverterString.lower(credential_definition)), _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer, @@ -3551,13 +3633,11 @@ def build_create_credential_definition_endorsing_data(client: "LedgerClient",id: _UniffiConverterTypeVdrError, ) -def build_create_credential_definition_signed_transaction(client: "LedgerClient",_from: "str",id: "str",credential_definition: "str",signature: "SignatureData"): +def build_create_credential_definition_signed_transaction(client: "LedgerClient",_from: "str",credential_definition: "str",signature: "SignatureData"): _UniffiConverterTypeLedgerClient.check_lower(client) _UniffiConverterString.check_lower(_from) - _UniffiConverterString.check_lower(id) - _UniffiConverterString.check_lower(credential_definition) _UniffiConverterTypeSignatureData.check_lower(signature) @@ -3566,7 +3646,6 @@ def build_create_credential_definition_signed_transaction(client: "LedgerClient" _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_credential_definition_signed_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(_from), - _UniffiConverterString.lower(id), _UniffiConverterString.lower(credential_definition), _UniffiConverterTypeSignatureData.lower(signature)), _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, @@ -3578,20 +3657,17 @@ def build_create_credential_definition_signed_transaction(client: "LedgerClient" _UniffiConverterTypeVdrError, ) -def build_create_credential_definition_transaction(client: "LedgerClient",_from: "str",id: "str",credential_definition: "str"): +def build_create_credential_definition_transaction(client: "LedgerClient",_from: "str",credential_definition: "str"): _UniffiConverterTypeLedgerClient.check_lower(client) _UniffiConverterString.check_lower(_from) - _UniffiConverterString.check_lower(id) - _UniffiConverterString.check_lower(credential_definition) return _uniffi_rust_call_async( _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_credential_definition_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(_from), - _UniffiConverterString.lower(id), _UniffiConverterString.lower(credential_definition)), _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer, @@ -3602,17 +3678,86 @@ def build_create_credential_definition_transaction(client: "LedgerClient",_from: _UniffiConverterTypeVdrError, ) -def build_create_schema_endorsing_data(client: "LedgerClient",id: "str",schema: "str"): +def build_create_did_endorsing_data(client: "LedgerClient",did: "str",did_doc: "str"): _UniffiConverterTypeLedgerClient.check_lower(client) - _UniffiConverterString.check_lower(id) + _UniffiConverterString.check_lower(did) + + _UniffiConverterString.check_lower(did_doc) + + return _uniffi_rust_call_async( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_did_endorsing_data( + _UniffiConverterTypeLedgerClient.lower(client), + _UniffiConverterString.lower(did), + _UniffiConverterString.lower(did_doc)), + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_pointer, + # lift function + _UniffiConverterTypeTransactionEndorsingData.lift, + # Error FFI converter + _UniffiConverterTypeVdrError, + ) + +def build_create_did_signed_transaction(client: "LedgerClient",_from: "str",did: "str",did_doc: "str",signature: "SignatureData"): + _UniffiConverterTypeLedgerClient.check_lower(client) + + _UniffiConverterString.check_lower(_from) + + _UniffiConverterString.check_lower(did) + + _UniffiConverterString.check_lower(did_doc) + + _UniffiConverterTypeSignatureData.check_lower(signature) + + return _uniffi_rust_call_async( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_did_signed_transaction( + _UniffiConverterTypeLedgerClient.lower(client), + _UniffiConverterString.lower(_from), + _UniffiConverterString.lower(did), + _UniffiConverterString.lower(did_doc), + _UniffiConverterTypeSignatureData.lower(signature)), + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_pointer, + # lift function + _UniffiConverterTypeTransaction.lift, + # Error FFI converter + _UniffiConverterTypeVdrError, + ) + +def build_create_did_transaction(client: "LedgerClient",_from: "str",did: "str",did_doc: "str"): + _UniffiConverterTypeLedgerClient.check_lower(client) + + _UniffiConverterString.check_lower(_from) + + _UniffiConverterString.check_lower(did) + + _UniffiConverterString.check_lower(did_doc) + + return _uniffi_rust_call_async( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_did_transaction( + _UniffiConverterTypeLedgerClient.lower(client), + _UniffiConverterString.lower(_from), + _UniffiConverterString.lower(did), + _UniffiConverterString.lower(did_doc)), + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_pointer, + # lift function + _UniffiConverterTypeTransaction.lift, + # Error FFI converter + _UniffiConverterTypeVdrError, + ) + +def build_create_schema_endorsing_data(client: "LedgerClient",schema: "str"): + _UniffiConverterTypeLedgerClient.check_lower(client) _UniffiConverterString.check_lower(schema) return _uniffi_rust_call_async( _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_schema_endorsing_data( _UniffiConverterTypeLedgerClient.lower(client), - _UniffiConverterString.lower(id), _UniffiConverterString.lower(schema)), _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer, @@ -3623,13 +3768,11 @@ def build_create_schema_endorsing_data(client: "LedgerClient",id: "str",schema: _UniffiConverterTypeVdrError, ) -def build_create_schema_signed_transaction(client: "LedgerClient",_from: "str",id: "str",schema: "str",signature: "SignatureData"): +def build_create_schema_signed_transaction(client: "LedgerClient",_from: "str",schema: "str",signature: "SignatureData"): _UniffiConverterTypeLedgerClient.check_lower(client) _UniffiConverterString.check_lower(_from) - _UniffiConverterString.check_lower(id) - _UniffiConverterString.check_lower(schema) _UniffiConverterTypeSignatureData.check_lower(signature) @@ -3638,7 +3781,6 @@ def build_create_schema_signed_transaction(client: "LedgerClient",_from: "str",i _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_schema_signed_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(_from), - _UniffiConverterString.lower(id), _UniffiConverterString.lower(schema), _UniffiConverterTypeSignatureData.lower(signature)), _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, @@ -3650,20 +3792,17 @@ def build_create_schema_signed_transaction(client: "LedgerClient",_from: "str",i _UniffiConverterTypeVdrError, ) -def build_create_schema_transaction(client: "LedgerClient",_from: "str",id: "str",schema: "str"): +def build_create_schema_transaction(client: "LedgerClient",_from: "str",schema: "str"): _UniffiConverterTypeLedgerClient.check_lower(client) _UniffiConverterString.check_lower(_from) - _UniffiConverterString.check_lower(id) - _UniffiConverterString.check_lower(schema) return _uniffi_rust_call_async( _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_schema_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(_from), - _UniffiConverterString.lower(id), _UniffiConverterString.lower(schema)), _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer, @@ -3674,6 +3813,69 @@ def build_create_schema_transaction(client: "LedgerClient",_from: "str",id: "str _UniffiConverterTypeVdrError, ) +def build_deactivate_did_endorsing_data(client: "LedgerClient",did: "str"): + _UniffiConverterTypeLedgerClient.check_lower(client) + + _UniffiConverterString.check_lower(did) + + return _uniffi_rust_call_async( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_deactivate_did_endorsing_data( + _UniffiConverterTypeLedgerClient.lower(client), + _UniffiConverterString.lower(did)), + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_pointer, + # lift function + _UniffiConverterTypeTransactionEndorsingData.lift, + # Error FFI converter + _UniffiConverterTypeVdrError, + ) + +def build_deactivate_did_signed_transaction(client: "LedgerClient",_from: "str",did: "str",signature: "SignatureData"): + _UniffiConverterTypeLedgerClient.check_lower(client) + + _UniffiConverterString.check_lower(_from) + + _UniffiConverterString.check_lower(did) + + _UniffiConverterTypeSignatureData.check_lower(signature) + + return _uniffi_rust_call_async( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_deactivate_did_signed_transaction( + _UniffiConverterTypeLedgerClient.lower(client), + _UniffiConverterString.lower(_from), + _UniffiConverterString.lower(did), + _UniffiConverterTypeSignatureData.lower(signature)), + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_pointer, + # lift function + _UniffiConverterTypeTransaction.lift, + # Error FFI converter + _UniffiConverterTypeVdrError, + ) + +def build_deactivate_did_transaction(client: "LedgerClient",_from: "str",did: "str"): + _UniffiConverterTypeLedgerClient.check_lower(client) + + _UniffiConverterString.check_lower(_from) + + _UniffiConverterString.check_lower(did) + + return _uniffi_rust_call_async( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_deactivate_did_transaction( + _UniffiConverterTypeLedgerClient.lower(client), + _UniffiConverterString.lower(_from), + _UniffiConverterString.lower(did)), + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_pointer, + # lift function + _UniffiConverterTypeTransaction.lift, + # Error FFI converter + _UniffiConverterTypeVdrError, + ) + def build_did_add_delegate_endorsing_data(client: "LedgerClient",did: "str",delegate_type: "str",delegate: "str",validity: "int"): _UniffiConverterTypeLedgerClient.check_lower(client) @@ -4070,15 +4272,15 @@ def build_did_set_attribute_transaction(client: "LedgerClient",_from: "str",did: _UniffiConverterTypeVdrError, ) -def build_get_credential_definition_created_transaction(client: "LedgerClient",id: "str"): +def build_get_did_changed_transaction(client: "LedgerClient",did: "str"): _UniffiConverterTypeLedgerClient.check_lower(client) - _UniffiConverterString.check_lower(id) + _UniffiConverterString.check_lower(did) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_credential_definition_created_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_did_changed_transaction( _UniffiConverterTypeLedgerClient.lower(client), - _UniffiConverterString.lower(id)), + _UniffiConverterString.lower(did)), _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_pointer, @@ -4088,19 +4290,19 @@ def build_get_credential_definition_created_transaction(client: "LedgerClient",i _UniffiConverterTypeVdrError, ) -def build_get_credential_definition_query(client: "LedgerClient",id: "str",from_block: "typing.Optional[int]",to_block: "typing.Optional[int]"): +def build_get_did_events_query(client: "LedgerClient",did: "str",from_block: "typing.Optional[int]",to_block: "typing.Optional[int]"): _UniffiConverterTypeLedgerClient.check_lower(client) - _UniffiConverterString.check_lower(id) + _UniffiConverterString.check_lower(did) _UniffiConverterOptionalUInt64.check_lower(from_block) _UniffiConverterOptionalUInt64.check_lower(to_block) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_credential_definition_query( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_did_events_query( _UniffiConverterTypeLedgerClient.lower(client), - _UniffiConverterString.lower(id), + _UniffiConverterString.lower(did), _UniffiConverterOptionalUInt64.lower(from_block), _UniffiConverterOptionalUInt64.lower(to_block)), _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, @@ -4112,13 +4314,13 @@ def build_get_credential_definition_query(client: "LedgerClient",id: "str",from_ _UniffiConverterTypeVdrError, ) -def build_get_did_changed_transaction(client: "LedgerClient",did: "str"): +def build_get_did_owner_transaction(client: "LedgerClient",did: "str"): _UniffiConverterTypeLedgerClient.check_lower(client) _UniffiConverterString.check_lower(did) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_did_changed_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_did_owner_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(did)), _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, @@ -4130,39 +4332,33 @@ def build_get_did_changed_transaction(client: "LedgerClient",did: "str"): _UniffiConverterTypeVdrError, ) -def build_get_did_events_query(client: "LedgerClient",did: "str",from_block: "typing.Optional[int]",to_block: "typing.Optional[int]"): +def build_get_identity_nonce_transaction(client: "LedgerClient",identity: "str"): _UniffiConverterTypeLedgerClient.check_lower(client) - _UniffiConverterString.check_lower(did) - - _UniffiConverterOptionalUInt64.check_lower(from_block) - - _UniffiConverterOptionalUInt64.check_lower(to_block) + _UniffiConverterString.check_lower(identity) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_did_events_query( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_identity_nonce_transaction( _UniffiConverterTypeLedgerClient.lower(client), - _UniffiConverterString.lower(did), - _UniffiConverterOptionalUInt64.lower(from_block), - _UniffiConverterOptionalUInt64.lower(to_block)), + _UniffiConverterString.lower(identity)), _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_pointer, # lift function - _UniffiConverterTypeEventQuery.lift, + _UniffiConverterTypeTransaction.lift, # Error FFI converter _UniffiConverterTypeVdrError, ) -def build_get_did_owner_transaction(client: "LedgerClient",did: "str"): +def build_get_role_transaction(client: "LedgerClient",account: "str"): _UniffiConverterTypeLedgerClient.check_lower(client) - _UniffiConverterString.check_lower(did) + _UniffiConverterString.check_lower(account) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_did_owner_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_role_transaction( _UniffiConverterTypeLedgerClient.lower(client), - _UniffiConverterString.lower(did)), + _UniffiConverterString.lower(account)), _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_pointer, @@ -4172,15 +4368,12 @@ def build_get_did_owner_transaction(client: "LedgerClient",did: "str"): _UniffiConverterTypeVdrError, ) -def build_get_identity_nonce_transaction(client: "LedgerClient",identity: "str"): +def build_get_validators_transaction(client: "LedgerClient"): _UniffiConverterTypeLedgerClient.check_lower(client) - _UniffiConverterString.check_lower(identity) - return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_identity_nonce_transaction( - _UniffiConverterTypeLedgerClient.lower(client), - _UniffiConverterString.lower(identity)), + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_validators_transaction( + _UniffiConverterTypeLedgerClient.lower(client)), _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_pointer, @@ -4190,14 +4383,17 @@ def build_get_identity_nonce_transaction(client: "LedgerClient",identity: "str") _UniffiConverterTypeVdrError, ) -def build_get_role_transaction(client: "LedgerClient",account: "str"): +def build_has_role_transaction(client: "LedgerClient",role: "int",account: "str"): _UniffiConverterTypeLedgerClient.check_lower(client) + _UniffiConverterUInt8.check_lower(role) + _UniffiConverterString.check_lower(account) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_role_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_has_role_transaction( _UniffiConverterTypeLedgerClient.lower(client), + _UniffiConverterUInt8.lower(role), _UniffiConverterString.lower(account)), _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer, @@ -4208,15 +4404,18 @@ def build_get_role_transaction(client: "LedgerClient",account: "str"): _UniffiConverterTypeVdrError, ) -def build_get_schema_created_transaction(client: "LedgerClient",id: "str"): +def build_remove_validator_transaction(client: "LedgerClient",_from: "str",validator_address: "str"): _UniffiConverterTypeLedgerClient.check_lower(client) - _UniffiConverterString.check_lower(id) + _UniffiConverterString.check_lower(_from) + + _UniffiConverterString.check_lower(validator_address) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_schema_created_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_remove_validator_transaction( _UniffiConverterTypeLedgerClient.lower(client), - _UniffiConverterString.lower(id)), + _UniffiConverterString.lower(_from), + _UniffiConverterString.lower(validator_address)), _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_pointer, @@ -4226,36 +4425,51 @@ def build_get_schema_created_transaction(client: "LedgerClient",id: "str"): _UniffiConverterTypeVdrError, ) -def build_get_schema_query(client: "LedgerClient",id: "str",from_block: "typing.Optional[int]",to_block: "typing.Optional[int]"): +def build_resolve_credential_definition_transaction(client: "LedgerClient",id: "str"): _UniffiConverterTypeLedgerClient.check_lower(client) _UniffiConverterString.check_lower(id) - _UniffiConverterOptionalUInt64.check_lower(from_block) + return _uniffi_rust_call_async( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_resolve_credential_definition_transaction( + _UniffiConverterTypeLedgerClient.lower(client), + _UniffiConverterString.lower(id)), + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_pointer, + # lift function + _UniffiConverterTypeTransaction.lift, + # Error FFI converter + _UniffiConverterTypeVdrError, + ) + +def build_resolve_did_transaction(client: "LedgerClient",did: "str"): + _UniffiConverterTypeLedgerClient.check_lower(client) - _UniffiConverterOptionalUInt64.check_lower(to_block) + _UniffiConverterString.check_lower(did) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_schema_query( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_resolve_did_transaction( _UniffiConverterTypeLedgerClient.lower(client), - _UniffiConverterString.lower(id), - _UniffiConverterOptionalUInt64.lower(from_block), - _UniffiConverterOptionalUInt64.lower(to_block)), + _UniffiConverterString.lower(did)), _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_pointer, # lift function - _UniffiConverterTypeEventQuery.lift, + _UniffiConverterTypeTransaction.lift, # Error FFI converter _UniffiConverterTypeVdrError, ) -def build_get_validators_transaction(client: "LedgerClient"): +def build_resolve_schema_transaction(client: "LedgerClient",id: "str"): _UniffiConverterTypeLedgerClient.check_lower(client) + _UniffiConverterString.check_lower(id) + return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_validators_transaction( - _UniffiConverterTypeLedgerClient.lower(client)), + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_resolve_schema_transaction( + _UniffiConverterTypeLedgerClient.lower(client), + _UniffiConverterString.lower(id)), _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_pointer, @@ -4265,16 +4479,19 @@ def build_get_validators_transaction(client: "LedgerClient"): _UniffiConverterTypeVdrError, ) -def build_has_role_transaction(client: "LedgerClient",role: "int",account: "str"): +def build_revoke_role_transaction(client: "LedgerClient",_from: "str",role: "int",account: "str"): _UniffiConverterTypeLedgerClient.check_lower(client) + _UniffiConverterString.check_lower(_from) + _UniffiConverterUInt8.check_lower(role) _UniffiConverterString.check_lower(account) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_has_role_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_revoke_role_transaction( _UniffiConverterTypeLedgerClient.lower(client), + _UniffiConverterString.lower(_from), _UniffiConverterUInt8.lower(role), _UniffiConverterString.lower(account)), _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, @@ -4286,42 +4503,45 @@ def build_has_role_transaction(client: "LedgerClient",role: "int",account: "str" _UniffiConverterTypeVdrError, ) -def build_remove_validator_transaction(client: "LedgerClient",_from: "str",validator_address: "str"): +def build_update_did_endorsing_data(client: "LedgerClient",did: "str",did_doc: "str"): _UniffiConverterTypeLedgerClient.check_lower(client) - _UniffiConverterString.check_lower(_from) + _UniffiConverterString.check_lower(did) - _UniffiConverterString.check_lower(validator_address) + _UniffiConverterString.check_lower(did_doc) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_remove_validator_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_update_did_endorsing_data( _UniffiConverterTypeLedgerClient.lower(client), - _UniffiConverterString.lower(_from), - _UniffiConverterString.lower(validator_address)), + _UniffiConverterString.lower(did), + _UniffiConverterString.lower(did_doc)), _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_pointer, # lift function - _UniffiConverterTypeTransaction.lift, + _UniffiConverterTypeTransactionEndorsingData.lift, # Error FFI converter _UniffiConverterTypeVdrError, ) -def build_revoke_role_transaction(client: "LedgerClient",_from: "str",role: "int",account: "str"): +def build_update_did_signed_transaction(client: "LedgerClient",_from: "str",did: "str",did_doc: "str",signature: "SignatureData"): _UniffiConverterTypeLedgerClient.check_lower(client) _UniffiConverterString.check_lower(_from) - _UniffiConverterUInt8.check_lower(role) + _UniffiConverterString.check_lower(did) - _UniffiConverterString.check_lower(account) + _UniffiConverterString.check_lower(did_doc) + + _UniffiConverterTypeSignatureData.check_lower(signature) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_revoke_role_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_update_did_signed_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(_from), - _UniffiConverterUInt8.lower(role), - _UniffiConverterString.lower(account)), + _UniffiConverterString.lower(did), + _UniffiConverterString.lower(did_doc), + _UniffiConverterTypeSignatureData.lower(signature)), _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer, _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_pointer, @@ -4331,25 +4551,29 @@ def build_revoke_role_transaction(client: "LedgerClient",_from: "str",role: "int _UniffiConverterTypeVdrError, ) -def parse_credential_definition_created_event(client: "LedgerClient",log: "EventLog") -> "str": +def build_update_did_transaction(client: "LedgerClient",_from: "str",did: "str",did_doc: "str"): _UniffiConverterTypeLedgerClient.check_lower(client) - _UniffiConverterTypeEventLog.check_lower(log) + _UniffiConverterString.check_lower(_from) - return _UniffiConverterString.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_credential_definition_created_event, - _UniffiConverterTypeLedgerClient.lower(client), - _UniffiConverterTypeEventLog.lower(log))) - - -def parse_credential_definition_created_result(client: "LedgerClient",bytes: "bytes") -> "int": - _UniffiConverterTypeLedgerClient.check_lower(client) + _UniffiConverterString.check_lower(did) - _UniffiConverterBytes.check_lower(bytes) + _UniffiConverterString.check_lower(did_doc) - return _UniffiConverterUInt64.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_credential_definition_created_result, + return _uniffi_rust_call_async( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_update_did_transaction( _UniffiConverterTypeLedgerClient.lower(client), - _UniffiConverterBytes.lower(bytes))) - + _UniffiConverterString.lower(_from), + _UniffiConverterString.lower(did), + _UniffiConverterString.lower(did_doc)), + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_pointer, + # lift function + _UniffiConverterTypeTransaction.lift, + # Error FFI converter + _UniffiConverterTypeVdrError, + ) def parse_did_attribute_changed_event_response(client: "LedgerClient",log: "EventLog") -> "DidAttributeChanged": _UniffiConverterTypeLedgerClient.check_lower(client) @@ -4391,6 +4615,16 @@ def parse_did_event_response(client: "LedgerClient",log: "EventLog") -> "DidEven _UniffiConverterTypeEventLog.lower(log))) +def parse_did_nonce_result(client: "LedgerClient",bytes: "bytes") -> "int": + _UniffiConverterTypeLedgerClient.check_lower(client) + + _UniffiConverterBytes.check_lower(bytes) + + return _UniffiConverterUInt64.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_nonce_result, + _UniffiConverterTypeLedgerClient.lower(client), + _UniffiConverterBytes.lower(bytes))) + + def parse_did_owner_changed_event_response(client: "LedgerClient",log: "EventLog") -> "DidOwnerChanged": _UniffiConverterTypeLedgerClient.check_lower(client) @@ -4441,22 +4675,32 @@ def parse_has_role_result(client: "LedgerClient",bytes: "bytes") -> "bool": _UniffiConverterBytes.lower(bytes))) -def parse_schema_created_event(client: "LedgerClient",log: "EventLog") -> "str": +def parse_resolve_credential_definition_result(client: "LedgerClient",bytes: "bytes") -> "str": _UniffiConverterTypeLedgerClient.check_lower(client) - _UniffiConverterTypeEventLog.check_lower(log) + _UniffiConverterBytes.check_lower(bytes) - return _UniffiConverterString.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_schema_created_event, + return _UniffiConverterString.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_resolve_credential_definition_result, _UniffiConverterTypeLedgerClient.lower(client), - _UniffiConverterTypeEventLog.lower(log))) + _UniffiConverterBytes.lower(bytes))) + + +def parse_resolve_did_result(client: "LedgerClient",bytes: "bytes") -> "str": + _UniffiConverterTypeLedgerClient.check_lower(client) + + _UniffiConverterBytes.check_lower(bytes) + + return _UniffiConverterString.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_resolve_did_result, + _UniffiConverterTypeLedgerClient.lower(client), + _UniffiConverterBytes.lower(bytes))) -def parse_schema_created_result(client: "LedgerClient",bytes: "bytes") -> "int": +def parse_resolve_schema_result(client: "LedgerClient",bytes: "bytes") -> "str": _UniffiConverterTypeLedgerClient.check_lower(client) _UniffiConverterBytes.check_lower(bytes) - return _UniffiConverterUInt64.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_schema_created_result, + return _UniffiConverterString.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_resolve_schema_result, _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterBytes.lower(bytes))) @@ -4540,9 +4784,15 @@ def resolve_schema(client: "LedgerClient",id: "str"): "build_create_credential_definition_endorsing_data", "build_create_credential_definition_signed_transaction", "build_create_credential_definition_transaction", + "build_create_did_endorsing_data", + "build_create_did_signed_transaction", + "build_create_did_transaction", "build_create_schema_endorsing_data", "build_create_schema_signed_transaction", "build_create_schema_transaction", + "build_deactivate_did_endorsing_data", + "build_deactivate_did_signed_transaction", + "build_deactivate_did_transaction", "build_did_add_delegate_endorsing_data", "build_did_add_delegate_signed_transaction", "build_did_add_delegate_transaction", @@ -4558,32 +4808,34 @@ def resolve_schema(client: "LedgerClient",id: "str"): "build_did_set_attribute_endorsing_data", "build_did_set_attribute_signed_transaction", "build_did_set_attribute_transaction", - "build_get_credential_definition_created_transaction", - "build_get_credential_definition_query", "build_get_did_changed_transaction", "build_get_did_events_query", "build_get_did_owner_transaction", "build_get_identity_nonce_transaction", "build_get_role_transaction", - "build_get_schema_created_transaction", - "build_get_schema_query", "build_get_validators_transaction", "build_has_role_transaction", "build_remove_validator_transaction", + "build_resolve_credential_definition_transaction", + "build_resolve_did_transaction", + "build_resolve_schema_transaction", "build_revoke_role_transaction", - "parse_credential_definition_created_event", - "parse_credential_definition_created_result", + "build_update_did_endorsing_data", + "build_update_did_signed_transaction", + "build_update_did_transaction", "parse_did_attribute_changed_event_response", "parse_did_changed_result", "parse_did_delegate_changed_event_response", "parse_did_event_response", + "parse_did_nonce_result", "parse_did_owner_changed_event_response", "parse_did_owner_result", "parse_get_role_result", "parse_get_validators_result", "parse_has_role_result", - "parse_schema_created_event", - "parse_schema_created_result", + "parse_resolve_credential_definition_result", + "parse_resolve_did_result", + "parse_resolve_schema_result", "resolve_credential_definition", "resolve_did", "resolve_schema",