From a914350a7bcf9cbf47fed6d0ed634b5278f8537b Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Mon, 22 Jan 2024 10:34:05 +0300 Subject: [PATCH 1/5] Updates CL contracts to use event based approach + Drop did:indy2 Signed-off-by: artem.ivanov --- docs/design/cl-registry.md | 279 ++--- docs/design/conmponents.png | Bin 70248 -> 69990 bytes docs/design/conmponents.puml | 3 +- docs/design/contracts.png | Bin 121815 -> 109330 bytes docs/design/contracts.puml | 24 +- docs/design/did-method.md | 10 + docs/design/did-methods.md | 86 -- docs/design/did-registry.md | 183 --- docs/design/endorsement.md | 211 ++-- docs/design/flow.png | Bin 236136 -> 212355 bytes docs/design/flow.puml | 52 +- docs/design/legacy-identifiers-support.md | 72 -- docs/design/registry.md | 49 +- docs/design/vdr.md | 1017 +++++++++++------ docs/migrtion/migration.md | 106 +- network/config/besu/genesis.json | 60 +- network/config/nodes/validator5/key | 2 +- smart_contracts/README.md | 7 +- .../CredentialDefinitionRegistry.ts | 42 +- ...DRegistry.ts => EthereumExtDidRegistry.ts} | 17 +- .../contracts-ts/SchemaRegistry.ts | 30 +- smart_contracts/contracts-ts/index.ts | 5 +- smart_contracts/contracts/cl/CLRegistry.sol | 43 +- smart_contracts/contracts/cl/ClErrors.sol | 40 +- .../cl/CredentialDefinitionRegistry.sol | 88 +- .../CredentialDefinitionRegistryInterface.sol | 66 +- .../cl/CredentialDefinitionTypes.sol | 25 - .../cl/CredentialDefinitionValidator.sol | 23 - .../contracts/cl/SchemaRegistry.sol | 67 +- .../contracts/cl/SchemaRegistryInterface.sol | 52 +- smart_contracts/contracts/cl/SchemaTypes.sol | 25 - .../contracts/cl/SchemaValidator.sol | 22 - smart_contracts/contracts/did/DidErrors.sol | 27 - smart_contracts/contracts/did/DidTypes.sol | 21 - .../contracts/did/IndyDidRegistry.sol | 90 -- .../did/IndyDidRegistryInterface.sol | 83 -- .../contracts/did/IndyDidValidator.sol | 19 - .../contracts/did/UniversalDidResolver.sol | 61 - .../did/UniversalDidResolverInterface.sol | 33 - .../network/ValidatorControlInterface.sol | 12 +- smart_contracts/contracts/utils/DidUtils.sol | 88 -- smart_contracts/contracts/utils/Errors.sol | 19 - .../contracts/utils/StringUtils.sol | 44 +- smart_contracts/demos/flow-with-did-ethr.ts | 90 -- smart_contracts/demos/flow.ts | 67 +- smart_contracts/demos/utils/actor.ts | 11 +- smart_contracts/package.json | 1 - smart_contracts/scripts/genesis/config.ts | 42 +- .../contracts/credentialDefinitionRegistry.ts | 4 +- .../scripts/genesis/contracts/index.ts | 3 - .../genesis/contracts/indyDidRegistry.ts | 20 - .../genesis/contracts/indyDidValidator.ts | 11 - .../genesis/contracts/schemaRegistry.ts | 4 +- .../genesis/contracts/universalDidResolver.ts | 25 - smart_contracts/scripts/genesis/generate.ts | 6 - .../cl/CredentialDefinitionRegistry.spec.ts | 191 ++-- .../test/cl/SchemaRegistry.spec.ts | 138 +-- smart_contracts/test/did/DidRegistry.spec.ts | 170 +-- .../test/did/UniversalDidResolver.spec.ts | 73 -- .../test/utils/contract-helpers.ts | 124 +- smart_contracts/test/utils/errors.ts | 16 - smart_contracts/utils/contract.ts | 2 +- smart_contracts/utils/entity-factories.ts | 10 +- vdr/src/client/client.rs | 15 +- .../cl/credential_definition_registry.rs | 384 ++++--- vdr/src/contracts/cl/mod.rs | 8 +- vdr/src/contracts/cl/schema_registry.rs | 327 ++++-- .../cl/types/credential_definition.rs | 95 +- .../cl/types/credential_definition_id.rs | 12 +- vdr/src/contracts/cl/types/schema.rs | 73 +- vdr/src/contracts/cl/types/schema_id.rs | 12 +- vdr/src/contracts/did/did_ethr_registry.rs | 30 +- vdr/src/contracts/did/did_indy_registry.rs | 438 ------- vdr/src/contracts/did/mod.rs | 5 +- vdr/src/contracts/did/types/did_doc.rs | 2 +- vdr/src/contracts/mod.rs | 3 +- vdr/src/lib.rs | 8 +- vdr/src/test.rs | 287 ++--- vdr/src/types/mod.rs | 2 +- vdr/src/types/transaction.rs | 36 +- .../credential_definition_registry.rs | 114 +- .../src/ffi/contracts/did_ethr_registry.rs | 16 +- .../src/ffi/contracts/did_indy_registry.rs | 80 -- vdr/uniffi/src/ffi/contracts/mod.rs | 1 - .../src/ffi/contracts/schema_registry.rs | 92 +- vdr/wasm/demo/node/src/main.ts | 127 +- .../credential_definition_registry.rs | 111 +- vdr/wasm/src/contracts/did_indy_registry.rs | 89 -- vdr/wasm/src/contracts/mod.rs | 1 - vdr/wasm/src/contracts/schema_registry.rs | 96 +- vdr/wrappers/python/demo/test.py | 75 +- vdr/wrappers/python/indy2_vdr/__init__.py | 48 +- vdr/wrappers/python/indy2_vdr/indy2_vdr.py | 496 +++++--- 93 files changed, 3217 insertions(+), 4077 deletions(-) create mode 100644 docs/design/did-method.md delete mode 100644 docs/design/did-methods.md delete mode 100644 docs/design/did-registry.md delete mode 100644 docs/design/legacy-identifiers-support.md rename smart_contracts/contracts-ts/{EthereumDIDRegistry.ts => EthereumExtDidRegistry.ts} (83%) delete mode 100644 smart_contracts/contracts/cl/CredentialDefinitionTypes.sol delete mode 100644 smart_contracts/contracts/cl/CredentialDefinitionValidator.sol delete mode 100644 smart_contracts/contracts/cl/SchemaTypes.sol delete mode 100644 smart_contracts/contracts/cl/SchemaValidator.sol delete mode 100644 smart_contracts/contracts/did/DidErrors.sol delete mode 100644 smart_contracts/contracts/did/DidTypes.sol delete mode 100644 smart_contracts/contracts/did/IndyDidRegistry.sol delete mode 100644 smart_contracts/contracts/did/IndyDidRegistryInterface.sol delete mode 100644 smart_contracts/contracts/did/IndyDidValidator.sol delete mode 100644 smart_contracts/contracts/did/UniversalDidResolver.sol delete mode 100644 smart_contracts/contracts/did/UniversalDidResolverInterface.sol delete mode 100644 smart_contracts/contracts/utils/DidUtils.sol delete mode 100644 smart_contracts/demos/flow-with-did-ethr.ts delete mode 100644 smart_contracts/scripts/genesis/contracts/indyDidRegistry.ts delete mode 100644 smart_contracts/scripts/genesis/contracts/indyDidValidator.ts delete mode 100644 smart_contracts/scripts/genesis/contracts/universalDidResolver.ts delete mode 100644 smart_contracts/test/did/UniversalDidResolver.spec.ts delete mode 100644 vdr/src/contracts/did/did_indy_registry.rs delete mode 100644 vdr/uniffi/src/ffi/contracts/did_indy_registry.rs delete mode 100644 vdr/wasm/src/contracts/did_indy_registry.rs diff --git a/docs/design/cl-registry.md b/docs/design/cl-registry.md index abe81a9f..54b1575a 100644 --- a/docs/design/cl-registry.md +++ b/docs/design/cl-registry.md @@ -1,5 +1,16 @@ # 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 @@ -9,60 +20,30 @@ | parameter | value | |-------------|-----------------------------------------------------------------| | id | “did:” method-name “:” namespace “:” method-specific-id | -| method-name | “indy2”, “indy”, “sov”, “ethr” | +| method-name | “ethr” | | namespace | “testnet”/"mainnet" | | indy-id | /anoncreds/v0/SCHEMA// | ``` -Example: did:indy2:mainnet:Y6LRXGU3ZCpm7yzjVRSaGu/anoncreds/v0/SCHEMA/BasicIdentity/1.0.0 +Example: did:ethr:mainnet:Y6LRXGU3ZCpm7yzjVRSaGu/anoncreds/v0/SCHEMA/BasicIdentity/1.0.0 ``` ### Storage format -* Schemas collection: - * Description: Mapping holding the list of Schema ID's to their data and metadata. +* Created schemas mapping: + * Description: Mapping to track created schemas by their id to the block number when it was created. * Format: ``` - mapping(string id => SchemaRecord schemaRecord); - - struct SchemaRecord { - string data; - SchemaMetadata metadata; - } - - struct SchemaMetadata { - uint256 created; - } + mapping(bytes32 id => uint block); ``` * Example: ``` { - "did:indy2:mainnet:Y6LRXGU3ZCpm7yzjVRSaGu/anoncreds/v0/SCHEMA/BasicIdentity/1.0.0": { - schema: "{ - "issuerId": "did:indy2:mainnet:Y6LRXGU3ZCpm7yzjVRSaGu", - "name": "BasicIdentity", - "version": "1.0.0", - "attrNames": ["First Name", "Last Name"] - }", - metadata: { - created: 1234 - }, - }, + "0x8ae64c08cf45da3364623a7235a9e7d132fdc8e9f6e63858b53a90d9db32c3af": 110, ... } ``` -#### 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** @@ -72,55 +53,84 @@ Contract name: **SchemaRegistry** * Method: `createSchema` * Description: Transaction to create a new AnonCreds Schema * Parameters: - * `id` - Id of schema to be created - * `issuerId` - Id of schema issuer - * `schema` - AnonCreds schema as JSON string + * `identity` - Account address of schema issuer + * `id` - KECCAK256 hash of schema id to be created + * `schema` - AnonCreds schema object as bytes * Restrictions: * Schema id must be unique. - * Corresponding issuer DID must exist, be active, and owned by sender. + * Corresponding issuer account must exist and owned by sender. * Format: ``` SchemaRegistry.createSchema( - string calldata id, - string calldata issuerId, - string calldata schema + address identity, + bytes32 id, + bytes schema ) ``` + * Raised Event: + ``` + SchemaCreated(bytes32 indexed id, address identity, bytes schema)` + ``` * Example: ``` SchemaRegistry.createSchema( - "did:indy2:mainnet:Y6LRXGU3ZCpm7yzjVRSaGu/anoncreds/v0/SCHEMA/BasicIdentity/1.0.0", - "did:indy2:mainnet:Y6LRXGU3ZCpm7yzjVRSaGu", - "{ - "issuerId": "did:indy2:mainnet:Y6LRXGU3ZCpm7yzjVRSaGu", - "name": "BasicIdentity", - "version": "1.0.0", - "attrNames": ["First Name", "Last Name"] - }" + "0x173CC02518a355040F5Faee93D3AAAb1259F010c", + "0x8ae64c08cf45da3364623a7235a9e7d132fdc8e9f6e63858b53a90d9db32c3af", + [34, 123, 92, 34, 105, 100, 92, 34, 58, 92, 34, 100, ...] ) - * Raised Event: - * `SchemaCreated(schemaId)` - -#### Resolve schema -* Method: `resolveSchema` - * Description: Transaction to resolve Schema for giving id +* Method: `createSchemaSigned` + * Description: Transaction to endorse a new AnonCreds Schema (off-chain author signature) * Parameters: - * `id` - ID of the Schema to resolve + * `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 * Restrictions: - * Schema must exist. + * Schema id must be unique. + * Corresponding issuer account must exist and owned by sender. * Format: ``` - SchemaRegistry.resolveSchema( - string id - ) returns (SchemaRecord sschemaRecord) + SchemaRegistry.createSchemaSigned( + address identity, + uint8 sigV, + bytes32 sigR, + bytes32 sigS, + bytes32 id, + bytes schema + ) ``` + * Raised Event: + ``` + SchemaCreated(bytes32 indexed id, address identity, bytes schema)` + ``` * Example: ``` - SchemaRegistry.resolveSchema( - "did:indy2:mainnet:Y6LRXGU3ZCpm7yzjVRSaGu/anoncreds/v0/SCHEMA/BasicIdentity/1.0.0" + 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, ...] ) - * Raised Event: `None` + +#### 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 ## Credential Definition @@ -141,51 +151,20 @@ Example: did:indy2:sovrin:Gs6cQcvrtWoZKsbBhD3dQJ/anoncreds/v0/CLAIM_DEF/56495/mc ### Storage format -* Credential Definitions collection: - * Description: Mapping holding the list of Credential Definition ID's to their data and metadata. +* Created credential definitions mapping: + * Description: Mapping to track created credential definitions by their id to the block number when it was created. * Format: ``` - mapping(string id => CredentialDefinitionRecord credentialDefinitionRecord); - - struct CredentialDefinitionRecord { - string credDef; - CredentialDefinitionMetadata metadata; - } - - struct CredentialDefinitionMetadata { - uint256 created; - } + mapping(bytes32 id => uint block); ``` * Example: ``` { - "did:indy2:sovrin:Gs6cQcvrtWoZKsbBhD3dQJ/anoncreds/v0/CLAIM_DEF/56495/mctc": { - credDef: "{ - "issuerId": "did:indy2:mainnet:Y6LRXGU3ZCpm7yzjVRSaGu", - "schemaId": "did:indy2:mainnet:Y6LRXGU3ZCpm7yzjVRSaGu/anoncreds/v0/SCHEMA/BasicIdentity/1.0.0", - "type": "CL", - "tag": "BasicIdentity", - "value": "{ ... }" - }", - metadata: { - created: 1234 - }, - }, + "0x8ae64c08cf45da3364623a7235a9e7d132fdc8e9f6e63858b53a90d9db32c3af": 110, ... } ``` -#### 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** @@ -195,59 +174,91 @@ Contract name: **CredentialDefinitionRegistry** * Method: `createCredentialDefinition` * Description: Transaction to create a new AnonCreds Credential Definition * Parameters: - * `id` - Id of credential definition to be created - * `issuerId` - Id of credential definition issuer - * `schemaId` - Id of credential definition schema - * `credDef` - AnonCreds credential definition as JSON string + * `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 * Restrictions: * Credential Definition must be unique. - * Corresponding issuer DID must exist, be active, and owned by sender. + * Corresponding issuer DID must exist and owned by sender. * Corresponding schema must exist. * Format: ``` CredentialDefinitionRegistry.createCredentialDefinition( - string calldata id, - string calldata issuerId, - string calldata schemaId, - string calldata credDef + address identity, + bytes32 id, + bytes32 schemaId, + bytes credDef ) ``` + * Raised Event: + ``` + CredentialDefinitionCreated(bytes32 indexed id, address identity, bytes credDef)` + ``` * Example: ``` - CredentialDefinitionRegistry.createCredentialDefinition( - "did:indy2:sovrin:Gs6cQcvrtWoZKsbBhD3dQJ/anoncreds/v0/CLAIM_DEF/56495/BasicIdentity", - "did:indy2:mainnet:Y6LRXGU3ZCpm7yzjVRSaGu", - "did:indy2:mainnet:Y6LRXGU3ZCpm7yzjVRSaGu/anoncreds/v0/SCHEMA/BasicIdentity/1.0.0", - "{ - "issuerId": "did:indy2:mainnet:Y6LRXGU3ZCpm7yzjVRSaGu", - "schemaId": "did:indy2:mainnet:Y6LRXGU3ZCpm7yzjVRSaGu/anoncreds/v0/SCHEMA/BasicIdentity/1.0.0", - "type": "CL", - "tag": "BasicIdentity", - "value": "{.......}", - }" + CredentialDefinitionCreated.createCredentialDefinition( + "0x173CC02518a355040F5Faee93D3AAAb1259F010c", + "0x76943530d3587e81f029e8ce20edb64f9254350d81c59ecf6b7e3ed553e9a8f6", + "0x8ae64c08cf45da3364623a7235a9e7d132fdc8e9f6e63858b53a90d9db32c3af", + [34, 123, 92, 34, 105, 100, 92, 34, 58, 92, 34, 100, ...] ) - * Raised Event: - * `CredentialDefinitionCreated(credentialDefinitionId)` -#### Resolve credential definition - -* Method: `resolveCredentialDefinition` - * Description: Transaction to resolve Credential Definition for giving id +* Method: `createCredentialDefinitionSigned` + * Description: Transaction to endorse a new AnonCreds Credential Definition (off-chain author signature) * Parameters: - * `id` - Id of credential definition to be resolved + * `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 * Restrictions: - * Credential Definition must exist. + * Credential Definition must be unique. + * Corresponding issuer DID must exist and owned by sender. + * Corresponding schema must exist. * Format: ``` - CredentialDefinitionRegistry.resolveCredentialDefinition( - string calldata id - ) returns (CredentialDefinitionRecord credentialDefinitionRecord) + CredentialDefinitionRegistry.createCredentialDefinitionSigned( + address identity, + uint8 sigV, + bytes32 sigR, + bytes32 sigS, + bytes32 id, + bytes32 schemaId, + bytes credDef + ) ``` + * Raised Event: + ``` + CredentialDefinitionCreated(bytes32 indexed id, address identity, bytes credDef)` + ``` * Example: ``` - CredentialDefinitionRegistry.resolveCredentialDefinition( - "did:indy2:sovrin:Gs6cQcvrtWoZKsbBhD3dQJ/anoncreds/v0/CLAIM_DEF/56495/BasicIdentity" + 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, ...] ) - * Raised Event: `None` + +#### 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 diff --git a/docs/design/conmponents.png b/docs/design/conmponents.png index d677834e373bf0971dee22c2258064466cac5fc9..e5d0c2d2af787fd4c1f90a4978903e03e2e5a95c 100644 GIT binary patch literal 69990 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 literal 70248 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%0Ae0~@TUQ`v&b^Jj^9wqm9|7&{gSPA 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 diff --git a/docs/design/conmponents.puml b/docs/design/conmponents.puml index be627ecb..5a717d34 100644 --- a/docs/design/conmponents.puml +++ b/docs/design/conmponents.puml @@ -7,9 +7,7 @@ package "Ethereum Network" { component [Account Control] component [Validator Control] component [Upgrade Control] - component [Indy Did Registry] component [Ethereum Did Registry] - component [Universal Did Resolver] component [Schema Registry] component [Credential Definition Registry] } @@ -39,6 +37,7 @@ 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 fdc23fb9af5d6926fea5f01833c4da47aa330612..7c2d886d098b41c33f9fa24dbe0376e68c5826ae 100644 GIT binary patch literal 109330 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

JmtqNyS4%uM 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

ed4NWt^Wky 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 UW=)1s#NR$ECVM*mq>j`70TxNfTL1t6 literal 121815 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ɾ`Uz186F+Dd2{i>oA)btWcPdI*` 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 W< [Role Control] [Identity] --> [Upgrade Control] - [Universal Did Resolver] --> [Indy Did Registry] - [Universal Did Resolver] --> [Ethereum Did Registry] - [Schema Registry] --> [Universal Did Resolver] - [Credential Definition Registry] --> [Universal Did Resolver] + [Schema Registry] --> [Ethereum Did Registry] + [Credential Definition Registry] --> [Ethereum Did Registry] } @enduml diff --git a/docs/design/did-method.md b/docs/design/did-method.md new file mode 100644 index 00000000..e5b5cd44 --- /dev/null +++ b/docs/design/did-method.md @@ -0,0 +1,10 @@ +# 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 deleted file mode 100644 index 67b59d08..00000000 --- a/docs/design/did-methods.md +++ /dev/null @@ -1,86 +0,0 @@ -# DID Methods - -Out of box Ledger provides an ability to use one of two supported DID methods: `did:ethr` or `did:indy`. - -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` - -## Indy2 DID method: did:indy2 - Indy/Sov DID methods adoption - -New `indy2` DID method represented in a form compatible with `indy` and `sov` DID methods used in legacy Indy based -networks. - -Users having `indy/sov` DID's (like `did:sov:2wJPyULfLLnYTEFYzByfUR`) can keep using their `id` -part (`2wJPyULfLLnYTEFYzByfUR`) for preserving the trust. - -Example: - -* Legacy DID: `did:sov:2wJPyULfLLnYTEFYzByfUR` -* New DID will be stored on the Ledger: `did:indy2:2wJPyULfLLnYTEFYzByfUR` - -### DID Syntax - -| parameter | value | -|--------------------|---------------------------------------------------------| -| did | “did:” method-name “:” namespace “:” method-specific-id | -| method-name | “indy2”, “indy”, “sov” | -| namespace | “testnet”/"mainnet" | -| method-specific-id | indy-id | -| indy-id | Base58(Truncate_msb(16(SHA256(publicKey)))) | - -The `indy-id` is received by deriving from the initial ED25519 verkey the same was as it is described in -the [Sovrin DID Method Specification](https://sovrin-foundation.github.io/sovrin/spec/did-method-spec-template.html#namespace-specific-identifier-nsi) -. - -#### Ownership proving - -In case of `did:ethr` ownership is proven by validation of transaction level signature. When an identity decide to -use `indy2` DID method we need to add provide an additional validation to prove an identifier ownership. - -The process will be similar to endorsement flow: - -* Author steps: - * Step 1: Author prepares a DID Document object (`indy2` DID method is used) - * Step 2: Author convert DID Document into contracts representation (which will be stored on the ledger) and encodes - it into bytes using `abi.encodePacked` (available in solidity as well) - * Same bytes are signed as in case of endorsement flow - * Step 3: Author performs Ed25519 signing using secret key associated with the identifier - * The correspondent verification key must be presented in the DidDocument - * Step 4: Author passes Ed25519 Signature as contract parameter -* Contract: - * Step 1: Encodes DID Document into bytes using `abi.encodePacked` - * Step 2: Find Ed25519 Verification Method - * Issue: We need to decode the key from string representation. Maybe we should pass key bytes as contract parameter instead? - * Step 3: Check that DID identifier can be derived from verification key - * Step 4: Checks the validity of the provided Ed25519 signature against DidDocument bytes and verification key - -``` -// legacyDidPosessionSignature - is optional parameter -function createDid(DidDocument didDocument, bytes32 legacyDidPosessionSignature) { - ... - bytes32 hash = abi.encodePacked(didDocument); - - // if DID is of `indy` method additional ED25518 signature must be provided and checked - if (didDocument.did.isIndyMethod()) { - if (legacyDidPosessionSignature == address(0)) { - revert InvalidSignature("Ed25518 signature must be provided"); - } - string ed25519Key = didDocument.find(key => key.type == ED25519).publicKeyBase58 - checkDidIdentifierMatchesToKey(ed25519Key, didDocument.did) - checkEd25518Signature(hash, ed25519Key, legacyDidPosessionSignature) - } -} -``` diff --git a/docs/design/did-registry.md b/docs/design/did-registry.md deleted file mode 100644 index d0e8981c..00000000 --- a/docs/design/did-registry.md +++ /dev/null @@ -1,183 +0,0 @@ -# Indy DID Registry - -## Storage format - -* DID Records collection: - * Description: Mapping holding the list of DID's to their DID Document and metadata. - * Format: - ``` - mapping(string DID => DidRecord didRecord); - - struct DidDocStorage { - string document; - DidMetadata metadata; - } - - struct DidMetadata { - address creator; - uint256 created; - uint256 updated; - bool deactivated; - } - ``` - * Example: - ``` - { - "did:indy2:testnet:SEp33q43PsdP7nDATyySSH": { - document: " - { - "@context": [ - "https://www.w3.org/ns/did/v1", - "https://w3id.org/security/suites/ed25519-2020/v1" - ], - "id": "did:example:123456789abcdefghi", - "verificationMethod": [{ - "id": "did:example:123456789abcdefghi#key-1", - "type": "Ed25519VerificationKey2020", - "controller": "did:example:123456789abcdefghi", - "publicKeyMultibase": "zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" - }], - "authentication": ["#key-1"], - } - ", - metadata: { - owner: 0x93917cadbace5dfce132b991732c6cda9bcc5b8a, - sender: 0x93917cadbace5dfce132b991732c6cda9bcc5b8a, - created: 1234, - updated: 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 -* 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 - * `did` - The new DID - * `document` - The new DID Document as JSON string - * Restrictions: - * DID must not exist - * Valid DID must be provided - * Format: - ``` - IndyDidRegistry.createDid( - address identity, - string calldata did, - string calldata document - ) - ``` - * Example: - ``` - IndyDidRegistry.createDid( - "0xa9b7df62c953c4c49deebea05d3c8fee1f47c1f6", - "did:indy2:testnet:SEp33q43PsdP7nDATyySSH", - "{ did document as json string }" - ) - ``` - * Raised Event: - * `DIDCreated(did)` - -### Update DID - -* Method: `updateDid` - * Description: Transaction to update an existing DidDocStorage entry - * Restrictions: - * DID must exist - * DID must be active - * Sender must be authorized to perform update (owner or sender) - * Format: - ``` - IndyDidRegistry.updateDid( - string calldata did, - string calldata document - ) - ``` - * Example: - ``` - IndyDidRegistry.updatedDid( - "did:indy2:testnet:SEp33q43PsdP7nDATyySSH" - "{ did document as json string }" - ) - ``` - * Raised Event: - * `DIDUpdated(did)` - -### Deactivate DID - -* Method: `deactivateDid` - * Description: Transaction to deactivate an existing DID - * Parameters: - * `did` - DID to update - * `document` - The new DID Document as JSON string - * Restrictions: - * DID must exist - * DID must be active - * Sender must be authorized to perform deactivation (owner or sender) - * Format: - ``` - IndyDidRegistry.deactivateDid( - string did - ) - ``` - * Example: - ``` - IndyDidRegistry.deactivateDid( - "did:indy2:testnet:SEp33q43PsdP7nDATyySSH" - ) - ``` - * Raised Event: - * `DIDDeactivated(did)` - -### Resolve DID Document with Meta - -* Method: `resolveDid` - * Description: Transaction to resolve DidDocStorage entry (DID Document and corresponding DID Doc Metadata) - * Parameters: - * `did` - DID to deactivate - * Restrictions: - * DID must exist - * Format: - ``` - IndyDidRegistry.resolveDid( - string did, - ) returns (DidRecord didRecord) - ``` - * Example: - ``` - IndyDidRegistry.resolveDid( - "did:indy2:testnet:SEp33q43PsdP7nDATyySSH" - ) - ``` - * Raised Event: `None` - - - - - diff --git a/docs/design/endorsement.md b/docs/design/endorsement.md index b7304492..ed1b60f7 100644 --- a/docs/design/endorsement.md +++ b/docs/design/endorsement.md @@ -1,24 +1,36 @@ ## Endorsement Not all identity owners may have permissions for writing transactions on the ledger. -We need to define a mechanism of doing transaction writes by an Endorser with preserving original author as an entity -owner. +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. ### DID Indy registry #### Flow * Author steps: - * Step 1: Author prepares a DID Document object - * Step 2: Author queries `nonce` from the ledger - * Step 3: Author convert DID Document into contracts representation (which will be stored on the ledger) and encodes - it into bytes using `abi.encodePacked` (available in solidity as well) - * Step 4: Author performs EcDSA signing using his ethereum identity account keys of concatenated nonce and did - document bytes and next hashing of the result value: `keccak256(abi.encodePacked(nonce, didDocument))` - * Step 5: Author passes DID Document and Signature to Endorser + * Step 1: Prepares a DID Document object + * Step 2: Queries `nonce` from the ledger: `IndyDidRegistry.nonce(identity)` + * Step 3: 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), nonce[identity], identity, "createDid", did, 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-8: Application specific data + // nonce - nonce to prevent reply attack + // identity - author account address + // `createDid` original contract method - added to be aligned with did:ethr contract + // did - DID to be created + // document - DID document as JSON string + ``` + * Step 4: Performs EcDSA signing using his ethereum identity account keys + * Step 5: Passes DID Document and Signature to Endorser * Endorser steps: * Step 1: Endorser builds transaction to endorse - DID: `endorseDid(address sender, address identity, DidDocument didDocument, bytes32 identitySignature)` + DID: `endorseDid(address identity, string did, string document, uint8 sigV, bytes32 sigR, bytes32 sigS)` > Optionally: `identity` can be derived from DidDocument.id instead of passing explicitly * Step 2: Endorser does regular EcDSA signing of the **Transaction** * Step 3: Endorser submit the signed transaction to the ledger which executes deployed `IndyDidRegistry.endorseDid` @@ -27,12 +39,10 @@ owner. * Checks the validity of the transaction level signature (Endorser's signature) * Contract: * Step 1: Get current nonce value of identity - * Step 2: Calculate the hash signed data: `keccak256(abi.encodePacked(nonce, didDocument))` + * Step 2: Calculate the hash of signed data: same as for Author Step 3 * Step 3: Checks the validity of the provided signature against identity passed as the parameter `ecrecover(...);` * `ecrecover` returns an account signed the message -> Should we add and use some nonce to prevent reply attack? - #### Contracts ``` @@ -41,7 +51,7 @@ mapping(address => uint) public nonce; // identity - ethereum address of DID owner // document - did document // identitySignature - identity owner signatures (EcDSA and optionally ED25519) ower serialized DID Document -function endorseDid(address identity, DidDocument didDocument, bytes32 identitySignature) { +function endorseDid(address identity, string calldata did, string calldata document, uint8 sigV, bytes32 sigR, bytes32 sigS) { // sender is endorser when it's not equal to identity if (msg.sender == identity) { revert InvalidmethodExecution; @@ -49,8 +59,8 @@ function endorseDid(address identity, DidDocument didDocument, bytes32 identityS // calculate the hash of DiDocument // this hash will be checked agains signatures to verify ownership - bytes32 hash = keccak256(abi.encodePacked(nonce[identity], didDocument)); - + bytes32 hash = keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), nonce[identity], identity, "createDid", did, document)); + // verify EcDSA identity owner signature ower DID + DidDocument checkEcDsaSignature(identity, hash, identitySignature); @@ -74,8 +84,12 @@ function checkEcDsaSignature(address identity, bytes32 hash, EcDSASignature sign #### VDR ```rust -// Encode DID Document which need to be signed by an identity owner -fn indy_vdr_encode_did_document(did_doc: DidDocument) -> Vec; +// Prepare endorsing bytes which need to be signed by an identity owner +fn prepare_endorse_did_data( + client: &LedgerClient, + identity: &Address, + did_doc: DidDocument +) -> Vec; // Build transaction to endorse DID fn build_endorse_did_transaction( @@ -95,6 +109,8 @@ So that DID assume to be written by default -> endorsement is not needed. Endorsement is needed to modify DID properties, what can be done using the set of existing contract methods: +#### Contracts + ``` function setAttributeSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 name, bytes memory value, uint validity) @@ -107,12 +123,6 @@ function revokeDelegateSigned(address identity, uint8 sigV, bytes32 sigR, bytes3 function changeOwnerSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, address newOwner) ``` -#### Contracts - -Should we extend DidEthrRegistry contract to add roles check? - -> We already extended `DidEthrRegistry` to use UpgradeControl - #### VDR TO BE defined later. @@ -121,19 +131,32 @@ TO BE defined later. #### Flow -**Schema endorsing** +**Schema endorsing steps** + +> In case of Schema and Credential Definition we do not need to add `nonce` as we do not have an update operation. * Author steps: * Step 1: Author prepares a Schema object - * Step 2: Author queries `nonce` from the ledger - * Step 3: Author convert Schema into contracts representation (which will be stored on the ledger) and encodes - it into bytes using `abi.encodePacked` (available in solidity as well) - * Step 4: Author performs EcDSA signing using his ethereum identity account keys of concatenated nonce and did - document bytes and next hashing of the result value: `keccak256(abi.encodePacked(nonce, schema))` - * Step 5: Author passes Schema and Signature to Endorser + * 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, 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-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 + // issuerId - id of schema issuer + // schema - schema as JSON string + ``` + * 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 sender, Schema schema, bytes32 identitySignature)` + DID: `endorseSchema(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, string id, string issuerId, string 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` @@ -141,75 +164,119 @@ TO BE defined later. * Ethereum: * Checks the validity of the transaction level signature (Endorser's signature) * Contract: - * Step 1: Resolve identity owner for the schema `issuerId` - * Step 2: Get current nonce value of identity - * Step 3: Calculate the hash signed data: `keccak256(abi.encodePacked(nonce, schema))` - * Step 4: Checks the validity of the provided signature against identity passed as the parameter `ecrecover(...);` + * 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 + * Step 3: Resolve and check identity owner for the schema `issuerId` + +**Credential Definition endorsing steps**: -Credential Definition endorsing process is the same as for Schema. +> Credential Definition endorsing process is the same as for Schema. + +* Author steps: + * Step 1: Author prepares a Credential Definition 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, "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-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 - id of issuer + // schemaId - id of schema + // credDef - credential definition as JSON string + ``` + * Step 3: Performs EcDSA signing using his ethereum identity account keys + * Step 4: Author passes Credential Definition and Signature to Endorser +* Endorser/Ethereum/Contract steps are similar to the schema steps. #### Contracts ``` -// schema - CL schema -// identitySignature - signature ower serialized Schema of the schema issuer identity owner -function endorseSchema(Schema schema, EcDsaSignature identitySignature) { - // resolver owner of issuerDID - DidMetadata issuerDidMeta = didResolver.resolveMetadata(schema.issuerId) - - if (msg.sender == issuerDidMeta.owner) { - revert InvalidmethodExecution; - } - - bytes32 hash = keccak256(abi.encodePacked(nonce[issuerDidMeta.owner], schema)); - - checkEcDsaSignature(issuerDidMeta.owner, hash, identitySignature); - - nonce[issuerDidMeta.owner]++; - _schemas[schema.id].schema = schema; +function endorseSchema( + address identity, + string calldata id, + string calldata issuerId, + string calldata schema, + uint8 sigV, + bytes32 sigR, + bytes32 sigS +) public virtual { + // validate identity signature + bytes32 hash = keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createSchema", id, issuerId, schema)); + checkSignature(identity, hash, sigV, sigR, sigS); + + // store schema + createSchema(identity, id, issuerId, schema); } -// credDef - CL credential definition -// identitySignature - signature ower serialized credDef of the cred def issuer identity owner -function endorseCredentialDefinition(CredentialDefinition credDef, EcDsaSignature identitySignature) { - // resolver owner of issuerDID - DidMetadata issuerDidMeta = didResolver.resolveMetadata(credDef.issuerId) - if (msg.sender == identity) { - revert InvalidmethodExecution; - } - - bytes32 hash = keccak256(abi.encodePacked(nonce[issuerDidMeta.owner], credDef)); - - checkEcDsaSignature(issuerDidMeta.owner, hash, identitySignature); - - nonce[issuerDidMeta.owner]++; - _credDefs[credDef.id].credDef = credDef; +function endorseCredentialDefinition( + address identity, + string memory id, + string calldata issuerId, + string calldata schemaId, + string memory credDef, + uint8 sigV, + bytes32 sigR, + bytes32 sigS +) public virtual { + // validate identity signature + 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 + createCredentialDefinition_(identity, id, issuerId, schemaId, credDef); } ``` #### VDR ```rust -// Encode Schema which need to be signed by an identity owner -fn indy_vdr_encode_schema(schema: Schema) -> Vec; +// Prepare schema endorsing bytes which need to be signed by an identity owner +fn prepare_endorse_schema_data( + client: &LedgerClient, + identity: &Address, + id: &SchemaId, + issuer_id: &DID, + schema: &Schema, +) -> Vec; // Build transaction to endorse Schema fn build_endorse_schema_transaction( client: &LedgerClient, sender: &Address, + identity: &Address, + id: &SchemaId, + issuer_id: &DID, schema: &Schema, signature: &Signature ) -> VdrResult {} -// Encode CredentialDefinition which need to be signed by an identity owner -fn indy_vdr_encode_credential_definition(cred_def: CredentialDefinition) -> Vec; +// Prepare credential definition endorsing bytes which need to be signed by an identity owner +fn prepare_endorse_credential_definition_data( + client: &LedgerClient, + identity: &Address, + id: &SchemaId, + issuer_id: &DID, + schema_id: &SchemaId, + cred_def: &CredentialDefinition, +) -> Vec; // Build transaction to endorse CredentialDefinition fn build_endorse_credential_definition_transaction( client: &LedgerClient, sender: &Address, + identity: &Address, + id: &SchemaId, + issuer_id: &DID, + schema_id: &SchemaId, cred_def: &CredentialDefinition, signature: &Signature ) -> VdrResult {} ``` + diff --git a/docs/design/flow.png b/docs/design/flow.png index f0367659f86eac66bcf7a84532d13ed8c06a22bd..7b26b8eb9d8493b6652b853a00e0ea14fdf16e3d 100644 GIT binary patch literal 212355 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¥#KF&P$8O`v*5prWV6i^b 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

    lx+G`Fe~P{TFbJ737P=Sl`6r*} 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 d{C8 zoO4og#v(4y>U4Xmsl zTJm#oJv7lav$8fdIj>`GYExfLgFqaxGrX%}wfB9*KDZ7#EJta;ocQ`l=aLfC6RwvM z3d!8Jn#GT~8JgzoyEQaqA@Jp^&S~2fgSENvuAUh6sGPPpy)B!oHlv~DOeT`BF66C%f#YRj%A;#V)vfXdggy~X{hqajhmIUBI+zpN zNG_cFe8K$$+B!+iSj+~QR_OP6FMiytUOOFMH!isD57$;y2R z&Ekj@VxbtfiSC%8YXr$}C>~Xl-3h$5kod#W_viCIT3^qJ8*BEHu};lHcQukZCvu(& z7L}#Y7QeWwtis?=6L2|8x9s-!bMg-HBWKocnVrg<2={UFC&iD>pVbcPdz$)jD&<*h zIh(UA{=|an_ktq^?mQ!(G-v`k)mw_s%M0g)p3gq|I^#wB(MI8^rzl;M?0il#Pdu-Z zW4c6UALbpyK8En!@U?gm#OoPz!H)XyLF$N8{c4v-WZp7lvj=KV4M_gD(jrh&=Or@G zhg6JVO3D`c@$tF?(^BRxIj*rz>vOwj z%wp+djugklc&0EvTMUeio_H5EtVa1DM`hIbyq&6NWen5BYlDPx!x8eueMSYu6vloJ zu1E7cuVV=^i(z$aGo*d>DlglHYew!$<#X5g#;Kp<`&sYh+N|UpcWjDpSJ;jiAs#DD z{rZLXQe_xj#>=z|0l7Dlol^`2H691uI)Z zwC5XWbp5_#-(E4?EPXG>qgQ)J>x}C&z4b*&9zAby(c7nr!YU;d5Qu%c zgXJERf<*|rmkcOWBHzo(9?U7*HIr}k?anBKW4$+pzw_D%rD%D1V~<_fB|OB*JD+CI z#NUXxU$s(y7ln?q#)-er?2Eo?st7!%&PXif%kV7NlDjF3^$M`avxZRpCh&I(!|w zy;VUS;W#g8{hT{Hk{l5!^7)H|rt?~y(p5Gkj=5g)CT4p9zfcJUgxRa3$bgxiykttT z`0qo!t~Bq4JW4a=8JCn?=7;sh^r9$Tww4IS*hEQ;2#14IA9{FrpI=Z4xu~0K+QY=|6o7eh8>h=Sx4c^*`iHVSqkgn6V$UL*Y?tDxA3~9Kzx0j8VCzI2v*WGBG zJ3rYi1Ox;mrxh1ShhB+#HRUfWl>g%e<@v(tiA5t zUbOYt^@_gT|Iq99_qpPYRC)8R%#k$brQ~2O=X^0QGJ2T-+X1Hp*~p;e=<+!U4~<#V z<>{_L*1UfE{`X2I_;hwIx(#Gs=07s0?~hCcjaaWu+9c@q9bISXM))R z<)glk#)u0pVYjuE#=p{s}1vvn9rl9247SR&F<{$p)lnHaUF+$*#( z6}Zwx)xdDm_in2Cz1BjjiRKa)>}y6TCPu~&nnkMRv?0x+SL|1RxQX>S&;BTLtFZL< z_m6a1?g}+8?yBDE%dse5ZTb}%3ztkP6_^s}#XQv=OnF|t7mYJ$qK~F`DcW2eB6J_= z%Bpl9iFBz?Rmu2-zG|%Wl|Ah?&4usUa=iuC)`4uKVwf)djZ`h{{J^$Nip9u+?W&~z zA={bm((0|ioK6mTD(=_)^+Qa}r(D$@1kHA&4Roptt&hhv+Gn6DQcJeirMLvKMT}BG z97Ibj7y)@y-U`!f0|XFCQBO~AZGOyrX^`#B6;stnA*alkc-xVQ%p>3FtdQI))hyfH z##sbsJ81(3n!55APUut$Wm$~CZMiVEn{_YRkAIE371wL6T$!mW<)usUE#{o5e(Ozd zjhV;2^7!YuUp0vZBr2!%uP;q`k#X8rF$SloWPF)Ldq!%h3!@I?>-td(J_u6%_%KR^ zMJ;zaghxM$(@Ly{Ki!K2VKES7F7vH zUZ1}ccPkKkR+6S$_PA>U-F@u{@d@+`XPP^)zGGbZT1Qoj9g{w}!DgA6_n(WRYIrmh zAvgO|S@Ry_t>1%!r)e$G=3cN?8W&IQGww1iM`Wu{qn5=ay2#gl^T&NA<`JkHfy5sdUT4<%$5|yu-V`NctliE%cIo+8t1PO_aj7>4=+!XBb zZDo?EIm{_ONoU6QbbA>aY2Aj|ETbu2?I_9Y&M`K8ZiRe~UDB#NeLgJUt$oP*lEr4r z67_MkSzp0=Fn)4=s`Oh$bMiGYd>Dpz73TLPH7A0@GH*I>lDaP$1q9f&A z%g0AL>?{>`p40R5L1NWV&dts;Ub2J>$lsAA!ZYQQ=8CQf58X-j=8^<`|pF z@hWaO_}I~}-V_S4-`04KT{dXE=B)N|%X*YPH7+56nUT>0)f6pOk(pw=hc0Sc_8p)m zv+aXeB;-^|4T~>-r?Kdp{lWWs^fp&9 zHho=~THiAz42;W-MMnv!kt!clFWV)bPF`P}U??HIByX=ALGYdLSBk7SJvHO$-U~lc zSEL+V_l^9{Cp34)CZ=)>i+eaeR5ECp^-(>B%z5f$x?_RNgmXx950-x6z&VPHzuj zLqq(tdhTIIL&Jr)tg4+?S4wDv9c(%pg!S1&#gZ7<0OvRa#v=xq?KcTRJHx|}b{3Vs zR7PzN?GHEZr;@#W+y%R_HP0{!HN9%CxF1f&4f!^&8^B2EyD3Avf3O?jEsu3s((~A!y$0(|%VOKGxGWA+<_wH$NsVxI|7AaR9Q#eT^JwAh^ zc6r+kAoqLe)3G`=t3gp;Cjru$X!=RihjqZ^jo0^EA&(BbkCW_vz`1Sj2=bj(W8QXM z8VL>+_o@C?zwJ-;;l@_qoU^cDbGnF|kcAKtkz66H`J?zmLZQ|B7&KrG7I7HSIqlA-7l3N3+G8eNo5oj;3E+3 zPruvjEE?~xMH`?HEZylHWRUxezj{wZ4R}-cnHN`Setei|$?WcaX32)S!S?OjtB)+E z^As}TIyL+75Qy^Y4+SC)T8J)&?#AouIq!)3yK5iedf8@LRR5*tFf32~8}9CW5>Zhf zh`%ubX`eHfzuNV9NB>tYqE~wkcagk-?LgQB@w>NiM$kTGA(ukz-#*M^Ja|#FT+l>a zg028v+;WOa7J)ElJ-72Z$Xx&GwoSXeJ4>#N*M^v{cGK?tUTdtRf=)@eCuha-w zmf%Sb=G;q$=z-mi>9wQ&;z5xe0EIc2a^SE{<#qy{mXq~Smovmf(o-|Yh`CESb_=7O z<_RdNZ6yJOtLDGD0007ti=w^!+r!=po?1>z378?bt1GVV@0HERFzDvi@1;Ro|}!nEYqhQ~Zu6ut55RyefvMt^9R&2N*G=~Vh6ZOtMVCfwcaVHJ17)V4GI z_}G?$oC!nj-N@qz1cs;=kPq&ShU_j4v8=f4xgFp@qW_uLd3%lQRR;YQ>Rv0)MR6+r z#a9a+?(W^V%kfA%t^T-K_Ci+_ZY&2yxnu|(Ht*wE^!5$dLc+i9?H^kRbC^S0sXa=& zOuQ}}eaWGRK6Z=`7w-VVF!+@6vc5)vtpCn|a=0h+_qOG{n) zk+NY|try2JD+5^9)if0{QfmfCCO09OxIoh$E&Qt$)}Rm^--+m(%Ab!}fAwyvr>95l zgRGP)C~Y`Ehd?}I_*XA_lKT~;sg8*F?75Q&#FszSo7kW~)tisYm*Sk<;6;-0N4UEe z{8|$FoL%scy1#w04POjh-7?!}Zb=sIS;R;9*qz)DvT8;`;@ZNPpXcNHaDn8whwep* zhk-%iJ@|enQX_xCnHW_4xQEY9byCMmArCK23m|G@fTWd^z&ayv5aF5*zd#X#3&&rH z^Z(xqvd7i@ar?hl>XV6ouGD|T&+nwp|1q)izwuJd?3)6jWoi6T!fKi&DSfmd1ng3L z;!vgEfZbU5V96vX7mdjI%}v9TI*aBm0#{7mt|qjXV}_Vdy?G+( z|J7umxSfx>p^_{{+vOl6C?6`>jO4mdUN1b1mQNv`>p`8mx7IP@KGvH&l_?YyLzUhX z%-ePEeMeD93N>$jmuI4rI7qh;#T>I2kz-T=*(6+KzN`~< zca7*1;K>{&{ra$cn;F%OC>656mrDr5*u78as^qj(i+*za&pMU$P%o6I?i``^Lqp|~T6=V47TmHcy_c=1;Y_}`uU zM5X5aV*7|k6Yf2Ysu7BCJx0oMGH1MxZcO+j-+c0O!61z$`f#k!rS zslCULcYUny*Y88p#MmN*SHB;?q?zTs^?L7>V?>HL#vOCh&$6Ew|Mnv*>uYpqfn4$v zTSUa~aB0;0raA7j_<=n=N+r8nO$G^72Am7^2g~W|3qGi@=RRsDlAD~#mipW*5k}Pz zE?`S==90vR7qmEt%Z50m^l65z8Pj^?@!2NJq7y|2=f_o`%d|r7W-7p@TQlaB;=YdS zTG(of)J#(2iYq87AZ<4*rcR2$HIY;eWp0GRORWk(CMqdE!(DfN)0hr%N8)F0vP7i< z1LW?8r7MfX-(qxtz-Yt-?4d(a2MbR|H##!aqHvp|Drc%}D|wcc^f-Lv5G?1=J&LhI ziA4MPqQ~qh?T-#OWdJWbj=r^vLu5Z&EKR&Y3L8IFF<7$cX1s5BZh%TwnMS!`p=|Eo ze)7ORcA5cK>XD6BBK)j=nZkn{KEr84A%4P=r$z|R?z{G*v?rCGO4jG(HzL7~o<=EJ zKVJx>!K5L(^~E{p4m)Q1ZUX0bc&z)gWF^Tlo;7@xsdmo(kC@B)g0dA^<(A>r-pU`D+$bn52fuTqt;8TtX0)<60hii|Kc3eD}C+Dd`fSgDBWh( z(P3@AtKQz*bIeol>XiHQ_VgArH-hlgkI|dTT3dYCSMBC&fxxE`u*ntkY7bVYWn_#4 z+|?3am&2RYLB^#y_=1wZHhkl?B{tXWKzoN4_D<5>L@n$(uZ`H*t<0M9!Vb$^^FPWx zTDVG(ZFaOhxu$96{hMdTEQ&9mNmu`oI|O^Q8`#C9wl_o#qz-qI5qAvSTNOFpP@JQo zk}avD1sDj=wKRFWh!4+NppNe4*mK%`E!FvgniW#T^_Ixu+Hd5mb1p6;>La%@4rkD0@Q$&S-!SMjR6ZC?%y`RcuD>kR5mUiR z6sT9L^3tC&YO>Avep+|YhC$t1We-04p|4aHre!aDhLf&875B6s=L#cTAWDz0(^HX` zZ~jrHF!AhYLl32Z{?GA!HTh1RRf2b8_SKMP*j`wf z8xX$#*_B7X{yn=o{W9$`!*YBo!u7_r*i=+$E$!MAdfn*IQ3KrL8+`fmrA#^p6>h5<0KWF8Zehd8d_CwRRnli z;+~FFjWmaqjTz1g526jb`KkfW>e>)|^N&#?pv|N~xI?W&E?xrTeY^=# zlk-9-^RVr60cP6-@dH8Zs5vwQ=GH1^$mp_``xXFaMFh)1(Mh(^Q{RriF7ZuB(|hT< z)4DSqr?j^`Hf-}>h@6^uTiszGDt^PHdW)+GSs1Z5@^-6=Ee`Im}M1Z7wX7+ezQL zWslvevj{}5m1F4#mnK^h24G28;pH(+&V9;CgkLi>B-O7~NjK?Iv#5cn3gC)d9`-K@ zG-sM=n~HLywzt9zc2r>X2R#aHY5X^UYRyA;7CHCFs3gdQlkhl~IB!+V*YVmGtn_OF*BLxu!GkLQc#M>-x{ki?`>Xx! zTPwmW&21kaHJmtm_3pV`Rt3G0XI{r-d=7Cam-mBq>mDhgQ4zL33MgR_H@$C))dD&dL7@I@j>pW@i#RTKIb%fEMt>YQEaO$ihc$Se znKwVu0u;R^)Q@ln{6O4_98qzPptR|(tJ=Es^vKzHcJ%U$04tM{1DVYs4(&j;w&A=r z_nbJXV8h<48nuDC)d8eDA1%jnVMV?yE|N*Vy+neqtS)EPot%@u4Zxm>GB)0h@_?+KfhyF0y zG`3L&kuP*Cygt8HU@GAbJ7J~M{$kt4s5dI zW)Iw+nnri4-D-eP4&(E3SebQbk*2C3fj1Uzxh-|9U5#$wh;j0?>Cf+Ss4P!Xb`Nc@ zAvVgMX3VoM$M@kkS(eEZHft796PJ#xV!|?X5-Xmh^x zFpZ<=UD4yOBgH))Z0~Q^@e|a5nD!IuHXCt%0J8fUO1rPX2O{+ipJh}p)AX;W2ld*M zUiE0jw`9dad9xwY&lY&V`>;qvTajAUHqfrkqSy5g;TrASS2xUk*Zvd)0ybxfh1dFQ zv2(n+FA7i5L;xQ%*8ZU8L6weQoFLo&@#gmNah=# zU-J~cNr`lr#hZW%_p0YAv#l5|Ia?w3y`%MLR;=X~emYz@G!aSh3}U@o{8$m+sQDi? z2$Hb#LY*J%B`*2cZ~BolmZ^O?Q|@Su*`mB)N0yR1-wUS90tjQQkOH=|Ml0TdoR;Su zb-twB;~G_8z4~dBcwa_XKtSue(zfLw?G+}{o73$x#lyqH3^$9Flq7LQi%I@-b#*sW z>RV7{rDprQuBl^a7}CoE>9d96=z%|bbJ`B|#87WjVNPkcml22DVD zMH~qdQeBn*0IS+DP=@K-g?@f6gI~4YTH^H@fs}bSb+Ua%2y^Ew6k@`$1{b@D=D_Oy z@~YXs!Z~PUx-*7eqGw5!1B9(7!-~f4{93#-JbLc}YhE!>h8tVwn{?H_V%QJ>WLGWG zlDe2t89}Cu@*rj$7G)*1)P=BA{$P(?>gbRTyIKSQ4;88(Nu`~ZgS|A|{z2;$mu9rh zjJg^7fQ$m^wGeR!YRQVAk*Bp5*ezaEtiNR4hCKmK~oSKrrM z?^b@|aOt!l24+D|`T5M-9B1LEY? ziSKMM>X>~2C7?>T3zLmy?gRh>s6|ZdQ+ahz^K9Q7*K4V{ekb$%xU5c#=2(ho=fU#4 zyn+6i*HY(+0>M5&KygvEtEVf=B~dXswfCL#){9KWGfFt*c$6}Id(5Rc^Uy(}QJZX-U1~eA#a+Z(kfLHG6Cj;G*Z6?MSt) zNQY-vqw`f%IXYux$dB;hERxyRm2p&;eI@zHa2faqKB7MwG+8)2mEb{-tJ4&4%(vi* zQ|@UsGFJK4?O1nW(lA^j@X!XCm6@5Om>l%lV%w%WO-oqU)GE_LF8TBwC2LS|0e(c0 zA|%k!wxpKF8)z|BNT-WWS3lv}J`RbPXZ>f({*kh|ZIE$pgf2_l8=+;+5}V~710JX8 zt0Rvdo9ZuOj@}eo5^>AaJ-voYBjH}y?qr#8{xPKbcz^kq?X85cjpI8N>C2&%4{FL@ z4qby43i1kE$?AMF1K90q&7~IEg!Sc_M{6U&L0pmiHq$&{c6r0C6QI82vfVIIN#k-2 zIg(jZEwoU}AdC&;oI-6Jrv5n9XRAd_>6K%HqU6!L58xgOK=-@rGlyxWN6#KY(Q!8z zcD!FBP{|>VmW;rs~T$p7$xiv-<50}O2eaET;*(+wO=7*~W>)!+g*^JgwIJ9Ag zD(65hm*OhAbosLNXV-lv&RinrMm6k=c}~5VwW(LX+6o#TT`ISJHxkDkQN`=w9tKB$Jf z___9#o)W{zwt0JdCq&ra>XoS|Dbp>2w*}Cd4cs4TE?ZOe;SJaz=e`2#=wiLPw}(!g ziH(bcpO_g5)+&B@5Fzn!aE|S3%!IH0zVQW|*pxy0KlbjG6zSV*4gU0mOB0rPD*c5k zn>5BGQMXe0L0piKu^s5UC$zaXHVqADwd>Nxz})HN2&ddMb%19@Q)%Xm!D64;py=GB z;XGY4;AFc!S1BEV6ipozx#V7gra~Q2IU~m(0ZJ;nV$xkOja1C{n3r(Q;_lf$*=DYv zb2cQL-}*Hn4-XGmUf2X89G0hvk^w{yd{bP4o~JD-P~EI0-e;A07H5PA0vivb%~gX& z+I&yhoCBwB{7b?EWIa;$QI)Zh4V~&l1+`~^Y>F(3Y$G(-t8_}H{f^s1A(mslS-j^p zKfO7wqLv$m<#~wGA^PwPkXjN5`Mu%?Q;gG0nS!xfb7|#zLth0MXo%BKx?uRrPo`gr zwnFOHz10oJX2wcJ4$DW~z*}>c%`gH5AJqo#kQpB@Qg$YR2=IlxP+`218tjF>m1ER4 zdkTfulN;sM`rmW{57SQS+`FjA_T+6Z026Wz^8}6kLE-_v`h_+#0S<}Ryf18gQ4?a8e*3`O#1^UL zvSpo-WZaSJ&vn7Log@DQAgLo2e?^kqs8rY$A{g&GZOp6@suEDGuXbe>#vUegeiIhP zA>YB3k9qI7*19oQqG9&QsLgTeOUI#bfjlli*HXcu0fh@(atD-FX2YikkPLgw&{64A zfI?2?wcMm}vf99FPt)QuOPJ}-si~h)j*pMGnP?U>L&7ea`m%za?JrX6m4PJ`cTm0p zafCCpZ7JRPca&1h!IVS=HxE}v3q=FDawfUW*}@{!8dxKVjwXtEeWkb1u+t^YKsv6H zSY!z~&63I8Mk4L4T2eL4xwM27+Tqt(6<&BkVf;8f=ORpPFIs*hF0bYMJ}HJM57f7p zbc6NzP8&9b^dB)_DaF9IsDWCWEu16c{VeWtCI?pbR^UQj3#3wYv-YBmHDO6QYG*LK zz&`|<1Z62`c1a(z%}j9f3^7X1_BZK4cj0loYD($wO(qo7O+8Ldxq|G zd{8@wYOD9Py*$1HN3%rs<7{9fra?5O}d8*@BcyQQn#B|^s#ycD| zezh^|@rvHYL1+zyHl}$n1C1yvo7rBw=}vAOE~?&K!w2qozaY)t0*i?{&r0t$%`a#HO(f}mvsbS7xjdUZ_L z(wkqewmd_p(!+%(DJGv>_A6OTJq?`-PB)LXDLPhEe`%^UIiuqJ!p+8A!?H3(-$@8r zMJYVr9YwEqCzVG_;Vs~bXUE-u%VQInmZNGM$T>82RCzpoa@6*2RcSVJ&0eM-lhdvsWexAQ2rfv7W zTNETXR<)1sxo8gc?R)@8_NjtZ1|aadN~h0Wh`%WXwwxhumDAx9O}~6a6RhXR_CEY% z`pKteJ68oQyd&ZPPFnrUq+(0n5)%h)CWd_HQFry>^2Jlc_|D`{_gp#Gd3UY~)(B(S zi#QGVK1qsz_e4`OMzkD#yj@J+K6_V0LfIelz-!UENrk`bpP^2_?Sg-ip6$?7G>@R_ zj?i39*mMLz9Ju?urTh```f8$gf4@ewV9eoDJL_dYsN(KUJ-KHYI@%7dqQyJEbmy2q z>(09l_21>>Z{vTKlbNOWAr7AUT_yha26jSwDQJ`?Kf7*~9kT`%i=HP9#eEwFN!DR4S+ z`fdb~qzoC_=Zc9|{2oH_2`^QCmXYtt?8giK@%g_8PY|@xUv>V!kDK@sUw*Qkn~f2? zAF@sMVDI%p`UTyeCYlIwj;*wy>Ul3GwL)rKhtZiqW=J=XP?C04;DU?xjemB*Xc)5DS6V`e2b9TgI~!IIoetI$ z#Gu=6GcErx2h!c&^)sfjON&jSeJOcUjoOlw&Pz&4)&z4YUttM@nH<;E-@P(TflW_$ zD-W=%J5EQqIc7427LsZLVRsPq;pa#%gJN& z|j1Xe3BmJ52{N*p%VuJplMA~oGP3v_BXDW|MDDvggUioSrzjT z${!330NFbM(>xv|%r|_0(v;U%9Aaf<1wT8@C4;fr4Kr6Tb)I{EcWMOeXKuopSFK*ri-Db+RmlmvwL;2v_oYrKueoNY z_SIK7=N|$gfoOFe<0?@xT0a0^xgzM*(Dic|r1j+8jpZ3#vJ{QN3;|yEa0A-Q!|{!NrR7LbFEa%JQFdR(3=|_zU1=!^2 z2JICBoh#gz)w8fKOwfy&j2vPjG`GGn9>od0V!CqETTlh-*90{}ne1Fe|mq?enPIGD%Z$3Uu{f5`P zA65yXpZUsocTRGriZezx_`F6C$31%IO&BbwnE{cEaniQ;k=y3iS_rF}gl{$pBje!B zA8`Kh<@pK9E2nA(uPr}f%pB^1@t2H;aI2mpN*`3Azs-aBu*AefrP&^wLF9_l`XV@J za7#R6THe6;mFw^)RK>B4Mi|%toecUOva(K?1F*L*P`M18MWgmJF&pGsjTpiVQzl%D zs$4XHFa9a(L;iUevtu8b*@sWmBmz(wJl5${4bXdlm%mC+cWr)T4l+qgf~?p2SfopT zv>1MVl1c^&eAod!VEfI#{`62Z$Y@j;&@Hu!2R+%#^#JxTvI!DRYau2Evwlw`lEIhJI#balyvl=D} zCC*Oy(ndy;Ff}%8HZp+96o?pPf$bn6BSR*ZF_}?Gy|EC9?{@kod|!dd0(d>Pv%PE3H?kxb!-vC^i6iXjTU$SWltD7`uW?z0 z5f<1LULBE@&M_k$S}x&Em=0SuXxnZ%J8r|O2s|1T9cRPzg7cO2M0H~fetErY1d<|C z2sv1Zv|oI$>H`=A;ZE~AYW>6Rxo5ctvnXlekfD3JRy+kQPDI=M-PHGwlDKDRgBP@a z7A*rN`0>Ul;7)Q1=xP6|Rt^1|ip=)iSHCf8=;%w~&7Xd0o!o-m2dB_)BTR|p{?vrv zfYV+tk$pIYf=67y%iW;iai@OD$)@8gvm-P65 z)(8bYcu<)I2&;_tP&vLB6dRiV=0!-Kh8EF_ALH0agnGfTT!~2Il z&`quX6%_f;yKiT-m+?u3h^b+G0e+dH)p*jfmeo=|k)a4%B2u zUX!j&T_Dbl+Q_wF#2kuR))4iTYZ3obp+Vy0cGLGP1rq%b$|raktXKMMg*T?Npx!I; zvMqvPHPLBf*{H1)2IEh2X{IPy0wpE`FsChvn@Kjp)|PSx1dLyb2V1-u6? z{7pvtSF}p>^iN=s0A3h@;m3YuRuEP0PAzDE_x&C1{!ez3HfCsn(>aq4(Z@FcWkMAq zzhd&H;LCOJY0)?>%H^j_Hzxaz0VMD|%~h;hLuQSSkQU7^TRr)ovNUowod6P>bSD?hu`}apW~5MU2zwjNm*?R?V5L@@H-%m6Nj}2eo+` zpFEc(Lm&dR)~;qg(-`%%0MC^vx>wuL{qM5d-|U|d34z{Ec3HajK(>u7pbv)W=zJIK zHZXkBl9F8o)>D8AocpXhNVznDa8FuJh{erN$4iHju`8v3W|mg8{Pz9gREI2*0|Xa< zg&;GqvS~+>ds;F-fvW&1$9Va&Vrxa}gFJ4NM^JeIK76_q3_P!g=`giwwgI=zv`T*1 zt5;1)itPCu&Z#ho36phs>iHH+Qynnm-;q^zLg17f4jii(w5Nm=$zrNIH*mt-Rdt)$ z`U*dPDl<12__zE1_;A1w8;3?gHlSvhQkRyJ+E{Fn)#b)5)<=jhI2s^`MJ^iP7Z_P{ z1tNe?xGf{opQZ2Dd;A*LtJw?N<%OY2|DQIOQfu40P08u z=>l+6*LWp`Qq(7*3x&kk@B43Tr zD|skOns5ZoeHo0dkT{k8y^qT{kYCM4UDT% zpaxqGSWG$YD(D)aIV8g zQ4iuw>IsDzh=Wrbo8O-jme0dheC_W~c=qZAr**50NcPl^D3~`z4WpRn1w*4~G;E!d z1g9UFW@ctKH#esOe6;Pit33b02^OQm?i4;Gtw7o1TXze=BC88+?y}jw&nN%HjIySC z&sy%0g*!7jpFTIY!t!y{sHWe43_GxKw68bcvLdJr@{H5IwUnbIOn1TD0Q&)@*y*bu ziwg)3$96~_BD`MmI7~ZI29w&#$S`3SXPZ{vge^-SYC(Q*^T7qmgS3GN?eBuYTvyi%hT#!0{BGWiS*iy|FUa;QMp`3(o5HgtPj~ z6;!eqtw&&!bbCRKkGKs-VEi#*Du17%Z)}fN+L2w-P5$p$@33PWEfi5V!sL17kG~9_4oO!+U5lf|qX=)<`)sC;ikxH}Bm#8OO zAw_J-Cq5p#ckkYy3a}r3V7s94nOX5Z(7 zzYka81vNSSnF~7o;O&{K58vtD14;pQLJ#mOnhrBLpf?n)jfTQGALGLvx^OUsB~(wC zFYg6T53<;4PStY}g=oy6VzN>WY*aqJHK=f?p~BgMWZ(kebP?~x@|Q#UZhanTC9vXE zLu!yI2bBw&Uod%Pq>E+Xnq?1WuPvI~J(-C^I?mTlYVG4~rGmSzK=FVJGwPd9a!1Hv1QAes6%8|K2=e=0Iaao&{v<4_pk+*XZt7{_^yBHFA{td&Nt-t8F$H(4uz|Gub zXSutN?kX)i`1E#!KrL9{Ak+YYjcD=teSt$vZ0Gu^RJ-!bBd1rW_$)+I0>v`Qpq_R* zeV%?Odz^7v22!&q>xOsKGtSw8l7V|jr}gYCa=fv0(?iF}X|ZPt*`uc~5JT7JIm1QtJI~N1skqDdx z?4Q(6^S4GgBmc7|^OxH8)y-$u)Em@pR7tH96wk{-{MAVKi96!RzkIQ6U=5eI!`y z-8)x*uOI)uC5;x10rC(B_&#XX?)8N_G0->w85&fBnPxr)whp6#;v!Y+Drna@YpScO z<&}rM{`gpAidIQ6Z4@(E59IXMtd^j++eGLlgxx%A$PZfJDJ-!EMrc!TPz>;*|~h z8BX~=W^yXc0RM5%&6xx!k%Ko2r&0@Vc!9y?G!~nXkZ_t+{v02l9l(t)I_2^|+RmWH zglj6ldcD7tFaK3eCed}v0DJ_FFz7@IRef$7RJKTZ*X6Jrrn+LH0+#X?bp-1n>dCObDzK4vpaDgF&545Ut=GDR9{s z1^~cyJ3Ue1ap}{YFA-f5X-1s~_++E!huo;L7CzQ*4X+s;5%(sii&)xRXz+@Jz4OSX z56<8^{R2G7A%YGz%N5Gy0L?%sgXT&{81D=52*HrZZNLA_QXtx;ZQuga75v~fh4xzO z<3nwb!=Oayb?A0jK(_>L{vtSjt{-NQp;zt_AbOyucg3LbJIwEa3u_qH@^fi&uthbT z&=7*&2`BXM$O;G}|N&TSSyM(qIAR z)^ocFre;Q}Xr3rlRMxN_3%B+3ftX=gHtc{C@Xmk59pVGv3U(S$OZ*#y>?pYSAYRC2 z(bb;59O>~<&mI>tPvZ~)qHc) zjx09o!X0$stdLr&r0Z6;#|FOc3(80sjkyPWHY^LvGz8z1~bAR zPc6SgWr1)FKGt;*ZeNA!jxDo zokMzBpJ2&+VDBkR--I!8Lh=jOIJ_cNQ|rOFTiXdNrq^SUg7etI-wNTd%*C z8J4}N@9eow=;-a=!&xfV<5}Z|3~iY~@tjE-;sXa}O=i$}jilBx8|28>!Nwe}^!ugz zb%z@FiSm!*T3KhDb(7|WQvtFa1W&Fh+{uLKt1jD)T`Jj;#=IN!KAZu+HOo9*5nkDO z5=+xwHz_CH!4~~+FDqWfx<#6IW}rmN>})PjROl`u%`ld-tfLNk3`I#@L<9jdS3ROa zb=@d&3n8%VKbHIm?1&yYkXed`d2mX@a=@=pvc=E-dZ81me0fawQbb%6FCN1Z#w${TS}w^}Sz zocdbq)7j1pk!gLPCFiv}6KYc5UyaHXf&=$3caDF@wXrvZh=iew?V9$wbcJ&5tNdE= zH-OqT%j&qaq_2hSW;q;a+5!?e_(GBPa>O=&^Q_Nz-Z?xf)l%E)d<~b^X)fnVD%;~F z*C0Jq2e4W~Zk&DzqFRue*(;F~Mf8CF7{6YCt{H#hz&Fa@w6E7sYR8?$cNp(IF$@2q zbp8ywAMEl#rXJaP+VQ%!w$^@WGLTD4^OF?}eQ9Jq@GxO}4tpWZ0C#XCfC-rhWIi-> zkfYcs-3VYq;Gu*YkPF`G1RGWvE*PF%gC-Ot;=yZRc2L%|i`(3^0BJ_d>5snkRb8=! zPS(9_gIApvaM~MyVPaWX85tpqVF_59L^t0n)7SlIgoVH<0lgCpy`F|lJs%DOW>KPN zG&@f-3(WsCflSSkW)ypXm6_WrD_w`cL0wnauK0}3S8t*NxMiBDhO|_XQBD{d-h-KL zj;n!XhC`B`K(7qQd$jAc77f*(Vw}Ln(QqnXEb79Lt&Rz}{?uNP&_h{&=(s{UHSiHL8)%>U$$ig_+dgnz} z)`?~*E)5_?Gp~;$qR(1E?0~?0nBeR;-_1qPqFYln)Cf|5vRGbmt`Ff!0EQ+Syb(+A zovym#be*iK+FBFvzN@GeSWSTN>k*@F-KHqFOqNK^-#z{Cu%OlW%c}x|+VD^~O&p6t zccNHcz4%jY`?X>cuwuQ9xZ2j5tUL#1Wr7btt;Ng7-5QLmuZPzi?nSjc-ZTVfo>md$ z)0a>E(L+x>KZbb%d01fD{0!}}e_A&N?SGwjCw#<#^Z|YPTkV#@v`q2pAbyvNH;!)t zw4?Un1w-}q!^g=Rf#J-Vgb~cG`o}=k8iAqumK?E@$vok6ujil>yL0MtH}})GgKT>hIn-IrP9Dl-MIX@s|2I^2we>@68&wN!-)Mj@!66d{pWK(UW>i3- zPQZ5pN=^iR*dWk3^FPz(EKNwSHGkA#ZMkgO20 zH)S>CP-L%C_R7po#xX+n9yzvS9OIaW`#MG+mCxw&{oVH;_kH)@_wng_dcR-q*Xw#+ z&+GZTo)@iJW)d98#0HC@*fc-ALxg@ns~?3M?XT_hg7JVE?h2VGsZ*0;fqS>Di)W?w?K3rR zseeHk8hG`}1k*QhnfEOC1lJtt< zI=4nQB6ACP9~8{27L1ma(=$s=+~i}7QPHCkB%A5B?L6U5Ot<5)`%}6jgj@GT?0idh zuz;NS=+~%_gXWQsBF60N4Ly$B*vt5#A32=Ao$y?&cgR)8BQjeKNnJX6viPdNZ0#-5 zinMZDuF(X|-tOy(rW&KDrRfElU=NdCv|Qf1oZkJ~xP9y1Ei?kI6?9UkA@qq5TH`dJ^I@G@~&Vc(_bObi?JzLrU) zGkVZ9O_Q2a6=18crCGpgBzZxEr zm^5WZ%Mc$Xb<&l9;M;R08H%PRXE~%KR*#tOK&?(yNrhL|5%z*d!o@n1j3I)%yZ3K- z)a6btYhmGm7SJ1QZ=<>}b5&0617-TdZ(nm4r#|5R7=bs$hTQdLlG#PwoV$~GQU;lv z&Z^1xDxh_tH64cyw?9cDTaE}v5%p7a`%z0^XRs~$S;MJHSk(|7hcjH;UI)hJ&U09t zxXgEifWW8U#OYp|K1>7|-; zFOW1=Ul$Kdcqv$l2XGj6eo_bx9Re@Ditu1PFdzr_=%M2b?Cf@;b0rK&Xh+Er4{RQ8 zeos!$toagy5>B8UYH$-56_rbUu-k@5d*ovi+FY-7=AN2bH@Px8A(-@9wQf~pB>Dla z4Ow!Ua(vS!f=^fCPrpDvsKPkzl@|V+#f#4xXU{*^Zm#N!i@bF82^0AE6}vB9y(*f6 zGgX$B7OD*5>(a)J}9&Tv} zeM-bj37@&>aH*G4*ghBW5IR9$!DOqO($)w5?>JogGh#>dO4F2>Bv z4NY%3sGOc+_Xv^aLSEJ+oLBLgezKfhCRN8<&y**3<{pt%mi6qNZ!c~H>A8rDscR06 z@`)>zxbFe~L3&F?6*Wy41cPG&*I-J&nx?3dJJr2U#}d=rZ``0G8h^Iwl7V*2r@5An zpz|cEeHAijiEWHr#=RYbO&KZf)SNbRj%O9>4;0YI0-FPCmCc8KspI&uK(2(~N0Nj(p^rZZ+KjA9NTxd+&U>*RGp3b{HJcW0LWDhDz3lT1XF^cc5O; ziyc^2L6MBJTx_dhi0!?g)>eY;GRv=f@e5Z_qM5?>Hz7(c;-;x9(OOU`RA=XG0YL~y z_cky8aPeWp^C&CaR2%+XhreQ&5BBy|CeVD!T`10#;?SvAtw;2=nRU=~JH6h0>(=;r zVu(}KmhV*E(~f~Hyx-DCwURT~W8CL&RADaY-?VH{w7EQB?x&>y#+|3BY8K|F($fRy zu-T8Zp<2`+9pi)Cm($}F1fB(xr-wgxetx9acMwogK;UVvjP_%0JbNF`5>Pu>P3LGV z^remZ5|b^IfWgJ$Y$h5Lb(=T_d0AFd!eTKmXe)KQ@YW-sHifp z^~ZM!4_T~0JUi=u@nCniny`=%(AY)bX8lolsQ#2@1=_^w4cjK9KqDxSMcrIo0W_v-ekfeI_ z=usfMKI$nh&Q1`;=jKq^)zwC#hU#3dNl5IHvZiD`b?Oa-xdnfJEV=ythg9949=kR* z$?-(b%xECpMvaNRymEjqJ+wzdU44v7?|joUIMxTbwID8|U45t}hUWda&CYWlvpe%n zHzlOg7j7$Mo7<%{&;T)nzM_h3M+V=UO-LG3)*>fdS&|0j+~8NQiuc6=y zi6da8LWD%?2y6HUj%$~$eZikz+v74xsWe1Kte$ISzoG1Oix5Dg0xLZlz?Jf%9LtU9gczNwAJNF#n~|2dNdg5f-{5dTya+7k1UT*=3# zMl2WWxrJnp8*N9r^(+rE{%k|S;s`1N?7S~Yeuc|Vka0C>a5|)j9gevC*!mv9jl<)c zMX`$RcJvi~Q$D;AIUuX*F{66K7J1Yq?%lg{yu7h8@iaR1JUVvuQl_c!d);-OJKvKM z9Jy09wDTBu%ef)*(so@sM|;b&Tun`{$h(~>#F6;al)G4bpr@cG>>WaB>S0Ezu+S!a(uRgzcaWPgQ zya@gj7WQ@C+G6{ zcGyfT*mhgD3KQ0MQ05(Sk!VPU@3(I~wF9ym{?If+q1&R708V*2AY4c;g5@!+w(W>6Hz+8U$Evm$-=jSw}dmjg9Z#k+HXq4WZGy+cM3->YmFe(z#H&u~SmF01AABHRYxZqD(bCDjC*-#swOhtLLd(hDab#_tvE4_yiF z_J;y5FK6L9&p>((2loui2McTKtSQkzwirlLqfP;!KY(A~pTPprHZn)|D~m)f+KZxr z_8V@-t!!LRmiOTS*}b0!trlh~ddm7{$KQ(!{3}>+VxFmZEhWZpqUcixuN@<}^zm)O zK_Syrm3oY4c8lQlZBz2biAg7zi+8bfl8ztB-WlP(W%ag_R%$1+EB zFXxA!BR_FHyo>sv+A?e)58?Tk)mM*jiP70k2X?rU2QK<4+#x+E5$_zk$j^9xaBWvY zm%?_scdu5!*o{!5Vg^Ej!pM@%I&+gdwr#6yL`mb5Yg64EUYh3sBQ&~;-z*rI6z#Yt zCx>xm$0i_oXVFPDB>5lBKeR4N9W^lP}7V_MxaWLFaX%MgDe0*;XS)jkK}T`w5ryw=O@{+ zk9hQ#M7bIPN!O@A#q%+k&BxELU=e3FU|84V-SGUyi!;m}hZAC+iuvyZ^3167lhFMA zHxz1Bry^Fu=zlu_?o`*1HQFnHwS&eC|Cm(wjLsH|XjWJs=S-i4q-I#cqPiVT%)%}_ z9Jpv)>iH58kpYCa5@3 z+KrcdK;MtP$ zVJTRl9XmeI+AUNb$-7o#H2<)*I%$w2NiR4G^$hKCGRp=TFx;2oCOHsJIy2C*bOjsL z7hI`2s+VWa?`x2RD&cc1W6FF`_}t>Ls7yhTE3=T0kS(Tg_q@;RLx1jo-$1=$WU}>( z6;Pi6H!Nu=Wi-Uh>V%8SL4J7wm8AnhLvCN+0bmM;vBN`zGT=$=`kcqyqy|`-bZ09I31sUvA;At z4;mb^hvIV3oxSC#Mjs6xHnwLyoSGHgXmkvdVjOtPIpEhB>I!#hi^qG6hE=7t*Hw(v ziiu#l!v5^IbBRgNyCf(}z5beMQuyQK+BL%_cXtPMWoxT=)+noPbNwVm7hBhB}0GH$h^)f$ud(B4GMF#cOeGj<@;4>#S0IK!l%)#}H=45(N zPe2%(VS!9dogYZVprxY|MwR8=1{35NZH7tEc({hAi54exs<04O9zTCj&i}F7{FbS# zwRIALnl(*-siQ@ji;y}cjQrv3L;H7{E4#4e+2&M{xj?S3LIL-515pMA3GRd-OytXT`|G;Xd_%ANC zrnJ!A+m`QyV&a%1W&$urK*P+iBA_IQD=1p}>^YLqi2Ki0)bS#Kj+nN zZ57YZs*xy+Ed~oLQn|rEh!^TYJPsTwpbw6pOrZXcNKbgUh>SR}vx|-9{#Oa{Zm{-q7zSxK{Nn zU^M0d9^7=Ews>4hp9p@hQF7h)o`}MKuJsPFCvZcA?oPfapTnIRyEn!tvQ#2Ock2?k8 zR4q4o?_v1EG7P~wgpJGyJbBmu%8&|zlRKz^Py9%KxWU|H5L6IJ4jH#dO7NBr*Pe=2 z$)AIAgUY9Bj2d>>YKuf&#!-m4ieCAEt{qk0$b7#y9p&)ZfQ{!bS9qBY(rB#H7Sedx zrB1eKe2{5=k1Q%Wqc}H-L2)<4+acIrALb5PAam8yIt3{x8p^2e-^bJN-Pw11Q<}&5 zCJyKo5LU4sDr=en-mJK!gz5BY4Tg+fzumF&Cnh?S^{S2r6{bCqoA^we1m#c+erJR^ zIk_~w)M@C|Z~O3P;DquG80OWv+Vn+9p1d_ zoB6g?q_WmP!@(MY%0BukOCQzc!xA}J0}aJHMLQ=4cs1Td+~2`XZk6=-Iil~;CL6wm zvGTfTayG5%j|yqgTfF0*c6IdtkC>WsSXykuM0YLe7KacGFZ8i5h`NlB|BZo(k2 zai=XYJGOFa3FNV|u((2f>_TxFR4a5_F1j*!y?(9IJ`G*#xmT{%spr+!zJqG8PdOj5 z^*T88n?pILF=^MKg?msAL!TKKh!hYqa#2V!;Tc$k(Y7%wFnWR6nVaykNab+8foNsa zYV=)RCqT`WY`wt6VN3nL!%*gbC>f$wIq#Bv~aw%0)wnc9Lf zbqFvn^<)9YH4(WDH2k<8@6jD=AR0|X#8@_5@Jz9pmgHd~Pk&IG0|E;2<(B(ktjUDHf9%RCGv!?%3N{124Hc9qv> znUtD9#Q?Ap>MisPX$f{clFP{WXVknQy#E=-M8!8vs$I|z`kG-9HFY}pzkngiZDgZm z1O(mSzx`#=->ZHwHch&ON$&mzJjh>w9H+y}a6sVkwl{N3id+m#Oo(Z&Oyl&7%TKn`15AbI+Yzo;gy$AMnx%p;dqD-Zwrw5~7H2-1H4cKbB& z(0B6Yk5nwa5^yfy@2inNePCN@>dL=iZ}$qyvaQqz*UB;hhnN!Jn?-%!BDQ?gl|ZMm za;974J5PbLi=HYABH(D{=s z;GpdJ`k?8U z2`wJK_GT}kaok(_*8whLIQ2JpQ#?)Q2D1e|fG=e{TzHwL1BHcUa%u}Rq-f;aR4A|j zUT6LDk1i8`jr z#{1lkp1M*-Y1Utb0=W4vzzvt4Zn<*h3JGO(Zp8hPw2l$b*7rBDY64gXfe;xLRlXZE z41ET+sGhaI3ZF~Mg3^da`e z9(0oj^u;AWk>8Eqwu?f|wEyeHW1)4xg5Z-a2f!XpB27mO48+2(Q|3#sXjMlP6mU$~ z;F}@MMn`n&7g8j{W8xIKn`=@TcD!L&;oMdU_#esuvX8gXdA{4YfX45E=<8U-da6(W zVSCSx@kSM87N&@10aG9Agf51b84%iqg>+J4KPFG!o+t(sIo%&>7op7Ww{#yjHP#87 zEwy8=cI(G)^;-@*;4#;>U>nmzOZZzEjilzTC$cx?!BYZb`2tw;=Hw@#ZwJRYY@@07 z4W{I01|7E$ za)0U96-s=y{EycR{Bp^yN*$KjO}|@jE^H=nJiW~HQbFuVYs1z?wgGH~%-bIq`RRS2 zz#^`6VS%!K%SAowm)nA^^ysa4{+ic&SQECH><$2vMbxVkNsVsk;!9VNHCa~&6wRh~ zfk-%PmkOJSg0VK^T5X=r|1t>z@4h5*ML;UPip^=2svrjRP}^a1xb6S}!ToEXh;W#h zL8+4D-+v6Y8c29Y7vS)*`GUyx@tE*)|J#Y#RuoBD{Uknr5 z#>v_A^5sj-O0N$NM0-XWGE7Q+S*_ZX?u&gg*o%#Vf{v=Hsuz>Z9Hi4j4g6qgKnr}C z59H%_na=>ea8Nc9dm;9g>5=alLe;~ZJ z^{*qm=1^|ITP;-HJ8WgN9bJr$zvkpX?Ev_DalCBWv2zdq;bdCMD^|^WwRJ^AR4gr< zx9lNlO4SX-H68N!2{+C{#M|EUowexcs|S|LIoh8+UJsYGf zU*6GD+Eu#kSzMpvu6P{tH==0oGFg|g@3D2P+krP6i_wL=(=sgIbBhQS- z=JLA4dSv5QTG4_qru2U?)x2}(4wz{y4dv>Qj-Y^sTSvA1hvY~~v+A|y0T6^AWn!wB z15Rii!x(pJEl0;QRp0ZIa5}w%Pv+Vp-v|JBJw#8S2Ll`82+b8mf z^czvPYjiK9eLTt-q_j%`XD9Xbr$W_^aD2e|{*f1~xq?6keiG7Nnl!FewIk+6)_Cc~ zW5T<8+@e{<_pYfSNB)#PV#A}B%L-Sec(Mm)+O3wL{A;c?5MAF1>J3?UXq4%O@frmV zz0WCl=gc5$8or#z_{Wc!5J(Vsuf*>FVSHl1Jna8r(&=mTkH-XGsRAMu&%Ce6IWwBx zm)*Yn1e=CzOE%>hc5b{wY*-DlOc8NC+mTk=dC8z;_IbfCtr7sabwivDCo5yr2wckL=GxlT+0%<&yp8D-2eCyA*UgVS9C-c_ho#cbjPH zUJ2w%`L2pYoU8p)4~eEQB^VWy=ML)S_#(mIW|+S#9Y}R}LA}M11l7%X5~cPvVZ6Y7 ze5vGXfjJ(dkYAslpUxfVuhQkQop~q%>J><=SkKG186e9wk}6r)qtS}SBdtN|b#aQ8 z2AJ{A(DXvN)cp*I!yIGv{r#3tc4wo^tKYso0U{{vh8!L`IxNa)2RBiUb%ah}Q^a z8LHPtsC@XqBCv0};VpcIkM0DrP76FPe}Wluo5`8Ik~pkNsPxZRO_aZeg7U;N9f0Rp zET`TkCUyk`pmpMh_eIR;g`uF%7o>aTN`X5a&gHq6_53j3yog*c)JTP2P)I4|0N6bU zW_>vd3DuJ`187=t_sQ!k>&y-79IL-HKgyrj2ONP)zzx1#8kUxWklLyfvFpi@@Rr44`; zJ|TTWvhiJrYcl02AL$O@^x!q&fwr2v6hb$v_AN6gL}?G2-s-ko7y*#$=n%W(W1w+O zSg@a5rrA=PEz?BL!ktXhgP55$)ulT-S$TsW(Dbb_Om}Ab3JN}gra2+s+^Pbu4D-(F z2W{fu8muBOztbv8B6tX@%jJ7aN#s+)83HO6ekRyx$R3t9VOGv1;hqs>5H%ca0S7&> zjfq2JaMK-y!RPIwae-z^!1se$6d%x#Tjx*8F0yJ|PuQanDL@uzzhSz#d@p#u`5x?k zV&Dh|%-ca1iZ!@)P3aPCCti~*Z;VKOzW%>oovSSR(46Uc#2Twa@!}=KHpR3>y;F%@{{0ev*Z^?7GgPh#V zwEnEz{B-eIeg0u1Q=WL6fJ_ zp?5&1Dscw^iKo-XRX9f!pN%?-LK63~O59ZByK zU*uqAwSkzsfN4$l0I_BwQuLaV__b>hU`}Q+AzZVC=%R+ECgs6`6_`0DKZF9AITW!p zgoUnLfw{B~+cK=b5$J#p02(!}U%!rmu{*oQ#{rDDq>7=QsjI8|OylmPk2AwHD0hyH zO$#b%%lBZ-MBg3|)UsnAI1uLgaGCIMivrYj2R?h5pPOnJ1)WVIEtt8qMawWPxqL(9 z-Kbu#sc3oTD3VOm>y?DEh{ba>$vWPA4;rcKi=Bv{?AwoO6s87g=XhSzqv>Gxt_inOpHBTH?*9Iua{1l zW`cIM7l*vD(CfbkLEWO~*0Rg6`jli52`yhS4LOg6;WSw7GHit@KwCgol0VcGjd$!MWdAQ~}{PI=D~IN6!V3`(_qTShorK*Ru4 z+D$fPa}}%@JFYnh51567{E27}!<>|%U{QPfA2T$d$DsURS-n<%084pGJQuv4a9SGo zW{^+*{dIM_ zwYv5{P!oDyo(JgZFM_B%#WqrMB^>@QQ2bjZ5`?xuel_RTp86}X!Y@c`ui(BvQT68| ztKwj7J@S9P&(YwMl-b6^_w@X(!|^Vh-pJH*djIq}`mjkWYY zlkGofhPi_Dpwe_{iY`}8`vZ|Q~|5aCo{SAN5$m|5=D%fNr8)z?@5LQn&QFporv zc3jj;>aV)NHj=b|&rItMES13|fM(DKKN<}EykzZ!KtK4m`eP3nNpM{iLe`MNNDhMJ zA7w?wI;$+|_c9+ecM1-e+unXmvC9`cTh1zF&46iP*Zx@N z{6FrgsA>cQ_c87eu-XBmy#v9-u7CtSkX{oNEo3+@Sv~=!FoKXDii8_Jk-Zs@L?G8| zclWzeW8wTb5o@jsO5n!~?eH|*rq`_n&%?(d@C3KE70q*B4-*0Y&-T-;TtQ%RbGH%< zuRL+=Cr%X3We$TCMKjFmu20sgf%<~Fh6dpdn0xmgM4gacp)oKbu`S)GufM+^xH*_D z$$N$m=2;A>fQ@GtIM3C<7ZhfYaw;^#fl@P?+QSQwA!2D2lwER4toTGE*3 zSr{1^j~?v;lb|OS$GJzrHwAc{W5ymM!k6Y)O-PhY(had?F(vCu$95!-IWUGpMmXF+Xq!)_f9R*J_E3_L<@up zxz3nf1?y6sQFA`rWDObvLkOBsVCCWK;4_xrTM<}hcPIHi>HN!Wvu>B2Nxrp7O#ETm z4x{#*dGUUPX?ksQX}LI8UXXK!a)wX|@KG*5R|xaH-2J(AyYc^HuNMb)ipF|O01JeV zB|HjPsOHl^QyC;k-u#)?v*Y0QH0C`$+~N%>C^DqU!g{=fp~(Tl4c}+@z$6MtkEMNF zc8q@j^Ty3ED%$=qf7b#MrrY@88sA(d8hY6~8ZNx>q@du6(IxgVh2iBVP zTNMM&De2qFD^OrrR7!I}w|NrmRCp}LyTL$4Qz{e131&Z7)myjrEn#3h$6bDKH$++< zUqS#Sag;lfQ~Z4=Gx?^qh^6a;>p8kYr7Xj}Kl2;lt)mNXxUMv^8%d6yHvbM0WFf=@`F9$792nv=icuZrG zMDj$WhTC`{x$<=}G2O2rdBZS`v87|NK4F2BZb(IdE2uu7qp+|L9P@;>L9=bI+2(_Y zRtO+^dqmLRzQV_)Q-8dXR{m$?yfC9!l9p3C1{m~+g*viR~2 zzXRmtFgoZ78vov(xL+;xEiKSuLKySfiD@~v<4wlF1{WgW3BGS|DgUd$%SBzu_{pw? z7XpOci6jUe3sxaJp(l~x5!w3gBf9T|F}|nhA;6u0EWfC4h(7SFgW-k}yI`_&kkyDU z#2tu71;;!$;V1u`UGF}yj4l42gh+?o_Xz&&I$@`!*`3tC;TiBFq%brxs=^p=g-3|m zGkZdmF)``437jzmeoxRp5>*M_fxnga|J|*;CdgWDpj$`gK>Ti9-kO(eOI|(yhj#g& z^U7Xu09w@VtbqIspJ(ko-|c-S@?W(^|DzOWqXsTT$z`!0kgZ1?zv6X$D{VPH<^gLR zLVrWeZT~-nMg9}OU9D2Bge};!(T`S}5uwkjr$;Q2h|Y0*nFRc$<9x#w?B79|zxIgz zKTZv*bs)G7tbIkbj%}2yB6z&8z~c8B&Y`9;7qNyTJ)t305W3X=Dq?NS6cb=gSfRMd8xVrGW zISO5oN~1#0)jpTsXz={Snk4TA#C`3i#6l|>(Y73{ z9cfNs))cy0#|xdyxJQSQM7^V(cMt2kJ$b93S#wtJQ1_{bl-o+iIVXR&Yd2KA!loe~;g z%h^GFE=1z`bye&GXc>cEw>JA=o7C4m^$|BOYk-{wHE)Kio4bbxuifJQVuI&XX)22kudJGEfNr@`^BpfIuL=UTz_3 zKSZrK3eF*XIODQi?AZE(-q z{T=RXQl(>{_pYfTs1+ zT1rGphP_a6GaIpX;%x_i6J8qV<(j&S?93dEQ_q7FU4&2k8Rre4FX?f}GFivJ@X(z% z2$~F`Rgy<(KtDyH<9wM%U_ah+B>YQw;V}%vUmDfBV*ZU`}B2wZD%l5joQkM$y z|I|-(TU}Dp16)zFfRDw;9t}uy`5EYoVDiR0kQrv-$RqB5d;k7Dg>%(PQ`GK#$z0|S z`LSqdX50-eKPC+(>TbYRFp(*PHqq)1UVHd(1MQ&^zWEjdyc-yIGefOYzU&{8aNQJZt=*{Atsts)w4@^9CF=h#LdtRPdUn1CC6ShjA!{_RMKEvO8eAv)}`y zc>%Y-9_G{gzMc-um&#xj{=nrUdV~CX3bJ1K^F6zOvxr4#!jaBD2R=U?$&p7G7`V@$ zA4fMO{!09W4^Sj?>9>2r?)Xmbbb>L*{02=?kah7HlLUd?6@0ui9zbaWs}i3cb~#$Q zWP$mR$!L2dm@J){`FeReQRVco`EHulc$1+6^Bpc`)@5g47$DEQ0oZ<=`3ABA4SX!- zWzJ>Lf)F?q&#c;%cpTJ{1`7p;9rg~sU%Ov7tkWXBHxGUBg~2zKc%>oR{ZaEEe!H=` zp-f8Ws*pV9?>fc7l};fFQqr41ktk&w;;n|bt6A=Y|LUYl{z!rl6SR=}P#~8g<{odM zN=iz4v9k;1kAX*kI}%8ZA_q`rSYfk@gcZ`5au9N!zI zq5qhl>Ce_EMUHfYzHgyS+=3`L1(9h6S3`&J7YM|Orld3ZP&Y|@K+VsB zJmP5i@2++Gj&0!GZIV0R7D!2{d+plJ;Yu#cu7bFUKD)Uxeh`(~fbj>9IWRaAA0k!H z83VP4tCM;EX6yIXBXBUf&wu{u3Uf3CvG@aj&y3f1UIeAPLw;{6aNjGLHmvCQUzMC`#3;;o{@tOSK0> zMs@bIr3q1aT591T#;tgA*EXd>A_UaM;80$ISUxsG4_UfRlkcdgM#KmC0lxOeur#SS0GHvfQ9h7}W_0k{^rXl-%*&_$tM);sow zUi>iU!_HXf7vD{7`D9m1x{;OX^_3o|@*3X78J`cTqdN65BGS@D&bv;VXGPo>0joYh zfD(T^#m%7X#zRosgY6bapeg#^y+cVH+*1Izs99M$YJYK*Oa%+C<|igprBTpeJzBwX zzdXRk*?MPnjbxK!;)R(5QhpYn-lGPvf@$fdR=J_$@B&b&(-YTw( zV;D5w8A&K-yc3#CAkzJYITV<`Ndq_ldyKv>z5#)Obs%cRC-K`>fe!7tRiM+@EO?$) zIZL+v&1D5F>QCKa3wIERHa&cO!3nHEuOnv!x{MckNJ&XAJ5Mq*%8x^*xmYlt3K$!x zs~18`N`q2MAZQcu4h^EeDqfWf%1Ate$HvUdu!gxAk%r&!>n_F3sDiW7$9N{<&pLmHsY{{GOOB z1#5BSY#++>e_QPphY4qu7c{s`a91JXfnnJ3`TWzZ*TL#hO!J#}PE#55vORhD1-jR) zCad^s<7stiJp5apv8#lOS#f|rXvo_EGTM$9c<133YCS(KYL%gSL9ddJ2Ki2^Xx}mR z@sUiOCd?T-8s#;Fwm@M;FW|iEyr&}gU%-x|NKgYA*P)AxU4=Cktz6sQs8uZPO29N3 zp96Fp&-oGOq-R9kjgx0+#<-4Y`SICowju{Ol7NJ4btm(IWWIw7wF?sl+)h#}^3LVr z)_POdzhGV0bJC}a72V4_wC(x=y}{9PG%HEslPc09&E0f#k=yM_J0`hZ)c`RO3u#lk;4ue(ht;z1{@KZ?|r!!rPubrLHg!Jp&6YfhOes- z4($3;_zspvwu#f#{dcR2E8uT~SNyd%K6lZXYgFAc-idDyYsa(#1Owz0Gke+%uRTm^ z(@235(g?U>Ob8F%0M+vSg+70WBn@6^EhOs=jBXy-r@UQ}AnG0S1l(s2;^_;@g(hWc zpuIC)z~jD|9T&qW5D$GvwzcCNyQ;46NUvB;N!y4fT04I5LwTB^M@`! z?do?1a5W{}ogN9yFddeapBucqr%i`KXbi!Sbk$`Bw8>zTnl<(rjmKu0<%6AhIH;;| z;%jI<_*P2M6)5@0b^nTQ#lsg(#`BBwZsQZ0hdC3cKokc~L*V)7-Licni6h>y!~Hrm zq;@2#6Jy5{6YpW$*N|hw0yQgX@@^`%laj~)>W)Cw8^uv@2Ek~_7i^8}a1Hvl7?=L1 zPq)vr==mnuZNVD=gH_O-MQ^)SrGAbEf%bTl!$|he`e}Y%UgL8^WsRbZWpE3TDxJJ< z!{{lQ8MwLL=X=M_dcysC+p*snd_D2S&R4JYjb!R~3e#p6+7H$Du_voa05Coxw0P5U zCo@}lh(k~RU6!?x8%B@j69sVL+ zM`*Ah9z9`BzuJ3;##~F;qcCs-tX^`sks+ZV9tD~^j8|OUJw0v`N7&l2otTC@wT)&^ z)eUjQa><9_Nx*u(nP;XmLAT}bqA8j2_s&cZ7XGQSiMSD3_OnEHvJKSE^X2++{$LCS zZcF&Rq%30ZxY)xiah(1l8la;ukK{%|l^KbZ6WjodiJq}aduxs45j z*Zj>ub!e_bNO0s?Z@GV8uc^wO>T3Dysd~ny6U4Dg!P%^v;-k2xrx8aaw>mu++0M%1 zNJruITagIhfr-%i<6d}?gAKR~+A*Wl7s z`p3^n z7#|(MqbG_o6g73#m@5V2_Z!}_D#n^0F`L{J?9(pzijIWsX)whj_sgFINperiw+F(2m7WSKfDMLl%0xm~kW^pfOccxh^9L^K;5V6vm_QF ztVs(MC&cXEve&QxhAw3uIToa4Ib0DF6EioJG(RIgI4To@=ZJ2nyUpff)E#9b`p3JNn* zxKf*}Q{@{c&Ew8J_ekQpK3&OP=R?a2Mt7I4Iqv&EE+S+tNI`QLtzdiJ!ZD(qv0{5s!6DJl$-RCAeVxy@~Bed4-*r%GtqNMnz73R51ca-pc!aRr8PJ&Oj zZpFZ>QG~2)NI@a9<-dchegp!NL|!XtVYg#llzMA_89y2G+NqUore;jOylWXb?%K@u z%){{7L+3(9VNl{iQt+-DZf0m%Qk%w8x@{S=Fn9?;vnSVs-c>2#uEr$C(dQIsK5=lK zPB?&{8glD7k)bf{*bd6JtN3LJcupb1^5^@7E@It?3d% zv;!I1b%N@X=8=^MO?!)1GHUzOp$lEeHRG)1VbZG`ZQA1`lx>s45gse+j(PODlc_k{ zQc*s-o)e1EGWy-!CDg)hwufg`yD@-JFPJ}E>bJONW6Gmi5t`j_%9V4+J&NlI{elty z{tV(SY`?s#i-GV+_fw*nXZwYP_b`H=zdi!hYBkFIHu#q9cuDD~O}rJ%Z=qt3QMmC+WzTS%#i?b!om{O*@n2tF}y07&3S}6AR!)Xk5SbqxL6l*!9ZDCQamov+tZJ4$v8bQgb(Kz-kO-(JJBURVs zgs9Tfpu<(H?Qe<0!=jgW-1)Bkn+eSSdc&;`k&-H#bgJHlQzK`Gl!M)D2MeAJ!xZEG zrlgkUlz70@su~(?)rop{ZEf3OsNDz4sn0g^^;*nYuzBP(15JivxAaxmjKhSgxLZAF zyG5g#csrcv6bw6>8hjMU?Q;5d)Z}1v<^72Q>v$A0tu9tUv)KJHsIX)cyPcr#uBKhw z{|a?Sj!iV#SwpfjK60?yyeCf<%diUP9B&V3Pm`?M6f56zQNMjMrC~AQUSXNG;MD9# zY6+9;FtW#LD#LhjAsnU>S(TjFCeQoyWs!pMw_4*Ae1!VfK_dL~=6cr3g)|h$Q2jv* zP~|=7NYb3jUCK^>_wEKSo9#l|X_<;(?rD)Jb5s$(H~qrp@%mW*j)(bs+K~7?I`v9M z$v4N!Oa!LY(Tis(?}8zP%!k-YO*7qJ;@{hY!K^mg`{oVzTuYNyZWAH#acm25EpfO6 zZQmk?ZnNwZ%8$+EsGA#mcmqaiTZBxx4@*0>Owv_T9x%+CoN7?01L>a7?RcfLhJ;tj z&0UxR{NgS)+T7tOc`C7;pi`ycV3BbOgzgVK>+hPdGY+Ydp5 z`v}7Ub8*AlrymttbY;sxcZZ(d{wYttJe*gA#^iCOY14AQtAj|3i7;*EXPn_O>0Eq< z`(jZ8I8zS>{y&iW_fzRtIZ6H+{5KB8Vfw;>Bx|SC+)SW7*Ukn`B-rMEp~7$ljZ8Cv z7wi=)5pO1P3+3+G7w8>1^CLrpJup!0EUs6-4^(sJ*rwO~^AE%(c`)tK$!G;%qdq?0 zASG0gl`ReKLHBVWh;Dm)3BvizqhjRt*SZxJve;t!IkQWr(Q<)aURZRJM=R##u_s?K z1vTr>*KbAi6JWvNoIYHfZPgG(%dWSO)PmtLeV_xkl97@BLJxB#E$`fiLmlZ!veXZ8 zQ#huqgpxdmQ6X?GG?{=iQ6FzN{OR$O1K|`50EdEDv}lJ5JM5S+ zpC9MMOU2A3iDe*(DP^4kD{jKm6)`m=9!5*RIB7;{t7qWV7EBy z+<%N$f-_tb?!BEm$3u~r7r=X_81?edOmJ8De1iNHMl?NokDr|7d21!nDeh-l-staS z@l|dc&@|Ia*q)n<+{^W_lg(z%dU_<&t{vQ|VYp_$-Td~-hb}I}MuvX4$#DKVDcUNN zNfb33{p@G=DlyRgP_AX1VWai|jb`l@xICiKIWRJOX3OZ9vp9!lQFY#RsMfAFqD49` zfYyefYrKaUT7xy!)d6FIVCDl$?l>j-?Zj`SxxZeqN4vB@6kG;l0gGYk-`9{F%e}bQ z63hA5&&l|Psq^}9wl`sKetg5Eu@=mI?v~+O&c=Se`0$gu&bTe7ek)1Lvw^e6DL>zE zn0dBoJ16~SuLkc;1eZZydJV_U&aOF7?R{OCOit`yCVXpo?RMFx-=;B0q?$TTKQswi z9HCPRT|4krlzI5PYEh^)lJ(yKmb~>Tkop``@l#Ddz04#rf9Y&1yXnuw{%yANuFW<) zf4=H(#UQ%3ArKa$VKz00Hr{J$Zk2h3Px6b;Al{lgu}Vowg0~#hk^0rk)wV!cwF$yCkT^8 z)=cWTJoWpl?E&*dTT<{yif-r6inr(t)fP#c*|mNN9pN4%hkH&40t&Q{>c z^`d_h?l2?vccdjoTa4f zgQ?Q@N?wsCiwGeO-%8Pb?Z;MACmLjDn>hapX5pYRhHTw~lrD=!w}YFz>7dU=-ElJJ zAXK)=7cH0P8h9zqwbvj>VP)4}^yj89a?V}C4MVvP^m@Xs(P?~^lPI6p=DD3CZ6`pF z7^OIWM}29rV`;MH_OsIh*NgrliQMR9;VU7|t0xQpwcE3qjSh!HQmBx6W`Yogki+<1 zhdKvH?%^d`vMg#El;-oFA7qBH=GUmvraW~l&_gs*H&i`45ez=~!za8C+-JqF&ku+q zomoUwl=-Sv_f8yh;IL&l>GvB`ski9RQZitw;~u1vvf%h`}ALHRUR8o zBacAUjrJfU{4Yx5z~15LH2jCX9vAZ762JKs=>7eDcaSzARnG>7yIq7)zT9SH-a;3) z_Lch&a#UoPTpdx7N7nEPaaxQ!uu$1!=3c=3p~X}IhnN>HCLo8TXu`bU#P@PTwm&@- zF+Uye#-5Ky4%CuxysXF@%wK;*TIF^Eh^ciOOhfR5U07s(N>M4vlyO7r*WkNhDE#66 zd;LYx-Ni-O;IL-z7vXEi{A{eSF)#qo3fm+y!U9%Cm=;XdH)mQ)exV$-ro^S2lDxRd z&_Rsjj_JTel$<AK_xH08@t22LaW^pb$j$3)a^u=B4@IIZgNXUfwuAn zf0W2kw^OcBTQQ#WN&TNg|9u?zvy6uUA3-$l2rQjgwws?8lW;QjX z8)d>O0!l=HwTn>&=K!q#i23SKEC(;xF7fLpU>knGaTo-uJ`qRzn;tM`P#H|EvOPS&Ft=I zMb&Rm)?Is@Pv74y@5sD25z`mSz8c#$?-TRFH}9B88_HlGM%IwR!=tZ_d}6XA%OchH zw*NIi63_QdJg84OIGMy3rIMt>#AY2O?KTs)A-se)s&TMbTW?V&h73d_ znLzjyaPnh|mXfqvXYt)p|CduSZknDY5|v2Z%)9f+-VTR;RMO1?z0eu92M_|hSo z@}*@zqRS4=cyM7_RDE7;qDAFE8!j+7C@6j?oN0B*2^3d=bTQGK@J-q^l z;rmay+sz9fmB}zN>{zozkW-bEB+^GXAFH*P#z_~2^km&|wX zbW5J3?^*KHbKAKUm2}d)pV719s`Y2f!}rua6EV)Q!?7s|5zx;Pr4r2SgC99$E{l|JwY-DNA6BY*d_^1hP{g4r?%7h6N1M0;sx}~ zCvkC`_*!1p@tG+-8mqOXAEQ1#aeg8L3u1cp?aGmA+cI@SZ0h~HNQdjAhe?e@HtqcRLgarkuDM4g;!hWY)!Rn>5* z9A3lVZG_%G_oy$<(rfnaty9k{ypH6(QLiiifU091yGP>SINd>l6sUS_c-N|$G6$RT zm|Eis0SWc_sF*TtXESfvXw{x$1KYeXwtz5s-ex=AHz<7gj%?z$R+9*H-6z?16q&W`piePT&o=VgTwAdEe2%V%AsEM4?p&FA6x*Nbo0;UT)Fz2n3biN zq=d@YH=9gH0*xFIdgeBDdxY{(NQOE1l(*VXIS_b%=If`y9Je+0;TPx0t_?YEb*)Hd z@#J{muSx(*%f`1LUM*H=1Ll`>bNfH&ujoopj!=4PMD4|ing90f&E4S$8;v<_t*`G^ z>+iq9%CKEtS+l$iBT(X+6FBaN6n(_0b%leyBHl#A?11++tLsa$jWmP)PN5r8{&7_u zT9iO(sZh_2(u^v3nyuK`GBhA7u6`@db?-?f7NPiF0h`W7rDW@;NlB*#EBl!h&zD}j zA!yZZ@Tbkk|&L&-MU=6h_*a)qPmb&);zSwpn{?TU%rT?HY!EG?&J1G`?IHax_*S5SG$PJOvJ38%J4nceP+x# zy?AlfAtrES1qQ59u6wD9EJ9Y`q2GH8VtldqgCq24YtD|F32fPxZc;;%Ij^-(sec7J zETc-1*-P&3yxo;jLFp?{=8*7TKi6^AV)b7H)Q8_V*M|neMFy6g_$S0(*^azG>i3kn!y;ojETWq_DDyq&X@1BsjJ_d(ES}{pDA4MWYoNSHCo?>0Nx0Q&?jm8o z&D`Wc=Y4_KWIxc`YiKQ?roR8AWHU5i zVHsuYtelP_yMP{}Enef2?Io~tAe8GWAWOLG-lyTKHRH6iX`or*1+I2MhQk^o3V)4( z0;{5}QsE5bZ7241BOD{j1B;S-&NM;KJxkdCDP=f8Bd#i+VO5_iF5@qzPjO+q@_uqMN$Jx~PLB6JJ#Qn`*D}t3ke!ux~z6mR88rJ&?TARs_kR02i8 z3R>%9lAD*C8$hOWk$aZkl4NnH5Axj@e}9K!Uxa4)0~a#jBJrrH8xjmhm+L<%K4X6! zHCiZDo+XxO44ov|U>$-es-iQ5Bj|WG*mRNfe_E%wh-bOLyGXV8=)Ny$ zd!L42Yr8x@ImeC$IskcZinyI-Ssx#B>g9*}-6=XCa{8S+V?ms?A*lR=URw_tgoh`z zzH3HfCD)6&;4&KUYx0uG*2`?VA`hyiBl%OmfTu__5%!poyI~0RZ06j$ z(tEqTkH50-d_K)0IHbr)?2R|6!r(qjlvwASjomKRm42d$VbV!1+SNWmMly?84-fbk z`v{RKjeRGlj-8|5J>kb=7g`2iCFDr6>bL1`BKbFIYjYU6E%(J6R3-pmg);)W9L|&E zSWr)BMjXrrmw^)<=&#?r&8ok>+>vjN|L6TdHY?fdC%8a)DnK3Z=+NHyO3|@k^kacDKDJM;1P)EU|MQ? zywLtTDfbtvx9^+#@b5g#qz;eqg8PUkNhzre&Ad_N#Xuqb{kP$>k1B7m{1=v!ahPUR zk)B0igmTnQ$6oQCbb$#n!M`Y#(>5hSUhiligr7Z#X`7ro|2cg#B44pSt%em zKOkc1=y4hRa)C3$O2x;7r>f-F21~Dsa|`8$SKO$JYhiZX?O`_?)S!I?jg2vEvSfC3 z#(6YxGupa}Sm?+WWt+EKla_HGWKBNyBD2m&^+~e*&lC+jHkiFho>&;oUxJbO}ObXGH!u$@>p zJRj;BiWF^0Iy#S4Yv3~zb2&XCs<{WHv3{!E2a6Q>#8Vk_FsG-zo5~b6&1yPNRhSCDC`ydBY*`oE%DRyJ2sk}l8Y264T3b6Kk?Sx&0>5S0@`4Xm zRJ}Gy@+8=%38F81V?>$sA|BcUQv`X1LKc9jGT{$Z4A(?$(`{}j% z13{-^r`8okDL0kW@?fyhV2FR@KDAljv9A4PH-9kQVrO%C-xi8dZ)elvQyE(fHt{xG zyu!{}BZg?BGmbM=hHr|$S)od7g|HziK13o_@hD~u)`|)ux~lhTFf?c+Z$wCH7_zT4jHNHIlI(3&QHNcgyDaV`$4a=&65WHIsXW9ct1@fYZwRH`bB@;g_VqIi9=(457Y>(~3-V+Tp;zx}bO z##+nMUdM7S9s1{dQm@XKRTAD(G#I$Bn~EBp=z|&s--s7Rn67I+cG0DFo?!n6yZ*sG z2eTEmx0HhusdjyxhC{y%27BA9rP>#Mel=7&%dWGVcd9X*5J)1`~=!jX?#rF z*5j1ChNCcrcRYy6N`STH34PV>na}i!a_#!dOx)g8(r+Z0)a8ezD!wMna|kSZ>k?v- zS)I;gZTAL&qGe@V&4Nd|S~T(H?`ZTU3kQSJ=-L=b=P@E{#zwwn)5Le~HL6GoyGe1k zPh3QrCi*2{&aJ-}0Y4@*FHC<>Ri(Uw;t9)6ZnR6ST~~Rt%TRmB5K9cTr#Ueyf=b*V zXYOKpdkSxOm?%q6_^FIRsrQ}jdE{^kGgq0#I~Q%8VnICpWVoP+3v)63Y|d)!f!?C|D~^bRQ$X}tQ*lfQTUP-+X|UHG3~)6l_NUeX{?}|3 zkAI#kPzr4hUA(1uulC*IiFXj;h{+DEFop7C-ozspgnY4orFle<>#DAoLQ7V1r1QMs z&l|_9{M0SC33D2>hHb+z;=WFt(+X1`SP`XswOZbmeH}Hn0fSB!t2;n8f(lUWlrKGuiI!JBp29-P^v`D z*c%EqJgtf_+BM|_MtD6^dT8>-g-s<;vIECb$!73Fp>GNtA-w42-oFqoKX4Hfy_ zUZ9W-`sxCM63uU&p@P`xxX!mt*AXp)=!G>9GdhtdtdYFQ`dPIoB=sceMWmpzSOc_X zs1`Uvv?2`0IgAq4Uq2=0P}00V!@E`zNKJ(k*ydr@c9NGQN6@+$7v6#TXz_6y@)G>((v*N@Gk|wf!jyxwO<+`GH3z zG2tpR)4C&?b!%w0vKaGZhqd(5EeU@U0HHt}1_kDTmKQW5e-SYM}>1z_y?fQ=&^{NqBo#32k+S*0e z`wxfw*+avBnCulJDAsv!{0IFLtT)aM^Q+OARd2uVpH{s|)lx_j3+2(ellqzy`Qocx?FV`X z5R{qY-G7mXEyIHbjE1o*zc;T*ME9g5NHIdjT65Ut4C^PuzOmb3;-gzBF9`sqcob446T=Nv*a9_D5Zv3PNb}fyk{C5W;^YiOXTkp4>y4nbTvIrw7_N|> zm4(T8F{A#a7Nnqts>VjLDjV1#C>#Ez(l)d)^>s8TC*Bww=yT|;4{5ec+Q+bO7JP(9 zC%sS@3GJ<815?^__oJnu*&;R3wEnP#7E+cs9DPz(^0eXQr8$iASQTRR)h$SZg0Y8# z_R+eL{)-@n&VcJ1OO!fAKiuA+8Xkf~&Uhh{8ZB@k79?mEe*XRr1&YcKHIl8-t)P1! zAO{dZw>2OjfK$rl28Xx?3j%uaY6rMbMKrMcJk^(&@f`Vmph!Vj#XURqdMqF!! z?}qeLT?3Rn=!+a`sow%v5Mk4j9E(-aOs09@sW}XE6cNCH3J+W)d#Gmv^p!)0FzJZ) zwkSa&3vQ<>dpkuDu7pLg)Sk{#0~Eco{>_9ca*!}Pu@Yt{2DP+l6Z^)9XYQlnDt-RX z*1hk#g@2R9*v-;P(88drE36wHRt_{7OL6Bt=rGUQtO{d zfQVPLAoZZRTHDl9*eu){=A9eC2fau25WmKbW&8K-Q&>w=2OLdw7#g(XPr^#mk17;> z&N-rpJT##Idk5P42pVWqZw{)AoPO6GO=zj3R@3#G?%e5V5!=fIW`kl_44Je4%ZpjX*E-luxkRx z3)^--GQUxzO){>2o9W4K(Ntpg={b6J8%y;QH&o0e!mhzroIYLCSRB)Z^>-#G0OMCR zXYmN(;o`p(WC)%sd4dRRBm!^e=9VHHQO_@ZYY!Y=Sdy;NKkEs-EMMVbjXKYbTNcxB zZwa>61(Fj)-=U_*{3hdH0d$~> zT<@eLQq$6o#ky*uAQui{yHHRBpOcKxZt=dxnCbkOBpih8L}nQbija5=s`hQuFZ&p- z$lKM8EiR=kOQhK{bNIy?&tekCPL&SL9UYyYp8SxLiw=e}09CT7W)Trzu{?IHDMK`Qc1k$v&Ywc9yne z<)h=T$}K9(ldRg%nES?gxm2vk>)}pG^nN;pX+7$*+@6Q=ygrM@H8e_p+|r9w>N1e# z1b>y8S#wHZN21AcHrefMD@RQ;?9b4R%OE{o0huK&*_D!C-zm(3r4;taymp(gpJC0; z=Oer^X${H%hW-h^uv>Bn$?Q%eyq2U8tsJ+*JC}qNCy=^4pEjcWbOEo zQK(nvuI@)%q$88qN6cPE?tR?Q?#R_c_wANf(tqb?8ioyZbvq@tj*~d{{kg$>7bZv) z9y)S_cqZsU1mzEc?7>SfzhP_mL?ipwwLfdOPMF!k>#w4sf)yNoJ~(99%`)CYPZCad zXa2L>cXGyImhNxs*Z1d;?cKe-^%CmWjkYrXY5bA>LraF~XP*+%cv>H~tF<~E{X@C_ zf9xLa=bca!j$kw4Qy40}{oIdk{Wy=-!aog%6IS53{_M%cgKr%1|J5JPu%8WBM;I%WU z%_<=8pPHI_J!2g&Nfgd4Vcq=S@CDPvwTxt10$n6^{i=z`0ivDnk?q17VrQGRcf7$+ z+Jm1s)*RXcIqCyv6(^WQh`FzzrJ0Tbj9Qb{YUy)nfxt32>tn19QJ-Vm#2%_9UR5d~ zNPUuS(?P>Y^zg007QgLARh2`77HO-}7qwXkt<7PX>C$~=eOA3)e$L+aZlvKi;q|oJ zd@p^7Eq%&_)B)}GI+t3#sN_O;kpafC2k4I}?0Ut~UlPn3@~K}k?pUDYM3@Sa6C7w^ zA!XC9UBBMfUQZ0};86_Us*_v&ib-6-kxkgtvhLoMvT5iBynr0U2*x{__VL!|5E^4* zVuHjktB!PHAVpV5XGIim-u=v`uCKQ5c}u-rf!d zkm9`|LA@@(_z7Gx$Okj8{azsJlzL;Uh3viq$g@j(*wYK1s4z*}0M)xtTpslqv zKO}_5RK#_&!_C9>Oe$1jvdQ@=(`bbcBkTnf({lo)_EWQ0#JrTZ&)+PbP}k+`7czDD z^ji1lLmrPKe-{cAJp1u0V2<_uxh=9KSLQ8Og43M9dnnoJ>+4ZCC_1V>JFAluu%{?e zeF@S}&wRLx8z26HEIt^ASFzUD0uvj{yY8g+pXzO|*OhSAG<-3GIQm6OG0?&9)~z7+ z(32>+qY`N0D0Ny&V_VX$G6VO41+E2{JMomwMlii4vhh8A2M87d-=c5A@4%2pO;G4ZPlylGCQZ@WaKf)sC%+IIbim z-vpgfGkGu2{0SQo+yE_wk?M(fpG2+O4H*mO{tcZ~&#%C{KO}f^8EVH8&8K(V-9w9z z^=*%?cx(rXWI_G1?uSf~50=&1zA|v=Q;jw0B2X3wfwI{7&y{Q?y3X}RZ*PsKcD^I( zG|8k_4tq)3sGm`f>vdR`#TgOxDmiCR;wW1o%E>OHs$!Ju>f`WU&?yHV4QNakFJ8pY z+AyZASnuqiG>}3|#=M-*E)lFgNM6a*l<3@TPPQ;&TDtj!MD?*M&yz|Xp8`9b`s+@l z80h4aSk6yq`Wvl}USF4FVE97$u9XkoS^t@IU8lha^E<%P+g%8k+lkk+EvhY2`+Qk- zFlOXZ<=1LA*#t+t!|kz}z6zAKpgS6eqwo&uL>L^hX^It#i#}b3*9ugKCgfi+yWTj* z<~cMI`i*tXqsvcXmN2*ifl}2_BA!#`|xpv%z{ceMy`%l`L zZmx{os_Qp<2kF>BpY6id3l_c~4G4MOx+iIkNy)fI|L=OGEd|mVE%j0VgGvDP^gu4~ z4c2kP`~=O~6@vO|)i;|z;T2^UiUY9kxvts&($4n1K#_zw$sq3Y%&wD0sZN3>HJJtu zM=M_@zODuuyF1^HWEE|lWZPrhVcFSO+`Jhl(_!(&i0YNJ8#v_M|NH_0XIiikRo~se z#pJf+)6Yqjdqmc!7n8uD)VK?{6i|Wiz<1?F^O<2678Dg70I?#ysqSDR2(e+Kon0Xt zUYPrC5)}EbyImyMqUIkOid`b)k(n7J?Lcg79xbY@003MqeqX~3(}`-UtK){&xD?H~F4zN} zOhMFf=DZSMBy{t&yuQAKjOjT5*9T5#6(UhS}?3CnG{m~FSSULTYwX+D&bzvG~bWDsvV$(J=t<0V0O7MlWwX{O{?VFw!`JojFJ0+kO zyppr+-m=rq<2z}cKAnY`Rybh6|MeE74&EB~5SEMn_h(Qi@d40fiKgvi@NJl>^}yyi zfM0|{SoE2k)g9fqL`VuT@|{J^wOAhQ^?3!Ka)b7lKGC73fHph{U!?9K(GK4hTPe0e zT-i>?nO1DsRaI3;T~mxyD;_vp;ld_@(cxPxUgC`5Q;R#)SGU^R2#E5M7dJO|Ep7@r zKF$_|-|7p-S!9P}tc*CNa2nCXT!eZscZW;XPc1@eL)TNQZmSd4*3_$XxPUFAtZZKAAU^+ns? zF4*OUQ0T!#@OM+D%|s&IacuNVq^~ignm2x=!$Y4qBw@KGJ+pq{K;oHhFJeCfBO%W; zpF`}yJ98|1Qk`h0lh9H(994^d{k1O8es7JkQx8r`Ff*9twrlx;)2GR49A=s1$gPEa zTz*n3Cg8A9Zhp}XZ1Su>4b4i^!l$CWJ|0z}hiI_8PV(4*mC!x>Y-7oCw3Rr3AN9w%)y)O=(uvsf}36*b|c_}9+&e;aW% zU3D5kH!yz#U;iu_3%}O&AAXH6OP}a=;r8*I$a2HKhnTfTMDp13AEB#pn%?&eVGrKc zE#G$51LNMHgS2z6`6S|JczV|;ms56)fJiyxWxZW~IdkUBA&5$hurqPUdTxhj{`(lm z^p@b5(j3Q0E{n2mq#S>B8PzASqZlu51pc9>#J7~Vs<1I_kVzX^Tj%Bf!Wogzo>{zj z@%$CrA3+=vLIQ7bF)dZH)R%p%Z=dkEj`IE^cjWc&91Pp}f5_a0TnK;BcUW6SMg|Sx z{QUd{4!ptT=@z&MiN91GBmBssf6ztY$jF4oz^wjli1kn?CG*INnqS}A-W?thSt3bc z<mO`cukV&NF>nXU3#j-d)`z;D&KDEEmwNHY1^trZ`~F_1WDnAtQaA<2fZY(!r}g zi9d3Ba2%DHuZV@Yw;yfiB>~abME2gqC^?;RRN3TFa;CC*eeblDl$6lW9mupm>U)Gz z`1$H-4BG2|w2`UbhSY>9g4~!-*sjDq8g{WuV(y1yUGzUfp!+#VO$g-p%Ob5F3$+_2 zHse?b!ZBcc+uk@E#Q&)CPfGiL5@+{+JOBO{I{*GVfA}{F((QmeF>2NK(C1LHx;Qff zLnS8deT#;a-V(U{_22SnzO^)3y6VufL|RPmzKm~(Ol;?$VtAVQ@(}$NY4R9Iw>A6; za)0kDmKn=CaXYX@pArL&$71)T4^Q=!F)%P^jaB;WS(ASp^Ir@u-?kS^SLruRmIOI5 zbbj_uyL?RI4UleiWm)u{aL=*sq6w{~vRl$W&>tMbgvqou>HC%TZc_iTlW+WfL`q+? zn-X&oBbgVtt>IHy_2N63Y!h5&6RQ9}Ew2Eo$_vb3c9LE?NKtP6PB5lxX5BjS#FkM! zQd1J|QrtbmeG_scU9}`-t;QlWhxY{h72#796KG-%y?Op%JUWWC{p+(8S8BT7BXen? zP6Bz?1)d;Md?81ddR1~!Tef&qO@Diy>{BC60|^Q9!Z}_#2g_I7H;H31e zEK$@RXgIQdq#n#Ovq)LBVM9~uU_15bn>$*HpvBH$E882j)lsY$_!Olpx`aaMAMS?xinD?S74fLdtYL@|x%+^ak5WH;xHXeM zJCrhG#*CX3gO86sbBp&}WpyB!=9~TfwjI=}*Vo;w;`f_U+CW>&lOcI4bznroLK+=o zu0z-f<{sp8e6LaW*Uwpk&Tnyp5V)Z@(2aS^2b1NF9`#Z_uqKBs8z4v48SMLO8*`K$ zvnuM`)B2wef9c=r24siu#t$Fl7-(`q|q4a5t z^UL58XnxV`|CrKf`Nk$*(v*_7;d%0v;8Hqb->(!*KC1ab`Q9k9eu>3JwR zu_a*ObbogKLJ12}LDXHzNHmMJsC1-Ut^95CW^qH}Z~wB&I@K*zml6N>(Jv3DbP;H= z(#dDL(TVD~>xFdF)ceJEcTVft=F5(eb)oW|7L~YtW~uAK%t$a<6inwU+8az2GN>SR zY!?wJwMz$;EUe*7>MAp-h@sgrr^=n^ zjxZ;_hU$kt-~Nm}hn*^qv8=2%3^e^Sw~N?>+B7%zQUo2|+ZC#4&toTbGdXm>a$hG; zNIMuz-NhltCM%FWV~N^bNs!t6uqkz@V&`cZ>JFw_5r!Q`LXs!rW+d5kH9Oemt?qxp zWKWDoUssVK;EEaUoyFSvj?v0d8shz*naX`=0;^NItLDVs0Hm;Q&yiYaGQ`oG8Cz~% zx*M$~;L<_6P&TY@9le+O6gP+XUv_ZL9isAD9Z=3lRr`HnlrfIt5YkxDKN8j@yX7G4 zAH-y97|JFveR>7L(Q!oW)x{5i&{LhZh62<=|Ly!6!MmmkY<-z59G! zV&xZ*A?19|DXh%Obg zjT1~4?J5hD%#RZc_?*>v7<`Fhfx}RjgN;K8M-Q<)pyf>Ysm67K%gY+*acg*yZxO${P!95^gaZbdC z@Rcl=`rh8Xb6NN4d5sgVWM{8+FTC)MyzlIxK=QONTTU*Wt{}nn(1fkDG^8js_F1c@ zU_)*E6|S}3VX6tRBY_*MT^%kR$5Z$4b;+*)ia3g)35&nXbrLM zPmXD19e)ibNN>Au#VmVB1qUcx<8cyhiqm3;_@a{zEk?QUeBo#nzO&i$!ujq8IVZ{8 zX$%r8X0MmH;r6+iDi#sOiOAwtIEj{b$e>5Xxb4Cl1mH2OSU6%!SW@k`>=&nORuC${ zC~5bAL$@z$7Hf|261EohV_{**3z3a__)vi3jM`*>?%|0(^L+aS$UJxA)Hqg5a0{#n zPwUQVFaP!#3op2E?>HLpl|yszvG2J|VZUd{+umxbms6ajl(e!dbH@(b!aAj^yXIFR z@Z2bE&V$z0==_zdOY$D>(H1E+>@xDdHJ2@0@-p!$wi?l^FE*V$SxA3E1o7Qdy`E+M ztZGKQ_ROg#Z068+|7tw^Rd!#vRF|N?LAbQ|aw56!fmWU6wk=p7xm9hhEDO(S6X|x# z1ODOfno?q(JZYbQ=GT0wgB0eKEdF;MI2{vF#ohb3p!}%mvlte>x1#(D7L=+waRmI~ zICl4o%!muzR%TbGy*5z9@55W1WShQPrCaJzU*RefS9=n7lVubPwwesDcchat6eNF zTyk0(fVH52EOwVgF+{qH)3xE}{)<3@B=IxzXDnX*CLOmr97s@V{E9jhsF#Mo>Z(I9 zr})gZ;0OV2U^p7l{SQAv;+|xzortdZ@cLTF_vkDUQ$BC_*3GlvSP~T+a0n5LYDVbD z6DjpDBb`G``I)-HfEeG0mcy&ssi>}FgJYEmhN|GORHqzVbg` z32I5M3po}rth}JAytK5K=x4n={xUyS?CL-E{kLhO#=$-JkmwRuRmk$j{MqIP%M!FM z=6o2pj21@auW1KyAx6rAO5N9ft<^dBegvQJ( zOxmap(UQ>{he`l!tWZCF=r~kb2HO}C~p;`8{en}^Dk$nyfNKQNdW=#eQ z*Ts)n+fK8|mSUK~$ezZl@rTXnl`EgcE)bVk#Yn$8#cBJmN1P%Xh_!ky4w*Y^-A+A! z`SK+cNth+sY#JZKt_D#|AbanL=jW%ugj+<}DdI=FM3@j^_JEx5R3}f;mmiTjgx5sM zO-d%%K5&m)WzliTDP`Ov-+?eKZIc*x57IgpS6%t7dU&t6GIdUl*`M!{R`lE>M~+xR zwT^HEj>&CHB20lK&S@QWmKtUSioKT57-;b{#Lot^+26j}c;@!rgM1r6%q3P`?DmlR zN1%6oKv)9wrF*-t?76;pt>1QNr^ryNcbAu`&k3Xe3Mv{xYNqXh_aIE8>jESD2koh8 zj_Z{@emU`-7yE3bO9|8HNwvO|phHKNC$SMlgsl&fJAVALP_2)=l2Rd%ES5o2d7|YqEK#cES4YWe#=Sj?~F~|ux=eaFHqrt$EKab?rX<@ zKv+0roj(Nazw_?hJ6uATBW&PJm8qH(S>gKo$m1ss^|#UFScE(}-q+OBxInhMcZK~h zUx;6*SO9c9qU?twW&4q$(`fgS($T3$(G%t>+pgNdTo96gsmCzR!}h2-1KweT=~{G@ z(P%V?xOMzfs&?MyJuv+{TWXq~sno*JQ-9U!%V*;HEKe%QU%GUur>6(nPaDYqriETT zvWnOFFgDqN+OJS}bBx3tu0(o@*(C_eJ4}%`e8TN#xr;57o7SD&Re`?Dc;i!winoN9 zLNjiSnSa_Y25Om~eLZSS#6fogQp-`0gyPRi*aWPfV+B7v^7zDHe-AA#I9O8L=)>Ke z2^J(XT0UG%^;3Ex%+Cj2z;S}<5Ozaw+QNP-_fs&E`sR=gJ44#|3UKeq!aBJL zwE+FigJAT1Tw&rEgxeZo?W=l}>z1vjo&9E&#s+qd6lC3L{i$IHzf^5ltWrpM;1T$oE%&YYZ7O~p09sd`{ufFu-MwP5xj`+HOukw|Rs z1hFwFcztVhU_pL<=v}dUSTotAwi_;xRug3X#f1It+)-9lwfRu#eXx|SK*6uDkt`qe z%83r7G0Q6KUMA~ioQ&FENFTT{c;e0cVPQ~6WFLPNji1!fyxy1MdNjI#psjYvvbFW}_VIb2+$a74usMmY}%d9ZmE`%PdTPWq+y zmpQkTz!Q*{atVs`GWuPE!ej7UAynaC-&l3~SK*u`1Upj}(*Z(gD!K2R^4Xa6PdA@7Z*vxFeCdpsQYNx8P& zIy5{SWSP9Zy*=Il5!1RqdT+_bMsE5}VZCa!bOf|9Ri9WiehS?sD2l-CqGv8RwyUFT z6Nnm;pkB{9jlauH8`7Ab8AvsaocUEVZZ}~j(_h_roNmNGjZ-PsJQ zcj3>$H-MuOW13_~1mo}jf!TO=W=$ox_{?Tv%q`K{HT=noF0qz>AG4?>d0pG3Go3+S z4)3y@+~?Z;zQa}a@)(zpCQNJ^0RW@eiO!nLK2}jx%}}zkQqf(ou&Msfx{6psJEjgl z<4Iow;sK3Tg}^ca4dd!TC#GK*{&@bMR@(mtF!*u(@SD3N!vf{9gqPoW&8h?v0>^OB zf`z-cjy%ujawmpIcgc;Q$$OGT!#^{IF8@XqFIo3ThKAS>8F0jD$NGewnNr+ZgCmKG$8)WItm&ei6xq=A8RUnUn*s4W(c+ zsse1P9!wlrH{R#NosO_q1=_EbB(o=j zA09XpOkVqek15}Kq>`Kz)e>;;`voHgqUUZL{cdKyS>u+6g>HqPf-sc(R zzMm!9CIxkJ@87>)og>9juv6eub-J5DLVd8jj8G8H$o+RV78r?7+o%$)h1!k6W}&8` zQ2_$ebd%64tctpw!WPXBFxA!QG5eal>s+V{eclnaeA+sgnaj4*(3&_k<+6rVsaCLHKWHmajakJ5|TuR-tU#6%; zs~unM^zY8DkyVBiI~h3V{bBd)Xo$tbVnG0mJoiDb`?4M&vF+_s#AKR{xm=i5Z2u6W zE!#omB$HZ8D+iz5zrW@jSqImL<}}N}o?6EFD=cB3rQNkwg6VVLvCl6rp_B(U7~1JD z4H=tJsJ4pW?1eAw4m2NlbJNZX^P26#%0^pgdjn#-;VD<1#x+yAFCZQ78qy>Q7o5JC zSqIEv?egfm#e{%(t#phFv*>f+^K3o9w$nGvl~jM<4G!CTRlw9duG`$wmMhd+)aUN; zjfbbs>;qsuibL&pYnGk-xPJHAz1|fsUWt1mw(=<+Igp>MSkL`^TXI|u*u_Xrr9I6R z+q^808s@R-_(iWgpdF66gQdSj|7gMfm?Js0&KXrJv=|)gwN@1$AD`@4(lynL)Zzas z+mm045;Mex)S{GL2oIrHOTAJ8Z}Iw?dIL9vp;i^CGuY8_QbU6<7KcYfxKXb@P4^48@^ zT@^M3WEjTtYww>v@dxSb?R$%~_VM+&<zqEL4U<6)@HE^j{=3Ns1k=RaP2iUQ0@AU zJ$DJwN1554C+rtSG0hh33N?}u`r;0PqI%=;6VIcgx0HLg2^~W@fVa%L4l-9MIxyyQ z&Fp{8XMc~~8jTL7Wp$RpDWN-q#RA_9*$8>8f;_`+`*o*Tmh0O6?XzZWITesCoAd(l z>){*)i85lfDA+wtg--X(-EY6a&c#}41OzeWB^Nu^FWPH&VoMlXHVW?8Gda6B7zfTx ze2+#XoXgNa%S`Km($s#=f1-omU8L zp`UD(pPIbH`KETs!uGBe+(7G=x4GoGGVbsx*G6b6uz{oRD77w1!*8I=A4PuNe5aVf*ZszIi1_@hUL*u2n< z`Vw-Kj95=K?3k&L7xqJMKUrn5<5%u%t%(x^I%Q~7lLWVRcr64 z1a~1)Ooh3%ot!Q^t6d|v#?$@T<6-N7A64m1}O7H-r?>W0xf z!!;eBJ$v@-{5-HcRs!-kMR|F6as~13U)|aINagarKh`Bz7v*;KuHU$kXvrwuQ zC);~2WEQpf>cs?0lvh*u0a(hHtacI{iKnxX3^qT$Gesz8?)WfPo%p* z;Am^?I_5@bu5bTX#X~$SqCXbP1J12&Gd+b&g0D4DIp@b=@4R?%>aF9Tp0dRH8t-UW zOH*rV4H3wdC41O(CH8|Km!!&rw!Qk-leReBBDD-Ar9lLotze9!Zs?U>> zmBQw7?%cV~1G>7psP)6MVPmK8XOjY{I{ceAU4Fk+VT(>4UY*z2xM6jDAalr|2QV>z z=(${ppx&B4dehQ8ywdn+=ot$+j8SZQ9jPk!XSJ99A|@xVCMS2Z?wR9+iXQKi_RAmE z>ETj3Pte>{?UK9D3Y`XvG~+UUAJl$P@B%7#v|iE1w$HEV{GYHET(-NM29F7++?GHU zp%JKP`Z8>~HJ?sf=GK=`rf$fJ*>K^>&D$zJ>+qEheg$3Yu+Z2T+|ug3C4$~wJ7~-e zSNt{Ezd9zE*0p2@4}`=n%BRj|Uj1L;?Lv+Zvo<5;%f%a`!~$rs>&o(Szd18JSI-x?k0K4Ha#53v z8IltYD=7u1QtSVv0I`70G%-d!(VU>e?fO^Rp;P;^gz7@NMhBkVXH z{9N7Ttp7jNVH$RhN|8`SZ{4{QG;?8&-8+AtEOPsIoVi4jHvY!PG^iL?cy z?7+W9tL(+Px^U(UQ(6oRU+0a3zJI(etaH9G0sK0v96Ser;3Cqzbc+_E{W+0d!Hzwz z9!+~_jmZoZN3|=bqM{>N{-UFQ%3Y(;*2ZCN@*nVw@;XldAQ0CAGm@;=*7}QcHr5qH z+_8G|dFy?u(6Q&|fo2=1l|@FtyyW#v0$U`x(tD=u*y0(vDJSi_Lf=monCDEjXsxTY zRs{tGy%gvSD+c4FcMJQaw>K2ET;q-06lkVp6?*fk3>U*f?mQMQukY{;Ka#q1o?{cV z^b<6rDR7G6FhI}gevWKVnF!Mu*4p4^OQD5F$ZY@odw+kw1MC__bU6AP5M@-P=`bM8 z?VAr_1BK&YHMh7NHyB|B1%)+P@dKTu1usyUAwe`3-8*Qvfjw>qW+vI~6~%a%tH^{w z$i{1kd-=bBrcV$?`~!h758i;M{xABD8Ntt^w@J7;j@sJV3WrgUqmI-^)G#=@aZo+1 zq6Kv|7Q1a@_8oeWpgKj(G-nTY;pVd+H+7h@WxLPXk(6$F=_=R1qZU2aPb2!A{D`Ji zE8roS>0|m26%9W%wY3dY#PzU2EyFGH6L%Pd@tlmz9e^Z73djebTKb3GOe~8R`&H_IeJRxP)Ty9r_uos@ zMrF6;23;360p6zFh4BcVK-{0k^bvM?(%s=Z)GO{!GjJ-}LJgEC*_hqTmYF-8?j%O2 zz@+THFMJMRR6_k34D9}^{3A@rKfOL_nrYfSjz-i~9S?A;x$Egep9_>V2aw{BAAM^7 zK%lTT&V1BniWGEcD;iWEE7z>6{qhCd0xw;#FMSR9kfLIcEBX_CjAV4Vgog+%%2ymS z1=v!@jwAN|nS;Btg@fa1_E1BNI#f?VLe%uq`JIu&_K8yNSr3NbQePhVNFflBwhi}zkD&5vraHlH8x%Aofe@^*>)6~A_2BVS)9hc@Ad(3lB>q=^M4%DZU1GM z8;7X9kg5eqF;G#SEZX@I`Q%!e+4R0?Bm`7 zde5xdPO~xP4+}+*i4c!Ff8gYnH@nlbk3Knbll5VAv@yOJ_Q%Zk?+YA6{GVlqYM4SO zgK%{ytmexXb(^NAo|4Ea(Ug{!#v7&Z?CH~|*O%}St&GuH(RfP$3_98&Z)?~|jNqQb zFAjJzJeQj>VpJYBE!@x1ZFk}%SpV@?2A$3UhyoNRC`a6MA&X`;wx|aW`U_)IZn?S1 zA3Z9JgQwc1)>GRLxd?h4hmdlxc%xb<6>v`c1ckrH2MP@^4+JAxlq%Or;+X)V&0Drb zVxHwhFq1V5W+EH`Y|t9 z$uq049eK`7Z~fy03e?_vXjwdkimm3=l^9gd`6gSOADt`RM%|#Dt%U}{Fph;g&W1jG z_%JkdZ=d?vw^PU8)y;bC2mV17E0iA;2+0k(6~5vQDLqFP{SS4B5iN^_ZFc$uS*h_3^!6B=Ac>Vvqsp%@$42JW+ zg!r0!^;V)-;ZuEfpx^Zr%Xi!$Kjz^GuM&d=4lW~b6(yK1qNZjGV{|(rmSAM|;n#K< zyi->GFNKZ(M|}%F=!ZBOG-|Va(G;qxu71vMdgX$jx!Rn50gbvBnioNb_6NyKSV_OL zs!w=3w-@}%AaMaN7fxw~`|ljxXe( zmkAkHz?cy5;8P*5`$Ai_Tv#cY>cm zl|GesK~;f*=sr#c2LB%~r$giwx7VvwS!tM=JsqTDD^4e~iubOPr?ertoE1si3+G;{ z)0#@(k@TF0k8l6H)d8ZTCf7$(<;eTEME*2BeiymoZ-6uZY*hh`-nknMB$x5pq2iv; zCcOUWlf8^YO`7h;U5Pk@5Fg`xpzLmMR1c?u5#-yj;T)WK&?{i!b1R|yY&+-03Pnf> zzAyRg!#5XlN`{_|im&m4K#|f@ELmGS<)Vl83=9vM`oU;&69=@R{b9X$LBJ945b2RmcInSd@QqK|N(-cd6q`u4?o z>o{5J!6(YdxUk~-YH;X!@N3H`Di(l)0wLZ=uwlI_G@p~Go)Y11LemY3CGEMW3}y_` z$qu2m`nY|u71nx4IB@96&}>f+!n-GKq@wH)YTO+RQMtWKE-n*kn z+1cbUKiXahPS;mcMJ0?%Bxw|o0SyZv+f2Rtr)%W(oCiDdqg>N3{)~aST;|d%K1da} z?rQdRbBn=^L%IH;EeWbiWaXn{FD?@0HL_{z+TaT_rO3xh5GlKCU6u5FJIVLRi7m+Z z^5qKzsde#G&+Q=r0jqPg%ixrKCz1TFE2S$Lkx1L~et{%Wlzeow{zv5%NyT?o6puXe zcy*7@?kn0;4d3p%aH?xL3?|!xt)jOfO19slY&RHiXX|&6f%55S^&)?ylN7oRW)qe)Km$PE+Iw>e zMOJ!7LDCw(pmg_iB1)@==*w{#Lddb4c=%4&Y$12oS?5PQ>csjvap>R_h84bP58#ns z8ZhECsXF64`0*qe@|+&Lg%Iy(^90L2;GKp_4E8<>WjInSnZ*0Q;@ttQK8&<>Q{;2d zNP)Hv+>#SOwz|Iq$)IzTuxt@)w}YH6nuf*P;SLG{Fr^uRp;_gVK17?}+gbf;C?YDL7HfPE4-K(N~;&bTP4=M0n zIP8@W+&*97u=hCiJGLe!)~#R=E*Bh-J4T3pOM&zJ>C6*rkZM|j50fwz050`Qi z@5y#KJjES6=dn>y-0>i@#s*6P7$z6HDk^C^xJ`Z}rJ-rCvE(UlC4Ks%=@V^M2e1CbX0=ye zPf1ysjAQri-Mc_@0|tSJMIc&BP}%-XesGrWXLz1-byx!VP8-0IRrFig;1#hwmiCqH zL?CMWDve{KUgWJ2Xk^*G8chbtX(J(82O=X=pqOFO`RT;^brS%28u1%%G4xVG zV%KyoA5(xe)j`*S7QsGyWx=y@50`h+~M~s-@CM<~I-X^YF zL^%o>n?G>go7_hW`j~DHvrn9jRF%7bZFbu0t_R;*2zh@MGOC_hU0%`QLA03=Ihv=p z^1~0~S8IoGu9|6;hLv_*2OsWEHZn^Bh^&?(Dk>Z^TvA)pUvWvs!9{?2?wlWue1NZd zdpaVTUXqp)3BU zPMDHl2jem$`hT!Vb|P=|pcsF~e#X^JjHjlF&k8yC#_|O5O>%?PnOL`=lkM;I439ia zrXLJ{SkH*Qb>FQ^X#BAQT?rBb0}SCKW!PV}+I=l{B?hMAV{e1GTnJkL4L-#K&U zOq0)Y-`9Oz@AqqaqrySPz3tQ;02b{iP!_LpNq=*^k0P102UJTgyI5 z$fZ&o%mB;bNV|)?|G}cqsIIfyqc5OTd4-J@<;5p=k?fZ3N1vR7Xy5U9@H(JuIQb4E z!`n9xOb5~FLHdnMuc(F#z1I_UxfHMXuWCa&KseZpsC>qg=ZRtkMX=f1ySFCQa&{e+ zP!>sMmb4RHVNez2SD71v?m(Rm2CHPfy#kcqHNE_Ead#mCcZ=@q+6Tai`I0aGD@$TgvoME*4 z;pxWvo(P6UXE5F=`&n+Bh;4wWg$OJ_>4&;KT;RmzgP z;|ruA_@Sn{1=fP#YoNogI_)jFlqa@CEwU9+b)O+IK_Gi4YP1(o_r;9{C~uUOBEf*g zQAtS&n!?(9mzz)@2}ABhFk8G%*ovy15;eEZA4PL?`Rd20`;77X_U`Rz$N~6UI$2_u zdy<@28#fq1e;u1!nVuRZti0x%g>njb z2wflQ@JldBofZOHto*hr%bMdM9Zjgp5#^GNc5XBsUl}GQo7*>U0z3JetA`Szy5T&w zR{?ihj6UxjCt5ZZadWV>gmke0{&>-DcZCjnAPXdf)IJc#V`_`1srnJNld5Gz*hZ<` z=Sw6!dSPKFNiB0`^=Fc?23JJY+L0ah3i3~!ZyZMAIqBEW0kg9en7`A zBw&U8faK?*f2*0r#4UX^4|5vUCzQOFm>dYn(~!VvFsSOOb5ZJmME=~OKK`CAW_fz9 z#ouW6TlQyGoKw7{m^0%j|E^Wkf1OuVp7HDCgBiGN;o;#(!fG!hEJ|y?8IOcBA>Pc7 z>`7|LB9a>GFz4gi5DnmFFK3H&Oe*yP>L6U(pItV)p93R}a73LXLWy%Vku^bV$VQbP zh%69s){Lz34V50 z@)vYvQgpg9)yLjc8JW6FGGo;0jYhSv#e#YNtCd&TlTc|Zia1oAg9mFtYr>i2L>_N^ zEjeLR0&IXQGSPh*m$D))b24UIAlY_o1ZgD-z4qGZJ;sie>m-g>r@GjT#M`Wr>9!}b z3yl2#0G_&H46Wp}*T)DIQqrdv*cwcr`Rj)lID&wz~68*E-O_#2V zndSOQO7_?Y8-#QohKtylSrvRbm-gx-ouFjxXQal)yAh4`WWP|}sLz<%wNu>rJkO$% zBXw)-t`6DI-MF}H!FNH!xQYc7*PDL^8d^&dHZW-OJ}}~ljCDhlBNlOna0KT1w4E9g zj~Kgr?eFb(s@oSQ7mI_bX%DhVbR2sGYzC&KjIK5%M2x7kthFc+RE;KmaP; zhm`Dr=fq){QwQ0A2JiY&Fu5ucS3fTe^;DV+xq#5lYJdiyr3@T+hy=M8FVyoW)_Y-P zi*s=m*hdlBRGMh{iJr5FD>A`k8JS&efbx=4E@#i7Fy7q^Cf99MO(Q6zyHxtZee=gvFu{4j;Iu9VY@+RcknGS=-6Md!JkU|)r zII&k%j0C%z!nJ+VT;r~(a3=VWuvU{N9qN%uJJ@6HdWen~S|c&q8uU!&HGnwCP}NvK z!jIp5YgSo+?e;`@^jYzJR0PgOLwKNC`_$HhwXX6*j&(~^>;sFNLN>KV@k&>=G(&N! zBszUZdZ$uMI&ay4v;~4GJFeY;AyC*_5C!v5hdii5ARFNFTh0wk8@-ATc_-VH1@6#dDcOOC9BWm~TXjG@Uy<0E8CvGL5zRm>u_tqD zLS5%SZ$@f{Y_Ty3Z${u23s9Vyq6R4nK%vI4MC>bc5knrdcV-Q?)pg{rNT)0h&4Vj2?uX>r!kxt4>7bEWtVIj7=t`}RB zNac!P7i8F65*`8kakX&0Kxh@$SV0?Qm>`*e1hYb}UaLwEk{eg1yWv>h-J*Bq+h@PB z7oS~*ZU*wPcuG{I*M<|=s3AKmw^V<>7MKrMVDsQ=1Pd7)6cj_gam{nt*?aR{t`n&s zHHG7ubAVgT=1l$~xj03@^o;hAukjd z%&{$0GA!Rt?&$=8UzS33t4T>0zC^A3-H-Ss#Nzv`!vDA<-i`#&)z`k+1-{!6pJY+l zCj2wwST4RZ*A&k8RjfBtoc%pf=0ml=v0Z-lBArD1l!gX))2no{50M4hzU%LyCy);c zA4PAcYW|DfE>H?8C}@A`ZygeHJj8_5*O+Dhw8DxiaHvbnz&O5_pFza1unKtLvwiM1 zkmv%w3X3Tu)j76plEnAkF!Ns98*^0dnDK&mxc(`!Wp7hGeApS`YEWGuh&c)phkbeV zq2C0Ef33Rgt4n{84RYN|)+sS9AtAw(38D(Ka9b|q;>IkSwRV5~Di(Mu)6E;Tg@l(8 zG2T5gH{yM50x$a#!w21wCfqLdj~lUag&Y54a?2tLnN2@KTyk7s@jixjnFyFGEq%>Y zihK+B1>Q6?Fa3(9PJ0$b*Anpe+*vA5|AgvxLhD1w+)xn^Z~#X5mSZl^OvAp+Enp)Q zk+ZOo12J5#?+NjUPZ?=B5lQgX>MDAbc$-;4N3x*QakzC?DDaqixIUJh8Gh4$Zfb|8 znz_R-Hzu*!@_j?*Pl&Ja`XX2Tho8Lj96_w){NEUx|3Agp{0G8>|E1_6@}*)Fxtya% zu&d}V=sY|2@a1-jZJqtDMdyF}H)_=hO?V&uYhN(vdVNuC304}V}9_^wKv zEH7;*O3=Y8vVcSO>=Y8b!g*hV7)fM>ex4-?I!9&@YnTn;=OOg8#t^w&6cRHx zl+Ul*`)4I#Sdy!kBY+GU+Y}=+9SHC8r2T|uZBOH=afljYz!i8ntJoq7+!yU$f5W7vFlz&;k5Ky{jOKCz&Ert?-Cquz~LfnG=j$byB&Uj%Z;Y5?xnpgc| z@4kHu{pt7`g}atdw!Dz|ft7~LP|y71;H2KXz@n;tB5D=ZEm#DX_c20Fycum+OS&{0 z4-Zd(_XomIrZV;+9jDJ#y4BvT{b7Qp2lwpZMa&4%j1~FC(ZX4(v4Vg#ee4e+@kH-2 znPbDkf2%Dg%X5NcMsuOwkDLlJCO(f$^ttB2?1nU(HbnLDDJQYO%LefR^4XbclXh<+174I{2&7YXh3J>zQm-Ek_BlcPeV^*N6Bgd3263MDy_W%O(maYBfz zyWTvKr?-2~OmdG1RU`5|PfM+0D#bcVI-;wqYqjN!87F|lwt4S8=Fv#mR9?5QG{q|F68=yc znc7k$#i2Y7Fe1gb0JeW$1lnHxth(0Jy~?)@w1Gw|L{jpigqNB~^<@f2R}JY#;(6Ex zpDudSub6X&_^cGW7N<4JVF$uAh7}ceo0*+SYN@@P5%*IK{0+$+EX#Bb7ms>EIJ|-k zcR!JF>U?MN?I#fSiYh{~J+j6XwxTv>W1L~q1$>p8#MKKli;@b7F~{~AVn8(d_ELhT zsBWuj5s$!5gLesk*ljnU*+aawnQnSBLUS?z`QNk$;A*9HES+{RgrA7SG8JA%2n&D* zxUy`s*x{;E(QZ%Ny#o~w=!S_Q;#4m0%g=S9H@dCOFvM50d=Eu_7vDuiov z=KY}ebIsyjIF*3$eROHwXjtzt-|hM+3JL2RZVr((+~?fq7#W{V zTfGJl#m(~=&+OFy?rEowO8B<^Pv*iAM4Bii5Qt8DAQwa|XImrxLLM0WAVC+btfV1b zPzH+7U{2`Z+q~$ouo@7hI*G_u0koL}Mj0RcIl-Y9x`hOhC?eP?HS^uVRNoy;DwFTm zQWPo|<6nPSi@qHoUu(uXSAk23Eu+|nUq(vgK|paoF`j$<`ujlms-=*ZQ{9vIqzDQr z#%&hYC)?^VXO`EnY|RR%u3Pu!Q?F{Ot{)_ZRgWpe5U5nO6!9oK40R{EbYmxri)U zP^0+#B`$r+(blgM^EL*cIkkZBS5bivqif{MIK1AxtIwo!UBywV15kLEqa*sWL zZygXg0N>fSPvuZcXkuLq6LO1IFT%=*r;y!6aojp`l~m0KVyqp@1$wciSZusY&XPw4 z{Jx*SiSzKD%#Uqv~v+C6UH}3i8s&dA0zLrP}!>Lx>EPHx`B!?TQpf6IN-8c(Id>dk;wAkIuYrDVQ~yKo7S-TL~W z31G^moMB^i#%pGFqHUMSBVAIIOTPZ}8=idTXD%{a$9mu@PROr+yri6-_?s;%caIx6 zfKvPRV^EdzXrqz}(f5D(X}{>*a3n5{ixBU8`LTZ1+Hjd2wkZq#X_n0^{3=Y zEhGQeH*M)Qh|K%kd7^aGPv*(Fc&{^c_gn|ZSxl6DSju;(wA#&IvZTL#tEu^xtPWHQ z_?Wju+HyP8<9*dJx?3CY{XNmq@|u%z6TSVTE+vY0KcAtm-mpQv#V|9$>T=sD^5?PB zrS`in+B<}rr0cxc$P@fN>UMW^(%W12eC4Lz!kR?9$C57HxP~LqU*F?x)=6E+nm~q# zTen|Fkp~N>SzSB1?}gY{`MY;+jAkRbk$gd$HZg5+9vi8$-{_n;H2l0OlZ7wi4DVC6 zXblIN(e_T=n2Cd&dH(&(jGMeRGOU|tti{RL?!70E4_9K9Gp_TtAU+qTw@+6_3c=Qt z*7jx#0Rpa#Hfk$5i=$}o*a*}E!>JnrSXyy_dWBD+L~TuA&CjPNz2zTh8z$Ns^Ze$UPJD?7k|pJbk!%5o z6K``+D9bPLbAbdA`JV$j(O7{ZQ)v}n5YyIopB;O14zoxcPSa~IlT^C8`gN{z1EZtn zjfmuu)uJOL)J>S_I`H^{A5=PBy+!JAb-^Ka@{PG-+FBV^ZOa;+%`sFv9~0tky{o^! zqAT@!98K=0-e&=9Ji?=`%g`ci@6H((>R3`D?%3r1sjs47#V382@we`2u^=zD3Fsrb zy!y7^X6J`0o~}-g6PW0R5$(w`ew#H9+gL`^1g}fc9xjlGuzxAQcJQu=<;Rx-<`b6n zyI0ac7;l98=Ax4$>lZpCrOYUL)WN7x|1v4?C8;i*#b(H_r1XKZGNc75`&!zA?-U<- z_qw8VgvyJ$BXX6h7{}HlgU{s$4<^QNXmbyWF>H^W$gEm0=6osGTG>UXC~iVF?PBN_ zfg3P`O|;991IL29BfVXYMz@3xffC^h#p0K|SSlz$gXh6oVd`0Vvx>o4@%=SB<&UC$ zmE_1AzB#GUg+umUJN7?jppsj&h;{MO1q!Ec&$F0wX^vXUV~V5pn>U_!V|k#sIC4S4 zTsLX|HJeZKUYxsZ%b4B{>J!u#sKThJ9xbt3qSerT?9G7j9w`;|dgl)1n-zy&l7}a9 zN5>-G-W#jyJ#@H$Pbj2voM*J#p4ZWM?;+MUp5VEZl+YV}e$w_<(EPweW$Dx6h>-Oz z>#YwD1?I~L4t7-bJY#gc$ySxz;o5a;;?8Rxh#=Ja8V)CCf2A3Mcr z*sjf!^1ACjzg{(ytL;JGu$Dmng%IDMmcS^%37hwq{Te#oZ1uf+ruZEx6L4~3;<~=~ zw?-OWS3}?J^6+$P&bXlHr2TqRA;t*3{HDE?F969eHP2&Fql68bPjVg?M6LSV zk(|LK(#YDU=6ds`a$?PugEZzMD)EyYF7xyY+(3 z{eet=Q{IE)L#7E`cS5vyw-io_uQjfle&L}TPpeVd%&E(m(%rcwDyV`HJk$k&DjboQQ>b z*~+wn#h!fY9$#Sx18*$(&7b*$F+pibGEc{ za94x46b7Z}}BelA2E-KQv9f zfcp4I3QuUf-us0I>2)?t%%L2RE)?8;1FF+CboZP{mtFWjuzq5GX;l`{$t))9<-tFJ z``zf+cO4&!a5S;0JBRN{+nO;ZE9dNe>11?nnTbK#BE6CMFX!u)Y$Dd!@s&&}#D28T zYwOkk`FV5ZWB`KTGpjqNE-~4rv(~tJJ%X-157ww-u(v71{yIwMBV9K8`ucwS^eO4E zNYjU~ai>o`T*VP>B_Z&fhFz?=tvg}RrktXgYNn-i(bhv@1-VYp`;e2aT*s@}SYQ59 z>}$CbDPzSXjE}d?}U9Ijr+a|KF2V9 zZ0wHM*abywid91{HVod_pnjG2y~Mf$S#JBDy>|FmM)o)0QgOK=&d$PRwP1{^XRJJZ zdT9<>U%FPvB5ZAO&x|R;{@s}aY0QhL`A3=;q^TPV#_eNSXQX3QeKOiPs<}izl74E} zI%$SWxRd+A^a3qoix^F8Z_}Y|Z@Jm%oYz)2>MG#pGCFv@Pi#}}M=$kp64@MY_(tM?n8Y6TelM-_*B@aKL#HxcaXnZ;_cFwm-0U3o=?%qW@xh9ZIwJv9OW4dB9xQEhVpM$ zM_Hibu&I4#V!@y#{X`^PttjF_B+!(Gso_I{rWTkpUazRdPTGuvWw1)q3Yf)AY z|B$*xR%dD6%oPwmJAQV~!}r%8y5ScMURx45tZM*};Ir^#t!!P$c-x!NnAF{EBB;@0 zk++2+b9L`LBq8*5x-Z^o`COo5mqAyza7oTpD=84=AJ<#e>*7!T^o?(?{$pn$_v_eY z*ES8iY3cqh*sL9+`I}Jd!>NyyxpIF;htb#?57lrhCE@ZK;Rn7aQ}r@o;Gp=)ODxIp z*#C%T`}D_HzJKxa6s;g->$@c>Ep;2{dod2<^m#42Rpm9&EmW+@=ciuSil=ae;E`qJ z3g=eT`Tst===akvB+tx?>i+AK2R0+vmm;Ci#%sy7O}HzMZ_fPG|FgH;MP8k;B2#A- zg%<7bZwjQ;HBt-c-(R(kPP4IPYSUKAA`I&GE3$gGM5hhzFHk2LFJjdTK2hOaa@kQb z<@TH~i_~(C>HA~Bb9;?PndG&@1%$2XbgX?czM}{2^PDxBZ%!+z#;8xf%fgKdqC&o{ z3ZO0?iw6RyU+cPb{I?6Ylc%Fwc=K+73~U+zfdvol8-i7d$i*{BUueOyc){at`Ov5J zel=di=0OJMjEa=Rooe6(q1zqt0b>MD3Cr8S{= zO2%}sp^gp6f6(8z?~i(4A0LQ?a|T9T5!0@WDqchXv<{z8%kmWZ{?U?e~Bdw_0;7OGN$u-SI(yh$K55f~*AUU*4fky}jC;&;s?*gv z*KQ*As(*P-?anVN>Akl929t-Jbtg#jO`fa2uC)zfVoEF?i_fd4$Z-iD!eiZg>7w5p zHa0d;DH4G`5bAQD=f(JLTe@Y%(_bmydB+BJPR<5^{3caYbC0h*x<75h@jtjA`|r*2 zGGh_3z33EPXa?EfjU{m{9mh(O9%mou>Z|X@cWEvh6H4JlNYKZRAMu4@c67^*0XxND zp#AQc$NI+?32d5n)s`KMf1dLbxwvS_wOa+k5z(557O=)lJ;BqP(Js=`qw~J*5ZJW1 zAI#VroTw9QMF|xI1_EM;;vGnB?m;|T$pph;b&L$%{d$P@G2f!x)RgaBw&3>dS&$mz z?@S^X@yMHowLF-zesaf-9a>s-AnXkNsS!B&1Q2~DSfT#@ence2S#J29u&%CKmxzoe zR#sN9SW%Luo~RbA{jXeEHNYGb6VtIqpK>p~m;-+i-Jw(2ek9>ju9A`an`rl3khBnbfY9uUI9Ni8BZk)eW_IheY%YSCJX(Xk5-!lzm{r(O~oDPpmA0CabnvgAB`m{21)s zJO-igHDdwrKQ`bWRDlZ%_atoLc(&$e;+dm`m4-_iov|%la;{^Cw0B=XYflJ$+58PF{L?I?@?AIXS@= zT%3#88$l$U-p|Ldb$rtHyLVqCnz2Z@WJ9ai+KkB+jqr14W^T(LdIf_%H1cl(%o@i)b_`Mw zJ^4X#Y3cLlYnKrBNOlMlUIc1RVh7PPp{gzY*X=VanFkA(i&o044o4y&Z&!; zEqbLerG`vH08=+9U;SoIX0cZ`fGymj7sbWh2$_Xl0^R@(eO}2c0Yy|7{rpsvl|hsK zPOsV+$uS;uZ%4`!XW5jMr-%uJiLRPvf^LG%GAz#NSm^2AqsSBs*ftTM{^8_fr<7vp zNw9UYgg+>n?p8|+ZOhJG1{bi&-(Ej;p1qhp4R-Oc?z51hohlY6=l$VvX9IBz-$DT} zEdQ+FbU;7==+>8ELYm8uLmr-PbM#HwI=&A33JI@B30HBSun8)@_pojeX(dOFtZ|l| zFDEY_ZTf1RdK~UYd~xmRR$W>-(#E6TPzdbICWaW#Ph#a&VkAbHypudJe-c67rw6NGIrwU!LE@W}W$&VtP1?5JaJ`eT`b zK%4qKds%x3z8Y%!c&vB8qP3f&gpV9N$k6lhz-s^O#P)W>8}Ck7!hCZ>(&ix?bD^Rc zmMzi@=-bBJdE3K|b}BsY&JN)X5*=jAhNnX>5~hbTCXHg=sPQE8EkZ&eqU?PKAE<<8 z2(=&M-ZU2eG9~zc7Ss9YzGIk!f{>-JIKdyzfyeKkG_;i;q|0~#lref|4YI zOR?o2coi;hj8aiUnU^G{5DZ~&CfHs8N3h;*VLT(32`&#Yy-1TlXyKn@_lAnwJVv!b zeH2rcjHVO0(ht&B{QRu4mTPv=rLfpuw`k)6R%=y**ZrNzaaF!t%^$+d*Nxh%Eb$TcY7=w+&&kN~>%J}_T?Y6Z$M zQn+ikNU~p)2K7n72YdAUU${>&#`$F-IT1Z$WrSmBDFH5=*PU_gNJ=k5`QnS6+ze&n zR$6107%3_O+LS=1LP~e)7|?q7jvkIVCFJ(X6ZU%~;wd1r zUW!gEmiv64FIN}Ji$=Slx8EWm5xLqLOgww!_3LW}>8eA06w@&uyg{09cL2a>W2s6hiDq3GoUK{D@7U70Dd|Qm&X8(7EmU((6Qp zo!vTJUsWH7c|bo^IJ*C~XlFYI>cynAtLHCX)L2ghK|=Nd3|-L;7C4MRxfU6zgM-J| z_-1XH5zebx<8m_|?d(icBzlW^uMWKpUXOk}b<76?U~|(=Z8FJ&#zgFUM>Cs$ku5=4a2I;Uwkb=02zOh?ue4cu*j0 zO>rT%)UNUv$|A4snglhrf%W&pBF-_;DC&9+F2L@8>-3clxt)4dihJPcu;}) zXQ`1HKlEp>wYoxMPWu3#HX<6&>$ObFfHLglTUOeLoeINfj50w8pHHTuS@>ZVey3 z5?`|bW{G1Z*?o#bkhOKmC$@X#bgFu84gb=5bBmY{aV&LsU2F3_Gnk%+J#dmw3p)%X=yRh(L1H2jvYO^mW^#tXEeBrmQDDOpN;75)Vp6BsV|s8JI9lS zW`$?IVhgIaf3>|uXfP=(l%fR1sG6IJIT^29-m9mGTx>TXP?deVr~0w~;AP6hfqZ<# z*T!)nP-lK%=YQ3|r>w*GI+S62Lr@s?ehp06koo+992{sZzf)H&o;X>xuj%XIRi5WY z{iS1nRbvzGDDd7BUbZ#sj34ktyAh7hQ6`mt-`#8Nw6(Pb$F+a|l_7;|4=I_uP?JZw ze_1?L?aOEHLj)jDw*$WdEhI^&bFMfPIy)DfD*6dDU=fae8eNoAV&&$UP!E-{^}??h z2`ecOz)Ax0N_On|_p5gfMfNlngr#=3 zv0?dcl%`R1e&{yef7-aW!`@gv7KQLylZK*tc$!1CR+vz&`JJ_H53_$BXzIfKE^?<0Qn7i0#91 zZ)0ZGtF9up+ZJdOiaXWeP=2GOHLJuNtN~ISIda6>nuHjxjaBbK0vIqat!M$N zHO}!TPoJW-lxI4HSOK_xEzk(Jw6q`c_Oq(wGdFqHF?nOu=qIPjabe`xKmLkUK+%;8*cwSTl*oV&fa2mVB-gkw@vM2)8E*m2X2rOa!P>QBgUmBZ#cT|n6x{YCu z@Fm%--=A){gk}u$Y+_@}dI-0+S}?Ny&ORejNXBIP(P+`o&|n_%ni?XAx=tiM4hrpe?JSNC3#QL;mU`uK||Vn30K`_cgW#@|;tc<^ei zL2*e5sI$1nBUq@ZH4C7(U0P#+8*5FuB2BS<5{n|XzphSefCy@N)vIoMoRh*nEU7_P z>+Fx}hF_Fe$-&a3Bwt9hHzYxWOthOWXg62cib{+${eDMc)ZCHN46bh%&EPYqn-k>GzjPbV)ZPE`-KK$Tvw@L%Um%dUg zUmOor{{F1|Ov>__@1A8i4g;sD8t@{EceY>0!CSpgDF-G7^kIYw9%Tsz9z8mJ`ZTcg zr3mwO1TKb(p4p+Db+;O1+bH*m&~TKrXpVr=C`(Gt@p;>6Pb9~o{oA;HeKcLh78N5M zOmXMsJqSwz&_aYzedy~`A=@_GE|sMfp6&w!HL!N1FRs!R+=*qSrKM$Iv8CuP<^mz5 z8bd9H0*cUCqcH=eoQ3sxd%Vq zO(vBdag^0CF?<{zj@P+Y^;qwBMqDH;qjMv}&PA>*P&edp%!^o%Tt38go~VqYsh1EJpPU$OjJM2J1XaengqN3> znjA^h^!uz+uGZK(M84JOSY&(L#L#CV^QAgz<*3etruh5&`R7Vr0kkMj z+Vu5Trm>61Int?fzgGQt(Td7SlH`J@ZU3nKCBq`3qM~plh+*vbn?GZQe%7@7jDibQ zrJ!h%2LN11e)i-ELfSpYHz{yOr|rgN+P`AzeZLSSKRdXGI;;BfJ+;s^{i|wG$p6~4dMFIBIQfWPVfF+25020mqgtD`;R!)wPSQC>`D)hs z`>$w6;w35Akxla7dwE zc_U^5XTiqg(^SI01<6@i4S+)CFa7-p9mxKjJViMV@0^V#4Am4fcjH|Z49+MN&PTVl zww8GT<#{dsLNwj&KtURcVX%cq-F%xO6i*B7I5Q7DEgr`Vj-?b$W zAvWCL&eX4rAdLg3=^=b&u$pk&l^;R82d43jz!`~?k6&Ee1(Q7Zb8(E|jZu51qpHV$ zjQO?^goG-Nt#dv;9I0yqSfxDu`2@jTJ$(2OK|lWU?f@CpV;L9#bX2Js;7sInA&lC~ z!-ELKL&3?9Y27kbixw;(phc9zMEy>TVujE4(W6HMp*Yli0A$tsQ6e~6PR?l0BZOQa zYD=dw^8hDB@FMP6`#EtBGBwpN5gq2kwLeFP+@8NLOVyFst!9QHsVJi>WQ~lBoSd9+ zFVM~GQCD|&cQ+Ch6nxd#7}=fot+c+8{Lb+@&T=-DTUuEIx9&9{ucy*Z6qc%TlrAvg z_aGS!dDdJ39v*WgBqVt4fmtKHO&meXcjmKfw~ED(a$-2R^NN~y9NUQK>q4aqcpLP- z`O<8Q=HH48VB^Aczfo+dE|a4M_tRWFaJ0d(x1F2Y5bG||d5HcLPiux}s3=0ytXrQv z*){MC)h*_p6iS1@2Lfw&nTlfh-|+@wMQEf1_RkrfgTUCIbl}7hqOsWv8R!7us}ql4 z49)QsWXkJk1ml$t1KkJkS%X9$qM+pD;6O2a(FC@kt^E*0@kGL`W$E3p$;U51FbF`f>o{a)hz|V!a}SOjAiITJCmMz!%&8s zoBO(s&hepggPkG~kxm0tH4^B>pTSGDV!#5=r8Q_a3e~^Jb1R&47Sm(jaU*2;ZuklePlj?RTn^rAEvl}r-Z6>wklrG9C>lsSv(KSE`wDTk z;~f<@S}jmYp-g~ru-X|_Q5~_s-PEoYUT!ton3y zyQWCn%dmK}Eh1mb_fKF&j6fGYO>Q{_TUioahS(ES&I5rU%=~-iE&4+%qve2hzfvg( z4X!O)EP!*q=Ojq`u(?Is)pT}meW8bkUyqD3pnL>it}=6=Wcqk;7w;U3Z-nY5Vx!!f ztVjCwNA!-20S|ExP1gf7p6Kz!U=jwj4@4hDBc7WJzP>IPu#CR^YDmaE>>|8Df2VQ^ z7kDz22C&Hxp=c;eP|k}zfyQDW5Dr=7Nnx;KL1QBsk?F^W)W$Co)@%gvISjNGVR2>{ zmLCOStL*xFr_hTFH6N5ZOA*3!}v7skMQd~_7N zBR7`sT>Mdzt*F7vt9$Vj-OsV_e~10l{~Giv=9$g&^L^V8Qv~d}P_12PtB7?wF;%fL zon-?de_~v2^wNj1{J=Oep-jMggT-+DzT0uU9 z(-91>Ze(sCcul!HznTU348kCLT!$VUT8lo)p!}Z3ZLdoI z?-ZGW0Y9V)sD>GGmin)*;<2gF=F-K)tm;?28{v%Ca{O)wp=9~jhVb1cWUT|$pO29# z3hPSZkTBs*CVtL6q#@5SWSXT7jBYWaD2hr*FvPql1jcy#_@EwHyTKBe0NTfoaDC53 ze$~zy5SPGHbP5!z(_eNj1JAl}Sj4vmZH5lR`1~&+ zYG)PoiRT8mJ9>JtE|k5~1Q?F;b{$F2FKGI-^75wVb4m(}m(y@Ju;BCBreDdVFO)&A zfH1*F_F_|b^Jag!0@D=6kEfbg=4cupWD}7#M?4|QBG88~YOM1NISC2eY-};NZ~HsD zv3&a)Q+=ia!8%Zs5hTfv6^7p_^(B3jXT!~_iDf4H&*s$J`rxmcQ_Wv2s;@XDq<-=$ zDwUM19`B|Ok7=}$X!^e1%KwVO`su0kO^XLb=5ft$ZS^JU8AZmw!w`RY%B=aHw@{nc z;V$1uPbY<$=jz66ZX!5FIu`wyhYTq>$#FE8nNdumMvY1e21-qH}jvX>L;Xf#9uJM%#p+6-2l2#re!RV z-?#5_G&hi~^{+2}{QRjDb)iRnHG@8-6&3vWtu%kET$!e_UwVB0ChdJ8(>(l!KYdR= zc{#PmvCJau%~Hy7eB|fndue?@a;)BP6J^$xvny_M6^38Aas@RcZC-IC`Ln@Nz4?E> zVc=W+ochCJQU;D@oTcW5h6&N!P%?@;4sCRXmhcq5S7*ukT3;^uD3k=Cm?790@|>+l`$IJ^?oKLo){u-8mDD3rzeysPTwfoP&RGV9?Uh>D)D;uh&J{ z2jGhq(*+kSIOppt?m*(Evh8|h3VngK7b=Cp_HuWVI)MMJ8Pi?V;T#8n?R*GjZZrp5 zLG)TcF}b+B#4M#vp9AgWb!TU1C(i1`rhn7dox$_CLL)%YK z5vda((yP6ePh5E~P2WkUF_|jA_S)P=`xcsk%Q`Nj#~Jj7s`C7^q-%v_H+NwwPoWV) z3N3f-noA%0Y#alKLPO>5t>n=ra+JI1G|Ykp^ARU0fE>4`rXvG82iA}I)FY^rmxJSm z+&nu3zN7wAvg7m?L#9TtfugJGhaUgorS$aBQST`5wG0!=+ik9b0LP-TsC)A$DFf`` zw5dtsfZ>vp1YMKnr;x4%1U9zYVI? z5<`|Q4->f{5TkX?N^&&3(5uV|8#!QR`}CbQ?|ix=ZqxPwwlCdc#0 zVcC@c%l&m3`3-jr2#I>+9uhwGjC!{k%+QBZMg`xYl*7|kl%I!G7bJJ9fpiJ=Z3Co> zm>*d;sOHwCwug6?KE(QhSEv!dJuzVswV~b)o5h1W^jNGW@hjs1z=K-R$+lU=q-Pkc zK`Q>5HBHbWbEg`<2(+7kR{XGw5c#o%Vm|dCd`i=RAOEKuQ+ z8f5Z1LG4)am94~-C(NVS5lC(%Pv|V=io8Kcqn!)G&YwG1#!|S&bW>YtB$wR$dGi8Z z^h3@P;72;Uu&{=cWdO|snut5)87DM(HL}oS-!wNsIh2@~@3*?9E?%X=M`&p6aNMUh zKQ!8#xfA*ypEZhfzI#01QA5h*`j9$X^FOia^}sh5oFaCE}AeuMGg>3h?N#qo@|IM^L-0 z1;IF;*V~N)Af9R|94b~KBBuPLrlQLLl#^zgJ!v((G}gS z-W||kbxFZZutSUrJj$LOda2 z6cW8auU4zzFxO{JdDpNy&@OYc#~MKYf%CO2gQym&s1x5{i@z`T@52^H zF1za%q@}0x!>Itd1)#(S;O~t5U9O!(J6S7cWC7B=_Q-+V1)rb+zwy?t&eH2H=txUH zm(pHDjphuP96pm4lqvaeTKN&{F4JO$j0Vd^IAp`0j7vKK;{P%0yPsX8%g@(|+nHNN^ zc~wF={>HQJL|4N76o(Jt@Dgl-ezVU;8uh88W(Walhc?Y8~mTF}f zuW%m0e6Jucy;7@BrC0p!1w}@xXp37LF3jTCw0}zwd?0-;_uggtZ5<|R6lf|Ak2!{F zm)n6-`06Lwc<9Pr-b=q$<)lT%_+GrYdYi?O$>X+t4N7h}F{l?VT>BPB%f97jCw;jl zib~qs+mY%03E^GXZJ?@L^9VHr4q&Sa47v*8(Lsfwd*>t`!3WkIJBLoSM|l-4FfKUR zS{Q(N9#Q1WLKB;wzIpQog4%0hj(0IE1zFQaln*N^784u$J6=+1VTOBfm|YBsNo7J+ zMPh*<=iPiK7Yt^w%iZBRbv_$&vvQ+Ljp=rk7=Xz{fwjA2&yge7Ym+rZ zB0PYz&YwFMWBwYusY&hSZ0zhFPA0vWuK^qtP|H@zF`RQa`m0eRMF`svtX}8J_0Hj; z1Lt)**+qha3vU}+04_r6HF>WYZ`=XT+TV%Lzt-@`?I)#~g0$?cme-~q-!pKHwXz>J z1~MK~IdM?6t&4GOXuO9pJP~j$dl10Ubt`m)Dl}gsA`i%n;jj6ClT&}{^4O)JO>@LU=L8DzR9#?tHD6$LxAUk&*#m-s#b%MjS6`G zrO9Pt9{&FRk00+`%C15%*n0QC22@pPWVB>K$B(F7_{b_)9(+bSgQ1)b!bfnJ0S$f_ zF5FY9vlP|Diw(Kgh*P**4h=D}4~L}dg=4M27?`}xY@+qR-; z#3vTRAQ7mH7gAH}(ULxuO328_1cmr};DOg4Tofi=Ld^kMX7vRvUI9R;A%Nm9g<%to z8rsp?Ss9V|9BF;v{@e4SOJZ9^qe@{rdhPHULnoHbWZKwHcaxY5F6xS$^bHeZT>&~S+mjn&m9LGF zNF7IeOuH&>l&VB*#83)FR~c}ZA%z6rRX{*~nW)}p@cz@hYbq}$`rvE?b0W5G9paAt zCR?`eCCDfAEH@-r7v7|tqRn9S{2>sN{TyZI2%hBlxHyb~Fa=H0U3rPXF^Q=XLzF^i z41eMtenKN~zdbVM?r&f5q?sr&;mS=~ClrilFZHL`lmiDUdR0S1?w1~)%>~SZVnT49 zrigvVB3yajjco>x@m$(CUDTtb<+{=Q=}2K;_?A;^_%Z3x0_)qA&-b1||>AR|qWATWWBc zbdLIReKVW?Ll2~pQ7u7n`o!X&_WwzRxWkk*47*$l(r{{3zaq7MmC8^1ye#h#V<0Ft zzMHjOTN?PJxV%qen7n2CH~D#QGNc0(S}SJq{ZHNtjQzEc%9T{UiBYF)Ifu0gWO~c* zGX*9A(b7EY*FP^TLO@?q4gIfN-w-4_qI=P}=-d7$=mhhcUQ(QFll^Z$oJ2DEoIk z)?QDMvX$EWK+10GyWb^sei&(Cw!aAWB*{6w$Dj=FzVTZVL;lCh?+^Yfr*Nh&hm=SJ z$jDIII!P-lUf~Fe;H(yj++_HDzR!CxT74rPgAae*cxg7!V}d#+KGHYQ7G|J^In8T_ zEOnb7eU_gon(A&}-C0m+id#(al!n}Y99-Ua#kABXNGBFgZ3*Cg+#p{<)`n1WTv@+0 zBce+wNVAhO{`%YBe0?-Y>#RlV=i@6=h|M&|cl^*~(XZ1}AG#m98VhABzUwzaW3~lF&PT{7;nyF%E$w=bif?+<*2NZEtAi;O{7a z{>H7XdevTi@n^M`XLYcjuYs)WIV%oy_Y)({;OQ=JM|gkK3>fp`;w~y zT|O@eAfa3N!~VYhemBm~fH3}4xuWjPUR_D(@sSn)d_K^tyu2LED0?YFmLH(+Dv#vu zq9j6w&o^&+k?{kODZ%f${b03)LPao0^8`wO4CIv)gQTZL#L~X2N74OO#@qJR)qvN5 z5DQ2uLBZED>!_)fV+_3VGhieHGm(~-mJzc_CpSD>4*($h0IK%}%K|21@;3zhn5W!s zMojHQ8nc|o#g9$ybe)IJ8>A>^E|mjro72h>8X9VS58%sb(a)bE$xf$6T=T;(gG`8q z3W}Wn3Oxc3xn*#l^)?m_;PEulMxyMBoV-)5I8%EWM|H#S1dK1HCEFouzV{_uoEkk|YKI zJ?E0%0Irs???)bzPt#ko2R^%Gk9MYE_?kFvD`PDN84y34J$mdehiotrpq%>8aL=LF zSo=WL7i*judoRPFgNmpI4Hb1w1n=>MHQHHL95rUZiqHYeGUM|f$f|2`#K@XL!BebE ztO5di6Wd*G#%$8gz9LS{q-UUqa0D2?kwsA;2YaBuzpAS0N6aV)=mGFr5ue^J5^*<> z=(yqiRAP1kFVMOJpcY2&z4BElwaFl~0PySr#-{T%^TcMPsz&vuM)%p*$_EmYZ~VOoRtPi583av;nUyEGoHGT7MnaL1e{N(FuoRA2Bo6RT~wBmc8pt( zdRS!@gn%l#3z1B_I)uv$PT2z(-5QgK39h_iVmZKMS`%05I0d*A@U30@4ozQK@3SK} zS~}R|cAA-OKD9qpI|t?h?`2$*j&&P!m0zIkgGjVKM8Tg|P8)jX;9d{(h#+k^f6 zzQ^(V9ml)>`0V3zZ0Z^A=f1D&JkRSqJ*fk-9<1%7?(R%s7h5c>sG6&dCzjeDWrvZ@ z7pISKtRk$5W6;LtXSBDTT;!gYW<xH%a zEWVX4A1RoD2`!{9X2CiaNr1sgd?^ zQ~wxDz;0T&czkidc|b*0icqCLQx1tb`sz2)Fhjn%nD@{G-1MNjVgyTWUhz#lODH`ZFF#hG+0v1V|3w`0v!tGl$7i6O=Pn-DLZy1MZ7(U#v zo5+=nZQbglAK9*NbFU?SFgt)CN%xNhV`V1e&hM z51Agzcx0@uyEZMpfbk$_*8oYvNuLK#510UrO^kl621|A?KrN*IMk?={&daV53hkPkO?-X=?haF(VP2d+ABkRiZ$&;*I-xuUSloG5eht zRig#MPt_F1Ts5-)Mvze&;kl8bvO`|}4J5x1j~4SkoG|SN}re{+E(|#t$1S z75+=;gPC%$(#gkGi0L0?_o&l`=_$$?~n9(E#%)~F$l?Yrq5lZ z`7aK{;|GH@FMO2;5en{y(am^4&w<@terY>eO1>0z87J;Zi;z#5@{dBCe}e`5O9wgA z|9NNdPX<@tOKW~Q6Y-bp<+k;T@6|xRP~gU?uKNy<`nj<7>#8RT%jUe=k5HvJ{14NCh*!lbPof&e=gk$_jjvDQheY#of$^- z>X3|#m}ZOj@n?@6KGXWdRC>wX7A<$zk8NJwqRM-&@9>e;t8O|6vmu3;SVMb-!BF#> z$L>?^QU`9DuHI)F^Aq#4$InSPiGd0~3u5kpsN+UeH`s<~;2OskBTL8o5 zDvK$hFK5;-UT4$rzGR@Mg=f(sr5<>e^+D+|aP5h#ue7jG>F@cJyZqg28`U2+82rR+ zVV@r0ym@zjK9H}W!kz2H%Ofua(FJa>F^~5{o7M@~HnWn>ij>J(v`SbC7oQ#;Y8;sJ ztb==}$3WMNmQPPIAMUYeroQ+3^KJjy-q02K`7w8{NOI8;oMiCGxMtAX=ym;8e}$=2 z`qjYr;Q<~~>$e^g;OZ4z0>zePi^Bw4i0RpQD+U6rryO~%usxAX-vZeJxFq6neD=|t zfB$~z=lk22RhL`YM*?#+WZ4(Qmy_es4DZqZV1ys9ZP)z zCN|IzGavSS?Ik1i_6IyuuPyLYd1getvhl(hXt5F#?`3~}q%wp@jWy9mr;O}qiS=9n zP{Zr?r|xE-FLKs;ziI5h)-uRFamkEb*JiKdU#`7$x#Mz&Nwd9U_H1z_@7ewG+`B2S zDED_>DC)bpX!iAu=QqytsPjDf+naMYcC6=fT&uKn+N*+?!Rq%+4B`Ya89$U!9M|xvu-SuIT zX&bpi&PhZ_{U!Cl@GO66`{DI8CA*1yRVSEdU5}dBvx&#P)?1QRb$4@#fPiArtLv+R zF5b1VDS{D*e@Zv(h!(OV{XI6MnC>f@qD8goEmN?0Y1tW2oMNAeG2|kn{hzFdE+$!9 zP?M-}CLzxaII@`2G@qyP30iJE<2=Fdj(oj`@(iXcc{hnct&DxSR zkr2Cb%^Ea%ZOOFgX$|G{n(X8tg^DVpW|@pVL6=Zh`Pw{#9dxu0m*n0zRG1cPv0lA$ zpo4s<_|)s&2V`kC*KSTQ-A<(#CPv=0AoV+NOQo4MT~8BUZMT(N<+&mksKk8lzfiA~6+vhkOT&(O-ev7eM|({CUslM$XQWnN}>dJ5}s z+$%-t&k(>A?|Z@I|ZnQM=-vFn=_6V9F;mnZyg^p-`anDAwpmw)QRJ6IFg-cI!0OE|6e30fUF zrmfek$F0npaC*}wTIDN?K*>(t^z`s&r#U@+d{WQb4wyCOvgsLfyB9+=+@_F?zQhi;{RAdQ4<2+?vS+_qMJt z1zl*_^t=H#N0Z&9@y>%V(&Za}x1oC!3=C=>?%6CmaDtx&@Q8kbx%lKsle(GTS?j~9hcttCEXJE>6m995e|$2#@#4URO!Gq4 z!YS_VjPApxQSi>?OUyH|C55etiassHt!!vF@5kdDDjt(>8M_ovmuWG*jeI+@4sT zt2rBW^mb@?a2|ij7Zp2O@auyX0Fn6m(!;`gUT{(zl(1Z}S#~j8N*c^AUSrq>Z*srk z$f=txl#d97HU)dd<}L2rHR3OIf+CP5cv4zhH}z;|E~|* zF;Tv7-q+8E!PWFK+-2^pvLl8-Jx__rNPhURNA^s=LG=%NCqX6--^Vi{nCkcQMw-dK zwj4|jGZ2E((Geec;r{(Je`)c!@K?b?<9Cl`K?FV+ap*TluBc^m>gt^c63{z^O8v z@mik-nvrzcVrGl2@)7pq=H_PS;HaVo?;8Kq!kGnXewSU#v~rf^IgDA&=!K_sz|Y_A zz#)oC&l#3ud69{U%SA=|5lPSZW`DBU@J#cMFn$q^q<4ZG9T-h~xg}iCg~l++inp$M zT{V+aql2sxa!2FpF7ue0$#F}j7%a7Bi9A1Dl5t89?M4}64KlVs&n3j%j1pr_FdEv; zjP3E)*QbH=|9mmt{r;jiX#|~`KDL>Swy$58lH92A)!(l-26my?alUl+M6r#oIZKG` zfr|oi}3-^zErGt2>)!ef>nQ&d)vz0HyZPPxp_pg{Iow zW-n*gl+RmAbrgH8_WOw=lm-66Ki!RnRgZ2g%Kzhl`~L05G@6p?bM19Au73z_ON=h~ za{H3n?lpyLTu_V_eOYCZeI2bxrduzqm^MJGPG7IML(|OOJ2tjmW|5<3S7gJyeLq`H zjG|-rrJt{CF@HC`O`8nV)$=`;^qz%IU#GQxgSuhMHusL}Q&^KR33sNY#3^cl+al4L z>U8~K0}YLwXD7AFG;3RgZQO%{y}i|LwHiIVCOhB%e8$iA%tb^)l<~)Rs(8ufcaXdv znx`+5F5&w`x1mMao4DsSmAjc5?(~fh?)uVO57GE54Qa#j^{smGO~dm`2VD8K_jZx2 zIX8tGAxBJbD_p$zJUdINERwpDXM`3#@d9%N_o77~ z?`_?^cP}YLr30CsZ*xa#UBxwWxi&Q9qzpaq3>?CF4=pB|H3?Bs`Z?y-btTvA2l9rc zTN}8!N|&x){rJB2^Y#Ltvb_UzN+(X}XNJ5PyiuhZFJXJ6>ur3 z@p)m4Zd-!gm$`O)`MY?p?)u{dtPzb5X6z=LzYdGJ6AmLxJL%DGA*^h3k6ZU-X++mq zD0M1-&dc+H?{iP4W)HlRG01s~HfcVBg4KOipIov;Tu6gNO=Yz(C>v;EmCIij9VPW3 znD54oVm?J47Z>(=LR&G1yG3cIF9 z3fVb99-i+VZF`FOi!(=hVg&+9`smA67nX@M(uG6a>x3=c1Ft8oAtjcD9#ZbysGCI= zkdnI18_o6G#EDKb;_4xYJZebMxasE?cUr9qioHb(7MR6_WjE1PtcL<}11k_tHr=`f z8Md&6bv{)$TVG)Osr9q!TYifpzFii~+_X_&b#>L0CneaT9)VD`6-3vC;*DFkUOu)^ zCD_H>w*TD32SNvTukn$y`PwYZ;?p0?_ zq&-rA{E^XY1Q*l0dgd1>blym$C|eclQ94@_4C@WQq_MHeZ@p+g*mBZ5Q8&A-NCIlR zYq82Lbn9f76n!T<{(ruS_>uhy#rw5aAL`(0O9M|;y2d3cs!%<*=G8KVjJ{L^Ohr0v z-709Q+1BvEf?R5#(9tPv>fD&W>av>p(3SSq)>RNu-{0w1FjSP4U7~i7H(RZPN3KyP zkXyO4dC_{^6IcjCeXip3JKaLYuFQ?UOM3j7e*29O%8A`E-|fq$ZE4;S(>pe^KGw5X$4kGU^8 zEY8w~r8&rQM>&;WrydjGPtpIH*8$ilwm#HGwi?XmNztoY=3Wy`N*Nw->|b@qeBhwz zbOC9#(c^PT_=o0mW90)rc;UkvQe~ztxgNr(Fz`ldyl3<~U{Lg4A-lYJ3<|@p$P&Kg zX^U2C>zEyXmE*4xVAZt8?lp9bkpFw~7Ut73va@US@O2z{arWlqCy&dUv09kduUB#B zwGRwTG@@n-t4)bsY<=~S3T5Glz5=MaWVJJmIXqA@my)U7YO%>p!Vm7;sWYgF)Z!g( zdZJZF+@$rln|u^=%7Sf20$jy~n4_tUz8}%U_FIsPA5bleGedfMWPE&5*f}|i#~O^K zQ6qE349M>k*MFwmQ`ucy{9Q>sR>tkpnvbfIw)@GKeWA$h`qCZFTt+qTrq3_vzB#0$9N0D3mK$ep-h6l@AG;epB=A7H{W2Z_ z9ZO3%wq4eu%z6@9+B6)xs^y;7)33Go_l=JN9c3JO{~x8t_l*yMH#cNMLJmppQW7cA zx)<4t3&@GJDvW}5^rc=)x_EHoMJ`6gOGKZv{`}SmyUX`Z&}hqJCLAPZ-p9SwRIM_@ z{vXRk4?+vWXv&-tUwSgs)*HW7s!vw26Sh$)-&V-=q>@cYnehv7dGVs?`t{|7YO;)b z`PRxFQTbYnFD6LDuK-NnA&S?#!F5bbmRq)dDP@9)81W5WgNqC@ey9f5VZe5YsUnJZ zLUwp()o>x&m5=e3or3UJPb|E3t5|YbkV?2lS<;tKy{~P+?jVz|&tpj!|F>UC$cMU? z7+PR<+pI0X-($AinbM%-k;Wdr)#JBMhE_xw?c3;KNJxqrva|g(FT1!Ltqk6Eb!=Hp z7mcS8^4PKB_6Cg@-Jbr(^WXW1Fm)PYXLPaMI8kY3^Ir#RVQm;2Q=XLPGpa@5(O>OR z*wFp^*lR@NGGExY3Q1@gqi>pMUA`}g)KEERl%HN=uvFv4S#s(npU~2AKkRM!rqHj| zDeB8k1jNabvamzgT1px4O~Z z@NX7{Spx|soHI5~=G ze-KUnpWs6+L;bnPNc`O8Z&5Ivf8M+-(HT@AB<3=he2%1%a|5!&^dOICXPHm39&E8p zbz(gn*Kx%iQ(OtO{rmT~O}j8?POs*8@E|;%!g;TmLKjPJmMni}>=qRq!VfRj*D|xF zb^kB57O$s;J(aQR0C)$r&QsgL-Sc@x_1~sn{X~1jYflQixe!4gNFB=SEg!r}qveEM zAoW$2(P|WU-YuBYdwQ(%pw9fzO(k1$$ojy z(jkE)-}d$GdpXgcRcxE?oUYccXmSzjLTl z8S{JsLZPR1b(`F{4dYo`Tc|JG+FG~-saRg@{rxHM6>q+UY0-Y4lzknYa)Y#&c#BS# zE=9QK&aD$q?P>B(FeokxWmN>=4Pm;x-E| z_At!x>683Zv(&$-*YIdl{#x2j)Q6(h6<{B3@}Bbx2q0N??H2PEFFng`%_1f$^j4ln zy60HuZT(bGYx4+IPE1$(KDn8^4t`bJduSEI2h!aJds8lQqhfCn6-`jjg+&b+sJUI=T`>WH z#2r2xmQ3KY7TB;sJL~3MUi(Btiko;!f8BC-zu2WwY*J>5io06dbEHr8wg~Dr-dYuD z0;SsbU0C$g3xjk!qwUgU@rMb=>3+nHAv zq{lHlLKObKy|ls^HYAC1!l|XeB!Q#NKjFnzgP-R(5u2%+vO; zgfp&Jug0qvYUX4qwG@UIR;3!sb>{~qe#p{n7@m1sE+y8aeqPV#3(T>w<(X5+`dZUC zTeQ%HN5-_XjvZQ*snhj`?T2$4D~5aQBQKz=vWg3f&GfV!Y!Q7e!DG@cX1h~;+&B4; zZ7E`L2k=b$+f#cZ-{NvOFYP(_!XdD-CH!+-XT4l%K&^%7a38gQfyPY&>o!Tf^k4`U z$>Py$MI$WNPTD8n;q;c%+^^y?4)%o7i2=JThga15mF?+vj1~tq~9y zDlt@!riz}jqrB;FO>pmXK=YTH>`L^0TEik6EeEHNhDGE1HBymn=C15NFp;zAY3%gj zq53P3FyezvJx`3HAJ^PlD&U#hSwef`Fc${m4E-?`j1=M^LW&LT_Ch-o2YTb!uOYmvK+~HHD7iOtj2;4ezZD6Q1%*n}5kW znRn%i=l%QSpw{_&?EI>9eB8A6d{FGkzqU+=)Ear}oqAM_WH01d?pnzO6iHQXy}aPs zusCk1XRb2Z(>e*JDeQuJPceOi+*?%Y*?z|=$Xbzm3h6Zy%^POtJyMw)`=XD%>S9=h zLz`Pjzvm90oFgXLqAC5^Wb>@#q3hQjuP%79dGqGs-jRT6S+`g&(k@=d;8E-oVwKGV z4m(=FuO#5y(TZ?q92FkfgO`pO6h~c=Q%|;uDIR9qMKlwIM+$Y@D-$lR&CIMgE@IjJ zsUOf4y|QxtW~cJOgo-b|h#aYdtKJ~UnmHQAajm;@@n+!j*Mu4RnmN&Hdka%|W=x$* z{?eUJf--SoZ&@saB z!_BE9-6;VlJ}iA0W1fp`7a&z15Xv*j+#~#D+2t#GF->oUhX#*SdaaKF&Imv8bMazz z@fK}}sO|xEH)1#erAoHZ>)VeI99pK4mdQIV0yE^q2X*N@5*|dX7Bp?8XO#$#9oWo zeJDvxKnBnCkN~Ueyn%8l7Febx#_Qk|Nx!w89}g$v%WV++r#?M?(EL{2keAZ^ygVmz z-7dUQT1jPv5>8+`wXL)Bl)iawoo)wt%a)>xEKY~cHW#RtJWsf6TZF10(n4H1AnYB| zM6N5R;Y;S1#*S!9d!of!oQVVwE3xbCn+gr@Bn~|-DtZes*{u{AecylpWci5`N48N| z%JAXNH=i=i>`&yrsfg?B)!nj?BExK$SD1!UZ_&=4z*3NEmNYAtZ;eZhE?|v$>`zVQn8n_U zq>w&G>9m7ZkCU6+@;K*SNm9Z}0RaJY@*?3SO`ljuX+@` z&IY1U{UTr9>f+*3layoK)*><(yldk>l1cC7ghWK(7dMTS)iBFXYV!EK_-DMNTm(43 z6)RTBjpWEDKT`4dIURXBDF$fCAEe!%bPL4^!k{ZJZnYTY|DudlLcXF#U~qq(iyTi{ z{Q^tBu=D%T65lepLO5YMP!ms4SJHnrGj8-I&%1_s)6OPfE42I|{9O8KX zJL+ctKK(N2<;|aoSt%;1ZGK__&si-Uq_^>964r}3TH#jKO4A3x$&N6+v`ZBm})GfSZ z1f$#~t=1c!LT)s&K9`gSan#Vz5ES#BcVgR^9pr<{RTnCF_Fh^8{^wEhFQO39T~wkuS%)6bVf_GtzLXScToxSwojoXIdVb(EX^F{mmTh(G1Q% zEzqyhksru>T+In{5(f-j6kx>g_{kGw0}{?d$g@L^F@|{PdaxCNAs)g6c;?TK0Z7cd zQB~dg`g1eePcWBw|9Sy0dND)WIznTo?*?4~t67|IpcVb8Z(yZ)TUZ*B2h#NUb>oyVV=pPo8Xq z|J(u|9v*J)B<*)|?Q-C^1+&jGOhv=d0^S|BL~bKL7vm~$MDWAV2Fi)~=p*J?=OKt9 zy7x#Td97TY|Gj%ldn`kgZY@nak`f4YA-#=%$&zzBIXFG+<#;N5s$?&>qUM>4>_+jk zl`o+OitO#~v)t%)Z*(Ox(zr(@H)9~^-{F=`GK<^D0n!#>@MgiyA%Iou6|CWq=zAP+ zwxpyaR@>2QO-)U(>wqIS5zq_b72s9*`QJ9Vd#;6fTk0A&F3Hz!UY?$ah|y597$LGb zt^3|^8WMJYa1&OfL>K66xG{qhp^}kz?i~H}ct341#%qFuFHzuBdkL-^(aLE7I&*qn zV_s|L%{Av(*C8CFz5T3RmhsdXFnvB-34bIMp$l}iwF&bYxKqFp>bcqJg8cma#Kc56 zp+wbW+X>nqgTu>#Fm+7G5E)6IczG+1S_^b|emiW=PiX!sUlOZQh2|qe!-_l*FF-^Uk*I zfw6>Z(t?x;d9((^0(nn{=@un7vO~3n%j6mC)*=|nNsPY~rGEUlwNHQRcOywRE26 z+nN-<#%;0mzdkOS_NgG#3O+}gamKZnb2>c*+9Pfr9(cu+z4{4ysp ztOfBEms(%P^w(|}C-p@Zf1p0yu$~$1jL9=1>orLm9}`LA@Zk)e)fhjdU=ui^xxYEO zn4)rg2FJSP@MYnR9yv;;c(J}szU4N8EMxZ9EJ&j{7E68CPvspcf(ImqxL{gU5byF% z*10)^O)7w=qL8}$a2wfI%W5!@X~UuMhg(yAL(V3KdI`t&UAab@Y}hW*+5zc++xR9I zjl`FMSPT^P(|K+tZnj!2hKR+$s8KifhB;Q(kxYaTpKLhy_ic`j?t!;jl=u-$^0|XJ z?>rzC5EcXy`EruuPC6oq?ui7v{supV+oik1L|nr?Th^UhS+)`c zk7a3^TK!ry%Lyl< z7$e_f@cd;d(fH_Z;-?0Jpn0OQGtPpf`t-2QLZ}#D!PyN)xR3(Cnciris}WBOxuN&T!B-cTrDWSb3a#Ll0U({1tQ&c#Hmd#xp0(uU7sSoFe_nbj0N2si3* zn8T;a7Di35^&%n8%l6G@K?)6KJy<WvpmsfPF(w~-I1szMr+x5foQT1to}#b6uaudq*ISQmXf63sC=NtpLY z=V|SBa5c>T0JHjrq}6_Ki)PxsW#c|p#C4_-hTPK5;*bK1| zSxX+FlwudfQkAl39YS)dE3aJnkPef3TeH#JQ)Ql!9V_y!`ialu*JNN}hZn)+-vCpn ziN$&s;c41opEm@+wvN;qc9VFs*3F34OQG2dSh=Whryw8DfcY53hS#XNuYSs;!Ib3`La{s6%?wq` zJ44#}I=s(eRF23nx_THr_`-z|f{STX1n?@rH5sEmoZQ^m!_23(wQE2Eq^ZCNC4Yfj z0^uFSeSJ)coZlcde#c+^+*e@LDvq_sw`|(<8Uv!3RXrcf&%`u)oNRLMDN|Pl>;Fw# zY3Qh*kywjy;-x6>5xG^(fpKLT!x8*z8{@h==+p!T`~8(LC2Ji}8M={s|Ne4zyD8iV za$(pe-1i*4xJA+Oy_cr1kp4@;{K)eSSgu8g`NLL`j*G0+|Ao(>Pj2?KB?cRQPImwF zJNmnV^E(APA;kE9L^+X{{XZef3-9@Ujx*8Qy7l71r%#DwFa*Yk$a6CFJKVXp$7Tw< zGV2Lu!lC|aOZ{+nQ0Cub0PbT=@=bKW*jdv;!nJYeBcfqQV%4gX@P$^D9a)bQ#I-Z1 zs6MLMy3-3B!Z-$2NZI|aw!Ua~*2v92+Ud~P@URabJGE@okImb{P(KmcmLHV{|1_D= zw{WyemJ$?vf-VIf!A~{P;_EqShWB)NYf8BZFY>+`Bu&PgYZ> z2Q7|bgs=VUuK`z(?N*OwEIh8x7dbN#)E}Eu8ziSF`);_*n_x~VKGoULasI*uHa0fY z4!hjHEbDo_`ba$N1RmVKAF3AX#$46d@rYkd>$5ta|Vu z5vEOkFPcg;q#KFQDLuGZ)?Xl7t9YUDh$Nvz%hre@(~l2(!e9}}^bx3f4GyXWrfUW8 zD6A9_;T>(JuSUnpn$)>al(JY~z`anq^#yf6YM{3*S0jg7zHY4%Z$ZiKFu2i%z!ekj z;LcaB9EPLk~uRlf_#AKGVL~djHX*i+3EY&43K|79QEt=VC|A%*+rh zi!K_KXc8h{A3qi_`8|ML`Yw6{7<3;5tO2g0*r9GQPer~r{?ZD5{$3a&+`nH_`Rc;Z ziqYg7q{_j=A!hhcVr`@BZ_-{XEK_HSD+S8>rvtS*n5M;7$E;n?&&LUs;{gGb-$}rl=?@*JSj`;9;LTK?1F6h+ip%-qiV-NpE}_QsxY+CLTD82sXHd# zPK~4-Jj%_hx^VL7z|Pn(&v(ee;z4B4eVyf4F-T;xj{=71BfL~qWEF$p^8piXXXmM@ zYmkun%D(IU0gBg%Dd`1iWc>lztFa`>uw@aF$2lOG zSCpX0unkX$H7Kqgn4n3nn%sjl+3SJSfXfce5we%oRW(uMMp>HxkhlZ!-FW54nRDxmR^VS_U2wqp@{SDf-dL(m<{@;aSYur4w!RIp#FVkCx9XHZb3YRdAcnA+88SZ_3IB$Pg~gSQyUC z*%M%wn-f6%QFj(@~z;_k8)&(Ty8V2U7 z1zucM(`Yowj+KgdfGky`M4hOUd3@%wgRI_^1wsd3@^ttW+GroImLe87*$UaOW-|+{ zEQ$Ss>gwpG_q1eeS=S?A2Iz09U*B`Fk*kyMlz-m^Z`Uel5MWT@1bxG3>dS9_+6T8` zyf|p<NK|FE5pS`<|VxdJRx6uGby^ zn|>b0CZ@}e>!H&MkTBY`Fzvax#it2``zUOLuwx)cP(nz^03mgxR;i#`b;piWu3e6q1bF?juM1Jw4|xT9h$d@+34=9UUg1 zI~#4|x~y9OQhGYDc|_mJV6@h?a*CB}*(MYovz?*y+W!1{1h#^r*Hezn>wyP)^Oq!2 z&K-AgV{Qs|S1kP^`>Zd6y%o<-EwF~C`vcmatDCD@TMRq=6i#Au}O8Bs?v{0VhU6lf-Qrjn>s=y0*y+iyklAouB45c8^@LHV6Ca zZ1s%MKC7+Qsg@1(zI*U7cF*JaY_huVGdL}A^)1UQIe8l=u$ea^PL_%WmP!vSU-yW@ z{$}Io!0#w=_T4%9ue9!m3B#sw&G78uRXj`%?06eNK|x5D$@};b7(*=`!<57*>VIe= z^3MaAApDu-A>v;KXukWq_t3-r(h3`!!TYs3^}F$OV(j4mSJbY0vA#Y6U5Nb$!DTN~7{=UR zF;$&YUGkU4jV33qeewwBk6dTgdKt{h<>m$=0idtT8(ILI9qKNJwMHA#{H#E;A3g5^mDK z6i3S1>?l-t!3^RNAP&+Toy2lJj2GUJ?JYH-IU>LTt>w*nCA5*;E{jA3R<3+V5Uq4N zVjk*pjY|WMhc6O8Q%X$kKi9{8yjpA%3Ya2E5WX;cSg(MBXFS`<11jx@j*>dHwzhWS zlo?Z}O*>}PQvj1e`ps#%DKV`fOlS?=nwuLcQsk^9-K{exF^#+#eE~mT{(nInbMQ{= zLCWVE7uYVI#v0U(K*h?&r&LLS;~t(uJq60)LUogDfCC7~ib5U*BH)MMc2DA2xDeFi zOWYY^(o2!7#lgV=P6FJAA*{3e58K%{pz!eY@+u}$>|r2UGx|`FelSKG!VC7t=J4jS zXbU}F?Qg9igY@{3T^-Wyol|rRR?|X6CP6eAp|DrUS&sF&xynjP+InG!pI_m=9}-fS zpHIefNuf~K<#A;H>T>~mig&x}g&W~<$ZTs$>g??7rvpDST=)i=Bd@8kW#*hCL4Dv( zfwK<-qNkA&b40t1fQe3%tQ6;7Iy3dP3T;1b)5vmI4<3|YGnHe`l=;eO*Vok5fdIe3 zO@#T{dVG#gdC$t|p2inyzO z$<|v;mA!p0Uaxc>9pL{}#x-95WEVwlI1<$nnr8${Jne>vHsQvnPoMC@XIdX{X8p<# zhDTO$D;H|cLez-Zj$qIs;BCS%f_a-`z3xq0`JP7z-|FWMg^_88*lXlRXXUIC5~|_9 zNzQZ(OgUX5#)DjL9agkytya5Q5XxIw@ec^A?^3}vP9LFk zs-_IEyH~&&6(kO(%T`MVelfIOawd{`vRqJLF{yUoF}kX#55Nm3ZcxM*!@>1bb8DA+ zjKLxB6GX~Pv(BX9SC-8M?1r}tKq&g>$}Vyj0lyWJF!)N+U+2R$qLDb=!z>q>eEJ>IrPe$W&H9Y|v0lo`xeUN0oUNfW6O%JJXU~_GO z4?-YQSy_4I%5SH+VwEsr z4Nt`-jviz6$;oGnju?%fS>t@_dpP3g#@)L;jxB^cE!LUZi?d7I7tEViYMQqb%LHLH z7}T+7A@_{N!N{1kJTD|N3n?%tMCy{MObGgOWHql@<56*@@k;yk<|nvJxZA#)VgP0r z8;4qq!7UGu#kT>HD$Unp9%TWAlzS#vcQ+wRZvyXF3zGV9nUGLuRMbZcKHLL1v6^}$ zN+fsYNRwLEvN3JADC~$0m^?J1#55YyIEE8%5Bk(_<^2#u;fgmsJIZkTL>y>qoF<{dZVDEIql}4WVt+S-Xhws zjW!Ow;ZvFH@8NC%`vUFa8JWDM68@6kJ>RTFWt{&)uK4~M#1+6|fuq&e)MWXI=MwHL zUu}i{TbIG)5S)tj4YT!OaA{<%=yksY%ET8LpBQtSYqOmFoO9t7A#R2 z+|e^oX$GY)t_^vvU>`N7`K8+McQ4|JBhC$^xwsUpX%QcfQ}MDjsf=Kv{|pgp|FbpA zomILC>lp?%gre+q8@Y)v;Q1@f+D|QQwys>gx^BeaTJui-m(1h0j-RST+41LF(N&^2 zxacQ!j`e$r_@~Ohmqs9`e1s02_mgTF$D#dy*Lr03xPIgN0c3*ii+}P{+mc_?XZ_!! z%l<|0Iey0WPh9zrM;Ie7XG8ip_z?3YsWI_L^toIyi)omJ0j+J%vR)JY~7dnjVjZG!kDtd$!Nzx1$^kA0y91 zr2QllKWu~1_e*R`-XiGB_{7A-mMl4j5+9;9fXEASBQD3f>FIE9dOycesiUI<%9gqg z5>wCbIEK6U-?0d(oj6PcVT|if*!8=thPcd*9lLvMA?m!LD!@$Yf$ThoU#U?#>--FP zU?n}6}ad>dkXy*GkXQ?02qSEuR=ZNp(71bc1R2Z z9jh8oPl!H45TSiYxDB}xo% z5SSr4bUUdVnN2df$Is;2!;JwIqhY8PLRIYhGd0PjYJ5!UH+KKvflxE~hH%rKcYWWv z&-@g(V0d(OXWj)kdg)lHdC6(SLe*RY$@7h~n8hng0+B~SD+4uBalfEy7@XK?5C@(v zv%Q0Inf6G$oU8>EBl1~VxpR>j50teZ7TQu!!{JVImO^-kL*Aerl?w`!GvK!1?*&Gs z_0yBWr?KT3n&~+w3qp%Ua6eGlnWB$@I!&lAl~pdn1~gwMoxi7LYa1W@7~w5fZNy)(G?7DF}?i5PhbbWgnM@0 zF0B9fnK$`t-nlayv5x1P$@KIEr<#XrUafHf+&iD09oOl??c?qJslbf%ot*D=jvg~u zIURnSx9;w`^l*61qa${kkvAO~jtd+6h)9YX8y_ODOp2c;v9wk$IAJHaYTF=xO#L6@#Lc>2c-OhOF zs_!7b_+~lubGYN~63HRDyFEZz6R-fFG>L%U)HU~lf~1G9vI`!_$6Y~ZoRdo=DPrjB zMgywMY-)jYKw|FOL*N;#6OcIs?bHi%Qntwrp+m=eI3N!?$VWTUii8AY2)r(t3JAVB z>9F1T%dtv*{gB{Q(IHzSj9IpZ)vG73V`EwkSGC>tV?+B91|K{W-z@t_glFcEq`uv$ zdR%$-#HvZ|+_@N1^zlzLu2tm8&CTsCpmT{C-0Xk<-01~+;~r1M-I*tX9YC=zQdrg) zhjcf5l$hs@_DOQtjS=hf1{$OMhF&g@`7nYz$wSWzH85GU7*}bIMsK{S)(VjbgN+(H zMI+$S$izF&d~Mvp1R1&^S2?03z~@82JBSJukpbl0yWgXGMd=DOwwg*Mavf0WBSW~Q zEFrdF$9PI(lh}EfHZ5}}eFSL(DVeXFY0Huu*RMzTT)%MxsjVT%+6FBTEaB-{w_?2^ z=o&SUnut`!E_6#66ycIK4~?CJZ{_;6YeWhk`UlvX90T7xGE^^Tt8I(~KfJ^UA1HX^ zQME!sfJ9EA24OZPi5kMWQ);CpLUDI8!oSDYAHw=wpiqSmMcqd!?LvsydRM|z2{=Z~ z*{V%E70_w}$3H|uTriSCL{_dm`ihX)QSmskz%O)sWgxszOF|9Q97#Q-p~1t+nOT0Z z;&L%Id(4wvku$@mj+N)1)CBazZ@u0wG+KN2?sYUNQj3s~?!!5Nhj{1!IBW1?cJ#oJ z{yBiAejq)_;7YmKwm?Udq!qv@j3U){fNtx zMUpil>NeWkb3@SH5Oj{TN?bh5R)&|z+OEL6eohqoeI1!1aDz(ul544&S%ZAdK7?ha ztz^;|Jr8YZR9A;;Mohfn_Xyi%U(o?9161G0Q;5aA-MqQ5*PQ`ZV#P&q86uxr{*;v`;a>ZLFQM|3@^ zmdSzd>fc%NnQrP64zwt@)Z4q)llIhY%-xR#;<)@`TlHGTie()ykUpH>0ES8}N_#u_ zwZ2K*Jjypu1Y*g6oaX~Xze8ulRssdyO|k;CJx z_kNH2gsym4) z9E>>n3P5VQ%G0VASFZZUnnyRE=<^BZW>8VuGCf9{_Jt9dd3{XZv$gxeKHx~WckkYm z;j2CxR@+GzW{Iu!HgneWu)to=Yd>VPw#omAIR$bkAY4;ec}h`6VPlT=QgB^lMz7vV zST>f!LORSQJ@>_|OnI>Uo3T@bqaK}aLvD+{lwccqPIA@)nf#y_!Y`{0NE9>hMI-zZ4;jhlkE1GKT=qy`sKIN zOI-5WMFP1z+xnw=e{hDrfre|crD*L_6dewig1&m1{an>Y&U}?b?az^J10+Idl;mts zyQ17+3=9!^c|yh~e0a;&txthy2cia&g`65-IHtP#`ub3gL>wKXF{a`Fpm>p%ZYYTr zu?8fk;dlM|GfYtRWDg;HDIUr9P`H63Ra8_=6KTyL9403Q+7I`?^Wt~9cu_}J7ih!< ziW~rHXs@2beO*-4+jf3Aw^k~+$^x!>C^>F|uc#IDJA-F7L?4N?;5)i^pK5BD(b=Lo z^31vp9OhgewsW+ZTz|XgaB9oO33A>$=XFM(JUe^qoS8wh=S)hQyitAOWXIWaw)}o0 z;@v%GgVhi3M4eDN?!q!8ZX(wtXlN#SBr7RzfA*kkn^(wyY4=kVvxEU2Wh-BhFTo)p znNHQSd#t#O4oaS;4Dvne_@RkyVPe@lZcGXwEgU=;fme@3Fa+x zuR$0uxImF6q8ovd30jKz(h4L|{yAQBvk6-f<|LOg(DX!b-dQ{`yZ&0A9trbx)sxEl zd3(3rX1D@7)fFZgCvY0QH; zJo9Km;7yH9$6pCLg@%TL_Lte~@P)s{zAu#*%!yvM?{kdgpg?iwmOd~EYXYugNs!S^ zW|`mBS|*Jo@4Dz+YY|kN9-f{Z0K&OMP6S@gJA^vUNHuRKp>c4AC%o|%o@zJgR_Ar0 zTvfzi8CJBGyA0oXVzf)+eWFPq%HJVlB2~<~HI8VK5m_fZ++sCs!@`0vEp)O@`(@kN=r+fLv-2Ja!78YE!e%Bulo3#dJJG#9~^w;5KL)U)2%yve!EvglkIIN>_>pr zLh&=|fL5^Np)(@fI&zv{v>F+#jF^on#xqiR#rh%_dAxA-zY(us<>hok4}V zgeoN(JRRBxuOhp?DyJPcgjR`xFj%f3q4j1)ocosr@9}Y48XHI12omjM=z*ucG@CfT zGl=nWCSM*}cc;v>b5RfZ)zpG%U_F;`xR6&LS2MsSR3_sbouG=*GaMm?MG+fY`SuJe z9;Q`5Lmk&*rY|)M4hy9q>De0e5)_nSbgrd9N_;0leoq;EO*Td&yNchzti>so`N zHF|5Ta#~H~c)F!Zh}61yg>m2yDKc)>rJ`;#C(l1#G;{2k-4IC>xTPXL=)lAzRyE+b z)?b)gd5e(C*hjQDHs3*6Nn}Z6rT2xw@XsrtNQ@Q|1m+Hb)4Gl{Hf85+y1KglY?v!L zGzF7u^b%D{KHUaibNVUd*;$rP>*(yXH>pzRRxX~yMxr1Qm-3w5O9NQHmr*I#N+B|Bf~D^>e7|#BwLME0}I)vsAz@nt~M1bz2w45f6+NM-Jeu<_^h_YCh^v} za}&2k3okw2U@4zTY5ipN=lb47WK3>q4?z;i&WbtoCoaqObo43`JF>j?((~0h##6Mi z4mFakj?@DIImn-^FJ(7G{`T0OEjSnq_xf*p?73Q&mQUAJVPC(S{JMLZmQ=|k*vV_0 zp0j7Iy10L%!Se+*Hx{*D?pbtX*`Y&+@F{8-5%Q@kl`!)4_VpEr;oo)p#GxBQ+{*o4 z{s;*q<7R-H#bE;iqM%$W{rhM9fdj8*M9VWMqM>Ke9uQ3B?c0kJEu#zLoo=UauMupA@%cQ-q2iRqEsUX!>x=gW#Y%BN9+iC5Tk8nv-B zH~)5p$XZcJgRXLk{E1ObXKl)?8ZQ3h!y41(4Of>qZ^rqzQby(rNNJ)sE+@;K70B>&{$%jDUzQj`om`*aTah7-v=ye3g%$(d>s=Hh((7UVig$cDR zO1?)6VXTnOw+SK%$ucFNvT?vh+5kpdT`Gf1*JD_lS|{xp1j!7 zVJv#4lnhYF*uGvuqhCRZQKSG2KOAGQiaAt0u0s`RCZw3#{`EYyQka;{^-(vzyf8#P z&KN(NUF2O(j%=%ux(*lTbfGOu%bzbem^{^36tSRt?ocl~Kin~Te0d%f9l#RAstlO~ z(}!o4ow|D3_zV@d>>^@4d)g{SaB3G7*0;gg>fA);;Wn%OdbyE)_n|_=dC&@3w8qsx z{&17NNNoC^9H{g|faK{va{#__AaVD!c#-Q~2X_f8uET%q0#0nyvtrrYwIfu!xo6o{ ztl)=)z;h%&!Rw%L%w;=&Vty5G{*ZwUs`MNaQ(p0EiFpT|Z*C*b;cG{My}WEh+TfNg zNAyMB3X4{<>6>2exqLYX>sk>-8rouC1xd7u_JB>xYGd#xm;leP#9MhQ3 zEXF%#_HD6twVOU^33ChE#Mx)DcUfA-wJu)jyPmN(Q4`!wg=;@U^vY4TFy)1L#e4@T zd0qNf$9~6?q;IF=S!@%?_Q+I98<|g!kr+VmylzjXeavt_2i(VsLt)bwBS2m5#&bT*s?4q&i>{JIe=-Pjpj(icYkEXdJ< zP>~|XX0|t`F{Y$Bk!vnB2e0>kI{L+~O>#`zWMkr?P>9Lz2~NMUtfevj^J$wxqZV(M z9%M}zFg9N`sQ~AL3;$I9cIED&obS0jVXDOVr^s1hrfx0D?uZ19x!#QH7JDTX5Ui@U zW#9KD*S#cpR&E;#+b(51L1$;94avzk8<~o1-FIjx{F)>u{6u7 z!eMhPzIDScey8cf~>R8szwfi6Mi?sIl3=I{E9CGeTi&6Ucz6bLl$?jMMb|*w4 zln~XjRN&h}J+$w{{i(yenoJU>M@xIQQ0hsm=Uca=fB%_$KGmgy%qd|gM~K1~I{f|K0vB$fi4V8*#2-0nf2?V z-}(l8=AW{-^6LU6ogm=lw5i`OucHP3hrKTk$8znv)?6ASm6V~#kTFE2XfQOABq>9Q zq(tW1Y-=)0NP{Vgin>Dy85+!rq(a6FndvsmaDVGEH0-C^&-1?D`~C49uj6=*8(ar}OPq<}p_Z~_VKSbVbA-&z!-K_ci4_qCPAs5EaI&ZL>i z+%fA)i|!W1$=l)GCG{Zfx|9)s)tUT>ZQ+;8twZeVy2a<1$5%qJ&JhS2Q_i}bC>+0~ z`8+$}g>eq+O zuUCWyrzq*mk@>Effc>|Xmpp5^SgLej{qKs=-+dWBmLg!M>V*`{?_BiZcFAnx;Jf;} z!}d=LW#C?vJ`u#xB}+?Dd^H`B$~zX1)$>{Z<`tpbD^}S!^@^=w&o0K1t@C~m?eW3GF=rO4E6 zt>WN?ls2P1z5qg$DA}V6#I$|SK}oo7NyXz+L0>cT++@3<;m%y=4D7R0roRoB`iyHX zm9k9wH%uGpeY3)j$&EzG{;$BGpteQq5t82!k_IQk?Rw3-`#9U4puweGm3QOl%M0#7 zaLSQ)e6d29i{GXKKpemMjE^n?KQUmmXwr88ZS_f!X&316j<=nO)Emmohm^0mv|LdMw}I==e=BomQ8grpX5GxoJS;^}wjXxa zJ@b4PYF($sK#fCBOhT?-x5F5kBhIAmyZHPkIMGn1?76;yD3k=0qD^t^X=s_9Uy*>4 zf{?~IIi*`XLhHaY2wIRm@+PD2+ z@F9!_yI};k4~^kO8=@U8?QA2W96%xZ{kT?-T!h*CgpxWy#rY_vEmFON7XUwVxlU&E z44Ul{XeRz?HBGMI;Q*f|7Mn`SiD@{9&9c$gs0R868|vAC4z}AM3X}#ld;!>G9YMW) zpCKe2vlIB$>N2UV_hK$AV&M%1DSjxG6u0S6oL&}DN`=B(WG^m3K_8R8@Oo;6@T%Cg zS`Wy^+`Jpi5e%{nV`@FGP=lK1v2zis1*nVYGe-L>bnRL=?Kj$t^{ZKn6h22e$nqXC z0uQ(Cc}~_)%cwrsW*PAcU;w8&%j23IcsFqwSLIvc^AfcYaili?>IS3Bq96r)Jv+d} zyLS)^umfA1M@K@TR2#^ax=(16bST%Tschm*%$nag7X)=8ZAw`G2@I(Rs9+>^yCUX4 z63prqnSy0(TdC*yf!RxAS}WXwod!XSXh|TqtX(HMS^f#BXQ0umhA* zS=K;m4JL&(7af^*i3NJM@rF5Z$t($da zm9PxyOL#jCxb@r6*n6wHwD)$PZ6hY8F0=IF4Ltgh+l9DYe32{ygL#D@3@{$hi0=lG z`d!jVDD~J?hAu-U0;X15D-WAbx$Q?1C%?T9@mBT(ZL1pMQ%R1?VcTT)XnQ>D!9_Tm z66ziks}5V!X89jW++TiQY`nWwRD!CcZeW>yQOZ!4S~fo!P4&l9}5k*!d{v88P3i_r>;T)auS3#I48I0TemPgvaho% zlkXGu9mIlttvgCEN>%Ki$!jBPnKQ7Tu!qTwwy20~8rB^8$WyuoQuTj5j3U;`$>}a! zCOLke0pLN{RI$j*TYQ7?4(JWu1e-JoYsq&CBhZG=|`o|{Nr}n^AE?Y=jGK6pasUk9iNa;>CeA@r=mSdC?=^; z8gU&q&F7hxiND0eLr(rdXqde7f{)=DXi<*T_xUZ` zz1wgX@Z$Vqf3N-iJHOcVPgqbxj8i%ku820_pX=*O;~dNP z0(zpf!J8y6?-lv)5-}5G;D56~nzz;4QR9QUpWNt2GyC(^g`~qANtItTbV8OEgeqq}4%z5@UAnV$_QKX` zGbPjUuMpIlvQqV(IXkzbF3ZSC$M^SI0{Jv{s;Jo8^u=_tMBL%rMtl(=j{eypdsIMB zLbK=c;a;GD=7$@*LZ5IfT=@=PYwkd(GBt6`>ZbIADu3}C%C=4ZybpHwwW_13{q})& zL2vH{Ve^{wjU&T3A>HLG#Y9Y#8&eMUTVD4samaLY>P*sge4M9zG~U76IbVu=;c~;e z24+vZ-kF=fVb2iqET8aTa zh5?)QG{^Ya(E2ZPbkNo)yL(wbGg#$QQnAWf#i}koPJaj>cQEIUzBp)kds&89ECnjV@0J}j#kmM%LuEpp2^5TGij?8W2^0(+(la78kmhV!PqAl`u?CFI?Y4`Wtwph9G!4u1JekN)| ziF%0CV?Nag67HvN*haCPUrLIqJKn5`hE*_t#n@<DJa#pP#R}e@Kj8a^uN> z(GPDK_0N2YU;;0?dxvDg&cK~)9fzV)8_GShPeXP*D41O%7js%+0keg_3nxuI4{``8?NOxPPBOCcd*_TS-?-QdJY;_&e zwlM8YO+6UbuuJH481-X7PmyV5)SiT6v-Uj8_HMIkzLa2A;ws(MF7Wg(`m-6V6?}_$ zXKQwUcx7N(Wb%&Zu=ov!j@VnhUy?pq^l&>rJhlT@>ooB6L-#uv?m|aTp>XpB3Et@I zusIwU#B9+ge14!(bhDT9VD9H*s?wqPp~@k;%?uTJd3l@cEDw*AHf7Ged$$p@fsbmv zTk2jw2lBpJ>D8_br;VxIt+zY{PX=B#|2#k)?9wpnFza-#rDGrL+qlYi*@l)(7gK(R zkGAp#@u{ERg+vc0(MLZsDhk!eZCTE3vh1OKkvZkd$5YatHya*8iV6jN+L>Z6=h25R zW#@D5XuMf!#*tpKbo^OdFCFI9;|lB0b$l%r^x=W_9{u4VM(Sy{r!}T1@H`@w=&n>G zC!ZA&6>VR@p)=D^me?^bOl+O*ciTx$qpuN+`|fMsDe7RDZ@W)ZN=Djo%@6O4jx~lN z$8xVst2 zgOqk|Zn@Ri9_Vs~j(8k_(MpIC)BX3y0psiRl1`oI^qG9KGhV<&X)Zxq>mNg1x~!Zm0s!O zbUd`Nne=gZq_?M2v{0hH+J4SDGe2i*>-)~sBvAo@zULRm22?(WNOAM!2TOUAD&5p- z9o~Q9xPkh|Fhk-~KA$v#sFF0uG32C(v!uZ7?M=GYd@p(FA}wXod{$9HqE=AkeL~tJ zY}3f8BC1lM^fjgv$DhmF@$EJ9T_=f_oRMB|&2Tv%h6372548H?4Kzh{bN!2Cd)g!G zZjKZT%ojXy(%DK`SdVR|lcdSl5<2MtuN9Svj&XB8XNW7v2KP3M#+NsoGHjCVioJR) zWH7xtEW75IO}Ni8hmsy*jrF88g-$CB+8!wT`R2v!g;m6sSDl?v_F zkCy2RU!waZ+mfDbel@eGMA zS{)`;g7nGB7u8vLyLcv-fkJtX?X*bUiFHuu6J0tiz!3@agC_+Yt4veh#?-f19mYf_ z`}IrXfQ2gx2g=5a;_9)aL<7zE`k^j1n-8(q$`em}(pmGD$6Kj_Y=Ury3myI&CMoxn zLt2$Gs_IzR>#?;)huLg2+LvKcwbE43R>y0#;&5+*4ae-PLQT!UtSuVkYr~a2^=Jrl zj-Muv)mq}Ep>FbgZlMoPH!~Zm@)OFSw4D5=3~<0iFNr}IM=X? zF3zztE0i}&H!`~0eQ~94vQ(&Qzoi{5OOajQNmH!B+ytAhn5?W3;Gf3F*pCkfyOQ#( zO0_#>>*8vZ4+KbBt)wLBsMYQtlgyCFjB|Zb!ekh{hE>qsK5qC zJ;HVF%$}bj6dZJI4WP_ZbjWZg4fhjzyxpmoSv#Dyh+aBW)r1ePk37TV%6W9)eyp4v zC4+kI(R%9Rbyo~FbvIXaf4XwtvrwAsqrSO5yD!mX*wc%wc|-U9p+LQ?%N;dRk51!c zknS3(SwtK-&`z#imlM@>$7ue_!gT$iOLWo_IxcBLlHm5)P3hO=?E z8U5@9&9=>7sH3~&#ZDcswmUTdkkpzgQP?pyYQN$1%H;a;*m7IkUH110g}kSn+ujU) zJT}XjQ$VM?znd{6CtjVa;FNNRNBvl*&HbtzZ;4sTPco<)l=e3_pX6N>I4pkeAjNoy zyCX--NScjz2QM85YiV1^=XY&WuN?bvku$a4bvyGJi94E9rlv(pxwnYLT>hhVj%fam zo05#<=+_(Goy)7qIsHzF&X22Jc@%ezrSEad6SVu1Lv?5vGjvuyYFI%|uLfSB?&%{o zSdQGrOP5Tn0J0PF&ZuD!_na*UfDzn1_`U=5nfLaw_UuMYlNCZxHlxchtug$VAjIf7~Ch z@1DcmkP^04DES0&5akf{FFU(l@o+=KoaLj9Og5D*A5J?bccn}FGCLNHF15>3AaJgX zB3OZ`ABG*{aMx{KonK^E8uj^&xEvJ*n=Vb((I@Nbn~h|}bj&pu)6>UYnpj@v`kJ2{ zW?j)keUKXe5}j1buC%k$EBfCy;*9HXwv)a>V!t*}mTTMd-ua03$^z31*##v>PbzN_ zoR4p|eBT7LzS{Y5)Edj9rNxLtvA5tg%l?Gp$Fn>P$;26E_@enecee-kWl71`S@H!P z8TXyFPsrVlslU4*ChN=|Z+E`M#b>ma<2n|EPwbh(9UuGZpayCmCY^U6K!K>J=yfq^ z@|V*AFMN+|C(HV2$V3Qt9^WpYlu_#%<@iHa1>}m6cuV44K%dgKIeBrM% zO^CyXO_=AsJ#od94FMB-QMi47`Z3K9Vx?NG3ozzkO0N~yeOvtW^-aP?j~2iMq2tB; z!+9OHJ<*R(S8O%5Y_raT$Lva}-o%}Og+`T0)o%?F8Wx2)q})@Bw&vWq6#Cs(z_R@C zvLPHR?q(2q8EiawJIpyQ(SAS>t3Jy!`rZA*^)+&xOP>qVEi!t4&)sdq1lDce!p>T3 zl*#DywfrfIR6_v2W`s`K#|-MIfpu6eU+4ZjnYwZTtqqadPp_<7XL#W5zLrSs0{t`8 zrc)2nQ`FAW8qPy}We=n7gFrL0zV`XjN9%ZoU+~WHAZfC*R*7F($55(dyZ|ru0>CgM z;qLhftkMVGP?#mYC=NXCvs&JHG(>TC^(p1FsBAvA##V)3`l6YNbgUchl$IL?k##fr zFL?KGj}4{2dIf!x2yqau6|yv79i^3ba4#LCKdTco3(JnObOJEVYhE=!ERp|I>!Y~B z+7}9<@@MkZ==$4j6>f;XmT&mt_xivzRFRBy_{tVQfy{i(e#`i-IJDgE=+V7lJ~rgt zScrNl+N|CVx5BvcQEj2LJp?d$N3#kiV4grWwUkb}{pBc5ad7z2QCEuWjT?OEf?nya z@4$iVIry^vLecB6k>@^~koXK%bsefWo8)_^+36Erck$DQbW^SK4vPk*ZF;I2X52O6tlGc9ZZ}Vk(EQvx5(o*AB$;%E zzk0P`;IFZ`m#u8XJsBop_lZIlWB9PO>`8T=#H>;V0G)ANYpc za{8`c=NXb9R}WCjIz#<<<^i7#G#8(y=!V6p^X<~=xgxMifOITH!n5^#jH2^R=^h@9 zXKkGHIle1;Q~2{$v6ShLO)X_Wzs&epn**=RW@ikV-=8bH{xdaA!cY%g4WO4Wdnbpp zv#t0J$PDM@(TxCS!f;@#)5bkB(Qg|H3$u3bh@+!pFpG<`)=no4;qLtiR`ZDQvaZ4{ zopPwn2h_HjCCQDM9Vw5$-T2Z?$?Hzf`BfVQ7GEUUWlIbNj6Qj$V`ji(_?f;)IrSDM zLScY$W^Am5z{`>;dEcV1%o*!~IO~c-q%%bf`okVPrQWM@JgxGHKXojs;)naA zlgZ?Md2{Il#sXWSPE(JGB2MxggmHZRi z+DuC@4g3Wu)W75;&c?@xoa(Q?=xYoGZRlv-IX-gxdb{3QowNt(bsmd^(njPD9lAHN zGAhBbfAE}Ec{;tcTTp52HQQ=it6Qjr_@t!+hlR8@Y;#u$72y&UjYOTBxfh^k*p1uq zrtt~_rdB@hWU$Q&oE9>tPwMI8wr+HW)`YfV8zX0wpXf?9>RHu&ewBD3Bb{!@aD#A{ z&duS?`34lJl>6j$7B(_frTt3_U&Pcj1v+Hb+wIvC;1IC!YN?mJN;noIa({v>izg;QyII6Q?w;-*Z>>U1Fset>=i70gF2u1$jZFhDepE7ELcpZ z@xV^AU9#uA%uu^%kt{E(hySJnZ}`AFSTki%viUfyWjJ)M@F+d;cFY${3O6F_XjBM! zk%%=AaP)NAWhhF?cik`h4lj&)wVi*Sd^;(-d+Y6bCJHSnZEfB7zLS+qM?CHJNsMIa zP|Zg8ecASQI*+xTWg8p)1h^-tBh!f3*(*gp_WI}4zbJ^tjlRCQ$1vFJ0x7AzqrAJ^ ztz*^D(_n(iu*mD7j+r$9RLPFEYa19w>roZGPrqdIC8lqF^;JO;TgU4CX5ly( z?rZg#qdJC)wUKS5l1zjenen)R`f|GOVANp1J+)3bWR5q<8mskUk_l>10YTM3-aufb zb^S|=JleQsQ;*~SO>1=ypzw%kyOUp!ugjQOVL4{=2w+%Q+FyyM$mJ3 zGXW;zwvU4Zh7a6a-snGDnolFVc8Vwb(kBnNN=IvKwT~6OcT*mcC;>h! z6|5428-kl-CFPS}>EDB#ovM#o)*N9mHBP{H*%GrF0iNz(KPW zfeq+YwoD+I+%XUX%j6ZKL_T$%$!%ctlt>W!kB zj2b~ji;T`jtEmBP8C!SpTk5sNZ z$9Qo~6bLA>nSZ2o>n5Hst_D90N)s@U_yD)7665d5#9zwH6pm#niaXXN)_UpYjLPTi z)|qb7*-e{VNMEt&I_i5m-#5F_lWzrk?4(KIe{BDw_h#p2@{Cl>K`>w#!Hza3kA z#>J>iuf<~_@|x;Gb$7EuzOUx(K_~IAB>1->8#dU<_lc&>y}4RxQcC!P_Vt&NivQ8( zNJCRo%uRNs$)>=E>tf`mKWo~q|6^OASSRx0(kW5ZpCqeGep2cv|BF_6Z{)5imF0M2 zY(n^Y^9M!uR&T-LN$ngxLmret#E9{l^FM3;EKB5+SmsYPR{y4q?0CO_@lFn!?fd^Y zKry;>s@sItY(LJvN(=e2j?OW{sJ>#3FVwyZXTQnB{KGq` zWi(!XQxdMYEgB=Ewr#WlnileJ}x|Q_ZBE-FzKNSJXqQt`A$#|ozIJBa>)kmF;ck;l z%3BPo^|jEX{$|1WfzaE&9<%Aii+^bUWCIw{$n`h=oichdjO56J9YvSj|2+=Ksr?tg#iT=BQ-=gphVqQbM%^$VMB+_9gv zgU4QDDrH>b{`bbaU&jvVP#6OpgdPmT4|J?DcVsmhFpFW1rUa&+_J*B#gH%j(P(YPw z69WXg)UO(T_g22op`X)g!5wO4V&7rpv$gOAW{0v0FwD)B2#=RWC~)rCleXnBcwAUL zlB3c7vxacu(GpW}M}FO%2_$A$@UhM@=? z_^f;x_TSsTqrE;xDJlqKr2)L^C&5RzGJL(%#IsH(m1J$*AHL-*EHl)a5(M z^EB`;SS7wY)d6`8dc$!!tTFp;=R>3SE=1%ZDk=B&$i zbu0Uan0k!b*m#gmjvFeDU^JDOhlF~Y7*>q0xLb_*ZAij^LUud8IIG~f++82@P-{gr zF|#wM(uQfCJJKQHmk@K?9h5P0Ti$&Mq@e0yZ#-mjkiD_znh58{jZf_QTI-H_uN1@d zimBW%k}kt6RlIpD4&`c|v6jI@yNVg&*_8;MOwnBn^}*6jQ_bd8rv;H6EcSw#ae1@9NWpdE5{RUeM98fegla)c5faQz17y zyO<#@5z#JC|4WI9^&!gaD{fQcn9iKbh8rOJ^Se*#hxhYtK^1rg1-{pT^AT&~-L?>peyJF@GrM{6WrpO$6 zqqLmP^l69q(0Zx(`gyp6XI4h^OZ&1td3T8Tr`iph6E8x!hnuIco{z79>5<>-Sf~au zc@9tZn{d?9{F~Tr)p_$GIN-SXg*km~!CaN+Af}VKT<0?iB9>$^9j1%=F|xcazu+|F zJgfWZRRVcbw=z>O;?4LRSk7~S!b3=zh@eCaJz&J`btLy&KG>y6*bQ|zX7yv2^;y1Q zICarl-F;EJui>`4Gaj0yYjPTCVlr@#k>$1VBuOdDj(pihF9-kM4!6=>sh64MoKnk7 z2$^HY+g(EU55`3dGwu(RjS2@j&CXu9%U1krsIp%2T%FRr*VODc49xS;^v_T}^Il!U z{VpD^{=R*0>#{tvmKFqAwwIYf_{na99$p=-+u2Zficy0eY^1Mwi`zvLJ>z5sn)&#D z!J+cTbeq0Bo55c8$VkobjiPlFmvS%<8{B0zWsKj1KZh|ArZbu1sxaTtGzKOo`O}3} z@(!?p7lDRr8-+0Cic8h%#`<_{T2sv%j%&q8_*E&Zdu4(e4}wP%4o0*P3g`L7}JXhABJ#q zcbplf`VjwcFcTwTCvjI?k#yspYZ&HuTq)IU@XBo53kjCJ!yzN;(!^~k0qx|>!TkOlJpYS`7Fa##mb@_L80{)*)OXc1q|*l20ITu8?l-$qrZ zF7Q_EKn699M8e1*3`Ge^EWN!$r)-qOB{#w?H9w(vz;X#Bg60cR!d7wfC^f&k>tES{ zTl<98u8mH1Fud#pmY0{bbB8Xto z_`92(O7_OK7beNKkn+1mVc@`(3zp>iog3&A%|pX`AeM(+JH_%E46=A;&tACFvR6KXjLlas5(`J~DYmF?ZV3aqHV?iB zIIH7I3qqjj?7^-XjNKbuacusF38JG40Ynf&pIqkfnwa8c!z-SU)Aapr)!zbT0(X!g zT?Mc1CFHfUV3_77?P=ETEVO+~x&zdnkxIUp7`M45V$fhK8D^!kki01*)0{p+Yg<$B z$H-)rH=&O)JncCzF!FWireT;g#4oeQo26s%TI|3y>m0RU&ybfp0M7nn2tyqCNU6e8 zhS^{Ifc`QEA(gR*kt5N@?LN_j0u}aK+j$3@s^A(7owMzuTJCiSgf>|=B2iC_aR({t zV!h*hiUpGKya=YF&o0@29s^gd;VkysxTda;k9TF_gt5bPY+lj|!i`e$YejFs@rY8q zFZx3J#%ezkiu}ZpyKj)#-FV_%iCK4@r;rB;n{H&r+MSnO;q#y*4}J16rKJr8oR}PE z;O>i-8_gS=H+`rbvTc==X#azPFI2lu-Famcz_2s{N`Ot*_MJR=Z{&VaK_2$rLZva z1rO$_O7hf))Xu4yhTQ&JEGl0LFqfRwrv<-(ukyyZvuo5fv~SCrr4ZH$yF;YZz3qMk znZ$G@*MY* zAMUj)py>5r{cUXmpuPl^3ylID!C7dZocPt2GT&#I%8+3T^OL93mQ1G{kNSJ{vg91R zRen9GlzYHhW*YI~N3KtT>EB=HFDG%`jWuFPjbp>q)gABdmW)y&At1IfQW$nw%#IoS zNEBU%=Dl!s$nt41CT0fp9xG(>OpeEnS5|~2$oa`?2cx6^;au(CYmShAbE@{gTuc9^ zsEA6KnECr(ZsUKsjsJ|>V8+5>^*DJFSR1_#waDRq3|82q`iWZEceXT_hUPgpHlFXp z6z3uog{FU_Eyf2`RS&4aysP=}vpcGh2VxK2lpQ^+2uykUxwfS1P*WPZf}(gEG7mov!e`k6jWUQB3*!abw= z=J2X;&OTDhr>6d{jV;rkoQfYG*pIo(bK7qsa*hxP;uv@9 zfSnkWNryVupL}-*?iqOk{ z-iLs7m^*=UQq-+m7*jh2*gQhzK04N5DEXU6^6?O zdv9&PJO=)IppdQ(vm-(>@LY5;Dt`QUlnmovxyd{Hx#|!DT`rXR#dX1S7r_XJ7c&?C zW^4egS@h;V%<%Q^0#wj7&0TP1lQd7=m~rr z4re$yQqEu>2TxO2SZHk{Gpmk=-3g{DLb~Z%iok;cItZ*Dg1I!ZnDh~n#~x2Uf^1Fw zI4ZJah>#b69>-bEjJha>C)~N*>Z5Mo&fC&Zh$$C9o~F!Xx8h89jO~m@cnaRb9jY`$ z6a;LrmS2RAi~?Q?gT*wK^o{bGX>stUBjg&-jN@2N`uh7HXqCsuVooR5RP$>q zDPQg)+eVXMFQt)~e#cn?1#7ll2;iwj0aBy!We;DRAy8T1rmS386$GS}5|d`59U*WN zmc_^n9*KJg$d_o>6*!LAnL33rQ#1t+NL!x$U992{H;8o^OkIy9aNBeAVa1FfW;gb@q;ShzSj z(?Cb6$WYFeS-@&KU$!t387lcc(Up>TQw!&Dsf5P1R|0zjyB3@lK5Lz00S>8dX`y5j zGsPUZ;-h=_JciBx(NGM=9pstbK#ND@nO6{g%c+?0Gx!3}B(G|U7Rm?%P1x%A5vee8 zJ98{*+)Yn`B6w*|cz)*->a6}4r-V}rSc*{6!l=mA4wgq4&wPVHy{k08n@@iJhv8Vl z4CD3&MDn%1y0^FAyBxK>uqMDu{|fLD z0&aNOnA^zc!e{CR2GQDW7dL zRy8u4Fw8@(=vVQyD?O&2Ij&yPs&#*yFic{Cbe%NUUJDN9r?#{Fc^wm09qXpr42#Fd z_$U#vQE*F(oqlisU30`NVL9!e2`1DUv>43Z8XFpDJzfsO`j=*h{FePNzN_dYh2pKU zwl7ZJ1lRW^oIBmNWS#&fv$Bz4bL=e!y+$vDD*}N54`88s@Rp|Vx!4^JFQm3oa?L=6 zA3P}4;lP?a=_BO6NkPvr#OliSedUsRITqLza8dLX2KfO@h+0{3ADg8)8;zT55*zpK zt7v*I@0;hg^QQ@=b@?kd<$mMj3HK1n>iue{Dn7!AX=UGMa7c#`b-U8)A#O94`2(G_ zLymei=_paNoMJ)xfk9OE4)wxhX0G#GCro|l&FnLxag)c8EjE$i-WE|9+x1C)arwD# z)4O_n8tq3zlGUqUT^EZ%NscK8_=WT#8FVne2_@xslb>I;gcdXFmn48F#hG?bGl5HY z$ZOFA5}!CI;cM~_=gsN>MViGr`X!=iE;uPS8kfBp3M~2uXOpR7?Bo2{A7~EC#ECJO zctnPTd*VvmsrS`mK7gfr^`B1FO^z)o^T7(P4JT5h;==My@P>ErnISgS>oV$@ z#@jSM){EojJinwProJ3J09{Jv;Dhq>F-t!iS_y}`cUxM|TJZ0!Ejtd!V;WUMDt zm#VRS(ObtSihk@~OjsNdql5oW=c)NpO=l`>1_Okwc>n0mVYhu8nxKbu-fe{v_GGm^ z(>7OX!p#i9XY5XQ86qxC)pg_U0sl8#CH_4doquDwUAptfYx`g4k%>Bf!g=HxkM|Wo z8ls7iVoKy^4PgBKUh&p&$IaV~Q>(8XS;P>w{`2~f-}zLr?wi7zlMWL=vED0$BTT0u zsSLyO=fC!vGD(^@z|*(EngBinoud^^)Pl0OV*&*qpW2YWX5Otkwb}5(yd5vX!Wl8J zpNu0NS+*811oUMRRdoFLSE)2Z_=)X5xi%?iM$TdSsR^zV@E*aK2jKe%Y=>j{N^mfd zD_})82is0pDLJgNzm;$3{C4A73oB#h9}1jqf&Wd?#9N(!fZju7*6`n;$uOE$Jmo< z-)nTg5BHkYF(Z2`z7b;QSBkBqTVSAf;@}Q`|7F6{$c%+og}0^7!M4cFX4k<*u`}Em zk+D4d%a7($zc@i~Fk*}Zr>#8*B*MGW_{oW4J#hKv7tz}S>$=lK*F2AN+l2*w6@}@S zNvEM%b6>)Fvh;ytxj~SE@m>!`aih18aC1sa55uMJ(iUOD){w}~4gqF|UXk!#@X8UX zMae->f*{up+}m#iD*}<`S7%WCm|r4zcMF{U7nn2K!o_jOF0;KNsC_840gXR@A*Kx{ z_M-d(*~@vM&q|QK$4lY`+A~irTQ0*pv99h7VoJQOx;wh!X}5qo(VS)3S*e+-m7OLM zXGYg17QkR*H>{;`9PA|O4s>LQwip`Vyt>V@nl{tvbx(-ebZSvpSD;0)#P{lDk|E(T z*jeIBn(IdecM9W5^>hbY%JCa=&SMCI4uYH2wQK9T&O7>b&vAoq$~SX3qS8zIljRD$ zc@)-p1BiTlVj6biMgp-U84w&h#r=DECk*_&xifRES%cgm(kMEv%dDh*mKyq>x4O zcus((I}1@Up^hRfHs5RLE}QZ3th~$}e?ZS*ARb0-OE}y1h#Qx!*1a4MV2Ssp=&CTx z{aE6{JT*c)=`%yw^T47K;q;kAFPWWQG)`r2yY5r#({V)jO_n13fYGg}4|HcRDC5}% zn^MynQ}QbS*dL0QwJ@}7I90_Rvv#%5GRk@7%oaDMRG4}a28$f3`^>}AOV@laZPHdN zGHfK;*9s9VMzE$I5HD3=Xh^4(0}nOXqPB z_LV`yNusJ}7OgViSw-#*)==yebr?KjM&aIbeQhG6z#;vvyIO*V(~EU^;M`DjY0b8s zNPemJtsr|`y*%8TwrGtt;fLC|DiV(z-g+j@7Qs=iW^t{OfJ^ zj|fC{_9N=O(LfEI9m>j`Cv?!A}vL(^}$HZEQ_E!66m6clM z!5(JM5J3pn$%C_MhAZGryWrytSr~uU5$QnNve8W$4yV;|RNT?t6ko)lGB9_%<}$>G zna^28-rX?PKd&%MPFH5BVMnE*t}*wDiTjdsdDu<#o`owGf0w6a{4hIbt<%jLgs(IT zODM95JR$yd<KYb@Ay+i^gALGl|K3;D-`$LECyu39IZJ2vyG1YP zyL;_sj&WuRAIokg*A3?DW5+gj?mwGfkEM2;Ziw9WHBUZg^r6$D+x2{#1_tVe38NCn zIb^o}!N>DRjyHvRL%eU@a(2))RXv(hqA~W2MNVVIDt77dw4uN5e7NNwB4E4af%`Q7 zT%E06M=mnw&Y4YfgD}{CuYT%nUg3w2R>7&4DHhKVcROvy?2&plD!fv+!1oTJf|;)1 zc{*^qZ`tyk!&fH4=sMMhI}$ntRGT{3!*FG-AMVH4Zs5UdlIaR(2;{>aw@03RPYp}| z$6zUwS{GdJbri=i>wq+aZTWI>yj!d`a!2rj62b>uIE2SxENgjqaxK_&7e2>XC@n6Y zn3QyN;uh73sgRYRus?ws_QVOE;c}!K!OVw(4%?`{IXD*NbN6?n$cpo8g#cssZm+Ru zdl^ysGjg$E+gb*97LBG2dW*psA6YlqI)#fKqrUxi_bP6%>7szf*_eogS0XtE#XZ6Y zVZkbT`SKXWF-_q-i;C{h44VohX zc_@k8r}n3-x6PgP{<>v+!eeU|ZgSK}fFj~luY2a^=3*CihF2f|ReygA)WI`n&AJ^O zZK$u`%u+K!q4}_#y%Q!aDRZ=X@$E}G^usWEd)_-#Tnx*@Rg?J@(b!n!{j@(n0 z3TxO_&=@Zo&xT!ovO~(`;>lJ-HsCN=9GN}@(_8Se9E#-gRLwJqlsxV*L@;@%=z99i zSkB0(L1I=0xWHP;yrT&G+V|Ncn?9KxXp3VINL>~O+y@4*c;&uHKfh6D@*y&+5J zShm-54OzaKQ|TSVjU>|Sr(X5uwfD7iRFUl0K7$%%XlZFlB9SoUkG`cV+2QN7AOBkW z-pGP)a<>iN-`uJ;zG$2!8KLhD$ z0(Q_&-PWahfB%J64_m)eoVsb8!-Ba8+kDIw(r%0gnHRH88bl0Duu%QITx*v zYWrqu-hA^t3$BjGlM;Iwkq)E$_M;Uu;Ze%-Ey#*EOTrbKF3~NZ5hsE^-|WEEMG`SB z3g0q~h&w@K8cjZ?#Zo&ae{DF=w@f2!o_ZHoYWH{C@!l-Eo~DeMhTk<}Mr!&T_OUi zEZ=?0&|UqXEaJ&;`|HJ}U*q#}?)dLqBlJ+eW){=r)!fIvV=JbhzVdWc%HxL*_j*mI zxwmn@#?^aUtP>Ztk@9s;PuJ=z#aKeIc z?x`y&y?piRRX@Kqir&KDOM`=%h3_r8*F;BiXC?D^i1z%6XL0#nY;nhesg*yz6Osbe z)zG)VMn&vWIX)fmdxSG!QqJR#jxmmE7mX!j7+0>#`xnZ z*=Hb@@_OP-AOckVA6c`I<4>N1%+xl&m3hjhm3cSaMe2k-#3e2bog<3r{>?g3p@T3*Ts*%n7O7Jy9T;~ln#VTqQgV!K(Z)t zYNLk+;?~Q}ZLm$3nqQB*#0pU`@+2%_rpUc^Ed~Y%*`V=7Bt^Ej8#{)fzPoVRi&;`+ z?b=)DjG394A$z*9$Xq5&kGxX!_$!z|qABzgVW!sSh|na*%a<>Mym`Q83$+Q3@n-Lh z)mL%)>SfWg>Y@mODhKxUOv{%if}CdUwL7=TzJI}r_2KB_@E2Bpg}g^c^wSWVO%-i8 znmFECy=|qwX~8*;2GeQo$o~BnI9+m-KFKlu3SUfpcG;0pe`?qG@SwioeL&dTJ1BUs zM*)qV!nd@0h+Bfk*I0p*20lWy6$mFpTtOAu3#iIR9zA-5{1WIkqh(l`nPtw@K0~F! zAtgnKSXK7y(FR;YOagdvi_ym;!#9DhPQj($o>xf7w5vL8MAN59tz8{wB(yd`o5|TalCYXJ|m9w2ly`hB(NmNdVx^c7+4YoJkPpypQPgR4j70wqVm(&p+@xveH9g1gL7TD*`Az4m1U`tyQ*A}7?B+9>3Fln&{%L--Fg zwWLY(`pX^kPbbzgR-_xq8RLPWjwuY0_8smZwQ3ij38w>+saE#KCJUE_M(O6k z{BvF4qV0&#P(wN*cqX~aV&vm)nls|dbdDOIZ#OQcoLl^_pnD2bU{6rj_zowsbEgey zu)sLZw(>p2q0XI~-ky|BH z>u63-QrnHt?^T@du*7s~ZK_q94|z9)YOnhZ*}QY`YP@FcuJP~lpGUJOJ9k;O>||2< zzrD*lu$%$&fn5MVdN>-2XWZtC=g#3qduI_HC3NpxU0sz}ZRJZg4EPvs-TDF@Qq)g! zXtRTSV_d$xJL#@ZQv%8N3Fi2%q2^5bY^0x`({v=X-`V`P8x7l)G61a_@hkJ&2 zy^j}#vMgB=VRQ&8eR$Dsf~=jjC@+stFXLL@mXyHqymBH(1-kVzHHa+^CY@R1OPJKY z0B0e~ABGC5w)V)F)h?TJ(UrPZ*Z|P|ikpEfkRNKJ{%cZJyq*c(*iTU!Uf~{gfmV|W zpb({nx@ov)9NkB7$#4cSr1|IRJm zw_^f?6Or_jpl6NcWtS_3j*iY9Kp1yIT--wZ4Oc0}cnotYu}?-~F&m@z+?$y`3|2u66E2 z2@lx2U;7)@=40wcD#krJyQc|wxlqSLF3-?8`B?-?nV~wq_e@-^U)s49&lgF4!^Zbw z2%tF*%{aF?ZKl~Qwg$5*C{Hkw`41Jq)Y0>Is%E?-k;0>`044ej`~Mo9{=+HHf{8zu zLra$}GcYu?AKe%2a!6xEdHFBvt_HD`h$*<>x_Ik+FdIrl=7C2YIyvVSAL5zdnEo%- z1>;$#L`gt|+;basNR4NmF8vmaNz}LhUZMKz?jK7djp@=2Q^f}qVI`t-*91h5S5E{E z3S2ORSd-04zpp<2baoQe9u3Rm2kYY#6ml50u5cSKYbL<=KQ1^IpYdlA0ixkww_53j zXID~yl{^gR&@{Pzqw@+WN2 zOCBM_dXLN&YXfM*hK7dpmeRaLT@~Nuy5Jj8L;M;s^<+f0(0GOa_N79Bp(BPo?JOYZ zoE+pECaQ$Vu3NXRj+Kk@p2BawW~RWF+_jrFIYQ2EQZ(bpqHbKtT!8>w#rX)LG%`mw{Si{Ix$n1rHBaZK~m4wH%r?6=bf27UbbHT{wY81Myih#bwQv+88L9} zUR(zN5298Hjl%02O_4Xq&e~q}bO2%sR!B_XTO}+hX^Re-OgfHI#DC!61&D+~&dyo} zkzu)u-lJKB0=%DhIg`Yh)zZhXHGu!DMyTZT<+)JVB+}Urp&>XFQznbL2ZII<2M->^ z@t$a0{-S=?tXcd|koAc(jYG-jOL!>PjmFzf%oD5TSS-923fkyv(LYM*;+ zSE8Q_`M#L%aQ;jebK=b~L}>Q4t;Iwl2#r+e;;q{`C*Hz4ha(B;V#y=a9jFEal>m2P zP5}D?qz$5fM!#}pemxL8;DIsqJEG3fu9<;9E@s~fLuv;My}(jIMmiK~A_V|ISpH=o ziV|~JS77MM5_>h=KkT0 z%TpbOL<$T+h~egyVc-whp1C&tGB2Q&K|_u(^G5CE1W8bP!oyO#*A1Zd8k9QU+?+97 zi-l-wYik^d>|BipT9m+fG!t9H_zkEcZooasA4^6M3u)$0A_e*Q?9uQ%`ILn53m>o) zMjtcX8K4^#bslp_)ZV-I3@~E*j~IK*_!#=y#usr(lt`wL`~3j{0cZh^HW@JzwQ$&2 zZ#0@tUoIMlp|eMfG8)@MR|r=2=&JTy%m_eyQUaxFm2Lsh`O%|ms9*0r^fly4tslZT zR@|tCxjAVBT|Wc5fsTrt0SXa+PUL=n=Xdhv^Q&FbPz&S(@9}Kz?^z4LkHFQJmt&Tk+BW)OMv>W z-x~c1P+DiYNUg*AhK6m9*)Lvfy)w@}NV+Sv2RwX_)j5O&^ymoGY{}8!a-c#8_+=1) zwd^J8<)kh(r_)?C0lRn}#>b0nI=gtQ?Ig!>o!NXp?0>&xdI|bu?)o`n?+ejg zZC&+Z(G*6v{q*9z48Z6SyxSL9?Y28NS8v1c&MNynRFTe4--)Ik#=yira1t1d8e>Co2mI%XXCDc&X72m+6eG z&pUyhFEq5oVgu5(o=IjYn#1M*W!V+EkuNidYkE~sa7-w#sHg_*E$GqCo;~aQwT1gA zTUyZ|#+5KW*noa6KEl(>iy40JWDczq%XMO6VlpzA@M=U6Ld3#mjP(i0T_co=fG6#Z z=(g~#TbJAtbpxr)2j6IL(VPJ*J;_2MP&w+3JZC-IKVCAe1&^R0q_Tp%yl*+siTb=L zAN|BfCRKK*BV-77b!>0T>1b&oGgehrUNk=uN`)>GCJi6se-8FQz(}1qF0G`bRD(cS zJXwe`u;U!3K{OC0ZNid8v@Hj4ANuBj=XorSKgC%k9kKyr0 zm$Van5@RIIpv%w9i_-@RuS@FnZhm{v;k4tp;g|0XIwVUxJUxMF--A_vokw%?iSo8e zvkW9?FwgtmH7O#t#m(n`E)}d}ihH`dFVL~EGBEgGy0n;yDR1oXtd7F^W|C{`oGE(k z$zcN9JzM?Lmg>J!o4OCB=vFkaUcP);?i>?aWy{Q>vUe0O)kGa2PK2e=T>U#v1F+}i z;^Jb)eUt!vti3qT&Vnngn13SjG-w6!!A!U+|mi27Poi z;VUElh&tv~S`a-<)L^zHaPz#Me?4@H==^D`nkY^EzEico>|l&zdeJ$fd|?3X=mV&~ z>0LYC&G?CUDB8)jnP@=#k-HsfKoGkt8gpy8xbjWxE>BVD-^zrfu$@un|F~55U)=^e z(c0QtRn>2BCd*VU_ML#%Im&r#`9HnnGs|mgHvGO~FGq?Mjl{A)uEW1~>Ly@%7WzO$ zr(vQb+TvaKGj}^tHz1Jg9}3FNsuL^Z-|tG4-Bb+vGp{*b@u*E;W1vd|a^h59W#YG- zOI0M#oGJtxW}NkILW5!O7#|mzB~#b*TQhK*l>qNoofUSbu)SBus0pXtjz9 zNblZ*@tR~`DTQ_odA!f{$4_x+TyOODmY+##|Ho5xtd{%rjwpx8f-XjYygiCyeyyav z4j;XNY>@i9&ud=~1~`?^JdX$0b7}CA@aMvi8)0EWit5=WFZJ2JpB@MFShzDaIMs~) zahW?*`AA7grJ&56LGJD@5c0Ht^L%zx?s<}{13`P8J9iFV6=0OX@Z15St7A3UzlTpi zRyG|+7!=*7FmE4aM9dB)U7QA9h|u9ER;{}tvJCDG2WywUR>~Af%%tEmg!yF5UF3={yyul|r z#0=dAvS5=q<8r#IEDo#^E5v{&t5b&}6g&qP;aM`RKe8D-8TRA4x;l_{uUsL@2o*oQ zvgRmGB{VCI>+#(T$fv=6>gm;aEaNM?HiU-(I^-}R>L@EqO_lkSigcR8C69o>Xes3M zuP5QnfS>jg?R!yw@Y_6oi<}<{qGB$dKaT^QXk9xPl1+ur)NZ~~4PBZ^(x=(|Eofg1 z;FFaU6yinz&+`V3&KKQvBTWH@A1Hrp_jZv)Qc`LwbZQzsh0>c*3SmGN>|9yQ!F#EZ zIn~;_eJCW#))_<#iimWBG~*XBtCRo4A2(X=`v$2r@IB122Hf7@EKu*K#L9$$m$6Ir zeIrS1=Qux$9WC;0zvk66|Fp#JPST!wsMLsw-S#?+vyTFw4;8kvK&~TrtI2lBIsX>1 zIb-QW;-NaOOPc=vL@HHobBab!_$EOS1k9!avlO3Ap zVDEG-Z&G&-0}HY+GowS}0l5W`vMDeO|G@(XpjHhI4TTIh#mmd<&6~Z;WguSx^+-nC z?K-t6Oa`wb`Vt3IC%Y<2t3;3QmY1Jdaby^ZjYMba7@-dUqJZQa!2?e*?$eHhs=Lvl zv~+ZgDq6O-0Dc?xJca*4`O}`@pDoqEKQ4v&{)Qr6% zIu=Bl2#5s)MVgdYKx}{&6d~AAP^uI~KtK(G5)_f%484cY0wKB2AHczpac1_ucb#?b zx@YaR&e=zW_iWa!Zqx23HDeF3F+lc2e`Jlic=vb3JUBqpVhjTw)$d%-^}3*v8`c zra~)02gBzWa8?oJZ@3MwvJw2QvZ-l-8s}KxA<*r zY!tO_Ej#iRV=kB{&|$K2V{>V~SK&RP2`! z*X{@>2wJMPpU89lrPvb{3zHCB?hJWJHZcxZ>pxc*fWDrss%xgV>!h%;^-kj?^V2Tn zTi!VK@*#uhQfG-y=ClknsX9$k2}hHp?$RlzIf-3Q?J$3x^HcCWXK8`H*TDpOPkU!Qfg|qI)j}P+HiGR((8FduK)oiY2(8u7NI=hn|0JL- zaJWPcumPCRsD7B{)+dErHI;S}DlLPD$dAHGOyG5Y5LPEZzpy;@4O!G&wV-?64rv!oI-Tv|GA4+|LW?KuF-+@qM*w!fe<{mhD9bKn;FA=FMiPy^nDSwLVl31FcC>;Py^~Q9+ko~E_BZ($XJI?qH5I)(1sW=GecczC zHVw8%U4S+%s&RnYHRN4xWTr`Zhf9HJH>eF)Tf{c>Kwo-G$&y$E>({@-!Yif`+30|3 zHv2Cl{Dlz4Kz_0#L|AQ%(~g4&4>~w>fq+e;Xb>r9|BWHubUeZ3SZ^M-+%DH-Q7Jxo?PnEnFA5tufLv6+CsMPShLYb25P&{ zz`%Zyl4>WduWa5mJbiUd6{*#GE&S^T;o7>w=Hfriln?{ig8{32bJ@MuQ58{Yy z0FJXixr2mpol_Vr^XJc=y_}o6fl_txMc$<-^G>)pw;6F&--l`mYA%a2 z%ZQV7?Rw3OG~1G|qdh6ZEU~g?gg%poFrrq4;a{txJwe&PPjmANLE;H#{t;pMFD~W9+SXvd50N1?ynYm zi!V>|!O+$X#~rGz(LS}*7%&7jS0yTs6qjn~DQs)9PFmGJeFg-f9ml#Q6l?_U(6Art zrZU$~ofb%-?VC3dzTw`EFchgb z%A1;b#VN)ggYFK)hWGWCaf;#MxMro};F_KgAZ#T0JY{xN`QqnvMPew4KWf>73JfDZ zR%YTSru;97N8>tNQZp&Vv`{Ulj+dfBLba-y7PN)Flg*4Y{$TC=xO;{k52T3UN8>tj zFN1gmr(YR7V=B&0Dj&gwFFh`X^W4hAnItZY24IR^?fg91t_Rm{KIf}YWn~{!@p5|m z$-vl_R7CkX)qa{A!ys-Wsk7QnWz`0FQD6qoSz`d?QINvlslKsEy(7;A?_|oo+`ScS zhj|U{Qcm-vUS@GpD-=Bk@Qzc7E$U;Ny3)&OWXe&F^SPeN+St;~{;E41Sgl8f_^Pv> zm@XTHAPzl2iL_d4IkNR+gi0zz&5QTEB8W?CT-94uX*C`;BoCa@q@>FRysH=qusBI1s+fS9({Qk3UK8%vh`MsnSH(Q z7xxqFdW9q;TzP+aC``r7l1TVg`Z?D8sz9tO{we`j;89|p&^CU>n99fBPd5jqPD6Fp zJdVJ?ue^1X-;xD2KZP)&zi~WO%`P11PR#u~= zGx1MBoBV;zpsP1?7@xoAe?2b!b?ZG55fO89bKFyN7sjmOm@^~*2l z7%QUHyyOUF5!pe|P zO|`VNoIN`xfj$HL6(30-iNdP&8w#4xIUPBszPx?JH&B?E$IC4k^S7&KkIGaL5gL@% zxGw-oqE2|(laKy;0pQ7R9Ku0dfspxwDx0Ct=1#HJ)>a72_L`XB7KAo$r54IT-22DZQxpk8;|~aA-xAzF@QeA>|1BB#pB$3Bq5s;TzhS5UKRWd9BP#ss zv$LUatLR^gQyO4m%;$gpr$^Zo3m&C7O9OnTMEG{3fEoPeS8+f+#3%>#HPZXY7ijY@ zG+Y&)1)e0xca!hM;GQ7X(9=lUqJ=q8#978)_8nOShgl%3`PPZhGdi&>B9}d;-=t79p|MTug%wV?jV&6gL-vewJ%>Wh01E_;hUy+MF;eR4{sHGf)`Y_K zGO2!{Wb4&67a(a2^EMH}^)n{G^!ih}VZ>kJ58d`jJ>rGSppM$VfB){?emzmZnQX}W z$DJ0}p0OxqgF^GgW;QI{0G*!w82pAD1E>(v9?7l_0#*WrEHY{dB)Eqp*2~^lblRLDbbmv5Z=Kynp}*M*@OPB?<8Z{9-FKLF%FQ>Odn^_PxJB*HNQ@0+I3l zy{RZ1j^{cVqx&~8F~Pv;b<|G7Odn+DDfq1HM+HF=KH0~LP|rANmhq{K0kfPAM9pJ> zh{G0&XNE;dL{V4IQFc&riM!{_Lc)LuWQ0*pX}PtS#)f;(m@*|rvl#Q>JOSXNPbHb( z(7}62K3lhJd6l`q$p`V8md|xtvv)bB-&YbKFFjQ~)_DIZ=VmWEd2A2gChPdis#iWUa z6p#*k8emxIvVHq!a7U8q!YjU4&-^=t;H14e=ESLh3-|kVRFk+jM`ip-;y8t`ZTac` zJAkCnuO$MAymDoV1a_+}VByW1GjUhtt=X_)oD=IvtXDO3e4>g6k9D;eD=oI*-oAYs z?;G0W2k4LC1e2dc=EA4-K_|Tk0HCm*3*o2=nma^Hp8WZYL!TcVp^Do-F^DJl*Z2(! z?On{n(H}KDCPOqx*!RQ2(VTf0?n$1a%2i242F5cRwpj4{kRcwFOJd(8C%0gp4UW8E z&kX|KglAV??YKT9Fx{XywXCcR4Ewl*YOeVCqz<&$4V%1XD%OFpfhL~?PPEIY8JNJy z7$*iG`ES~^9ZhuxGvDp3aaamxp!b{8Sj=ixrn;n*wC4kAhcRjVAkK)4Colr0Jk9Iz z^F60CB>)X4cx!Y_CyUUGmtNs=*)*<$#%x2uGl-C$j1@~&t!=SLF4w0w^av4Mq=vJHh`W{CvPq`UIEM^PX)TQ z&-zIR@t(ecj%TGa-w;kgFx`9%IFmhl<83SxoDmBPDJnJuGMM)kjbZ*|i2Tz#8Qq8k z*zCXO0AYM&5uc)v7Z2rtHuB*gAr}7 zZdmeBNpbDd`QSwnWT6;&?(v5d@5@&^cxa;2c@n{F%1;Gr0A1pFmln{g<@91MiiZRL z77&)%BlYIYX>!k}`o%NemFA9R9RE!MXr5+U)=Fo>Jhh<9+O(Y31^D&Ln(Ew$c0LI0Jq(jI zU1%5(08Oo~j`AS)6qb4!IZ4uR1VE{o1f92Xk@X0tv1-yhrE3hly*}*7OLk|*fKcPJ za@Vfug&z{=kL}~26?Ck=5KGhKbeTwW7Q8e;@f?rgHpVJX7EkE3pDghLr!IhE^WT4; zqPA}UezYwz(%ZEwZL@&W+KvUB4_l0u16}4lS-6h^QgKOq+H6sApJ5M?1s^$Wbby9F z-UOCD*dw@)RrY7i@~I|NDNtub1mv%eb7mcV?rpsEMpCZO*Y*=Did=etzTywXdm^d@ zpAP?46Z0l#M%Onz_}i+u<@#w?Ng6aRTG^1DdmHt7RRdUjlVCv3*pJl=z(pLh8mBa; zUAj8llpYu-=dW~?n%?Opt>&<0%NC3-@&s7T^O<2ii*zGbsq5;Xh`43fE_xQ=C!>_X z##NS=i8H2>k<{C0MfsriHvRfS-I=hCTj73Sdb2|)1{LDQ;GN)BVq;?07UyOCt4|I% zOWWYi2K=sP>>6aD++6BzMS_iXQz_%gV!bTtxkZc2q1iC$OMRYfUv@@s@lH#&rqf#J|>28@TNEf%_?|WKsZQE-2%-Z zN?^`c^6Y?6;ZvNxsF!3M*acqI@Xh`L_iwFi3D+)T*Uh-NKLdLM1F;;lfsGqBz&^az z^%I&8g1M>jF4flC-rby2$i&)U)qx|c0LaOs$ny`CHxrvOYKvwKhYvkAVqm()SHfkm3WgGLI}7OG(ix8ic{ta~WVa50#$h-1#Lz9**gOq8d$ zcM^2-*f;_)snA-$f@H?bncbK!FwBeXLtE}g*dO?KcT}N=r>0tgmU8j6OP5|XyQh=4 zQ8Y4QbX$pq>eQ9YFWDl3Hz398QRTgWd^-f1fgkkVFvGPYPZRZKxwh`8A&GQ};5hS* z5&J2PVFhFdP#5pV)wOBUdz5pyOesD-4-f3ddd0-y=+UE?+1$N*H!l^0P3&Vb41?J_ zFx~*|>$5%r+pLP>E>rcQ4?e)27F2KHD@^XKx`<;n4&G~BdJ2b&9PnTcS2u9&smD8; zK2R+4!pk8#hj{+hwQH}x0Eu632Z@*z(aEPkWBK z&{>=9k>GEyp5bYhk;x}HQR#OOre6X$+)eV5OAE4{CAe+b+PbC? zo3o7}I@^`P)+xwv5!~iZJpIIpH4@tE*Vm$!fEb^9CnqWK;Oq*VA_N5-vv)NeqW5Ee zU+9C6>g(epEG+zDEr?6HSsE$%xXezD;D22c?I3=Gpi8+Xp6x`f5B1kMOE!MLg*K!1 z5UZ5iYs8^CE;z|mU^DYfya_*?i```&lCCZ6S%#;HJB?dkM;UqL>51g49Z z1#7z+UDZwupd*BO`g=64Pdt%#^3$hJuq$uEDC(=w?R11zBqQbF&7%i>zw-a2?iI!f zBy=6-DIC2wg$>2t_vmATC5K?GI2tS;Gw7!LOBL9Y53|8&Sf)z3-F@;KtNfoMZJeeb znMnV~rLZJmF^?$UGt_w>*)KANATWvkbmv#Tase{r*4L^2rKW*ukH0h$i~PTkI^SL8 zX{fL79}r-$efu2E<--#3uA~PP*81moWCQ6xLAS-U#z$b|H=>H0J8xchzVvTAtZyjY z@7%Bkw6s6_u5BC2Zh|((kmPnzF`35|`TFhK4F=UMVDM?+M}Ak{f*IGO`)=evS~W#B z4w!<#rYQ&GRzPr=Z@`agy`_EKP%;?B)sVpq0L8=}{K2E-)lqBk4C5}~X3-gd2EPYA zz5@k^tou^VPL=}H>3DCOw5qD#B9e?o%!jMjo)x3V`NnkoLo{f(ebS1*`&1CzKxaqr z6N2vFhoYgy%iP)dXpZ!x{eHbc!WvKcf8-@}9Xu^U+eZ0Va z_ymh`fQ|V*1gCN6SRW-3CBR@xB2OP3Yfc<;w^w|}Ua3+%4uUH@QbNjZ^${Y!p~gyK zJk%I&T4QG4ztZQ#aqZE^3l}a#MMYgWfBv;}O`jRTPr+%>?|OT+ej+RW2LqS?dHP+S zk;f0l4L=7uXI zczXqV_qHtZuBK${-m#zSi~VF`=Q3uVOx5qgIKmJ zX85G(c3o88Bj1~QSUouatCyj;ohQvR)F>#O$-*b_{!}LLydrx*X;N}cvVuP3Ms!BmSRS@kAE&kWdi9k|@JH3;qsY_|j z_5}I}&cA=qOyDf&EYCaXyOR~@8cUCYw4ehMMA#9W)6Oc_bS4VX4I2m>2XsQUoCf^) z!lG>w!@N%Q2DdIy7D-Yl1G-ZA)+YDzH$X$Te#3^n z{4$FcP3vUx{p}(eLNJTnxigPZp|!;RFhb8j^5t@xxrtDs_$eG{h1DJknOOE?fQ=6x zJOEiT3~&%~Q!Y4BqvGPakV3SV3L>B}*o1(`ioIh%$LY9&9wCx2%_8m3x{V2e61ZLH zm7HUNca`Ah$)tF-fQ8`HVMwTaN*G1(b#!|9?AbB6bpXN+1GyM%C&D_byl$-?{7b9X zwzRKNr@_ULpn_=hyc!`WhCm%;`dIXMsWlPu4%Xp@xfUJ>**bIPjF%*d1059oh<)BI z$az57x=3nkpJG(af{Me00oa9E3@}lnqXoT7m7uL#xte3EDGV5Q5g9!xQJl_W)Ux$0 z$0z2~cCA}CMomWa0ztVHVSAkl3lt`i_TZhF3c}EOD<=z-#Nq4n$|a57UJm$9%^UF$ zl^q|9gV@K^5xn&-UlxY-jS^w_63_;Qf)5jehH-%~$);*NxelyRFm|cXq1`jET*qU3 zB(l&MX}Gc-I<~{b0oZ4d{(#7tot|D^`;sB;OK3?EfP&E(evR$Q?d&nGC1;cF zgBpeRYbIw}sO6_n`|%z>d7GVU*Wrc}4W_WzpEG;*$v1e@J!F~!KOdaWh$^vHTPAjrx9$NhcRuC9VZVG)hkc#NPT!nOjX?MbFim;!ayK4>w?~<#kAMTKId*MD&fezJv?Et~20? zCWe4c(s>8KB4dxxe7iQZ0v&%@2tAr)q&oPu>ZO&ZVl}G>=aULNIblkBQjpr3&8GtK zNGpV^oylunMHM0*QO+<@u_SHH z4JZFn*UP0FFDnOgkiQt-2qtz*agkM2TImDK9N3Qu=M#;FtUITz6*6I1Z%g-7J}BFS z4T8DUZtm}fSv!E7wDpdHkJ$uHD;5S;#5v2hx}1%9)ZDc#%r)$}>@Pk^J;lv=1nMuR zZ%Je9D+LWs;&{#ML}~7X!!*MRV%0vkRquWITIb3|q#T5Mz+p2DiaWT!)I?LORh%0< zcU9ncoBGFhu8F4CvWB_zKI>u)qvPr#zSOK)9cm1{M&kc`r0LMeaZpMrqEkGBfhC4F z0^>?7#LtWlneZ5!A*%7ljp>}vV0&dsw33SH$V)BjPN;$c4Gn%&kfAHfj1!#9bvWtE10u1| z=m0Is6@{(V0j_-p7omo7fI8J6H#dJ~fvr4tZG71a0n;^W-U8XcCg=sdHarNhw(ja= zqosRZodB*FRks%r496+{&U$f({lrc{@s zl+*{!l0@8>qJ?K62P}k6f$ep-=@^uNI0D!qXI%}yE?oZ>PanknW!;5EZb>bOgj^%QM}~n6t@4$l6x<~X(_TQuN!#JCgHTZ)n$?;jMql8!+%>au_t3S zkA~%`NI08`Yft1klo0dSoKM=+t6Y_t_MqI}qiTrm5Yg|n!M=M~)g7-23gaG8@GYyg zF>QveT#7TLYlILzhjLoClvKddr@Qx=~DIRyv84b3b@I8s})6Nh(?rlqP z$9+Ip8-YA16lk4nh$%`Uj<`S)+0cQQ-@y~9t>6vwJXg7uRvk#rB;V=5T$R%hMSC4& zppGdg&NBmurOEp%<_;&W4W0o?mz!ma?Zk~6H`4r7q(&xuZ4Y`=FPMjanCW^EziHv? z1XQSh`qU9Csq)IoI^%cr8I%CluxobB?RRyMZLxT#MtL=cIMLOrf!=-oi-0v>b zS9lL)J~y0(zsIZP*QNBgL4(nepZ!8ds=S6qukL@_f#9;e{o1Jizxa+x}B()!*4)4q{mk<!MtV$u zN>r}AYx#=W-~@N#qIl~& zNrE-?X_FS*4_t4)(rhR**6n6spkBK(w0BO3HdS6zbDpehUDYi$G*VK_mUX>8XF%zx zc^G6*Q8=Jb+L7biR=~i(=7O7B-u?Ssz<4ASYC1Lt6dX_7()Z0tS2NF~57-0`KK>r3 zV_5O)%Aqy7J43vx?|GNdl;ECr`#=Gjji%?`Ixg*V;YBPk&d@wL!6}#FK`G_4#cz4e zF%r0=)h1tS@u}EbUTJ1m`o=@qxfKCKd3jZiju#v+Jy5VL$ToRv zT4cSFjtZcuFqTv48w9Jj*KbxcXep*DK@XzMtzZrI%#o?LV&bIqEZY63JKxq;>&zcE zBA3*WIZ{3Nm*O7j(JT12uG-t->1N^f+bo$WN+-9j`OVW|>lWi{JC59J^gG1`=7FxB9zjW0DtKNgt|CgJJ*(}SGvj+Z^!D!krR&D(3;QaolXe*<2AR`j z0dYiKn(nrRunV6(T81FGCNAdtb+d~w>Z)J$oM=2Z-rMsh1k({&H*?ywebe7oyc1+- z>+Y^|XeD{jGW1gDvIqg#pq0^j)BK^L<;=9AXSFKA^A|1JBL!C>>5HcFopm|aI}Jr- z{olR4by{SRAHWSS%fg+JRO!txlTm#Y1sWZ0t8tS0WknL}p}&S}a-*6fqD(N7}dQW^3 zqOm(CChm=(zw7aaKtk0!zTV+zNN|Ul>3vYIfN8w@@^oQdT1twq+Y&FGckdj}+pDw6 zlq~NeZ=Y@lfX?}rIpV_e1ffM4|Rq!B9FT8N)jxv&#FZ1JL$kN1V+k#3I#={~sM;(+n zXM{oSTmLRF?*x1knf&N8=NO;J@RH_Uly5(B5U8t1RCMYjccEg7F`L%j<6+LtJE-<2MAFWIe;5J{`p zt6w-Ck>dGKJayW2?1yq1PH7uMQ0XZGYKWsZ}- zC9chR5IA;hgjGT`iBq-EhWv1s~tykM$E_nk`xHaD161 z{p(%NnRoA{f|$xF_gF0xhg}1$*+&}9>eUGf7 zSW@zw&ib@*<1K};dl=}QZ5wXD79hjnWn^UBM&F6*C&R#AzA6A>ExcQ}3|&rh-ud`@-|DT=^dTGzCCwy#bF3IA&6d^ z*_;&C-BYT)j9ScUChNF%=-#v`YV(i`Cb7e7=-wLx0=ru?IunwPo91lzrqtMa^kIK1e0{D>eNBx;_73<*tW26;U38xZy6E0l zzeIXZvf2X3nAjAAuqFPuB`n6VF9?fqA($DRGqi_~A0a?EX1;#?a#Pb)>(;GA- zHgK)zd&RA%iYAQ^zU<=WaQfe^^8BDhZWBISxpGR$a_@?RV*~|lIB7w=C);^W&er1i(v*}Gb?1txlQ4BBz7XLjNxUY4G0}YmFR1_E z52GLGFyrG}de+nPd1H)T-f1_tuDf@iW;%t>{?orqBZ{9a*+vbX%l(OmU4|$Y*8v2j zJA^^I`+kYZnzn}gr}oXa;Ky`|=AingfB&c7OiVA1Ti1O)0x@Z9@fZ89mM8et=Y+`H zcE)5lPOtb+PYB+#OBXThYR0s;rNvrMvW|D2Ap3w=vT29fb`LCB%mVWBZTtyaE#A97 z)T}~qDYPLkp7-s<;r%=+-bF>l>k!vRKfKv-D!fyiu#hay`F3z!nH>mo@=a|oQu}Oc z??j2nNfbY;b@Y|2>pS22KhNMTgeSDczP*45wdfR+h6#x@U{#@nrha$BT_U_c>p!vw zuXVhc&jtxfu&&43Ax5HO;qSdFObv$aM05IOHSf<*Y^@x>YgNbOuM;AZyb46qL`L(y zA&3rSUi`qfQ|aIaccSA8;cbW^Y8iGole8J}WUwZ=3sV0e+M1{YN(m@m{xV z;eF}8eG1Xkp_Bb@lklQ8ryZF{=2CtKt@?+{Eauh|E?q%7zMn=u*51Xp0WEIBKg92rjkt!RI z!Xc~Mx{AxWDYbT@L3Dby9tz842R{8;z0579-Z*=HUqL) za^&NZC6iM?b0wfe0M!NU~>Aj9tz8s_RaeU z!d)kjU9qX3gK_1f0ov%hAoMeP^6{NtEI~Kcu&K#1B6sM{kYs;cJ9otBHj4s<#VRTs ziqm0bH42%PaYxUpaoY4em`dHfy~oqK7G*{FWdV`Qsb6K~0{r~C(xe2JRoAvoY4G(^ zZf2YlT1!Cj^XFT7i{F#RVqpyF=TOuI$Y0rpk_SKHhpI`Gh*Luz3YC9p;IXPiZGA?gbyG;jjf-57KyGbdLRZ(%R&Ws*4>QLV4%z#2}7o8R8`r_4B3(6mryaV;B25iq-PYl!W zmT+l|pt=f8nNs2Z>D5V>JaEN(bao0e&t`0l&&V#Go41Ed=9Z^6!;4%e&+5az`cDs1 zn~EKwDB8Gb(@4pv{U4vO*&-Pkowypn(>!dKIbp>vfxeT77lL8Tx5d9(1~Qi@b=Z*$Oio5(Rr3t2j8#W4zPrae(;!n>gb+VEc zz)q*dSJulxB_%F{NPh?pHNX!DQXXvDY? z#GK3fdQ93)F9{c`RjX>0ORq&y>%a7#^n{a&;D-ZAy&b1v=k#p#g{qXwS#Hr+`>vFM zH*x~Vn)vro1>Jk0k1LOo_=QQuC6QebrR}!PcCsCD$)*j z&^sDK96}hqokrD1qUi6au?K_@PBdJZ#9dupR}>uVGGoR8#Mer?Z2#K&Nk_e^)_E+I zDAj86mbjB#E3cdFquS&Im#$rNW;B27KDo8Hl^6WY1I}U`YntP8js0%%#nRrxSLkWI zJ+TpGXC}~EC5?_BnBQ~RQ{A>st7FeVd0)b)kbI>dZx>;`+P8IKWU{QB%Ns39lkAZk zFY_aekhiqJjhJ*QLF+}>R}}en?96tzj#+wij#awB9Ak_T}yZ{KWe#<=7p&I&WA`PLF|M!Agp( z9Pyo&C(rEIgKg5&X=QS=r>BQWa`FflKAv}M+yXVd|M0fx`+{di)Ydlc3U}$bPnGDI zAlXu6qm8lHHB#sk8D!6mkVN)`Gvn)4Vf7M}BdHh)G@cqIpJ%at{SmL{%hNcih0khPVTr1h>}$6@w1RFAd5N{_ z;yyPUy0o@Tt#$a4BA4XMZ6=dukK}geb|P+ozM`d+8(JYb)3zg!tIp(IlkWira9UFD zdXr>rUDGQc6xWtdkzjwlVB#ystqxq#U3KfI(rG4N-m69P=kG66LUUbiW)|-ssQ94x zSmgJ&gu588KG;fdObvJZbs_YE8DP(u4wCfDnSPf)ViiPWcsu`xWq(_lS~Gje(xtz^ zu2}0&Knd8hMxg zREL=ogQoqy-ws;mF!V3?+aLHwuEhVWSdqtt-_6r)K`=Fb5vCjUx-$2;lJ)mz3C|PQ z=+gjL!AmR>Y_$VX^A=2$!?^*=7|IlGZO3TY?@*r1UkcgDar^wM~Q{HT_Zg4DM101x&c?pO^8!UwZweRe#$CH~NRX&IYwGh6JA9 zUL7NXAg2|;jeanSHN^YnDPRYqOaEmXupN^kvUs%ez^8i05hfyazP*K7vkJ4oIl+1C> zWF84QzHZZEMa3hZ?r$CVd^P`@3VMMNVrmrU7C>gGp=M5*^7<<@SxMfPg+b3a!MA?Z z^6keSpVDZjdsoxxCO~C?2-C<;)*P-eB-V>5&&?biKYdMcZo}{7xrv z6A$A1H#`Qm8zCtmV6@j;P?E##U8YItsq}5;AE~ep&Wl|+Izj$&vv&xdQ>lN>tzkt+ zXEUdbvI1KDXzNP%+ZUhgDgF+F8@%~~G!f5sXZ+9|wq=<(&0BN9jK#Ojvmc&(_l^M- zZG47T^>sgQ?HH>-R3XPINu?v=PEXK_vwp~&8yQ8;y}$ldcYD6YtMk*C0sQ)pYd3b( z|qoL<%@1C>6|;~b?ddf8wjKU*(d@?tlF`4 zB~XPej*5S++1r+2oI09+RP^5G5&2!xJ5c#bI#vv;&Ic`MCDNT1E)HM6Y11myClaQ< zl)q^-j9H)`TsHV+(V_!1iq?vW?DOEh>}fuj;gcJY8)<)TRDSflO>w1S^2gf}wmno= zH+k!zq(wm1<+_jRbFPUd|gv4WMHG?p&!Ye}LOa#x1g#avO9E-J9>9#?<+w0d#VM&RcvSeo;%FQXF zSQhs%)kx?YH-wkIadfSIEo&6I_vW*MIY;v&Rp1wHpBoz8Fr{f<4};1SSDhm`J&RfM zF;~K=LHT8B20!Y*fjLCU3?)6xMt(YousLjTpm%;x6xc>5_|lD_M(;YIz|*S_G} zH>*9|;lG#X;mGZ^k4XD?FKot{%f7L0g4UfnjYV%Rm`9kCdY&|F&@yisG}_SIQ<`XL z!PjHd;ZX9Dns1_%L?5qn@c0uM4|IjM$WEDxsGV*64toU#hrFHox zy936p3qz+Y#BfA@Q=sPN>9t3dG#x(P)s^w&4Mf<1d-lQ~w278IU8B3??Aa`<#QEml zM8hh|EVh^QBc`AH+M2BWSZnSXjP(-EEr&T>?{CKD3&4G`NLzD$duJytlOrw=DY9m* zN0d={x*Xalvz<*P>&G-+|NExPecn8)zyvO*p1l^6iU<=ABd12WnT|Vl^ekQa39-$Z z-H+UQyKt&CR08%`viEfW$hv#H#kq!sNLiaTd-j({tU2?z7IdOiMt7FCjp{Y6H7<*x zki;)9T|M7dTszccuU>5E9{H)liE}ONvw2$>@o~;`LZc)>&0Aw%HX4u` zGN*csq&4$HzbYnPg6Py36mE|BbMi1QpzU_J9F+i0`0lW!5U?$&rJl4SjE zTr4O+Z%7WeZ5VA=|7FRtxb|jO<=Q09p{(d!rA{W(MuHwmuU#4eOy$!j4%15Zj|mZ7 zYnN{nL#}tzy0b3zPd$BQcZ8P)ke%Cu#c8KbDK;c$1{?xG{cVXhnM~%GH+w~{zjBoh zVw7!1Jfh{V8Nl~Y(C9I1&E}4s;l5F&xnjgc+n`a+#VGqpQNq0Lx*m42&YL*`E-Qij6%W-WkV+pG(4E{ION9~5hnyhzV*e}TfK-ZY9W`?m)w z%Wywop$g3_;>IS4S2JI>efl&{Yk1x^I7-w3Qs`93{&dBadCN&mt`kLpl+;StnpRCm z4o7xG#AN^x7H5olgMC?--*z-!CC*4TINJPx*8DGD?&zWm(gM_;BiT381k}gJ&|a%% zI=|7{`#wGWtE_=)i;=X9OcyMHCHBQzm(R+$>1n#Y#5%PdBlT&cy(LMfl5BOvR4Ew8 zwKoU8lQ6O`jusGpzb9($+&3y!b`KuX9Wxdw6W60WOh5#f_oCmc*hrX!En3ihZ^r!j ztZhi$g_gLhdQCvo(ay~&-MOg`LzMH$Ik%KFXnGZtZ(SpjJ)(c>udE4OUR3ome&h}g zjmv(as#2ntS;7}`1IJOjxwqV-PLL$i-9`VsI_M<>bEsZspt(OibKkyw$C`>tRGKym zo^xSU_OK=WI@kC}aQPn2g*H2{GK0$sx&+7VB9;j8G`XEz3UTAeXmFa}-0~7t{$)vo z=VA`P-Z4@EQLUT+x7H_b9$q!ZbP01Mx3N+g>FT{EJBRGZ|7O?~tb#M{^yv0miuITA z7P?q0%hJSj$BS|ZmT6YDoO$Ca^BQy87J;1nV>q`FcQ9tc1ejJc{S-IqW0*BC&m3G! z{k)M02D4j~;@Zu)EaibTi}I{H;+Z3y-vh~Tu6sP+%jo2|_TL|C*|(H=)zmzK-rKJ6 z3QTPLNv-n-@Rh+;FCi@^tGD*MZxlJvtCIpO5?Q!F`f$- z6a*Xax*V(*zZC?U-j|rIbZ`LUdxNzxDP{CwyrjaIBM`m3{D`?T2DIq{a_rcQu=Y8= z-``h5%rM$!e6W+2TDtTr_}p!5?bxe-KRD|?Gk5MNBoknE*3P=Kd3hfuMM$g(e1Ld2 zS-#H(-~l2AAd6pS{`_?t4my>(*yk`kR7dr7^{ds&0!Bq#3KHR@afS5R$W9}|F>7pkx|6prf*e! z|7iZ^fPUQW2A_`0moLLt={X#x#;3;NUVlB=_BK@3uo{<@J&eqv5u?Yi)6$x@cG(^i zYPJCdA`%JZ!$oq`FXu=(v(^mTLfKtvY=QJ5%?0?DP5f3d{)N+P~<*W@`J^txG^^gX&=P$dS;4!|~!I>6Wi=F8oVi&77Ut5RV5QuX~)8l?9~^600@eR$7%$ zv3HCN318m@IowxB<6gab6&JUx!z<#Mqrer2NPi@z1_6O8@{cKsDqBbsu_UL9|u zmC3~OYJ);9vJ9ReJ45ve`GuLO>9OXLfYl2YEC5YS(YdPy+-TVCGr*^BIyD@$eWmgD zV2=$xpL&Yn^($9C!Fw5ckf@D_zl>aGt3}NQ@5j>!zRVCHz|~^A0rOpUMMVX^I5c>k z2&RVfv~~)=;EbiFXfYae_C!IL_Y?vMu=nv?oi8%2%7;~}hlp$1r7tBSfMGZVN>eNn zt9?kK@6{->*`ao}?Rb{R!1FPN%NI-Jxl;U~NH`Q{rMFr{;dT)Pvj zpi(@i>({SC1UTVIIl>N~hOWPEaHt_KA|(y#L^$O5L$;+s(R5K2wVFs-VuGTv&{xhV zQ-X-sO~x~!Yfz!ka(8p{hiS3~eEpV)ZZkAIyt%$h&*7B{?Vtx(WRq%6jS_J1*RXDI zPz|#DMc<$+#7cPbR)!XXI%CRP5 zNmLuuH!p3|_@fjGIPc-2gE+> zQ;>5ww8@2W>fz$5P5@$6^4s4Bil_(m(?!R8^`v{YQZr3usjGsZHzpPkik zMeeegllzVxJCHK!V{Vu(>JhtT`ecFeR zYd${REY>1}7uURJsM$TK_6mv*2?`1_H#1{Ua}>pCMDhwL5xEy2xfLgj;Ny$`W@ku% zxwZ$7IelMc=mhy4ZE^@TOek1t>&+DcGBVszlZ_-0zuu{8nh->WPk(4W3Vu~!yZDh zO1XL!0YdX$2dGgH{tKI*#pCHvA_gc~?#_OwMM#1Dmrb5Aqqe$QWYVN8guB6?$=mbT zjAMj^tzo{>4s1itR0wz%q z?79;~N?Edi(g{!44=PGpe3jLvhQK}-*#(dAw*@uYvJmiyGqXzl?WV%w9GKd{bFsI# zmqjJzHy?#)FtT)^y!=(Iy>{y2)lcl06Z!ZWzWGrQOq;r-HTG+MUe!4M>WTLQ&cXFd zm&%MU%0s7A#dYh32N3M9-kqj;ODap=iW~12z8tFH1hs0YA_g>?Pj}m5HIOxoshARpJW|QTN9|1 z;l+XxURKjczR%*VdOq9#?On-U831`C447w=goK4V2)ENi5mfehhl^DFN0WPlE*5m0 z{a&6HF65?BRee_6n`@&P$$fCV!FkmHPij%p^T~TrKDMYOCJer0Fxvd{?DL6&Dyl@- z=uH(85^9x4Iskt4g6&#-d`~~tE8#&%_FNpYF8p&NCL8US{^0}KRVSFbf`qBBFXl%9 zsr@XNYqN3Q_jfu6Jwqpd&wy;-qIFY}HGaYbsI1pyLyx;|@IiO^_@j@}CwP-XVroi^ zJYQ;tJjMZs0}ByC!dlwUx2g^1vi%;Y_#*xLV>_3uXbYDwgcYGGWf1b%o!|YE?y!#m zTgz9D<9#y1VJT_U4D?su284)(=e)<38U^8^J;tnVmckf=XCL{!CU@vsN+b(_?);e~%#=Wv}FM7g6PQ3UQ1^#if-@RLBvh*+fp)Ko$qBdZ9O6=cJ=KN$bMRj*JyzG$HA zhDNiYK_wGoV)a48HT6wsk*3X<0dMD$M_Z*p6vHKTPD-o>X&=aa>N2s{kZSGlc`#O7 z{)qrNc=^SGlb6nUCEb27?TI34O2nSP{~U(J5=dc#@9nabVfNhiQw8Pa6YtIX56)zV z8;ch#sDqV+nIIe$%%;EXV$k1AK5U&U|BIE?W$l^?wY9a-Ys5~E9#tWkxoR zdvQw|fmj9);2z7ZIXs<;$09}x8YKtRymD5$1vt9R`$@%cPVVxHEJq@b55}(}i6m`5jswkMT1;AxT&1>4VZYW)xZTU+2#!?nk)(?D9A0 zhQwZ0ehE1li=`NGv$?s85m480RKni(+&Sj6riVvOVWOFEyd5*#_3%AI@93CS99{JE zcD%sY=I{*V4`##X6~)ZrsX_CFGPRJonJ%%(r0oitrV|@zYkpP2Z!Y?J#2t)Az zq|0o_fo^I#r&KQIu<*0;vcC5|bVoD5`u{T%T2N@s>ea}haYB_29Xwt!ezZw46cq=6 z4miKU*9P;2WkQt=V#NgqFPJ;my_fK=CGz9u&wpoj`Y0aoLY+_|svD642y4qc-LQkh z;mDlqGdQ_}x+kYZYuDDTA7Q7^W#QX-3era$ zw-OeOxb=vbK;&b?tAI0wL`s6r`Q^)(t*u9!$s+cSsUhXiAqYsF#^@Lp9YYPr%#?7^F1e(@=W64Qe)CQX=&t8!_f4?+(}cXzNX8DRURIt zp`XSO*R-v>#=KP}J8bQ)nGGvYc`aP9;Ok`H=7Z6LPP!@aI$Nv1%-?G|f~t&{q+4nKl!raxz7czgmUZ-Ih>f{e`j#TN-BzxFF#p6H73 zKKFLw2vtGYPHIh)!dk2*MXrAVVSnKh{Qm^UkAKo}ctwYawY4>NKTGGmnEXP{Ia0@N z348z7m8(a&k-GQE)fUIcrZTz7w@Tj_P{gP+@@7VihjeD)#Uq(++*63qvSyD8bgY`u zK?hpFnqIwWq*ze<;_G9zi5$TOPXk!fI_V=ZzOia|)6T3^cd=4qUn{@(kz$XZJV8f# zaL)v|Mm=FIsJ72R10kC{y0bpln@g2P{Rr3^?>>ThK}2q!NqR=chXd~1IWs3pG%X%S zR4?@oKU}n+BZbZ%xamQ}x(6awyROzvat;SZ-QAcoqmVDyOTF58#?YxzQNlj|w(0vo zQs4(-hr>97Dtkwz9NsMs^miF!QKbSh_w=K+iK`rSQN?UvdqCiz{l?Q+X|GMP(&p*u18t<@66m*4PIPYdiGRydHNniL~L7NTxD%aH^yAr%mz zshhhy&?tm$x!~-^WlV2e#F=UizekxHw{FG5fL4hoF*69yc)KlHM99b2S57~!1#E0w z+7l*DM55|QZ?(-h)T#Jx+Q?LcN0Iqe40=?&kK|4w96W$gqH)b6A9Fs}f4<|x^*7tx zM%=f6rC`$`FR_$3aB%E8vEVfGX6FJ84J0=fu+1I)IY&cT3sI5GJh%F-IzHFYKfEM~+0J`u!8s9If!%H}gcO z7KUCeI6l%J5uT}-jub|j3xerg1#Z137URvEP(pYqs8P^4?5n2&Kcs1hOrK5&;#6Gy zKHUe#gU2J|+8CX?`IgdCcrf7(Oqm0e(d-DPD_DrK?8q-mmtHZO{zs2a6_=Kgm6gD? zhr?O&c+DLEpdjeJcf3enEsh*{bE~sSNhEF=g}zayS5}sJOnD`svfaC98hOE6A2mMh z=2T%}ob*24u%AKxWUgb8*}UN?ybBU<7uUSWh`cZx{6Q3VU2w5cM)9~8@t5f8vZc=s zDv!N^M0z(*bDGk@&%a{k$#w|Ku+K3lkd-T6mPa5Ir|Kp;g~2NM{b9A1DT9%U$F!Nn z;y-6x2Ma&=h&CJO$hvrtOK^lo;O6IO^1O2Mn!)MUWk86Hey~#^VW$%FpoBV^?_bu=_hSc$QN1rKHEr_w~A&MHN#%pF&@a(@lE&rap z8C?cTF~R}*t+!;Lj}HvxrPS3KlH5Pb>h-;jDHo+j!q zsy0Y87wv+fI%+M1-~k)QNodD7z<0vFqPiNibI=Do+}y&s35_v@Zr*5T<+k7a5t0y;l1AML0IotaN|xH#+-q!0>aFho`J* ztArPqBB|^q+E;+zh_^*}G=t{w*AMcqq${>%jhO&Ju=d`*eT&42;M=!<6C3IJmYAOY ze9m=y3=x^UYSpS;yKc}uR8R5`J~0LqB;S#ee;Wm~ABvThJDWESmWT~C|KdB*c#%%!S^(ELOW#)qy(W?BJ36vj- zlsb6$0y?hycyH~_onP22=9?h$`V}iuFb{b1$iA<=*11@Bx`{P{ua5s;9>wVf2e#|# z&JY(D7ZFi*Y^@kJV)Xro56?@vt~XHapHYgD*+DZgK;%+Wx3yoqbk2kWPC`+!@#j^4 zF|0)Bt?)n>1V>l94zX$?6?PEywrSq`j12kl_lRD0*Nz?S8P%)nJ~58XfhiHpE`{$Y zIyeMVwn_`}O{Er#uhHrg-2Whx{23g1M7bREoe6|4>%}BmTG|a|D+#i?eNz#v*BI2X zW5;6rS*ihIEnGX?&z#|u3zEwie=%2_uQUq{m$WohOdc(9#~ze+=zY;8czb#p5G|_@ zojuhl=Ud+z_4VssrIo1t^KT%&2`M)>$93^5r5i_`=AN2>Kp{R`7@Mr*k-SyoD)7F&U14@ntBtZe{!;D__oH zA`y#WQ9*=CpZ@&$Glu^5H~Gq#{~;XmzuJ2fs2tb!eK@pD8%+pJl!``#rl&$FNhOVv zA{0_-o(E&2NE&FOP?SbZDuq&t29?r;29*Y$=DGiIKh@ssZ4dAJ`~APQzV&^3y=%S8 z-nyTj>%Ok*JkR4e&g1-^Ic(htN)PjzCx_n%e?Ze~KBHa>8M*?plqcKvGqCn71jSH; z?tjMQ&G>4L-Xn};*2yC}ww~D!ZN4@xE1h!tp_1H;jx za{dIIVSKX#Q)eUDa{O}{;fZ)$JI#az>`@JQYXLIyf-a$?4`Kuzd42%bPmh7^r%Q}A zL0MTO$=tldT#n;lHS8RTdJZB`4H2IQlP9>ShPP{Gzu0i;FTuM%HFwknmJ|Tl)uqUPF-> zL;;vR4tCbF37}pya8F{emFc+2U{9nG8(NrF~5-0MfFNK*r z>({Q$-Q*1x?cUwHe4t_r!0(x6k!1k`K|FwAYGT$TaK()e)p-ZiyjJqVr!Bu3Cmpq? zm=Ed@8XB6Rp`kXmG)o!cWlWQhM;HJbq=0}lf}0}-A#5@Lu*g@!3NZyy=d`|Zeul}< zPr*g98UU7o@JHzM!ez?@czOFmYf? zCG~WZ)__JN?~h_4TPF=w{1(KRI@@ozX{B)KqZqyT5hJ)HVULK5VtZKje%p8S;H!JM z$lsPX!vu7kU=2e_b_al1gOshe^UhrD!z#fuUKA!o%v0_=MC~f*i{c&y74bgC8FO6~ zzK`8R$!POE(Ukia+E|~2OgSWx02J-*M=`REkTrhacK4rR+k`d4R%Rrcc=2G};PU!@ z9?}2z-NThpWg)l$~`Be{y(!|sfEZ@kF9zMH;MI6cRoyl?hOJ$ zPZg@H`4olidcg#~JEp`GkfpzkIwE8v<&S0KVPo#&oM7Bks@V$==YRz#I7s4Uh$D7-zV;^!?E8Yh0{B2 z8y)-JKuAJ=KJ~T|SFSKIclZ>dt_Cx&x5Ug$nGEM=YK+5WjBDm)C58Kh;<&kgo86gOYGbcrv`)zuYX0bn}v?c&wwiK~D@ z3|6vbY(RA+bZI_DoMQ6LIe=2^R>0M64Y zuWbL|v-Kxro8AEId za_uTKFC{ON7XakepSO}o4#o>M+C)c^BNYvtYA-`6wb)>cmZ0K||V0!br$h1*JEI+-yj83jHvZ zZZ`WW9+p*FcrfMkicB4BT}U?3Vf#4<3fSaQE&Q%qj%uzZ*?!ZT8r8HBf>O(W==2B` zgU!uvWK^fkWI)ylY>2EqBA<%{h30%*44QagnkFWWtkr|#I=g7&SF4)&8#KZq{y5B1m zy;S2K++pcW2A46=cIEL-{imMI0)9CA$z+0FCKI0X6NOx6%oh0@8K{0V=L^WnO`^8j zrd|M}C@RuzO0x1(2{lj&=NgQShkz5vfX!%s2L{WDtX+FMJv|+{H76(M_U(hMfqIhQ z9KeU5)_&MvNm`8^1!)+VRJ|vb8-t(W`@#7fGlaV}^_=ouEW6gNT)sRZunSchNM~3X z_YVzC!HoanW`l4takjAcFuD+ioqCtu+%Rk4S;G==MoJ0_zb;zz9&<`jMIyPLh(ev!k+qeq?LRgQ7Z!+6KE;nAPG&=2T1vc=&WD*Exh@F{{`&~qB_?^|Uf zPH+SFHV837qEipx^bd+x{i(`u_1qL>1zOUw{IyWsnZD*9j~o0PL7Mmu1G zARz?%Qqrwt{-ZxwRV*=TOJ~LRu$;;rS(`H_dugm*=H&rwyL{;qPDYhplI@*^`ZG$BStnwZGKB91#s-`?7EEUeBvnX%;PdP-<YIpXFaW?^9BGX-JxL zjrvE~$!X8;JSKmh|J{@Z!-ErwDT}rhu=0C4@UDOTY$MTkZWZ7E`ah>Qo@GRxa&8d< z-_OPM(vE7{a`0!eHgy_*8mimRe(PBLS&kPzpLYe86H>L$toJ+dr;l&USYuXNj6a-C_&;O2zdEBwZdtq{j!)N(Qsx2A;)zC^`Tik?PgK>_)q*j>z-w%$$`U z?soGltY}~=l^AkYxvHkF?y>IckzXzP-Uwqn(Oz4Z`jnc*zrxW(#Bq4jRC&WDpSJBc z+p6uAfi3`0uDO6*4?P?G-F4OEgAZfU9Rp(zcpX0}9_G`xA^k>6x=xDraxLKx^`|PM z@06G!U>+t?o1d;nWqZ$4pIT@?5XTDg^WiZZJT;8575DGn1v=|3(U{}nf|=78a79l? zmk8)i^7h@k$IEW-#1P)a3m3w-6!D+$SF{|w1~)(xByMAZDPlDjpgl;c#_VwRb?c4- zPwxsHDb|}bhm33f{P_q0=+RpEwGMNLm%Pw|;)9kL$m_P033)}H!7)`}#~phWgS&j? zSa1GNpe)GD%0pk0mOZp2S>%^Y?@et`8DRfO5&&Bc8lNREv%Karw)TLN0DiG=x8IYG zTRu7`Wo_pVWhD*fQA36R1z(pspL*k?W17Os6VIRT8VpEE6M)762@NqOYRRX=`pxfM zb^+4IRuE+(9eqwcsr?da5y-~%CkxGPE(vZy@nr4nB01X55q8|%e9M^Nvo2d_ObCI7 zQ@C;y`tYD!dL2@*@AAa?k`X;K|J*5~ucX|&8{SIQ^U7<yI*KUxnlwNXnFRjd`3+}n+U0u%~zt-CF+CHq!Zf;Lbjo7G^M(Jy% zQZ-{Yrw?sTw)PJl>@kBZ)7kNL$>=vVS^5-j5xHEu^~XX}?kh4yMFonS{W#&q)`O`m ze){>I+f8&ZhFI@f+QXbFC#OIGO)%B6-k4N1(H1_mWL230U%0jQ6I;v)^9!{RuJ~}? z+uifollFa@F%m~Ib~)VgTycep>HxQv&8mv3%dyR;>{EBklIBchbAF>r$A@jd7JgHAZTmHFO)OhTO3kv zaL<+zeEh>$Mf#Lg84PV?x&im+c@NVX?TzyBUYLXfc6&b0OBZQSz(ty6o2YfNF)O1c zx&G?m*Ey2|f`$``i@()9cNwJ8kumxuru8G|;Tx@~!+s-QUI3=>C32ZR#nC)49IZFn*uyg(qWl#{ElDT633 z2a`vKzQ&&+N)Y7Y6TQWP`gW+|^&K3Jwc#z}+wFbtk_9CRk7nFB*betrEL*&OaJcj6 ztHy2w2oYc^6-wfYlCdh0m#waYoi3J;aau9*;3bSH4@hqAUGTEoC(2eUQ9mD!=XFv& z{3_0p+Gjr8kzSBNkWITTEq;~L6p?_#@oIaBVx@kIQb+*|j}-MUz>!E>vRc3#;!ypa zq#MoXyjo6!X4wrx#~2w>CbfPU?pCXn;pdp7I~x$l&>XvQPG&fA7C2LKYnBCjw#%f;fO zQW8>E01oc@0Gii_r<{4eqWVNJ3yuQSG*O*NMq-yoH7li`ug z%8~2<{bFb{;VV{pqBwvU@+BeQp}kMZyP4yVTT^$TS>~P$hRk6c3{STvmW^YtJTzQl z=dPa=_1~^iyyx4(n%34l5hLr|Tbqwr`tz(P3Y=Z_dQp%_o5-|28*?)|YMOj8~ zb*xv3WlHV50A790n|I5fN>fn?k zdR4;`1R1w*z^_f+8<=Fei4`Q(9fuq|Ny&NG42~4OEXpGiVaQTeFu5}pd60PkmcY)5 z7)9nNawM0ESGz!nd&uuP0-v(7G8@S@f!Tw!SJbB)E6rogStM}aZlTm9nZ`kfJ|!q* zRRM;GNYXP2YCqoNqa17)utXXd>A_Fo;n~ zGHDRoY>T$8eT^?(fk0D5TqpF7kkVbgCV9$|C#LZxe>7J!hQ(1TdK6W>2 z8qlbcTiZH8PNKYS#?$p;wKgX*kclyQ(2bGs&~OAd>|NNDxU}W9&%7-!#_(Z}W=@5G zSU5Q0UcIz<#dRrOmXTmDWH<*NpDf4jF0l8<{pT;JryDYX2=f#@ijd0pdJM*RF`~bl zm`9g`dvUKn&-8XynR|FJ|82juu~U`*+84wX=p_ z)vpQD&b9}8!*5|!W7gmP^yQUKgX1@xdNSmsrW`BY-ctr{AfErSAyZE^Mq>b7|Alr& z#ha)23*Dnv{dQ6wM?KIgUr4pq>b#ZP=EKH?Vqy0U56P%4dAHl}iFWt7`U4AeA|xV> z?&2oYpdRR~4u@nFDFRS=4&ii6RP|iRPb^X5I66i!ingd|;?xi{$xaYp=%0n6qF1=#CzwKiIKpr)=JXKy;P z+)Uij`o_NOyOG)IyXcw&dd6nC5l>v*c=b9<03=021!8_-qw4(|8&q})$T`j2U;vpj z&ZNCUB4PiEGtj;Dz`ea!kk52I0@x&)({1aFoTbSLqvBQ1unnj$V-_g`Y>tbOP?)^9 zyi`G1IZ*kr-UPgrkyt;m^|TEJ*7soIoMP*S-5R{FUcX)*&*_sTfo70o^VXtQt+x(bDrI`Qsg_>RQ*Lm z&3lIkE|76o(PSxSf%oeD5i(><&T}VcJ7}hyu`791%|A8L7Hn=VHFofk_PzRvkl}qB z*dtsjSrc?VwQWVUZnp3suDEjPlm*1?CSSN^6jU&Dm^Ypw!y@JenjgpUDRL)mCV+8k z>(uc__19e{`@(S*jZ8JKI9GE9yHVf4YPV7eu)_f$QPGi`-TUaxhMT+u39fl1#$7K+ zTws-QK_vbyiY$c9n8*xA9xO!kc;*lX>{>t(X^iiuWVX|yaxYOWGv0KHMN<0Eo zFD5dF^YnzM&)jhrp2z^-Lb?RAu#`gAfqcf`tE>&&c>K`HF(iIcKf1cc~p( ze__D^>w;3$ka34IH4caJfgNR%bR0&HbW9x8)Xv;pd7C=ANlHLD7jD2sNN4px;@Y7v zt_tJV$`xH$tk_RVZKjfxbI9ES_o>-~)>zV9TXBOef{yBwC5|YD1a&aW$XHA#VrhNpgX{lQo(A+Ba*gAhO{I>yE90Mr`*1HO zE!1+~DNM;TvO^0_#Fe=ZvdpEbq3&FE?1{Emn0wG{Qf~Wqb#^)q*Z(oDWZ^vNK@ypI+?d~6E$>VJwM&-$xXxX)95^zj0|?`oRP zZc?0t;>fx+b9QJ=$DnncwztBJf6tyMQGL*xRb<$kd-*>6w2TbRfHf;Opi$}@*R1fO zB-CbK_6V!;h9KGm+Rgjy#jpAS1D(70hy5fLPQG}4(VSoDUffOV6FIe*YVGYZvW!gS zz3FUtU8Dl#9ZCP)Ug#Sa`+|#VUl_>_cgdHCZ-AC){%zLM-=dB_kxbv@9 zOz7EkKW6E{f{Ok#Ucbd&%KLb1*uUOg^#zpGgm(s}9$Togd}vX?~0moEZ}1 zL?OGP;_3!vzGC*J{NMu3q*#1*x)XvMew=6x+bhQ(?DIa4=AjlTyj)yxkB2jwJr)uQ*~6CF?5pC+!E z*&D4s9GjG?_aX|02!ZJs;87|x+LZ5wX-^o$W?Z4DJo_>zn|_RhbFqW(`#W%WU1Zz) zH}$Y?0c9b4rsj5BncM7l`O`^kT@7&I`t*+YOK@TM&V0&;Vyzjt4a64Em4{FO3d&)A zb@IbHD%Zc+^^{v^<~GDhTk_=RKYI@g`(QSmp{#EI^6Lwoqj!#Z%=sot&6jtZiIVFO zSFoS=KVEzP?FZh^@e!k&y}56~ad|d{!rSaVRYZdn>-pZlJ>sqrlr7MWYo}ZqCs|&V zifRrgs&Qr7v22c={=`8|m$GsvSG-V2Pp?rgOOin}kN; zzLK1j#4h(ZJV?tCQ`f*BYRV0mp`8W$nP_j4ni{$KL?9tZ^5n)Olt*A>>ljDMRxGk6 zDL$^bezKACDH$W@suGS$TWxjm&@;ZWW}6B05gFsa#_F+1O((sXgnQBsJy>s6cAd*Z z)1!*q|J{L5X(Kyw{HwxFW2tq4>RBZLb34ESFh%9XWrxf@+_q_v=rHi$G~9@LeA!!z z16|reZCXCUF-9=6E2+YwqwEe5Wm?i3$fT+9K2#t*6WroqSiCo{m%Gd}hh{~UoTrL1 zIySjP8#tJKrMY=tWewDvD$)R>F?`Ng)V4}p6BbcPFqn#%ukvVvv=5t@CE??Ov@TvV zz7b?^+nGj>+Lq3}O@ZrlcQbEJRD^gDTQN^sRG9!Uv)&*udD;jA9VX{N8&Wq$Ku0~< zL%L&k@|@$2;687P_KebesCEiTve|rOeBubS8Ke_MH+~gJ-yy(#!1y>(q92ljJJt9|KUiF@$W-n*003+_Ui zL!{fG;@*zp`gS!5N1L(<vtyKcV7c;7Enn%OS{5$jt>r z83TO+rl3DS$z?4ia2@^g{P0mi&WZ9SyFJ3I<#vq=tc(N!grW;76vRC~s^rzg>mxwV z^1p*Xt+#)b^2>@VAk~$I;8rqOyVMyLiObv(M_1C7e zEBLkhvA18p>SkTZqt*^E=8El`sqVd!Lulx1+5=N@qVWHk)mJj~!G+Ce|Nc9>eo;x# zDS7=m7Nwt($=5Bur~Q4RjzGKIVL-i8{d%xw*qbX!N#>nL524g-gbcjM$l;4Zcoc9pQ zaRleH$R7qP82Po=zw^Nkmt5|5(>5LV*aRI5;h`kR&yRUTtPI@uU8W|NuGvaku%4H< zxM)J9^E=E{UE*xU_;B-8v`&b2KdxwzR@nhPi1SD*VIn~7%M6oQR*S8ee_M-_4gLeFBxG03 z5X0m#5n>erX|UFc)5!ot?vJ{blNM2=?Xz9hi%%3EhZAZ#@ ze~b+Oo)CE=3y8ZGYHOkf#?6*PZ0L`0ZZtWl;m@OfI`lY{Ib#-W&(YZ7rOpUx6~1;i zKY`PQWBKXHXQ3z`a~YEe!=^WZodKdpDXDKCdAZp>UFfh9TX9J=d|a>JR%8~u`Pk*? zJ0KeLlM8*K8a~0PE~(4$)!=)mLN*jcZvRRhsADb2+eSnuU|Khd2VZ(HZyoVOyKw+b zzC0rhBcB!_Hd)T2b`laBeA$%fWHbc048LH@d)c&>!n3?QwKoAb*ZMEZ{K&{b;gxIppq=>EGWyr+9_460#Ipw;$@OVbRFC56z->y~m4_wg?Fgg^zo;;eb{> zvTzA3$3|ATv7tQE#+1B&Fo7#(~h|OOR1t8)~pZc1 zP$Lb@#&h|`-m5O-FIdx5tT`Xvl5%lIV89j8yhI~<|513MnUB0=GW8z!HVmucVJSsw z@&p(w){>^^m8sfYEBh@Sncuj&MRHNn>Hy`xDfG>J?7n+0kCSCQ{aNwS6P)$upGQ3LP* zunSecuJD6;MI}~9Sy-#(M^&h_JB7p&3l?4}J z{bXP=ICF|idZvsE`aqX$RDXEm#6eI_F(fX$TjRHPJ!)i0WN@&Jh{<4d*=cHV#vj$Q zUDM09w?feSbp;R6I?|HY**aZi8t!Zn21+94i zKJLLZ^D@MKnko1K__FS9 zh-L_J-MFY)lZl`jqruM`Xg~0UU+<}oPxS-Uf*#w&CTLAb+}RQ+#0p{K`CkRD2_n8x zu*{~Q&~~50=C3&Qjlt5uR6{jF#slxclZ@sTP@r-qLMMurZx#q_dlRggWowq`gmiBH zl2sqiG|Eq6^|=qow#00p$!9GQZDV#&SL#s?^@@tu$=G6E_R_fr@s4|+SL#K4FL0G))_Bz4 zv2DgC@N0%3FmY8!b$qyEP0|Skm4tEM!H}A$jisZ`zt4wfoV9BT@E{%eLjcWdL}StS$4@{qlY5Gf{4t>OwxS_ z@?T~Ndo@0=OEmflRs*IOfIG$OBC1TEC&(fB8^XAXf;tM*TYUqz=$mu6L7u0IXT5FN zQ*f_^si!T3n2ZrKz(p;LOJRtw1Hu z`yO0$bu>hDfnZrvPU6ykin)#Nzc5=G{top03&iaX?iN%sN%UkxNkK2o56T4$i&=k9 zUhsvsXr7e$r%ZGc=68`_6&BV|ejFK3hv`n)8MOgGxazR`SyyDKXiff>V_2}vj(WC& z2HG1v3%&h-om})5D0kMUa$NQ|=v?0nV)U2r9tAx6%M!WC&D&(OGrIYOA?ePMANP&+ zbTwahlA7w%|8?-=n&DEYr*5J#0#$G23bBtuVf#0&JF;$m14YGwbuATomA?C*-VKmL zls_<3!C*pT3#pRaAz-=}zu#XZrR(y`{t=oz_yV_H-Vww=0)%>`z0IP#WWwG+P{R))g~{pQEdpKVAel9S27N= z%FD*2Ly@Qz72boN%t%E~3$bS9tO>Mq5|wp!_1r`hsHaaNAQQJ4_CV@*KVrc9D@wsI zrt<8NyTKiB!uN6jJdx68p>qn@av~aopmNa-^Lqs0UfuAb)OPO=U~rEg!N-_^ z&=-&ae)N8n*zD8(h`_OOzgqA1I~?}Y70n}VD!X?H;Ot-dapT_KdH4>^EROg)sM~h) zczwk03X-487G}Y~-|Jio9K7Y9_R4v-(`7RUeslZJsgR$4V9=ybi45gOeFj}mj2^l+ z%M}1PONrVjCBs3rkoT`8FXdt7^E_wq&%fakKpZV`Eyc0a59*(x8+3h+`dxdIk?B5@axl)z4XAs6eu?9Z|il0&|gka*o4KmMYwo#5XAjJQSN&2rp z@PE!D?f;*KqFG%!6&3aJln*!kjye50qf|%5w6D^cn+3+GGyg0UIGy7cetN;|pItvj z42r)X2YV338I<5_Rkm zKPa8LS4-TU4FyE8iQkxlWiR@k=l*B7dzWnB?9Tf;>i2I?Ff!QxIl8}ob}Lf_QRTZuqDOVaLzIK|za_2D$%Uf4bzDJkXk>|gnj z$0c+D6cT7U?B0cPz;)Mm0sNnnNwT!8FmhXu*_*StKW#0?%ub!AGo9U$*lPT3V#|GQ zCWavp{TKCu%*|b>?Kht+D}&>~NJn?tkomG(mU+O)z|F9Xyi6hV0$|AcFF<0(yt(Pw z=3}y4N1>Amx!@tY3!`(ErTUKAxjTe1!{B^pbTE8XI(7*?1qgZAdy%4Pc~+?-fl7XLRq%EF=Opq&ZYgo1Dj~eMsvW0~8~B`Ur0>J5P~X!#>1+=jIxqY5 z7Z+>Nq89g&`)PLqcd)V%I-Z?9wz5xcC>dAYVl52eGit?fZc~x!FXkm7^3raN-OO@) z`|ZWMUrs#~G&NEvD@^;?O=3-HejlaGW+(0hN54v|(V$I7pMxp7=QDRl^sCp*9a)^8 zgYB$H*;v+z59IaNI6enAUe=v!=g0?DxFu;iqw!di09(Ez17FnNRw%f;ZacC=ux-BC z^3oMz1>GsWH1Qdqd*?4bEiNog`F#3>txa9FJ#}gE$mcothNOoQ*ke)ca98ne7734} zFGCZ`PN{ahjSA#HWRT}hD4sFci`;80U4oZ@=CG(H3bX_=iVC|4&2=XsQ?D+Nfqs+S}4(Iy`sbR^u--M?HNB^bd&59 zFLz0(7hfH=8K9L%BSu)7=0JOS2G|V!3zvR1)V2L&r*90nthSVXrE&UKyMg7?&M_J6T2ve;)yy|9(Y3w% zu|n=!_vB^*#|zw`(gdKpr!hM-eM|yc#KDIc&na84ls_MSL8c%kTHJQz-yV+o0#P=U zrmSY-E2fqOHUsEZQdSlOkp&bUl8wdW8>l}#$j}56np)u7z;_GLw^;2LPerw^pe~M` zMfnPCA)Q2ZU75n#t5`u`vbSv=bhVs>Yi56B=Hu1~31tx(pYlPz*p8fKuC264+QV(of!~9;uaO1*>^a`pB zPqv7iugPM0vJru0RZISi7A`v{!QEn(L*Y zW-IqsQ?3JL(pQfgOq!ZNg&N)qh?&lcvh6w!1G@P-PJi{ zy%U55v>!)z*+R&t8B5Pp{bo0bD9g=*!7~UO*QyC%Jd)-aYk;FgZkD9!uPV`D`z3Ve zcs=F%NaosQ+C*R2dII2_At9)WJ%OI;H{e~=#uD{0Oo7Dh!Y9~-AX`FgFqC23;&h2e~5 z`L%Md4MXn;i|3d`y{GQYN`NqW{ado*#6Z<<&*e}%wA_^!N=hQ`rCSTw9Mk3fK9}$_ z43*0nHd-i4wb`0;r3s6L?Z2in_uZ!#+|Fg@A9EYsmOb(_dEcuI#jVVjqE}bsP>N@K zy3E`95^XeZ#70tf%K126184G}BEP6Xl-nftOMS+L38_-|U*1Jm^xW8}+%j2baJ1#4 zU0X`V$MXt#=NEFW;8AnzO5~RFUS(6vpY1%9X|CUl_E7~Bu6G)sqn}?qReiWx{dH|q z1P0LZwJGdrn9p~#^IbO-z`TJrJ>&c8+4Evx>>%%><7~%$r|)2@$vllPzsz!|GYe%P z%hon)p^&i3y|8QcJXQtlcOqk=2%S9eQIj_zILAZWIR!$zybAS7f=}An9W=L_VVb3$ zbH;?qeyR;?Wx9C`+NzgamnjgcGZb<+6%V5}&l?v$-To%L?$q{kBtarjd03L5GRPBV zE)CDA&)_+b`G8sdgt6N)&3ADVIeyCx6%v_^(tMj$hE{fZq*{{htc|3OHEW*l;gDFU z?t6iKyT`Lq$-1=xkdTX+v0>&(qPq?*Ir`!Y3#Ja5SXU@kdyd804wDN^;|>k=CYLH* zZ#J9zt|oC_{)=ke;J$d5Zg%xp3~e~BwKK(p{=D` z{op}1@bS_*il$kKvT?>`w|#Z0;y>))%sRqW;weuZJJ!RresX7uaowE6@g^^YM>-JF zak3)hq}|&aDtWq6uj@*vknOl@YrW)`7S;#Ti@X_K17=S#j?BqH=4|%;Btl63b6MaEe%$YkhSxKT= zPOWdXqR()?d|Y!!%<8-}7Uj93`jbrC`ahR;Zw=lN#)uGoog^N1D6NN4PL+9K8&AjN zgdVI&()9E9Vs~TOYeUV`-*Mj{3g$>=B4H;jK28#JO#vWYNRI&afL|o4OPuL#Z1`Or)8^ zLE3q?62<{YIZlCTMrW;_eaAgjrSUkA1uX{pRnS=rPQ~litF;#F`UU-Zr{2Zh)CpiI zg+@eKQU?qX5}5owXqan79u}r`IKRvB=FaP#wxg%#lZ^}fcK8HM$u7-)KVmNahU;3} zB_io9^=adc&*E72{`Srnp)q$Go;0jCiNysmAn0uR@hivZ92lCt7<2Gb&AqKcTuLEm`f$u>eGnA}arOwj=JcF{9v?~z#_=mTm>kCF zQkut*oRnJZ1k_TM)Kx#CoNSmQg6)rV=R{j$o+v|`^mr%(hrW>En*+oxY36Lazo{g2 zEGT`6p8YB9mX9t|nKsD8^TJEIkJ$~MeU~$pT_NhDwZmJi+aUb)KD251(i}=9eTAMq zuo#I(N7M(;-KqE(m5f)+ggg&VB*THKP!MGv8S5cz9*vq_@kD^8ZUoTrCE z#U^u>Kc%8txmI3gr`kYETK$sMTat7#mSh}^T}{%+ee&sY5Bp&Vl_nb<7I@}ux9*C3 zUmkH@H4-d&(U2`y2~?Gj7;-K*kqe)JLMHqUn@S6x4aedSAo;&+pt^YDk1wRcpW0l8 z|0i#xza#k(1DmhY^NhX2pWGbs65DIYG`*kX*jV-{D0G&6+B>qJS<;NF#fI%neY!%I z;m6#g=Kj5}v=UE1H=^e<;nb#pQEjrFc|#N7!{5Grev_GBEb4OVdQuuRCTXXu?1y?> zM21#wgi^LJeW?~Q%*4@%`qx0U_^CoMd-MM|F7dVxBP2+fryv1P$DX%%PY z+UaURuHQ@KJDD|N%l%cN4xdUh5%&6+bWCp0ovu0WId?d7K(op` z4TuyjF{TC@p?SO_d+d?EOy1g&iVcbT1W=7tMZw<)LWQUPV;n*ZTp`0Li@a85o1y(k z>DE?h69%jKr9N~CEw6RsbS}GV>{7Aw=c#Jh-Z-C6GyMxC3nZ+V5Rm-16u~|R`1{{8 znL|YzC~`ReOrOx6w=Bw2uh%~7wxutmOJU;eHwexNHDD<0dyX!k>yYfcx%H?i6jS1- zT#gyt70mjUG*I{TsBwMzDKO}*=5JX_k)=s~&DwsVD1?|5c9mr;+R46!abE*T9 zzCXdzZDyEjkF+GQl|QXNz^Ij`oHYK8x-;*qsZ&{oVO`7IcU|uVi`3R$ufHSx!NZ%A zwMZ}y#;|hMU8_mrvbooVGJ|3ZuDa|StvRM#WE|p`8G(qpSd*nxBvvQGyfV5RUio=B zFZ09o4|+#4&Dn8|TS;?s-T0F0mIW13LVM1Nhnb;Z<}$=)GM==)rMR~ASE5i4V=0AT zE>$Vio+vDtFRwNoEB zmlrF;A4-~LX-iHhT{Dwat-oj2fjhhMk$QU^H2qQ;)osRkgoQMGWzRbO&xaHBvvqjq z1=x;ev`s!e`-we1dk`&&Z(HUDjE}C_EQq>j=hOWU4n%pmRmD_aW6HbrEcqC9tYWaz z>#o5e_T6i&%&%6S%r)Qrg{2g#K@8wIS^GH3zwW^*x@P@HqtsLza`QTP41&XVUhlCT zHJlHemIx=FiMvcwM}AM*?5s)27E*;98y!2|p5Rh;*6*%0=G8P=B{i7{9I7Y5;M%Cq{bJdwEq_1+NtO)RCFDo=mre+rh8aNI%~n!0zGAuVpgLI#Cib!l-lBLkoR? z;;krHJJ?x08MPBWZZkXNGTLER)R_0G=Y8LxVVE8C`j47248smuSI2P-hH(%F^k(I} zcbAu%V(Q|VsY$_5M$JKwDUH#lJ8qZHG>ks!^KjpAWn1@NG{bV-PeqESu5{zTW=#x5 zMblECJa_l1+1&|<5OI=wLDZ0_FN&JqVed7!;o`Ny`6Q^9EA<^VYcP# zq$h_=wM7+ezBi|bxp!WM9~yf^{}d#!W0UA-SL2hOy)WsiR-&hk$tg^wF!Td$4lx2=E!!m#ReVLIP<4S&*V?VG) zLjX;RO&8z0^}e7PLcZnj{s`)IHc7|WiP%(Q!83?@$Pkpr1b1q@D?lx^lB0>1_t0K( zo2Pfq3J}*_$30DVeyG2KLdSB{(U$jykUPqHG73r_*>OK9P1@~g%)w-z`rEqM^OHE& zs1vbSe)AEh(GE9c(q9>U^LxL2`ih+NwF@7|%Pl33d2i^wIW}do<3SK_cSibwdqw(_ zp~9x}E!vxzYH8e-*zGyp_aaGs(B929?7h!$!ATU7?epyrnE-$uZDDT z1nzbwBCfte;)zescXx#^SDA^m4=jnoUFu|+$0i27#HHc=)Kv20ar&vBRy<78!u(3&|b?pG5&GrYdURPDnPtDG)& zHnINDnvCHJUFaz3+KPAgDDok~7H5?1L8sJCE`Qg7&Um-^OV_OFl=9<{ux#&Bi5wLl za&;Fqlinv8WSP4+PejO;FQ314Vkk|-l+P^UJdx0=iG@v!F137W6r~?r&p(H%x1HzK zc7Gp3_RlYt(EAXur;69c%Z5rggo+<;|HcQ|DF-y%e!I@7}1CNzHd1 zWTL~*E$#4bv9LAku5sAMrQH#pywqWAyy)~+N<-B550$LPL%$sbw`G|fYTc|C)ClmF zNT1tn=k9QBGS>9zH|(HHU3TgF8*v*!ATs%2E?pIuqBy<~`XZ@8TSF$1V;2Ci0{iw+FdHCs=%qka>M=gXINlVscWFvo(%eFL-5 z%j8qY&g{GxrCPrO$?5L<8?cmQ$M-T_t<3`HVlMnKMNa14k%EMMz7t=N}j!$QGJe$a-uUBO}jPnA%_|3U}JL$-?>kHVJTeGCssMk9K?7&Ic zo^tC$lRSkuK#ubnAf#2heEXGK2BG!`fWSM=(h2_FtXvfO*H1r}-uc_JI{1Eg4X_n2 zpm8RbNlT}iI5mvGska*pP*l+U06{&;vmY-cnndaA#IC4|R-Q-YdSj7gfsoq{A9v@O z4%53q<K-OVH$7Ev8>zimUZz;=-Vo85UP@e=kj>`3IT+fa2cVEBkEZ@*i_y21OX7^%|N?I7?J_EDYb9<1IY&sR&-Q(jtudhXsb zkMY1Q?Dl9i{q2kTQ(2K1ZeaW9&NLU#e)ufeInzf;rSiSbXxH6@r$W)uarfQ>FsfU#FrfA(VsdMSl1fXzR)p z!O`RXM|Z%qb%b!_0!9jd*}hZ@Jl?A9U5zZ_jdU)aC)(z_yUP;d(4hOk5kanfASS$y zZw#oa!h9zGO;$vj*8XUk;gvZiOS6?CMk!|^^b_^ThW=W#F1?Xk-GinGB7UE$z9!Nf z+FzTLuVns$Tj1gYqUx71ooSuCcxw8#*g8MfFg!HNy1RH#I+0Hn00#T53NYfDx8N`F z76v)pZn$h^Vj;zObMZdq5v4Pac(TR5jB+pe#JLWe^euTrbFkFd$cAIVBb~(!w2aXhMwgZUUpie{O!!c|P5BUYL>z~e%C>eUd z!G4;!h%>hO=f$u0?EBS+ifZkmxwVw#n{A_gb)x^<9SV65xFBM8GREYIw%LYx8hW&e z5$o5E^^>`E3-1!PftBUdw59Z=>T-w&8_(BJ9warhBjk_w@25nLko9xl)usqajddMw zvptU%1PS6r5Z}Ar_?9*(Fc_ItmS3bRUE#1F56YD|*GWJu~uUZ&aF*0 z#I&B9C1#qQ67Ca}=Md6W^;_B)wjR?R$v(JtFp}663g@dRzfJheZ}Y&gXL?sKYtHE` z7L;PfS!*t!5z)*z(6zHmuIo+4V%YXzQ5lp~A;0gcOM^zlp=yNyodYfKT2)QxTbbro zQl2@x=RL5~B8jCUo_W)d3oN`qn=QTPgnPCq@eOB!9_E<9RxLVGe%&C);CG{+Lq~XPevpDv=^;kW-n%Q{Juu&*<4O8+z1ZYnDI M-AXcXyN;ayKUPfF8vpTV: 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 @@ -61,46 +53,44 @@ 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 - -== Endorse Indy Did == - -F->FV: Build Did Document -F->FV: Encode Did Document -F->FW: EdDSA sign did document 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.endorseDid contract +C-->C: Execute `EthrExtDidRegistry.setAttribute` contract == Endorse Ethr Did == note across - Not needed as DID imply to be written by default - Owner can add resource without endorsement need + Not needed for creation as DID imply to be written by default + Required for adding of a resource end note -== Create Schema (any DID method) == +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 == 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 (any DID method) == +== Endorse Schema == F->FV: Build Schema -F->FV: Encode Schema -F->FW: EdDSA sign Schema bytes -F-->E: Pass Schema, Signature -E->EV: Build and sign transaction to endorse 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 E->EV: Submit transaction EV->C: Send transaction -C-->C: Execute SchemaRegistry.endorseSchema contract -C-->C: Resolve and verify issuerDid ownership +C-->C: Execute SchemaRegistry.createSchemaSigned contract +C-->C: Resolve and verify issuerId ownership == == diff --git a/docs/design/legacy-identifiers-support.md b/docs/design/legacy-identifiers-support.md deleted file mode 100644 index c5f6f5fa..00000000 --- a/docs/design/legacy-identifiers-support.md +++ /dev/null @@ -1,72 +0,0 @@ -## 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. -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; - - // legacy formated ids of schemas and cred defs -> new id - mapping(string => string) public clMappings; - - function createDidMapping(string legacyDid, bytes32 key, bytes32 ed25518Signature) { - // check signature - // check legacyDid is derived from key - didMappings[legacyDid] = msg.sender; - } - - function endorseDidMapping(address identity, string legacyDid, bytes32 key, bytes32 ed25518Signature, bytes32 ecdsaSignature) { - // check signatures - didMappings[legacyDid] = identity; - } - - // resolve mapping done through `didMappings(string)` function available after contract compilation - - function createClMapping(string legacyId, string id, bytes32 key, bytes32 signature) { - // fetch issuer did from legacy schema/credDef id - // check issuer did is derived from key - // check msg.sender is owner of issuer did - // check identity is owner of schema / cred def - // check signature - clMappings[legacyId] = id; - } - - function endorseClMapping(address identity, string legacyId, string id, bytes32 key, bytes32 ed25518Signature, bytes32 ecdsaSignature) { - // fetch issuer did from legacy schema/credDef id - // check issuer did is derived from key - // check identity is owner of issuer did - // check identity is owner of schema / cred def - // check signatures - clMappings[legacyId] = id; - } - - // resolve mapping done through `clMappings(string)` function available after contract compilation - } - ``` - * Note, that user must pass signature over identifier to prove ownership -* On migration, DID owners willing to preserve resolving of legacy formatted DIDs and id's must do: - * add mapping between legacy - identifier and ethereum account representing `did:ethr` identifier by - executing `LegacyIdMappingRegistry.createDidMapping(...)` method where he must pass: - * DID identifier itself - * Associated public key - * Ed25519 signature owner identifier proving ownership - * Signature must be done over the following hash value: `keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), msg.sender, "createDidMapping", legacyDid, identity, key))` - * add mapping between legacy schema/credDef id's and new ones executing `LegacyIdMappingRegistry.createClMapping()` method he must pass: - * Legacy schema/credDef id - * New id of corresponding schema/credDef - * Associated public key - * Ed25519 signature owner identifier proving ownership - * Signature must be done over the following hash value: `keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), msg.sender, "createClMapping", legacyId, id, key))` -* After migration, clients in order to resolve legacy identifiers: - * for DID document firstly must resolve ethereum account - using `LegacyIdMappingRegistry.didMappings(identifier)`, and next resolve DID ether document as it described in the - corresponding specification. - * 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/registry.md b/docs/design/registry.md index 1932606a..ae1b9c05 100644 --- a/docs/design/registry.md +++ b/docs/design/registry.md @@ -3,7 +3,31 @@ General design for smart contracts oriented for storing objects like DID Document, Schema, Credential Definition. The main question is whether we need to validate storing object or not? -### Current Option: Strict object definition +### Option 1 (Current): Arbitrary objects as JSON string + +#### Pros + +* Simplicity: accept objects (Did Document, Schema, CredDef) as JSON strings (bytes) and store them in transaction log events +* Spec compliant objects stored on the ledger +* Small contract size +* Gas efficient +* Different versions and formats of object can be stored without an upgrade + +#### Cons + +* Invalid data can be written on the Ledger + * JSON string may contain not owned data: + * VDR must perform validation and be reliable by client + * JSON string may contain bad formatted objects +* Duplication: + * Some fields must be passed as an independent parameters for doing obligatory state checks + * Like issuer DID for schema and cred def +* Strong relationship with VDR library? + * VDR must perform the validation of sending data + +### Option 2 (Outdated): Strict object definition + +Define data types for accepting and storing objects, and perform validation of input data. #### Pros @@ -61,26 +85,3 @@ The main question is whether we need to validate storing object or not? * Type is not empty * Value is not empty -### Option 2: Arbitrary objects as JSON string - -#### Pros - -* Simplicity: accept objects (Did Document, Schema, CredDef) as JSON strings and store them as is -* Spec compliant objects stored on the ledger -* We can return state proof for spec compliant objects -* Small contract size -* Gas efficient -* Different versions and formats of object can be stored without an upgrade - -#### Cons - -* Invalid data can be written on the Ledger - * JSON string may contain not owned data: - * VDR must perform validation and be reliable by client - * JSON string may contain bad formatted objects -* Duplication: - * Some fields must be passed as an independent parameters for doing obligatory state checks - * Like issuer DID for schema and cred def -* Strong relationship with VDR library? - * VDR must perform the validation of sending data - diff --git a/docs/design/vdr.md b/docs/design/vdr.md index 739ff90c..fd433017 100644 --- a/docs/design/vdr.md +++ b/docs/design/vdr.md @@ -10,10 +10,10 @@ In the same, time Indy community follows to idea of splitting complex library in * VDR library firstly will be implemented independently and later integrate into existing indy vdr/sdk/frameworks. * VDR library will be written in Rust with providing language wrappers. -* VDR library does conversion of legacy `sov/indy` formatted did's and id's into `indy2` format. -* VDR library does conversion of ledger formatted entities (DID Document, Schema, Credential Definition) into +* VDR library simplifies migration from legacy `sov/indy` formatted did's and id's. +* VDR library simplifies migration from legacy entities (DID Document, Schema, Credential Definition) into specifications compatible format. -* VDR library does only basic validation within request builders. +* VDR library does validation of input and output data. * VDR library does only Ethereum base account signing of transactions. * VDR library request builders are tide to the network. * VDR library will work with RPC Node over HTTP. @@ -58,6 +58,7 @@ impl LedgerClient { chain_id: u64, node_address: String, contract_configs: Vec, + quorum_config: Option, ) -> LedgerClient { unimpltemented!() } @@ -213,7 +214,7 @@ struct Transaction { /// transaction recipient address to: String, /// nonce - count of transaction sent by account - nonce: Option<[u64; 4]>, + nonce: Option, /// chain id of the ledger chain_id: u64, /// transaction payload @@ -242,6 +243,18 @@ enum TransactionType { Write } +struct TransactionEndorsingData { + to: Address, + from: Address, + params: Vec, +} + +impl TransactionEndorsingData { + fn get_signing_bytes(&self) -> VdrResult> { + unimplemented!() + } +} + struct EventQuery { address: Address, from_block: Option, @@ -259,179 +272,605 @@ struct SignatureData { ## Contracts/Requests methods -### DID Document - -#### Create DID +### DID Ethr -```rust -// Probably we do no even need it -struct BuildTxnOptions {} -``` +#### Writes ```rust -/// Prepare transaction executing `IndyDidRegistry.createDid` smart contract method to create a new DID on the Ledger +/// Change owner of ethr DID /// /// #Params -/// param: client: LedgerClient - Ledger client +/// param: client: Ledger - client (Ethereum client - for example web3::Http) /// param: from: string - sender account address -/// param: did_document: DidDocument - DID Document matching to the specification: https://www.w3.org/TR/did-core/ -/// param: options: Option - (Optional) extra data required for transaction preparation +/// param: did: string - DID to change ownership +/// param: new_owner: string - account address of new owner /// /// #Returns /// transaction: Transaction - prepared transaction object -fn indy_vdr_build_create_did_transaction( - client: LedgerClient, - from: String, - did_document: DidDoc, - options: Option, -) -> Transaction { - unimplemented!(); -} -``` +pub async fn build_did_change_owner_transaction( + client: &LedgerClient, + from: &Address, + did: &DID, + new_owner: &Address, +) -> VdrResult; -#### Update DID +/// Prepared data for endorsing EthereumExtDidRegistry.changeOwner contract method +/// +/// #Params +/// - `client` client connected to the network where contract will be executed +/// - `did` DID to change ownership +/// - `new_owner` account address of new owner +/// +/// #Returns +/// data: TransactionEndorsingData - transaction endorsement data to sign +pub async fn build_did_change_owner_endorsing_data( + client: &LedgerClient, + did: &DID, + new_owner: &Address, +) -> VdrResult; -```rust -/// Prepare transaction executing `IndyDidRegistry.updateDid` smart contract method to update an existing DID Document +/// Build transaction to execute EthereumExtDidRegistry.changeOwnerSigned contract method to +/// change the owner of ether DID +/// Endorsing version of the method - sender is not identity owner /// /// #Params -/// param: client: LedgerClient - Ledger client +/// - `client` client connected to the network where contract will be executed +/// - `sender` sender account address +/// - `did` DID to change ownership +/// - `new_owner` account address of new owner +/// - `signature` signature of DID identity owner +/// +/// #Returns +/// transaction: Transaction - prepared write transaction object to sign and submit +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_document: DidDocument - DID Document matching to the specification: https://www.w3.org/TR/did-core/ -/// param: options: Option - (Optional) extra data required for transaction preparation +/// 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 -fn indy_vdr_build_update_did_transaction( - client: LedgerClient, - from: String, - did_document: DidDoc, - options: Option, -) -> Transaction; -``` +pub async fn build_did_add_delegate_transaction( + client: &LedgerClient, + from: &Address, + did: &DID, + delegate_type: &DelegateType, + delegate: &Address, + validity: &Validity, +) -> VdrResult; -#### Deactivate DID +/// Prepared data for endorsing EthereumExtDidRegistry.addDelegate contract method +/// +/// #Params +/// - `client` client connected to the network where contract will be executed +/// - `did` DID to add a delegate +/// - `delegate_type` type of delegation (`veriKey` or `sigAuth`) +/// - `delegate` account address of delegate +/// - `validity` delegate validity time +/// +/// #Returns +/// data: TransactionEndorsingData - transaction endorsement data to sign +pub async fn build_did_add_delegate_endorsing_data( + client: &LedgerClient, + did: &DID, + delegate_type: &DelegateType, + delegate: &Address, + validity: &Validity, +) -> VdrResult; + +/// Build transaction to execute EthereumExtDidRegistry.addDelegateSigned contract method to add a delegate. +/// An identity can assign multiple delegates to manage signing on their behalf for specific purposes. +/// +/// Endorsing version of the method - sender is not identity owner +/// +/// #Params +/// - `client` client connected to the network where contract will be executed +/// - `sender` sender account address +/// - `did` DID to add a delegate +/// - `delegate_type` type of delegation (`veriKey` or `sigAuth`) +/// - `delegate` account address of delegate +/// - `validity` delegate validity time +/// - `signature` signature of DID identity owner +/// +/// #Returns +/// transaction: Transaction - prepared write transaction object to sign and submit +pub async fn build_did_add_delegate_signed_transaction( + client: &LedgerClient, + sender: &Address, + did: &DID, + delegate_type: &DelegateType, + delegate: &Address, + validity: &Validity, + signature: &SignatureData, +) -> VdrResult; -```rust -/// Prepare transaction executing `IndyDidRegistry.deactivateDid` smart contract method to deactivate an existing DID +/// Build transaction to execute EthereumExtDidRegistry.revokeDelegate contract method to revoke a delegate. +/// An identity can assign multiple delegates to manage signing on their behalf for specific purposes. /// /// #Params -/// param: client: LedgerClient - Ledger client -/// param: from: string - sender account address -/// param: did: string - did to deactivate -/// param: options: Option - (Optional) extra data required for transaction preparation +/// - `client` client connected to the network where contract will be executed +/// - `sender` sender account address (Must be DID owner) +/// - `did` DID to revoke a delegate +/// - `delegate_type` type of delegation (`veriKey` or `sigAuth`) +/// - `delegate` account address of delegate /// /// #Returns -/// transaction: Transaction - prepared transaction object -fn indy_vdr_build_deactivate_did_transaction( - client: LedgerClient, - from: String, - did: String, - options: Option, -) -> Transaction; -``` +/// transaction: Transaction - prepared write transaction object to sign and submit +pub async fn build_did_revoke_delegate_transaction( + client: &LedgerClient, + sender: &Address, + did: &DID, + delegate_type: &DelegateType, + delegate: &Address, +) -> VdrResult; -#### Resolve DID +/// Prepared data for endorsing EthereumExtDidRegistry.revokeDelegate contract method +/// +/// #Params +/// - `client` client connected to the network where contract will be executed +/// - `did` DID to add a delegate +/// - `delegate_type` type of delegation (`veriKey` or `sigAuth`) +/// - `delegate` account address of delegate +/// +/// #Returns +/// data: TransactionEndorsingData - transaction endorsement data to sign +pub async fn build_did_revoke_delegate_endorsing_data( + client: &LedgerClient, + did: &DID, + delegate_type: &DelegateType, + delegate: &Address, +) -> VdrResult; + +/// Build transaction to execute EthereumExtDidRegistry.revokeDelegateSigned contract method to revoke a delegate. +/// An identity can assign multiple delegates to manage signing on their behalf for specific purposes. +/// +/// Endorsing version of the method - sender is not identity owner +/// +/// #Params +/// - `client` client connected to the network where contract will be executed +/// - `sender` sender account address +/// - `did` DID to revoke a delegate +/// - `delegate_type` type of delegation (`veriKey` or `sigAuth`) +/// - `delegate` account address of delegate +/// - `signature` signature of DID identity owner +/// +/// #Returns +/// transaction: Transaction - prepared write transaction object to sign and submit +pub async fn build_did_revoke_delegate_signed_transaction( + client: &LedgerClient, + sender: &Address, + did: &DID, + delegate_type: &DelegateType, + delegate: &Address, + signature: &SignatureData, +) -> VdrResult; -```rust -/// Prepare transaction executing `IndyDidRegistry.resolveDid` smart contract method to resolve a DID +/// Build transaction to execute EthereumExtDidRegistry.setAttribute contract method to add +/// a non ledger DID associated attribute. +/// An identity may need to publish some information that is only needed off-chain but +/// still requires the security benefits of using a blockchain. /// /// #Params -/// param: client: Ledger - client (Ethereum client - for example web3::Http) -/// param: did - DID to resolve -/// param: options: Option - (Optional) extra data required for transaction preparation +/// - `client` client connected to the network where contract will be executed +/// - `sender` sender account address (Must be DID owner) +/// - `did` DID to add an attribute +/// - `attribute` attribute to add +/// - `validity` attribute validity time /// /// #Returns -/// transaction: Transaction - prepared transaction object -fn indy_vdr_build_resolve_did_transaction( - client: LedgerClient, - did: String, - options: Option, -) -> Transaction; +/// transaction: Transaction - prepared write transaction object to sign and submit +pub async fn build_did_set_attribute_transaction( + client: &LedgerClient, + sender: &Address, + did: &DID, + attribute: &DidDocAttribute, + validity: &Validity, +) -> VdrResult; + +/// Prepared data for endorsing EthereumExtDidRegistry.setAttribute contract method +/// +/// #Params +/// - `client` client connected to the network where contract will be executed +/// - `did` DID to add an attribute +/// - `attribute` attribute to add +/// - `validity` attribute validity time +/// +/// #Returns +/// transaction: Transaction - prepared write transaction object to sign and submit +pub async fn build_did_set_attribute_endorsing_data( + client: &LedgerClient, + did: &DID, + attribute: &DidDocAttribute, + validity: &Validity, +) -> VdrResult; + +/// Build transaction to execute EthereumExtDidRegistry.setAttributeSigned contract method to add +/// a non ledger DID associated attribute. +/// An identity may need to publish some information that is only needed off-chain but +/// still requires the security benefits of using a blockchain. +/// +/// Endorsing version of the method - sender is not identity owner +/// +/// #Params +/// - `client` client connected to the network where contract will be executed +/// - `sender` sender account address +/// - `did` DID to add an attribute +/// - `attribute` attribute to add +/// - `validity` attribute validity time +/// - `signature` signature of DID identity owner +/// +/// #Returns +/// transaction: Transaction - prepared write transaction object to sign and submit +pub async fn build_did_set_attribute_signed_transaction( + client: &LedgerClient, + sender: &Address, + did: &DID, + attribute: &DidDocAttribute, + validity: &Validity, + signature: &SignatureData, +) -> VdrResult; + +/// Build transaction to execute EthereumExtDidRegistry.revokeAttribute contract method to revoke +/// a non ledger DID associated attribute. +/// An identity may need to publish some information that is only needed off-chain but +/// still requires the security benefits of using a blockchain. +/// +/// #Params +/// - `client` client connected to the network where contract will be executed +/// - `sender` sender account address (Must be DID owner) +/// - `did` DID to revoke an attribute +/// - `attribute` attribute to add +/// +/// #Returns +/// transaction: Transaction - prepared write transaction object to sign and submit +pub async fn build_did_revoke_attribute_transaction( + client: &LedgerClient, + sender: &Address, + did: &DID, + attribute: &DidDocAttribute, +) -> VdrResult; + +/// Prepared data for endorsing EthereumExtDidRegistry.revokeAttribute contract method +/// +/// #Params +/// - `client` client connected to the network where contract will be executed +/// - `did` DID to add an attribute +/// - `attribute` attribute to add +/// +/// #Returns +/// transaction: Transaction - prepared write transaction object to sign and submit +pub async fn build_did_revoke_attribute_endorsing_data( + client: &LedgerClient, + did: &DID, + attribute: &DidDocAttribute, +) -> VdrResult; + +/// Build transaction to execute EthereumExtDidRegistry.revokeAttributeSigned contract method to revoke +/// a non ledger DID associated attribute. +/// An identity may need to publish some information that is only needed off-chain but +/// still requires the security benefits of using a blockchain. +/// +/// Endorsing version of the method - sender is not identity owner +/// +/// #Params +/// - `client` client connected to the network where contract will be executed +/// - `sender` sender account address +/// - `did` DID to revoke an attribute +/// - `attribute` attribute to add +/// - `signature` signature of DID identity owner +/// +/// #Returns +/// transaction: Transaction - prepared write transaction object to sign and submit +pub async fn build_did_revoke_attribute_signed_transaction( + client: &LedgerClient, + sender: &Address, + did: &DID, + attribute: &DidDocAttribute, + signature: &SignatureData, +) -> VdrResult; ``` +#### Resolve + ```rust -/// Parse response for of `IndyDidRegistry.resolveDid` smart contract +/// Build transaction to execute EthereumExtDidRegistry.owners contract method to get +/// an account address owning the DID. /// /// #Params -/// param: client: Ledger - client (Ethereum client - for example web3::Http) -/// param: response: bytes - received response +/// - `client` client connected to the network where contract will be executed +/// - `did` target DID /// /// #Returns -/// transaction: Transaction - prepared transaction object -fn indy_vdr_parse_resolve_did_response( - client: LedgerClient, - response: bytes, -) -> DidDocumentWithMeta; +/// transaction: Transaction - prepared read transaction object to submit +pub async fn build_get_did_owner_transaction( + client: &LedgerClient, + did: &DID, +) -> VdrResult; + +/// Build transaction to execute EthereumExtDidRegistry.changed contract method to get +/// block number when DID was changed last time +/// +/// #Params +/// - `client` client connected to the network where contract will be executed +/// - `did` target DID +/// +/// #Returns +/// transaction: Transaction - prepared read transaction object to submit +pub async fn build_get_did_changed_transaction( + client: &LedgerClient, + did: &DID, +) -> VdrResult; + +/// Build transaction to execute EthereumExtDidRegistry.nonce contract method to get signing +/// nonce needed for endorsement +/// +/// #Params +/// - `client` client connected to the network where contract will be executed +/// - `did` target DID +/// +/// #Returns +/// transaction: Transaction - prepared read transaction object to submit +pub async fn build_get_identity_nonce_transaction( + client: &LedgerClient, + identity: &Address, +) -> VdrResult; + +/// Build event query to obtain log DID associated events from the ledger +/// +/// #Params +/// - `client` client connected to the network where contract will be executed +/// - `did` target DID +/// - `from_block` start block +/// - `to_block` finish block +/// +/// #Returns +/// query: EventQuery - prepared event query to send +pub async fn build_get_did_events_query( + client: &LedgerClient, + did: &DID, + from_block: Option<&Block>, + to_block: Option<&Block>, +) -> VdrResult + +/// Parse the result of execution EthereumExtDidRegistry.changed contract method to receive +/// a block number when DID was changed last time +/// +/// # Params +/// - `client` client connected to the network where contract will be executed +/// - `bytes` result bytes returned from the ledger +/// +/// # Returns +/// Block number +pub fn parse_did_changed_result(client: &LedgerClient, bytes: &[u8]) -> VdrResult; + +/// Parse the result of execution EthereumExtDidRegistry.owners contract method to receive +/// an account address owning the DID. +/// +/// # Params +/// - `client` client connected to the network where contract will be executed +/// - `bytes` result bytes returned from the ledger +/// +/// # Returns +/// Owner account address +pub fn parse_did_owner_result(client: &LedgerClient, bytes: &[u8]) -> VdrResult

    ; + +/// Parse the result of execution EthereumExtDidRegistry.nonce contract method to receive +/// a signing nonce needed for endorsement +/// +/// # Params +/// - `client` client connected to the network where contract will be executed +/// - `bytes` result bytes returned from the ledger +/// +/// # Returns +/// Nonce to use for endorsing +pub fn parse_did_nonce_result(client: &LedgerClient, bytes: &[u8]) -> VdrResult; + +/// Parse DidAttributeChangedEvent 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 DidAttributeChanged event object +pub fn parse_did_attribute_changed_event_response( + client: &LedgerClient, + log: &EventLog, +) -> VdrResult; + +/// Parse DidDelegateChangedEvent 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 DidDelegateChanged event object +pub fn parse_did_delegate_changed_event_response( + client: &LedgerClient, + log: &EventLog, +) -> VdrResult; + +/// Parse DidOwnerChangedEvent 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 DidOwnerChanged event object +pub fn parse_did_owner_changed_event_response( + client: &LedgerClient, + log: &EventLog, +) -> VdrResult; + +/// Parse DID associated event from the event log (it can be one of: DidAttributeChanged, DidDelegateChanged, DidOwnerChanged). +/// +/// # Params +/// - `client` client connected to the network where contract will be executed +/// - `bytes` result bytes returned from the ledger +/// +/// # Returns +/// Parsed DID event object +pub fn parse_did_event_response(client: &LedgerClient, event: &EventLog) -> VdrResult; + +/// 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 +pub async fn resolve_did( + client: &LedgerClient, + did: &DID, + options: Option<&DidResolutionOptions>, +) -> VdrResult ``` + ### Schema #### Create Schema ```rust -/// Prepare transaction executing SchemaRegistry.createSchema smart contract method +/// 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 +/// 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 -/// param: client: Ledger - client (Ethereum client - for example web3::Http) -/// param: from: string - sender account address -/// param: schema - Schema object matching to the specification - https://hyperledger.github.io/anoncreds-spec/#term:schema -/// param: options: Option - (Optional) extra data required for transaction preparation +/// - `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 -/// transaction: Transaction - prepared transaction object -fn indy_vdr_build_create_schema_transaction( - client: LedgerClient, - from: String, - schema: Schema, -) -> Transaction; +/// 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 ``` #### Resolve Schema ```rust -/// Prepare transaction executing `SchemaRegistry.resolveSchema` smart contract method +/// Build transaction to execute SchemaRegistry.schemasCreated contract method to get +/// block number when Schema was created /// /// #Params -/// param: client: Ledger - client (Ethereum client - for example web3::Http) -/// param: id - id of Schema to resolve +/// - `client` client connected to the network where contract will be executed +/// - `id` identifier of target schema /// /// #Returns -/// transaction: Transaction - prepared transaction object -fn indy_vdr_build_resolve_schema_transaction( - client: LedgerClient, - id: String, -) -> Transaction; -``` +/// transaction: Transaction - prepared read transaction object to submit +pub async fn build_get_schema_created_transaction( + client: &LedgerClient, + id: &SchemaId, +) -> VdrResult; -```rust -/// Parse response for of `SchemaRegistry.resolveSchema` smart contract +/// Build event query to get SchemaRegistry.SchemaCreated event from the ledger /// /// #Params -/// param: client: Ledger - client (Ethereum client - for example web3::Http) -/// param: response: bytes - received response bytes +/// - `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 -/// transaction: Transaction - prepared transaction object -fn indy_vdr_parse_resolve_schema_response( - client: LedgerClient, - response: bytes, -) -> SchemaWithMeta; +/// 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 ``` ```rust -/// Single step function to resolve schema from the ledger +/// Parse the result of execution SchemaRegistry.schemas contract method to receive +/// block number when a schema was created /// -/// #Params -/// param: client: Ledger - client (Ethereum client - for example web3::Http) -/// param: id - id of Schema to resolve +/// # Params +/// - `client` client connected to the network where contract will be executed +/// - `bytes` result bytes returned from the ledger /// -/// #Returns -/// transaction: Transaction - prepared transaction object -fn indy_vdr_resolve_schema( - client: LedgerClient, - id: String, -) -> Schema; +/// # 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. +/// +/// # Params +/// - `client` client connected to the network where contract will be executed +/// - `bytes` result bytes returned from the ledger +/// +/// # Returns +/// Parsed Schema object +pub fn parse_schema_created_event(client: &LedgerClient, log: &EventLog) -> VdrResult +``` + +```rust +/// Single step function to resolve a Schema for the given ID +/// +/// # Params +/// - `client` client connected to the network where contract will be executed +/// - `id` id of schema to resolve +/// +/// # Returns +/// Resolved Schema object +pub async fn resolve_schema(client: &LedgerClient, id: &SchemaId) -> VdrResult; ``` ### Credential Definition @@ -439,71 +878,128 @@ fn indy_vdr_resolve_schema( #### Create Credential Definition ```rust -/// Prepare transaction executing CredentialDefinitionRegistry.createCredentialDefinition smart contract method +/// Build transaction to execute CredentialDefinitionRegistry.createCredentialDefinition contract +/// method to create a new Credential Definition +/// +/// # 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 +/// Write transaction to sign and submit +pub async fn build_create_credential_definition_transaction( + client: &LedgerClient, + from: &Address, + id: &CredentialDefinitionId, + credential_definition: &CredentialDefinition, +) -> VdrResult; + +/// Prepared data for endorsing CredentialDefinitionRegistry.createCredentialDefinition contract method /// /// #Params -/// 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 +/// - `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 -/// transaction: Transaction - prepared transaction object -fn indy_vdr_build_create_credential_definition_transaction( - client: LedgerClient, - from: String, - cred_def: CredentialDefinition, - options: Option, -) -> Transaction; +/// 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 +/// +/// #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 +/// +/// #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 ``` #### Resolve Credential DefinitionCredential Definition ```rust -/// Prepare transaction executing CredentialDefinitionRegistry.resolveCredentialDefinition smart contract method +/// Build transaction to execute CredentialDefinitionRegistry.credDefs contract method to get +/// block number when a Credential Definition was created /// /// #Params -/// 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 +/// - `client` client connected to the network where contract will be executed +/// - `id` identifier of target credential definition /// /// #Returns -/// transaction: Transaction - prepared transaction object -fn indy_vdr_build_resolve_credential_definition_transaction( - client: LedgerClient, - id: String, - options: Option, -) -> Transaction; -``` +/// transaction: Transaction - prepared read transaction object to submit +pub async fn build_get_credential_definition_created_transaction( + client: &LedgerClient, + id: &CredentialDefinitionId, +) -> VdrResult; -```rust -/// Parse response for of `CredentialDefinitionRegistry.resolveCredentialDefinition` smart contract +/// Build event query to get CredentialDefinitionRegistry.CredentialDefinitionCreated event from the ledger /// /// #Params -/// param: client: Ledger - client (Ethereum client - for example web3::Http) -/// param: response: bytes - received response bytes +/// - `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 -/// transaction: Transaction - prepared transaction object -fn indy_vdr_parse_resolve_credential_definition_response( - client: LedgerClient, - response: bytes, -) -> CredentialDefinitionWithMeta; +/// 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 ``` ```rust -/// Single step function to resolve credential definition from the ledger +/// Parse the result of execution CredentialDefinitionRegistry.credDefs contract method to receive +/// block number when a credential definition was created /// -/// #Params -/// param: client: Ledger - client (Ethereum client - for example web3::Http) -/// param: id - id of Credential Definition to resolve +/// # Params +/// - `client` client connected to the network where contract will be executed +/// - `bytes` result bytes returned from the ledger /// -/// #Returns -/// transaction: Transaction - prepared transaction object -fn indy_vdr_resolve_credential_definition( - client: LedgerClient, - id: String, -) -> CredentialDefinition; +/// # 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 +/// +/// # Returns +/// Parsed Credential Definition event object +pub fn parse_credential_definition_created_event(client: &LedgerClient, log: &EventLog) -> VdrResult +``` + +```rust +/// 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 +/// +/// # Returns +/// Resolved Credential Definition object +pub async fn resolve_credential_definition(client: &LedgerClient, id: &CredentialDefinitionId) -> VdrResult; ``` ### Auth @@ -669,218 +1165,3 @@ 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/migrtion/migration.md b/docs/migrtion/migration.md index d958dc08..054a0edd 100644 --- a/docs/migrtion/migration.md +++ b/docs/migrtion/migration.md @@ -4,20 +4,18 @@ This document contains a plan of attack for migration of customers using Indy/So ## Ledger migration -All Issuers need to run migration by itself to move their data (DID Document, Schema, Credential Definition) to Besu -ledger. +All Issuers need to run migration by itself to move their data (DID Document, Schema, Credential Definition) to Besu ledger. ## 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: - +This section provides example steps demonstrating the process of migration for applications using Indy ledger to Besu Ledger. +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 @@ -37,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 ``` { @@ -77,59 +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. +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 + * 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: @@ -137,12 +127,12 @@ tool manually (on the machine containing Indy Wallet storing Credential Definiti 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", @@ -184,7 +174,7 @@ tool manually (on the machine containing Indy Wallet storing Credential Definiti 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", @@ -228,9 +218,8 @@ 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 - 2. Holder resolve Credential Definition from Besu Ledger (VDR converts indy cred definition id representation - into Besu form) + * 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); let cred_def = CredentialDefinitionRegistry::resolve_credential_definition(&client, id).await @@ -243,9 +232,8 @@ 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 - 2. Holder resolve Credential Definition from Besu Ledger (VDR converts indy cred definition id representation - into Besu form) + * 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); let cred_def = CredentialDefinitionRegistry::resolve_credential_definition(&client, id).await @@ -253,23 +241,21 @@ Now credential issuance and credential verification flow can run as before but w 3. Verify proof 2. Credential Issuance goes as before but another ledger is used as a verifiable data registry. + ## VDR Backward compatibility * Goal: Plan for getting of backward compatible with [indy-vdr](https://github.com/hyperledger/indy-vdr) * Reason: smoother libraries' integration into existing applications. - * Valuable for arise frameworks which are still not ledger agnostic (indy tied) like Aca-py or Aries-vcx. Such - frameworks will be able to support Ledger 2.0 after simple migration. + * Valuable for arise frameworks which are still not ledger agnostic (indy tied) like Aca-py or Aries-vcx. Such frameworks will be able to support Ledger 2.0 after simple migration. ### DID creation and resolving #### Backward compatible way consisting of two steps - Will be done later! -1. Assemble basic DID Document according to the - steps [here](https://hyperledger.github.io/indy-did-method/#diddoc-assembly-steps). +1. Assemble basic DID Document according to the steps [here](https://hyperledger.github.io/indy-did-method/#diddoc-assembly-steps). > DID Doc will not contain any `service` set. Service will be added by a separate ATTRIB operation. * Publish DID Document using `DidRegistry.createDid(didDocument, signatures)` -2. Assemble basic DID Document containing only `id` and `service`. DID Document itself must be already published using - NYM operation. +2. Assemble basic DID Document containing only `id` and `service`. DID Document itself must be already published using NYM operation. * Update existing DID Document using `DidRegistry.updateDid(didDocument, signatures)` > In fact, it's not really backward compatible as we require passing of additional signature for nym and attrib diff --git a/network/config/besu/genesis.json b/network/config/besu/genesis.json index 451a7931..9ffdbb7f 100644 --- a/network/config/besu/genesis.json +++ b/network/config/besu/genesis.json @@ -130,13 +130,13 @@ "149d22bf3f008a1407770ecbdb723975d92c5073caa510ba413c1db0f8063ed8": "0000000000000000000000886328869e4e1f401e1052a5f4aae8b45f42610201", "7f33ce678224e207038746a5939df116c5dff1ccc6e79de84c95388c521e898c": "000000000000000000000f48de4a0c2939e62891f3c6aca68982975477e45301", "f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00": "0x0000000000000000000000000000000000000000000000000000000000000001", - "360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000000000000000000000009dcd5a827215e8574997bf3cca972e3a7cc0452c" + "360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x00000000000000000000000066bba756037fac0d44ccf9d087c6a83ea2352997" } }, - "0x9dcd5a827215e8574997bf3cca972e3a7cc0452c": { + "0x66bba756037fac0d44ccf9d087c6a83ea2352997": { "comment": "Implementation: Smart contract to manage validator nodes", "balance": "0", - "code": "0x6080604052600436106100705760003560e01c806352d1902d1161004e57806352d1902d146100ca57806398772d88146100f2578063ad3cb1cc14610112578063b7ab4db51461015057600080fd5b806340a141ff146100755780634d238c8e146100975780634f1ef286146100b7575b600080fd5b34801561008157600080fd5b50610095610090366004610eff565b610172565b005b3480156100a357600080fd5b506100956100b2366004610eff565b610430565b6100956100c5366004610f8a565b610718565b3480156100d657600080fd5b506100df610737565b6040519081526020015b60405180910390f35b3480156100fe57600080fd5b5061009561010d366004611030565b610754565b34801561011e57600080fd5b50610143604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100e99190611151565b34801561015c57600080fd5b50610165610a1c565b6040516100e99190611184565b600154604051634f4bdc7b60e11b81526001600160a01b0390911690639e97b8f6906101a59060039033906004016111d1565b602060405180830381865afa1580156101c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101e6919061120b565b61020a5760405163472511eb60e11b81523360048201526024015b60405180910390fd5b806001600160a01b0381166102325760405163713ce51160e01b815260040160405180910390fd5b6002546001036102555760405163f1a1929360e01b815260040160405180910390fd5b6001600160a01b03828116600090815260036020908152604091829020825180840190935254928316808352600160a01b90930460ff1690820152906102b957604051635a4887e160e01b81526001600160a01b0384166004820152602401610201565b600081602001519050600060028260ff16815481106102da576102da61122d565b6000918252602082200154600280546001600160a01b0390921693509061030390600190611243565b815481106103135761031361122d565b600091825260209091200154600280546001600160a01b039092169250829160ff86169081106103455761034561122d565b600091825260208083209190910180546001600160a01b0319166001600160a01b039485161790559183168152600390915260409020805460ff60a01b1916600160a01b60ff86160217905560028054806103a2576103a2611264565b60008281526020808220600019908401810180546001600160a01b03191690559092019092556001600160a01b0384168083526003825260409283902080546001600160a81b0319169055600254925160ff9093168352339290917fb10fc4fba5b5eb2a6e82796887299220653537d6a5fc8a3fb60937bd2442ea29910160405180910390a3505050505050565b600154604051634f4bdc7b60e11b81526001600160a01b0390911690639e97b8f6906104639060039033906004016111d1565b602060405180830381865afa158015610480573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a4919061120b565b6104c35760405163472511eb60e11b8152336004820152602401610201565b806001600160a01b0381166104eb5760405163713ce51160e01b815260040160405180910390fd5b6002546101001161051357604051635dd7a94360e11b81526101006004820152602401610201565b60025460005b8160ff168160ff16101561063f5760006003600060028460ff16815481106105435761054361122d565b60009182526020808320909101546001600160a01b039081168452838201949094526040928301909120825180840190935254928316825260ff600160a01b909304831690820152600280549193509184169081106105a4576105a461122d565b6000918252602090912001546001600160a01b039081169086160361060a5760028260ff16815481106105d9576105d961122d565b60009182526020909120015460405163164688df60e21b81526001600160a01b039091166004820152602401610201565b80516001600160a01b0316330361063657604051635154e66760e11b8152336004820152602401610201565b50600101610519565b506040805180820182523380825260ff84811660208085019182526001600160a01b038981166000818152600384528881209751885495518716600160a01b026001600160a81b03199096169316929092179390931790955560028054600181018255958190527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace90950180546001600160a01b0319168317905593549451949091168452909290917f4583e1f70afe5f9f38886187732a4b1336bad46fc758cdd6ad86815931d6f6c2910160405180910390a3505050565b610720610a7e565b61072982610b25565b6107338282610b8b565b5050565b6000610741610c4d565b506000805160206112b083398151915290565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460019190600160401b900460ff168061079e5750805467ffffffffffffffff808416911610155b156107bc5760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff191667ffffffffffffffff831617600160401b178155825160000361080057604051635a7582eb60e11b815260040160405180910390fd5b82516101001161082757604051635dd7a94360e11b81526101006004820152602401610201565b60005b83518110156109a35760006001600160a01b03168482815181106108505761085061122d565b6020026020010151602001516001600160a01b0316036108835760405163d4c3bd5160e01b815260040160405180910390fd5b60006001600160a01b03168482815181106108a0576108a061122d565b6020026020010151600001516001600160a01b0316036108d35760405163713ce51160e01b815260040160405180910390fd5b60008482815181106108e7576108e761122d565b6020908102919091018101518051600280546001818101835560009283527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace90910180546001600160a01b039485166001600160a01b0319909116179055604080518082018252858701518516815260ff808a1682890190815296518616855260039097529220915182549451909516600160a01b026001600160a81b031990941694909216939093179190911790915591909101905061082a565b50600180546001600160a01b0319166001600160a01b0387161790556109c884610c96565b805468ff00000000000000001916815560405167ffffffffffffffff831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15050505050565b60606002805480602002602001604051908101604052809291908181526020018280548015610a7457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a56575b5050505050905090565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480610b0557507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610af96000805160206112b0833981519152546001600160a01b031690565b6001600160a01b031614155b15610b235760405163703e46dd60e11b815260040160405180910390fd5b565b60005460405163574a81d760e01b81523060048201526001600160a01b0383811660248301529091169063574a81d79060440160006040518083038186803b158015610b7057600080fd5b505afa158015610b84573d6000803e3d6000fd5b5050505050565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610be5575060408051601f3d908101601f19168201909252610be29181019061127a565b60015b610c0d57604051634c9c8ce360e01b81526001600160a01b0383166004820152602401610201565b6000805160206112b08339815191528114610c3e57604051632a87526960e21b815260048101829052602401610201565b610c488383610cc0565b505050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b235760405163703e46dd60e11b815260040160405180910390fd5b610c9e610d16565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b610cc982610d5f565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115610d0e57610c488282610dc4565b610733610e3c565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16610b2357604051631afcd79f60e31b815260040160405180910390fd5b806001600160a01b03163b600003610d9557604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610201565b6000805160206112b083398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b031684604051610de19190611293565b600060405180830381855af49150503d8060008114610e1c576040519150601f19603f3d011682016040523d82523d6000602084013e610e21565b606091505b5091509150610e31858383610e5b565b925050505b92915050565b3415610b235760405163b398979f60e01b815260040160405180910390fd5b606082610e7057610e6b82610eba565b610eb3565b8151158015610e8757506001600160a01b0384163b155b15610eb057604051639996b31560e01b81526001600160a01b0385166004820152602401610201565b50805b9392505050565b805115610eca5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b0381168114610efa57600080fd5b919050565b600060208284031215610f1157600080fd5b610eb382610ee3565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610f5357610f53610f1a565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715610f8257610f82610f1a565b604052919050565b60008060408385031215610f9d57600080fd5b610fa683610ee3565b915060208084013567ffffffffffffffff80821115610fc457600080fd5b818601915086601f830112610fd857600080fd5b813581811115610fea57610fea610f1a565b610ffc601f8201601f19168501610f59565b9150808252878482850101111561101257600080fd5b80848401858401376000848284010152508093505050509250929050565b60008060006060848603121561104557600080fd5b61104e84610ee3565b9250602061105d818601610ee3565b925060408086013567ffffffffffffffff8082111561107b57600080fd5b818801915088601f83011261108f57600080fd5b8135818111156110a1576110a1610f1a565b6110af858260051b01610f59565b818152858101925060069190911b83018501908a8211156110cf57600080fd5b928501925b8184101561111d5784848c0312156110ec5760008081fd5b6110f4610f30565b6110fd85610ee3565b815261110a878601610ee3565b81880152835292840192918501916110d4565b8096505050505050509250925092565b60005b83811015611148578181015183820152602001611130565b50506000910152565b602081526000825180602084015261117081604085016020870161112d565b601f01601f19169190910160400192915050565b6020808252825182820181905260009190848201906040850190845b818110156111c55783516001600160a01b0316835292840192918401916001016111a0565b50909695505050505050565b60408101600484106111f357634e487b7160e01b600052602160045260246000fd5b9281526001600160a01b039190911660209091015290565b60006020828403121561121d57600080fd5b81518015158114610eb357600080fd5b634e487b7160e01b600052603260045260246000fd5b81810381811115610e3657634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60006020828403121561128c57600080fd5b5051919050565b600082516112a581846020870161112d565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca2646970667358221220f4e19c76a78d7b12cf85e17f1072e4b266e08fd0d61e2f2b85c7ad8cebdad22164736f6c63430008170033" + "code": "0x6080604052600436106100705760003560e01c806352d1902d1161004e57806352d1902d146100ca57806398772d88146100f2578063ad3cb1cc14610112578063b7ab4db51461015057600080fd5b806340a141ff146100755780634d238c8e146100975780634f1ef286146100b7575b600080fd5b34801561008157600080fd5b50610095610090366004610eff565b610172565b005b3480156100a357600080fd5b506100956100b2366004610eff565b610430565b6100956100c5366004610f8a565b610718565b3480156100d657600080fd5b506100df610737565b6040519081526020015b60405180910390f35b3480156100fe57600080fd5b5061009561010d366004611030565b610754565b34801561011e57600080fd5b50610143604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100e99190611151565b34801561015c57600080fd5b50610165610a1c565b6040516100e99190611184565b600154604051634f4bdc7b60e11b81526001600160a01b0390911690639e97b8f6906101a59060039033906004016111d1565b602060405180830381865afa1580156101c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101e6919061120b565b61020a5760405163472511eb60e11b81523360048201526024015b60405180910390fd5b806001600160a01b0381166102325760405163713ce51160e01b815260040160405180910390fd5b6002546001036102555760405163f1a1929360e01b815260040160405180910390fd5b6001600160a01b03828116600090815260036020908152604091829020825180840190935254928316808352600160a01b90930460ff1690820152906102b957604051635a4887e160e01b81526001600160a01b0384166004820152602401610201565b600081602001519050600060028260ff16815481106102da576102da61122d565b6000918252602082200154600280546001600160a01b0390921693509061030390600190611243565b815481106103135761031361122d565b600091825260209091200154600280546001600160a01b039092169250829160ff86169081106103455761034561122d565b600091825260208083209190910180546001600160a01b0319166001600160a01b039485161790559183168152600390915260409020805460ff60a01b1916600160a01b60ff86160217905560028054806103a2576103a2611264565b60008281526020808220600019908401810180546001600160a01b03191690559092019092556001600160a01b0384168083526003825260409283902080546001600160a81b0319169055600254925160ff9093168352339290917fb10fc4fba5b5eb2a6e82796887299220653537d6a5fc8a3fb60937bd2442ea29910160405180910390a3505050505050565b600154604051634f4bdc7b60e11b81526001600160a01b0390911690639e97b8f6906104639060039033906004016111d1565b602060405180830381865afa158015610480573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a4919061120b565b6104c35760405163472511eb60e11b8152336004820152602401610201565b806001600160a01b0381166104eb5760405163713ce51160e01b815260040160405180910390fd5b6002546101001161051357604051635dd7a94360e11b81526101006004820152602401610201565b60025460005b8160ff168160ff16101561063f5760006003600060028460ff16815481106105435761054361122d565b60009182526020808320909101546001600160a01b039081168452838201949094526040928301909120825180840190935254928316825260ff600160a01b909304831690820152600280549193509184169081106105a4576105a461122d565b6000918252602090912001546001600160a01b039081169086160361060a5760028260ff16815481106105d9576105d961122d565b60009182526020909120015460405163164688df60e21b81526001600160a01b039091166004820152602401610201565b80516001600160a01b0316330361063657604051635154e66760e11b8152336004820152602401610201565b50600101610519565b506040805180820182523380825260ff84811660208085019182526001600160a01b038981166000818152600384528881209751885495518716600160a01b026001600160a81b03199096169316929092179390931790955560028054600181018255958190527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace90950180546001600160a01b0319168317905593549451949091168452909290917f4583e1f70afe5f9f38886187732a4b1336bad46fc758cdd6ad86815931d6f6c2910160405180910390a3505050565b610720610a7e565b61072982610b25565b6107338282610b8b565b5050565b6000610741610c4d565b506000805160206112b083398151915290565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460019190600160401b900460ff168061079e5750805467ffffffffffffffff808416911610155b156107bc5760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff191667ffffffffffffffff831617600160401b178155825160000361080057604051635a7582eb60e11b815260040160405180910390fd5b82516101001161082757604051635dd7a94360e11b81526101006004820152602401610201565b60005b83518110156109a35760006001600160a01b03168482815181106108505761085061122d565b6020026020010151602001516001600160a01b0316036108835760405163d4c3bd5160e01b815260040160405180910390fd5b60006001600160a01b03168482815181106108a0576108a061122d565b6020026020010151600001516001600160a01b0316036108d35760405163713ce51160e01b815260040160405180910390fd5b60008482815181106108e7576108e761122d565b6020908102919091018101518051600280546001818101835560009283527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace90910180546001600160a01b039485166001600160a01b0319909116179055604080518082018252858701518516815260ff808a1682890190815296518616855260039097529220915182549451909516600160a01b026001600160a81b031990941694909216939093179190911790915591909101905061082a565b50600180546001600160a01b0319166001600160a01b0387161790556109c884610c96565b805468ff00000000000000001916815560405167ffffffffffffffff831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15050505050565b60606002805480602002602001604051908101604052809291908181526020018280548015610a7457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a56575b5050505050905090565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480610b0557507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610af96000805160206112b0833981519152546001600160a01b031690565b6001600160a01b031614155b15610b235760405163703e46dd60e11b815260040160405180910390fd5b565b60005460405163574a81d760e01b81523060048201526001600160a01b0383811660248301529091169063574a81d79060440160006040518083038186803b158015610b7057600080fd5b505afa158015610b84573d6000803e3d6000fd5b5050505050565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610be5575060408051601f3d908101601f19168201909252610be29181019061127a565b60015b610c0d57604051634c9c8ce360e01b81526001600160a01b0383166004820152602401610201565b6000805160206112b08339815191528114610c3e57604051632a87526960e21b815260048101829052602401610201565b610c488383610cc0565b505050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b235760405163703e46dd60e11b815260040160405180910390fd5b610c9e610d16565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b610cc982610d5f565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115610d0e57610c488282610dc4565b610733610e3c565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16610b2357604051631afcd79f60e31b815260040160405180910390fd5b806001600160a01b03163b600003610d9557604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610201565b6000805160206112b083398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b031684604051610de19190611293565b600060405180830381855af49150503d8060008114610e1c576040519150601f19603f3d011682016040523d82523d6000602084013e610e21565b606091505b5091509150610e31858383610e5b565b925050505b92915050565b3415610b235760405163b398979f60e01b815260040160405180910390fd5b606082610e7057610e6b82610eba565b610eb3565b8151158015610e8757506001600160a01b0384163b155b15610eb057604051639996b31560e01b81526001600160a01b0385166004820152602401610201565b50805b9392505050565b805115610eca5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b0381168114610efa57600080fd5b919050565b600060208284031215610f1157600080fd5b610eb382610ee3565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610f5357610f53610f1a565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715610f8257610f82610f1a565b604052919050565b60008060408385031215610f9d57600080fd5b610fa683610ee3565b915060208084013567ffffffffffffffff80821115610fc457600080fd5b818601915086601f830112610fd857600080fd5b813581811115610fea57610fea610f1a565b610ffc601f8201601f19168501610f59565b9150808252878482850101111561101257600080fd5b80848401858401376000848284010152508093505050509250929050565b60008060006060848603121561104557600080fd5b61104e84610ee3565b9250602061105d818601610ee3565b925060408086013567ffffffffffffffff8082111561107b57600080fd5b818801915088601f83011261108f57600080fd5b8135818111156110a1576110a1610f1a565b6110af858260051b01610f59565b818152858101925060069190911b83018501908a8211156110cf57600080fd5b928501925b8184101561111d5784848c0312156110ec5760008081fd5b6110f4610f30565b6110fd85610ee3565b815261110a878601610ee3565b81880152835292840192918501916110d4565b8096505050505050509250925092565b60005b83811015611148578181015183820152602001611130565b50506000910152565b602081526000825180602084015261117081604085016020870161112d565b601f01601f19169190910160400192915050565b6020808252825182820181905260009190848201906040850190845b818110156111c55783516001600160a01b0316835292840192918401916001016111a0565b50909695505050505050565b60408101600484106111f357634e487b7160e01b600052602160045260246000fd5b9281526001600160a01b039190911660209091015290565b60006020828403121561121d57600080fd5b81518015158114610eb357600080fd5b634e487b7160e01b600052603260045260246000fd5b81810381811115610e3657634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60006020828403121561128c57600080fd5b5051919050565b600082516112a581846020870161112d565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca2646970667358221220c436072d13fd05c099ab9683ba146fced0068424513a53e1fd87d25d51ebd53c64736f6c63430008170033" }, "0x0000000000000000000000000000000000009999": { "comment": "Proxy: Smart contract to manage proxy contract upgrades", @@ -153,27 +153,6 @@ "balance": "0", "code": "0x6080604052600436106100705760003560e01c80637e5465ba1161004e5780637e5465ba146100d2578063ad3cb1cc146100f2578063c4d66de814610130578063e8f158641461015057600080fd5b80634f1ef2861461007557806352d1902d1461008a578063574a81d7146100b2575b600080fd5b610088610083366004610c59565b610170565b005b34801561009657600080fd5b5061009f61018f565b6040519081526020015b60405180910390f35b3480156100be57600080fd5b506100886100cd366004610d1b565b6101ac565b3480156100de57600080fd5b506100886100ed366004610d1b565b6101d3565b3480156100fe57600080fd5b50610123604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100a99190610d72565b34801561013c57600080fd5b5061008861014b366004610da5565b610475565b34801561015c57600080fd5b5061008861016b366004610d1b565b610565565b610178610791565b61018182610838565b61018b8282610845565b5050565b6000610199610902565b50600080516020610f6083398151915290565b6101b6828261094b565b61018b57604051638af69cf160e01b815260040160405180910390fd5b600054604051634f4bdc7b60e11b81526001600160a01b0390911690639e97b8f690610206906001903390600401610de2565b602060405180830381865afa158015610223573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102479190610e08565b61026b5760405163472511eb60e11b81523360048201526024015b60405180910390fd5b6001600160a01b0380831660009081526001602090815260408083209385168352929052908120600201548391839190036102cc57604051633af3b55760e01b81526001600160a01b03808416600483015282166024820152604401610262565b6001600160a01b0380851660009081526001602090815260408083209387168352928152828220338352905220548490849060ff1615610332576040516316d5788b60e31b81526001600160a01b03808416600483015282166024820152604401610262565b6001600160a01b038087166000908152600160208181526040808420948a16808552858352818520338652808452918520805460ff191685179055845293905291909101805463ffffffff169161038883610e40565b91906101000a81548163ffffffff021916908363ffffffff16021790555050336001600160a01b0316856001600160a01b0316876001600160a01b03167fc42e62d9f6b29d37599fcb472a6f30bc6e8c8d6fbbcb774ac585c02b314bd2ad60405160405180910390a46103fb868661094b565b1561046d576040805163278f794360e11b81526001600160a01b03878116600483015260248201929092526000604482015290871690634f1ef28690606401600060405180830381600087803b15801561045457600080fd5b505af1158015610468573d6000803e3d6000fd5b505050505b505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460019190600160401b900460ff16806104bf5750805467ffffffffffffffff808416911610155b156104dd5760405163f92ee8a960e01b815260040160405180910390fd5b8054600160401b67ffffffffffffffff841668ffffffffffffffffff199092168217178255600080546001600160a01b0319166001600160a01b038616179055815468ff0000000000000000191682556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a1505050565b600054604051634f4bdc7b60e11b81526001600160a01b0390911690639e97b8f690610598906001903390600401610de2565b602060405180830381865afa1580156105b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d99190610e08565b6105f85760405163472511eb60e11b8152336004820152602401610262565b80806001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610653575060408051601f3d908101601f1916820190925261065091810190610e63565b60015b61067b57604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610262565b600080516020610f6083398151915281146106ac57604051632a87526960e21b815260048101829052602401610262565b6001600160a01b03808516600090815260016020908152604080832093871683529290522060020154849084901561070a57604051634cc571cf60e01b81526001600160a01b03808416600483015282166024820152604401610262565b6001600160a01b038681166000818152600160208181526040808420958b16808552959091528083209182018054640100000000600160c01b031916336401000000008102919091179091554260029093019290925551909392917fe33956f8d60ae2b38d9860e46ec9b53d8fb58aa99a9404b1195b7ce35d2941dc91a45050505b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061081857507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661080c600080516020610f60833981519152546001600160a01b031690565b6001600160a01b031614155b156108365760405163703e46dd60e11b815260040160405180910390fd5b565b61084230826101ac565b50565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561089f575060408051601f3d908101601f1916820190925261089c91810190610e63565b60015b6108c757604051634c9c8ce360e01b81526001600160a01b0383166004820152602401610262565b600080516020610f6083398151915281146108f857604051632a87526960e21b815260048101829052602401610262565b61078c8383610a28565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146108365760405163703e46dd60e11b815260040160405180910390fd5b60008054604051636814b8e560e11b815282916001600160a01b03169063d02971ca9061097d90600190600401610e7c565b602060405180830381865afa15801561099a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109be9190610e8a565b6001600160a01b03808616600090815260016020818152604080842094891684529390529181209091015491925063ffffffff90911690610a0a610a03846006610eb0565b600a610a7e565b90508063ffffffff168263ffffffff16101593505050505b92915050565b610a3182610aa8565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115610a765761078c8282610b0d565b61018b610b83565b600081610a8c600185610ed8565b610a969190610ef5565b610aa1906001610f26565b9392505050565b806001600160a01b03163b600003610ade57604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610262565b600080516020610f6083398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b031684604051610b2a9190610f43565b600060405180830381855af49150503d8060008114610b65576040519150601f19603f3d011682016040523d82523d6000602084013e610b6a565b606091505b5091509150610b7a858383610ba2565b95945050505050565b34156108365760405163b398979f60e01b815260040160405180910390fd5b606082610bb757610bb282610bfe565b610aa1565b8151158015610bce57506001600160a01b0384163b155b15610bf757604051639996b31560e01b81526001600160a01b0385166004820152602401610262565b5092915050565b805115610c0e5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b0381168114610c3e57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060408385031215610c6c57600080fd5b610c7583610c27565b9150602083013567ffffffffffffffff80821115610c9257600080fd5b818501915085601f830112610ca657600080fd5b813581811115610cb857610cb8610c43565b604051601f8201601f19908116603f01168101908382118183101715610ce057610ce0610c43565b81604052828152886020848701011115610cf957600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60008060408385031215610d2e57600080fd5b610d3783610c27565b9150610d4560208401610c27565b90509250929050565b60005b83811015610d69578181015183820152602001610d51565b50506000910152565b6020815260008251806020840152610d91816040850160208701610d4e565b601f01601f19169190910160400192915050565b600060208284031215610db757600080fd5b610aa182610c27565b60048110610dde57634e487b7160e01b600052602160045260246000fd5b9052565b60408101610df08285610dc0565b6001600160a01b039290921660209190910152919050565b600060208284031215610e1a57600080fd5b81518015158114610aa157600080fd5b634e487b7160e01b600052601160045260246000fd5b600063ffffffff808316818103610e5957610e59610e2a565b6001019392505050565b600060208284031215610e7557600080fd5b5051919050565b60208101610a228284610dc0565b600060208284031215610e9c57600080fd5b815163ffffffff81168114610aa157600080fd5b63ffffffff818116838216028082169190828114610ed057610ed0610e2a565b505092915050565b63ffffffff828116828216039080821115610bf757610bf7610e2a565b600063ffffffff80841680610f1a57634e487b7160e01b600052601260045260246000fd5b92169190910492915050565b63ffffffff818116838216019080821115610bf757610bf7610e2a565b60008251610f55818460208701610d4e565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca2646970667358221220e2a4e2c158ec7d38443cf09da5dacb8f5d2cef32752a3b7a150d8d9a0a5dc4f264736f6c63430008170033" }, - "0x0000000000000000000000000000000000002222": { - "comment": "Library to validate DID", - "balance": "0", - "code": "0x73000000000000000000000000000000000000000030146080604052600436106100355760003560e01c8063af8b5bbf1461003a575b600080fd5b61004d610048366004610aac565b61004f565b005b600061005a826100d8565b90506100698160000151610223565b6100915781604051631859e3bb60e11b81526004016100889190610b5d565b60405180910390fd5b600061009f82602001515190565b9050806015141580156100b3575080601614155b156100d35782604051631859e3bb60e11b81526004016100889190610b5d565b505050565b604080518082019091526060808252602082015260006100f7836102c3565b9050600061011d604051806040016040528060018152602001601d60f91b8152506102c3565b905060008061012c84846102d4565b95509250905080158061016a575061016861016160405180604001604052806003815260200162191a5960ea1b8152506102c3565b8390610322565b155b1561018a5785604051631859e3bb60e11b81526004016100889190610b5d565b61019484846102d4565b955092509050806101ba5785604051631859e3bb60e11b81526004016100889190610b5d565b60408051808201909152606080825260208201526101d78361032e565b81526040805180820190915260018152601d60f91b6020820152610205906101fe906102c3565b8690610339565b9450610214915084905061032e565b60208201529695505050505050565b60008061022f836102c3565b905061026061025960405180604001604052806004815260200163696e647960e01b8152506102c3565b8290610322565b8061028f575061028f6102596040518060400160405280600581526020016434b7323c9960d91b8152506102c3565b806102bc57506102bc6102596040518060400160405280600381526020016239b7bb60e91b8152506102c3565b9392505050565b60006102ce82610363565b92915050565b60008080806102e38686610377565b905060001981036102ff5760008660009350935093505061031b565b61031386826001600160801b038816610482565b935093509350505b9250925092565b60006102bc83836104ef565b60606102ce82610539565b600080808061034886866105b1565b905060001981036102ff57600080879350935093505061031b565b6000806020830190506102bc8184516106a3565b60006001600160801b03838116908316808303610399576000925050506102ce565b8115806103a557508181115b156103b657600019925050506102ce565b60006103c28660801c90565b905060006103d08660801c90565b905060006103df825160001a90565b90505b60006103ef8487846106af565b9050600019810361040a5760001996505050505050506102ce565b9485900394928301928585111561042b5760001996505050505050506102ce565b84832085852003610457576104408960801c90565b61044a9085610bac565b96505050505050506102ce565b8560010361046f5760001996505050505050506102ce565b60001990950194600190930192506103e2565b6000806000806104928760801c90565b90506001600160801b038716858701818111156104c2576040516365f4e9df60e01b815260040160405180910390fd5b6001996001600160801b03988916608085811b919091179a50928290039098169201901b17949350505050565b60006001600160801b03838116908316811461050f5760009150506102ce565b61053161051c8560801c90565b6105268560801c90565b839081902091201490565b949350505050565b60606001600160801b03821667ffffffffffffffff81111561055d5761055d610a96565b6040519080825280601f01601f191660200182016040528015610587576020820181803683370190505b509050602081016105ab8161059c8560801c90565b6001600160801b038616610777565b50919050565b60006001600160801b038381169083168083036105d3576000925050506102ce565b8115806105df57508181115b156105f057600019925050506102ce565b60006105fc8660801c90565b9050600061060a8660801c90565b9050600061061787610785565b905060001984015b600061062c8588856107ca565b90506000198103610648576000199750505050505050506102ce565b80821115610661576000199750505050505050506102ce565b8584208282038681018890209091036106835797506102ce9650505050505050565b81156106915750955061061f565b600019985050505050505050506102ce565b60006102bc838361087e565b6000602083116106cb576106c484848461088a565b90506102bc565b83601f8416808503820160ff8516600080516020610bce833981519152025b8188101561072c57875181186106ff8161099c565b15610720578489036107138a60208a61088a565b01955050505050506102bc565b602089019850506106ea565b82600003610742576000199450505050506102bc565b61074d82848861088a565b94506000198503610766576000199450505050506102bc565b509190910391909101949350505050565b8083828460045afa50505050565b60006001600160801b0382168082036107b1576040516365f4e9df60e01b815260040160405180910390fd5b6102bc600182036107c28560801c90565b015160001a90565b6000602083116107df576106c48484846109e7565b601f831684840181156108175781900360006107fc8284876109e7565b9050600019811461081557908690030191506102bc9050565b505b60ff8416600080516020610bce833981519152025b8682111561087057601f199091018051909190811861084a8161099c565b1561086a5787830361085e846020896109e7565b019450505050506102bc565b5061082c565b506000199695505050505050565b60006102bc8383610a30565b825160009081602085111561089e57602094505b601285106109295760ff8416600080516020610bce8339815191520282186108ce6001600160801b03821761099c565b6000036109055760109150601a8610610900576108f467ffffffffffffffff821761099c565b60000361090057601891505b610923565b6109176001600160c01b03821761099c565b60000361092357600891505b50610967565b600a85106109675760ff8416600080516020610bce8339815191520282186109596001600160c01b03821761099c565b60000361096557600891505b505b8481101561098f5781811a60ff85168103610986575091506102bc9050565b50600101610967565b5060001995945050505050565b7ffefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeff81019019167f80808080808080808080808080808080808080808080808080808080808080801690565b600060208311156109f757602092505b83515b8315610a24576000199093019280841a60ff84168103610a1e5784925050506102bc565b506109fa565b50600019949350505050565b60006001600160801b03831115610a5a5760405163fee7506f60e01b815260040160405180910390fd5b6001600160801b03821115610a8257604051633b6b098d60e01b815260040160405180910390fd5b506001600160801b031660809190911b1790565b634e487b7160e01b600052604160045260246000fd5b600060208284031215610abe57600080fd5b813567ffffffffffffffff80821115610ad657600080fd5b818401915084601f830112610aea57600080fd5b813581811115610afc57610afc610a96565b604051601f8201601f19908116603f01168101908382118183101715610b2457610b24610a96565b81604052828152876020848701011115610b3d57600080fd5b826020860160208301376000928101602001929092525095945050505050565b60006020808352835180602085015260005b81811015610b8b57858101830151858201604001528201610b6f565b506000604082860101526040601f19601f8301168501019250505092915050565b818103818111156102ce57634e487b7160e01b600052601160045260246000fdfe0101010101010101010101010101010101010101010101010101010101010101a2646970667358221220a1e91916050d75f620d9396a2eb2cffa964cc4e642ae759fe0562362d564634564736f6c63430008170033", - "storage": {} - }, - "0x0000000000000000000000000000000000003333": { - "comment": "Proxy: Smart contract to manage DIDs", - "balance": "0", - "code": "0x6080604052600a600c565b005b60186014601a565b6051565b565b6000604c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e808015606f573d6000f35b3d6000fdfea26469706673582212208de99705f21830b33bf2bd4a57ce70f27ec58ac48b2c88e1c96b59a11978ef8164736f6c63430008170033", - "storage": { - "0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000009999", - "f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00": "0x0000000000000000000000000000000000000000000000000000000000000001", - "360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000c0b9d922716e5a6f1e912d40a956deedfdd1f41a" - } - }, - "0xc0b9d922716e5a6f1e912d40a956deedfdd1f41a": { - "comment": "Implementation: Smart contract to manage DIDs", - "balance": "0", - "code": "0x60806040526004361061007b5760003560e01c8063ad3cb1cc1161004e578063ad3cb1cc1461010e578063c4d66de81461014c578063dafffa7d1461016c578063f4653a1d1461018c57600080fd5b80631e715511146100805780633633852c146100a25780634f1ef286146100d857806352d1902d146100eb575b600080fd5b34801561008c57600080fd5b506100a061009b366004611045565b6101ac565b005b3480156100ae57600080fd5b506100c26100bd3660046110c6565b6103e2565b6040516100cf9190611158565b60405180910390f35b6100a06100e63660046111d9565b61057d565b3480156100f757600080fd5b5061010061059c565b6040519081526020016100cf565b34801561011a57600080fd5b5061013f604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100cf919061129b565b34801561015857600080fd5b506100a06101673660046112ae565b6105b9565b34801561017857600080fd5b506100a06101873660046112c9565b61069e565b34801561019857600080fd5b506100a06101a73660046110c6565b6108f1565b83838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604051600192506101f391508390611335565b908152604051908190036020019020600301541561022f5780604051630eb7cd9560e01b8152600401610226919061129b565b60405180910390fd5b60405163af8b5bbf60e01b81527300000000000000000000000000000000000022229063af8b5bbf90610268908890889060040161137a565b60006040518083038186803b15801561028057600080fd5b505af4158015610294573d6000803e3d6000fd5b505050508282600187876040516102ac929190611396565b908152604051908190036020019020916102c7919083611430565b5085600186866040516102db929190611396565b908152604051908190036020018120600190810180546001600160a01b03949094166001600160a01b0319909416939093179092553391906103209088908890611396565b90815260405190819003602001812060020180546001600160a01b03939093166001600160a01b03199093169290921790915542906001906103659088908890611396565b90815260405190819003602001812060030191909155429060019061038d9088908890611396565b908152604051908190036020018120600401919091557f5fccafd09eeeb6a3dc1c80357ee982c00d7fb00a991274a9b96fe4fd7cb60552906103d2908790879061137a565b60405180910390a1505050505050565b6103ea610f83565b82828080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040516001925061043191508390611335565b90815260405190819003602001902060030154600003610466578060405163186a887560e11b8152600401610226919061129b565b60018484604051610478929190611396565b90815260200160405180910390206040518060400160405290816000820180546104a1906113a6565b80601f01602080910402602001604051908101604052809291908181526020018280546104cd906113a6565b801561051a5780601f106104ef5761010080835404028352916020019161051a565b820191906000526020600020905b8154815290600101906020018083116104fd57829003601f168201915b50505091835250506040805160a08101825260018401546001600160a01b0390811682526002850154166020808301919091526003850154928201929092526004840154606082015260059093015460ff16151560808401520152949350505050565b610585610b20565b61058e82610bc7565b6105988282610c2d565b5050565b60006105a6610cef565b5060008051602061150a83398151915290565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460019190600160401b900460ff16806106035750805467ffffffffffffffff808416911610155b156106215760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff191667ffffffffffffffff831617600160401b17815561064c83610d38565b805468ff00000000000000001916815560405167ffffffffffffffff831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a1505050565b83838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604051600192506106e591508390611335565b9081526040519081900360200190206003015460000361071a578060405163186a887560e11b8152600401610226919061129b565b84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040516001925061076191508390611335565b9081526040519081900360200190206005015460ff16156107975780604051630341716360e51b8152600401610226919061129b565b85858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604051600192506107de91508390611335565b90815260405190819003602001902060010154336001600160a01b039091161480159061083857506001816040516108169190611335565b90815260405190819003602001902060020154336001600160a01b0390911614155b1561085857604051633fcc3f1760e01b8152336004820152602401610226565b84846001898960405161086c929190611396565b90815260405190819003602001902091610887919083611430565b50426001888860405161089b929190611396565b908152604051908190036020018120600401919091557f7e7500a71b0209575a3b4858a2a662e94b0cad314ecb249f3526e9b2f86a0146906108e0908990899061137a565b60405180910390a150505050505050565b81818080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040516001925061093891508390611335565b9081526040519081900360200190206003015460000361096d578060405163186a887560e11b8152600401610226919061129b565b82828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604051600192506109b491508390611335565b9081526040519081900360200190206005015460ff16156109ea5780604051630341716360e51b8152600401610226919061129b565b83838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060405160019250610a3191508390611335565b90815260405190819003602001902060010154336001600160a01b0390911614801590610a8b5750600181604051610a699190611335565b90815260405190819003602001902060020154336001600160a01b0390911614155b15610aab57604051633fcc3f1760e01b8152336004820152602401610226565b6001808686604051610abe929190611396565b908152604051908190036020018120600501805492151560ff19909316929092179091557f4360f12f602ccecefb32480e5314d0d3f57d38db8f52c76d8fdf4c39596c1c2890610b11908790879061137a565b60405180910390a15050505050565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480610ba757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610b9b60008051602061150a833981519152546001600160a01b031690565b6001600160a01b031614155b15610bc55760405163703e46dd60e11b815260040160405180910390fd5b565b60005460405163574a81d760e01b81523060048201526001600160a01b0383811660248301529091169063574a81d79060440160006040518083038186803b158015610c1257600080fd5b505afa158015610c26573d6000803e3d6000fd5b5050505050565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610c87575060408051601f3d908101601f19168201909252610c84918101906114f0565b60015b610caf57604051634c9c8ce360e01b81526001600160a01b0383166004820152602401610226565b60008051602061150a8339815191528114610ce057604051632a87526960e21b815260048101829052602401610226565b610cea8383610d62565b505050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610bc55760405163703e46dd60e11b815260040160405180910390fd5b610d40610db8565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b610d6b82610e01565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115610db057610cea8282610e66565b610598610edc565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16610bc557604051631afcd79f60e31b815260040160405180910390fd5b806001600160a01b03163b600003610e3757604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610226565b60008051602061150a83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b031684604051610e839190611335565b600060405180830381855af49150503d8060008114610ebe576040519150601f19603f3d011682016040523d82523d6000602084013e610ec3565b606091505b5091509150610ed3858383610efb565b95945050505050565b3415610bc55760405163b398979f60e01b815260040160405180910390fd5b606082610f1057610f0b82610f5a565b610f53565b8151158015610f2757506001600160a01b0384163b155b15610f5057604051639996b31560e01b81526001600160a01b0385166004820152602401610226565b50805b9392505050565b805115610f6a5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b604051806040016040528060608152602001610fdb6040518060a0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081526020016000151581525090565b905290565b80356001600160a01b0381168114610ff757600080fd5b919050565b60008083601f84011261100e57600080fd5b50813567ffffffffffffffff81111561102657600080fd5b60208301915083602082850101111561103e57600080fd5b9250929050565b60008060008060006060868803121561105d57600080fd5b61106686610fe0565b9450602086013567ffffffffffffffff8082111561108357600080fd5b61108f89838a01610ffc565b909650945060408801359150808211156110a857600080fd5b506110b588828901610ffc565b969995985093965092949392505050565b600080602083850312156110d957600080fd5b823567ffffffffffffffff8111156110f057600080fd5b6110fc85828601610ffc565b90969095509350505050565b60005b8381101561112357818101518382015260200161110b565b50506000910152565b60008151808452611144816020860160208601611108565b601f01601f19169290920160200192915050565b602081526000825160c0602084015261117460e084018261112c565b9050602084015160018060a01b038082511660408601528060208301511660608601525060408101516080850152606081015160a08501526080810151151560c0850152508091505092915050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156111ec57600080fd5b6111f583610fe0565b9150602083013567ffffffffffffffff8082111561121257600080fd5b818501915085601f83011261122657600080fd5b813581811115611238576112386111c3565b604051601f8201601f19908116603f01168101908382118183101715611260576112606111c3565b8160405282815288602084870101111561127957600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b602081526000610f53602083018461112c565b6000602082840312156112c057600080fd5b610f5382610fe0565b600080600080604085870312156112df57600080fd5b843567ffffffffffffffff808211156112f757600080fd5b61130388838901610ffc565b9096509450602087013591508082111561131c57600080fd5b5061132987828801610ffc565b95989497509550505050565b60008251611347818460208701611108565b9190910192915050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208152600061138e602083018486611351565b949350505050565b8183823760009101908152919050565b600181811c908216806113ba57607f821691505b6020821081036113da57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610cea576000816000526020600020601f850160051c810160208610156114095750805b601f850160051c820191505b8181101561142857828155600101611415565b505050505050565b67ffffffffffffffff831115611448576114486111c3565b61145c8361145683546113a6565b836113e0565b6000601f84116001811461149057600085156114785750838201355b600019600387901b1c1916600186901b178355610c26565b600083815260209020601f19861690835b828110156114c157868501358255602094850194600190920191016114a1565b50868210156114de5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60006020828403121561150257600080fd5b505191905056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca2646970667358221220f39b5b431e6610dc0202e1c0b7edd59db7a241b3067b8394f672f3b477922c3264736f6c63430008170033" - }, "0x0000000000000000000000000000000000018888": { "comment": "Proxy: Ethereum registry for ERC-1056 ethr did methods", "balance": "0", @@ -188,38 +167,21 @@ "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": "0x00000000000000000000000036ffe7a6e3ba2923483f3b91b68c3e7b30b5a8d4" - } - }, - "0x36ffe7a6e3ba2923483f3b91b68c3e7b30b5a8d4": { - "comment": "Implementation: Smart contract to resolve DIDs from various DID registries", - "balance": "0", - "code": "0x6080604052600436106100555760003560e01c806329181c6c1461005a5780634f1ef2861461009057806352d1902d146100a557806366874f25146100c8578063ad3cb1cc14610135578063c0c53b8b14610166575b600080fd5b34801561006657600080fd5b5061007a61007536600461191c565b610186565b60405161008791906119dd565b60405180910390f35b6100a361009e366004611abc565b6102a8565b005b3480156100b157600080fd5b506100ba6102c7565b604051908152602001610087565b3480156100d457600080fd5b506100e86100e336600461191c565b6102e4565b604051610087919081516001600160a01b03908116825260208084015190911690820152604080830151908201526060808301519082015260809182015115159181019190915260a00190565b34801561014157600080fd5b5061007a604051806040016040528060058152602001640352e302e360dc1b81525081565b34801561017257600080fd5b506100a3610181366004611b4e565b610518565b606060006101c984848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061062c92505050565b90506101d88160000151610777565b1561025e57600154604051630d8ce14b60e21b81526001600160a01b0390911690633633852c9061020f9087908790600401611b99565b600060405180830381865afa15801561022c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526102549190810190611bc8565b5191506102a29050565b80516040516102709190602001611ce7565b60408051601f198184030181529082905263fdc1b5c360e01b825261029791600401611d37565b60405180910390fd5b505b92915050565b6102b0610817565b6102b9826108be565b6102c38282610924565b5050565b60006102d16109e6565b50600080516020611f4783398151915290565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152600061035084848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061062c92505050565b905061035f8160000151610a2f565b1561044c5760006103738260200151610a68565b90506001600160a01b0381166103a0578484604051631859e3bb60e11b8152600401610297929190611b99565b6002546040516310e67a9d60e31b81526001600160a01b0383811660048301526000921690638733d4e890602401602060405180830381865afa1580156103eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040f9190611d8b565b6040805160a0810182526001600160a01b03909216825260006020830181905290820181905260608201819052608082015293506102a292505050565b805161045790610777565b156104df57600154604051630d8ce14b60e21b81526001600160a01b0390911690633633852c9061048e9087908790600401611b99565b600060405180830381865afa1580156104ab573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526104d39190810190611bc8565b602001519150506102a2565b80516040516104f19190602001611ce7565b60408051601f198184030181529082905263fdc1b5c360e01b825261029791600401611da8565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460019190600160401b900460ff1680610561575080546001600160401b03808416911610155b1561057f5760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff19166001600160401b03831617600160401b1781556105a985610aa1565b600180546001600160a01b038681166001600160a01b0319928316179092556002805492861692909116919091179055805468ff0000000000000000191681556040516001600160401b03831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15050505050565b6040805180820190915260608082526020820152600061064b83610acb565b90506000610671604051806040016040528060018152602001601d60f91b815250610acb565b90506000806106808484610ad6565b9550925090508015806106be57506106bc6106b560405180604001604052806003815260200162191a5960ea1b815250610acb565b8390610b24565b155b156106de5785604051631859e3bb60e11b815260040161029791906119dd565b6106e88484610ad6565b9550925090508061070e5785604051631859e3bb60e11b815260040161029791906119dd565b604080518082019091526060808252602082015261072b83610b30565b81526040805180820190915260018152601d60f91b60208201526107599061075290610acb565b8690610b3b565b94506107689150849050610b30565b60208201529695505050505050565b60008061078383610acb565b90506107b46107ad60405180604001604052806004815260200163696e647960e01b815250610acb565b8290610b24565b806107e357506107e36107ad6040518060400160405280600581526020016434b7323c9960d91b815250610acb565b8061081057506108106107ad6040518060400160405280600381526020016239b7bb60e91b815250610acb565b9392505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061089e57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610892600080516020611f47833981519152546001600160a01b031690565b6001600160a01b031614155b156108bc5760405163703e46dd60e11b815260040160405180910390fd5b565b60005460405163574a81d760e01b81523060048201526001600160a01b0383811660248301529091169063574a81d79060440160006040518083038186803b15801561090957600080fd5b505afa15801561091d573d6000803e3d6000fd5b5050505050565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561097e575060408051601f3d908101601f1916820190925261097b91810190611dfc565b60015b6109a657604051634c9c8ce360e01b81526001600160a01b0383166004820152602401610297565b600080516020611f4783398151915281146109d757604051632a87526960e21b815260048101829052602401610297565b6109e18383610b65565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146108bc5760405163703e46dd60e11b815260040160405180910390fd5b60006102a2610a596040518060400160405280600481526020016332ba343960e11b815250610acb565b610a6284610acb565b90610b24565b60006016610a74835190565b03610a8157506000919050565b6000610a8c83610bbb565b9050610a9781611e15565b60601c9392505050565b610aa9610dad565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b60006102a282610df6565b6000808080610ae58686610e0a565b90506000198103610b0157600086600093509350935050610b1d565b610b1586826001600160801b038816610f15565b935093509350505b9250925092565b60006108108383610f82565b60606102a282610fcc565b6000808080610b4a8686611043565b90506000198103610b01576000808793509350935050610b1d565b610b6e82611135565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115610bb3576109e1828261119a565b6102c3611210565b60606000610bc883610acb565b90506000610bef60405180604001604052806002815260200161060f60f31b815250610acb565b9050610c1e610c1760405180604001604052806002815260200161060f60f31b815250610acb565b839061122f565b610c3957505060408051602081019091526000815292915050565b610c4b610c46838361123b565b610b30565b93506000849050600060028251610c629190611e67565b6001600160401b03811115610c7957610c79611a05565b6040519080825280601f01601f191660200182016040528015610ca3576020820181803683370190505b50905060005b8151811015610da357600080610ce885610cc4856002611e89565b81518110610cd457610cd4611ea0565b01602001516001600160f81b031916611247565b9150915080610d0d575050604080516020810190915260008152979650505050505050565b600080610d2a87610d1f876002611e89565b610cc4906001611eb6565b9150915080610d515750506040805160208101909152600081529998505050505050505050565b81610d5d856010611ec9565b610d679190611ee5565b60f81b868681518110610d7c57610d7c611ea0565b60200101906001600160f81b031916908160001a9053505060019093019250610ca9915050565b5095945050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff166108bc57604051631afcd79f60e31b815260040160405180910390fd5b60008060208301905061081081845161132d565b60006001600160801b03838116908316808303610e2c576000925050506102a2565b811580610e3857508181115b15610e4957600019925050506102a2565b6000610e558660801c90565b90506000610e638660801c90565b90506000610e72825160001a90565b90505b6000610e82848784611339565b90506000198103610e9d5760001996505050505050506102a2565b94859003949283019285851115610ebe5760001996505050505050506102a2565b84832085852003610eea57610ed38960801c90565b610edd9085611efe565b96505050505050506102a2565b85600103610f025760001996505050505050506102a2565b6000199095019460019093019250610e75565b600080600080610f258760801c90565b90506001600160801b03871685870181811115610f55576040516365f4e9df60e01b815260040160405180910390fd5b6001996001600160801b03988916608085811b919091179a50928290039098169201901b17949350505050565b60006001600160801b038381169083168114610fa25760009150506102a2565b610fc4610faf8560801c90565b610fb98560801c90565b839081902091201490565b949350505050565b60606001600160801b0382166001600160401b03811115610fef57610fef611a05565b6040519080825280601f01601f191660200182016040528015611019576020820181803683370190505b5090506020810161103d8161102e8560801c90565b6001600160801b038616611401565b50919050565b60006001600160801b03838116908316808303611065576000925050506102a2565b81158061107157508181115b1561108257600019925050506102a2565b600061108e8660801c90565b9050600061109c8660801c90565b905060006110a98761140f565b905060001984015b60006110be858885611454565b905060001981036110da576000199750505050505050506102a2565b808211156110f3576000199750505050505050506102a2565b8584208282038681018890209091036111155797506102a29650505050505050565b8115611123575095506110b1565b600019985050505050505050506102a2565b806001600160a01b03163b60000361116b57604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610297565b600080516020611f4783398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516111b79190611f11565b600060405180830381855af49150503d80600081146111f2576040519150601f19603f3d011682016040523d82523d6000602084013e6111f7565b606091505b5091509150611207858383611508565b95945050505050565b34156108bc5760405163b398979f60e01b815260040160405180910390fd5b60006108108383611564565b600061081083836115b1565b600080600360fc1b6001600160f81b03198416108015906112765750603960f81b6001600160f81b0319841611155b156112945761128a603060f885901c611f2d565b9360019350915050565b604160f81b6001600160f81b03198416108015906112c05750602360f91b6001600160f81b0319841611155b156112e05760416112d660f885901c600a611ee5565b61128a9190611f2d565b606160f81b6001600160f81b031984161080159061130c5750603360f91b6001600160f81b0319841611155b156113225760616112d660f885901c600a611ee5565b506000928392509050565b6000610810838361160b565b6000602083116113555761134e848484611617565b9050610810565b83601f8416808503820160ff8516600080516020611f67833981519152025b818810156113b6578751811861138981611728565b156113aa5784890361139d8a60208a611617565b0195505050505050610810565b60208901985050611374565b826000036113cc57600019945050505050610810565b6113d7828488611617565b945060001985036113f057600019945050505050610810565b509190910391909101949350505050565b8083828460045afa50505050565b60006001600160801b03821680820361143b576040516365f4e9df60e01b815260040160405180910390fd5b6108106001820361144c8560801c90565b015160001a90565b6000602083116114695761134e848484611773565b601f831684840181156114a1578190036000611486828487611773565b9050600019811461149f57908690030191506108109050565b505b60ff8416600080516020611f67833981519152025b868211156114fa57601f19909101805190919081186114d481611728565b156114f4578783036114e884602089611773565b01945050505050610810565b506114b6565b506000199695505050505050565b60608261151d57611518826117bc565b610810565b815115801561153457506001600160a01b0384163b155b1561155d57604051639996b31560e01b81526001600160a01b0385166004820152602401610297565b5080610810565b60006001600160801b0383811690831680821015611587576000925050506102a2565b848183111561159d5761159a86836117e8565b90505b6115a78186610f82565b9695505050505050565b60006001600160801b03838116908316818111156115d35784925050506102a2565b6000806115e08784611833565b90925090506115ef8287610f82565b156115ff5793506102a292505050565b869450505050506102a2565b600061081083836118b6565b825160009081602085111561162b57602094505b601285106116b55760ff8416600080516020611f6783398151915202821861165b6001600160801b038217611728565b6000036116915760109150601a861061168c576116806001600160401b038217611728565b60000361168c57601891505b6116af565b6116a36001600160c01b038217611728565b6000036116af57600891505b506116f3565b600a85106116f35760ff8416600080516020611f678339815191520282186116e56001600160c01b038217611728565b6000036116f157600891505b505b8481101561171b5781811a60ff85168103611712575091506108109050565b506001016116f3565b5060001995945050505050565b7ffefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeff81019019167f80808080808080808080808080808080808080808080808080808080808080801690565b6000602083111561178357602092505b83515b83156117b0576000199093019280841a60ff841681036117aa578492505050610810565b50611786565b50600019949350505050565b8051156117cc5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b60006001600160801b03831680831115611815576040516365f4e9df60e01b815260040160405180910390fd5b610fc46118228560801c90565b60801b6001600160801b0385161790565b60008060006118428560801c90565b90506001600160801b0385168085111561186f576040516365f4e9df60e01b815260040160405180910390fd5b608082901b6001600160801b038616176118a961188c8785611eb6565b6118968885611efe565b6001600160801b031660809190911b1790565b9350935050509250929050565b60006001600160801b038311156118e05760405163fee7506f60e01b815260040160405180910390fd5b6001600160801b0382111561190857604051633b6b098d60e01b815260040160405180910390fd5b506001600160801b031660809190911b1790565b6000806020838503121561192f57600080fd5b82356001600160401b038082111561194657600080fd5b818501915085601f83011261195a57600080fd5b81358181111561196957600080fd5b86602082850101111561197b57600080fd5b60209290920196919550909350505050565b60005b838110156119a8578181015183820152602001611990565b50506000910152565b600081518084526119c981602086016020860161198d565b601f01601f19169290920160200192915050565b60208152600061081060208301846119b1565b6001600160a01b03811681146117e557600080fd5b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715611a3d57611a3d611a05565b60405290565b60405160a081016001600160401b0381118282101715611a3d57611a3d611a05565b604051601f8201601f191681016001600160401b0381118282101715611a8d57611a8d611a05565b604052919050565b60006001600160401b03821115611aae57611aae611a05565b50601f01601f191660200190565b60008060408385031215611acf57600080fd5b8235611ada816119f0565b915060208301356001600160401b03811115611af557600080fd5b8301601f81018513611b0657600080fd5b8035611b19611b1482611a95565b611a65565b818152866020838501011115611b2e57600080fd5b816020840160208301376000602083830101528093505050509250929050565b600080600060608486031215611b6357600080fd5b8335611b6e816119f0565b92506020840135611b7e816119f0565b91506040840135611b8e816119f0565b809150509250925092565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b60006020808385031215611bdb57600080fd5b82516001600160401b0380821115611bf257600080fd5b9084019081860360c0811215611c0757600080fd5b611c0f611a1b565b835183811115611c1e57600080fd5b84019250601f83018813611c3157600080fd5b8251611c3f611b1482611a95565b8181528987838701011115611c5357600080fd5b611c628288830189880161198d565b82525060a0601f1983011215611c7757600080fd5b611c7f611a43565b9250848401519150611c90826119f0565b908252604083015190611ca2826119f0565b8185840152606084015160408401526080840151606084015260a084015193508315158414611cd057600080fd5b608083019390935250918101919091529392505050565b7f556e737570706f7274656420444944204d6574686f643a202700000000000000815260008251611d1f81601985016020870161198d565b602760f81b6019939091019283015250601a01919050565b60408152602460408201527f556e6976657273616c4469645265736f6c7665722e7265736f6c7665446f63756060820152631b595b9d60e21b608082015260a06020820152600061081060a08301846119b1565b600060208284031215611d9d57600080fd5b8151610810816119f0565b60408152602460408201527f556e6976657273616c4469645265736f6c7665722e7265736f6c76654d6574616060820152636461746160e01b608082015260a06020820152600061081060a08301846119b1565b600060208284031215611e0e57600080fd5b5051919050565b805160208201516bffffffffffffffffffffffff198082169291906014831015611e495780818460140360031b1b83161693505b505050919050565b634e487b7160e01b600052601160045260246000fd5b600082611e8457634e487b7160e01b600052601260045260246000fd5b500490565b80820281158282048414176102a2576102a2611e51565b634e487b7160e01b600052603260045260246000fd5b808201808211156102a2576102a2611e51565b60ff81811683821602908116908181146102a0576102a0611e51565b60ff81811683821601908111156102a2576102a2611e51565b818103818111156102a2576102a2611e51565b60008251611f2381846020870161198d565b9190910192915050565b60ff82811682821603908111156102a2576102a2611e5156fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc0101010101010101010101010101010101010101010101010101010101010101a26469706673582212206458fdda72343ecd43312f719f8b228bf501d55027b952a18a7d5d4168de991164736f6c63430008170033" - }, "0x0000000000000000000000000000000000005555": { "comment": "Proxy: Smart contract to manage schemas", "balance": "0", "code": "0x6080604052600a600c565b005b60186014601a565b6051565b565b6000604c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e808015606f573d6000f35b3d6000fdfea26469706673582212208de99705f21830b33bf2bd4a57ce70f27ec58ac48b2c88e1c96b59a11978ef8164736f6c63430008170033", "storage": { "0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000009999", - "0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000019999", + "0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000018888", "f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00": "0x0000000000000000000000000000000000000000000000000000000000000001", - "360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000d1ec00788fef917a8480abb392df151db0b8a64d" + "360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000a3f794638578ed0b3abcea8482f5a4454ebd7293" } }, - "0xd1ec00788fef917a8480abb392df151db0b8a64d": { + "0xa3f794638578ed0b3abcea8482f5a4454ebd7293": { "comment": "Implementation: Smart contract to manage schemas", "balance": "0", - "code": "0x6080604052600436106100555760003560e01c806336ce177d1461005a578063485cc9551461007c5780634f1ef2861461009c57806352d1902d146100af578063ad3cb1cc146100d7578063bd7fc5eb14610115575b600080fd5b34801561006657600080fd5b5061007a610075366004610e37565b610142565b005b34801561008857600080fd5b5061007a610097366004610ee6565b61045f565b61007a6100aa366004610f66565b610560565b3480156100bb57600080fd5b506100c461057f565b6040519081526020015b60405180910390f35b3480156100e357600080fd5b50610108604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100ce919061105e565b34801561012157600080fd5b50610135610130366004611071565b61059c565b6040516100ce91906110b3565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060405160029250610189915083906110e6565b90815260405190819003602001902060010154156101c5578060405163012f5f2760e11b81526004016101bc919061105e565b60405180910390fd5b84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506001546040516366874f2560e01b81526001600160a01b0390911692506366874f25915061022b90849060040161105e565b60a060405180830381865afa925050508015610264575060408051601f3d908101601f1916820190925261026191810190611102565b60015b610309573d808015610292576040519150601f19603f3d011682016040523d82523d6000602084013e610297565b606091505b506102a98163186a887560e11b6106fb565b156102c95781604051634c92543b60e01b81526004016101bc919061105e565b6102da81631859e3bb60e11b6106fb565b156102fa578160405163046cb69560e21b81526004016101bc919061105e565b6103038161072b565b50610380565b80516001600160a01b03163314801590610339575080602001516001600160a01b0316336001600160a01b031614155b1561035957604051632eaf165960e11b81523360048201526024016101bc565b80608001511561037e57816040516350943b5760e11b81526004016101bc919061105e565b505b6103c586868a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506107379050565b838360028a8a6040516103d992919061118f565b908152604051908190036020019020916103f4919083611229565b50426002898960405161040892919061118f565b908152604051908190036020018120600101919091557f4caa3c04537f182db18e883a82444b9f9a8a6765fba869bb25cfa69694e7b8cf9061044d908a908a906112e9565b60405180910390a15050505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460019190600160401b900460ff16806104a95750805467ffffffffffffffff808416911610155b156104c75760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff191667ffffffffffffffff831617600160401b1781556104f2846107cc565b600180546001600160a01b0319166001600160a01b038516179055805468ff00000000000000001916815560405167ffffffffffffffff831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a150505050565b6105686107f6565b6105718261089d565b61057b8282610903565b5050565b60006105896109c5565b5060008051602061138383398151915290565b6105a4610dc1565b82828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604051600292506105eb915083906110e6565b90815260405190819003602001902060010154600003610620578060405163272a91e160e21b81526004016101bc919061105e565b6002848460405161063292919061118f565b908152602001604051809103902060405180604001604052908160008201805461065b9061119f565b80601f01602080910402602001604051908101604052809291908181526020018280546106879061119f565b80156106d45780601f106106a9576101008083540402835291602001916106d4565b820191906000526020600020905b8154815290600101906020018083116106b757829003601f168201915b50505091835250506040805160208082019092526001939093015483520152949350505050565b600080838060200190518101906107129190611318565b6001600160e01b03198481169116149150505b92915050565b60208101815182018082fd5b60008282604051806040016040528060158152602001742f616e6f6e63726564732f76302f534348454d412f60581b81525060405160200161077b93929190611342565b60405160208183030381529060405290506107a761079882610a0e565b6107a186610a0e565b90610a19565b6107c6578360405163ba33fe2160e01b81526004016101bc919061105e565b50505050565b6107d4610a2c565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061087d57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610871600080516020611383833981519152546001600160a01b031690565b6001600160a01b031614155b1561089b5760405163703e46dd60e11b815260040160405180910390fd5b565b60005460405163574a81d760e01b81523060048201526001600160a01b0383811660248301529091169063574a81d79060440160006040518083038186803b1580156108e857600080fd5b505afa1580156108fc573d6000803e3d6000fd5b5050505050565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561095d575060408051601f3d908101601f1916820190925261095a91810190611369565b60015b61098557604051634c9c8ce360e01b81526001600160a01b03831660048201526024016101bc565b60008051602061138383398151915281146109b657604051632a87526960e21b8152600481018290526024016101bc565b6109c08383610a75565b505050565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461089b5760405163703e46dd60e11b815260040160405180910390fd5b600061072582610acb565b6000610a258383610adf565b9392505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661089b57604051631afcd79f60e31b815260040160405180910390fd5b610a7e82610b2c565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115610ac3576109c08282610b91565b61057b610c07565b600080602083019050610a25818451610c26565b60006001600160801b0383811690831680821015610b0257600092505050610725565b8481831115610b1857610b158683610c32565b90505b610b228186610c85565b9695505050505050565b806001600160a01b03163b600003610b6257604051634c9c8ce360e01b81526001600160a01b03821660048201526024016101bc565b60008051602061138383398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b031684604051610bae91906110e6565b600060405180830381855af49150503d8060008114610be9576040519150601f19603f3d011682016040523d82523d6000602084013e610bee565b606091505b5091509150610bfe858383610cc7565b95945050505050565b341561089b5760405163b398979f60e01b815260040160405180910390fd5b6000610a258383610d23565b60006001600160801b03831680831115610c5f576040516365f4e9df60e01b815260040160405180910390fd5b610c7d610c6c8560801c90565b60801b6001600160801b0385161790565b949350505050565b60006001600160801b038381169083168114610ca5576000915050610725565b610c7d610cb28560801c90565b610cbc8560801c90565b839081902091201490565b606082610cdc57610cd782610d2f565b610a25565b8151158015610cf357506001600160a01b0384163b155b15610d1c57604051639996b31560e01b81526001600160a01b03851660048201526024016101bc565b5092915050565b6000610a258383610d5b565b805115610d3f5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b60006001600160801b03831115610d855760405163fee7506f60e01b815260040160405180910390fd5b6001600160801b03821115610dad57604051633b6b098d60e01b815260040160405180910390fd5b506001600160801b031660809190911b1790565b604051806040016040528060608152602001610de96040518060200160405280600081525090565b905290565b60008083601f840112610e0057600080fd5b50813567ffffffffffffffff811115610e1857600080fd5b602083019150836020828501011115610e3057600080fd5b9250929050565b60008060008060008060608789031215610e5057600080fd5b863567ffffffffffffffff80821115610e6857600080fd5b610e748a838b01610dee565b90985096506020890135915080821115610e8d57600080fd5b610e998a838b01610dee565b90965094506040890135915080821115610eb257600080fd5b50610ebf89828a01610dee565b979a9699509497509295939492505050565b6001600160a01b0381168114610d5857600080fd5b60008060408385031215610ef957600080fd5b8235610f0481610ed1565b91506020830135610f1481610ed1565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610f5e57610f5e610f1f565b604052919050565b60008060408385031215610f7957600080fd5b8235610f8481610ed1565b915060208381013567ffffffffffffffff80821115610fa257600080fd5b818601915086601f830112610fb657600080fd5b813581811115610fc857610fc8610f1f565b610fda601f8201601f19168501610f35565b91508082528784828501011115610ff057600080fd5b80848401858401376000848284010152508093505050509250929050565b60005b83811015611029578181015183820152602001611011565b50506000910152565b6000815180845261104a81602086016020860161100e565b601f01601f19169290920160200192915050565b602081526000610a256020830184611032565b6000806020838503121561108457600080fd5b823567ffffffffffffffff81111561109b57600080fd5b6110a785828601610dee565b90969095509350505050565b6020815260008251604060208401526110cf6060840182611032565b905060208401515160408401528091505092915050565b600082516110f881846020870161100e565b9190910192915050565b600060a0828403121561111457600080fd5b60405160a0810181811067ffffffffffffffff8211171561113757611137610f1f565b604052825161114581610ed1565b8152602083015161115581610ed1565b8060208301525060408301516040820152606083015160608201526080830151801515811461118357600080fd5b60808201529392505050565b8183823760009101908152919050565b600181811c908216806111b357607f821691505b6020821081036111d357634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156109c0576000816000526020600020601f850160051c810160208610156112025750805b601f850160051c820191505b818110156112215782815560010161120e565b505050505050565b67ffffffffffffffff83111561124157611241610f1f565b6112558361124f835461119f565b836111d9565b6000601f84116001811461128957600085156112715750838201355b600019600387901b1c1916600186901b1783556108fc565b600083815260209020601f19861690835b828110156112ba578685013582556020948501946001909201910161129a565b50868210156112d75760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b60006020828403121561132a57600080fd5b81516001600160e01b031981168114610a2557600080fd5b82848237600083820160008152835161135f81836020880161100e565b0195945050505050565b60006020828403121561137b57600080fd5b505191905056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca2646970667358221220aecc5aaf53f11187b0d44ce73a0ee1af74fc00166608ce4630304c278629df2e64736f6c63430008170033" + "code": "0x60806040526004361061007b5760003560e01c8063ad3cb1cc1161004e578063ad3cb1cc146100fd578063bdd23ccb1461013b578063e8d740291461015b578063eaa760c21461019a57600080fd5b8063485cc955146100805780634f1ef286146100a257806352d1902d146100b55780635915b768146100dd575b600080fd5b34801561008c57600080fd5b506100a061009b3660046109e7565b6101c7565b005b6100a06100b0366004610a36565b6102c8565b3480156100c157600080fd5b506100ca6102e7565b6040519081526020015b60405180910390f35b3480156100e957600080fd5b506100a06100f8366004610b43565b610304565b34801561010957600080fd5b5061012e604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100d49190610bc3565b34801561014757600080fd5b506100a0610156366004610bf6565b610317565b34801561016757600080fd5b5061018a610176366004610c82565b600090815260026020526040902054151590565b60405190151581526020016100d4565b3480156101a657600080fd5b506100ca6101b5366004610c82565b60026020526000908152604090205481565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460019190600160401b900460ff16806102115750805467ffffffffffffffff808416911610155b1561022f5760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff191667ffffffffffffffff831617600160401b17815561025a84610376565b600180546001600160a01b0319166001600160a01b038516179055805468ff00000000000000001916815560405167ffffffffffffffff831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a150505050565b6102d06103a0565b6102d982610447565b6102e382826104ad565b5050565b60006102f1610574565b50600080516020610da083398151915290565b61031184338585856105bd565b50505050565b60405160009061033b90601960f81b90839030908c90899089908990602001610c9b565b60405160208183030381529060405280519060200120905061036c886103648a848b8b8b6106fd565b8686866105bd565b5050505050505050565b61037e6107ae565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061042757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661041b600080516020610da0833981519152546001600160a01b031690565b6001600160a01b031614155b156104455760405163703e46dd60e11b815260040160405180910390fd5b565b60005460405163574a81d760e01b81523060048201526001600160a01b0383811660248301529091169063574a81d79060440160006040518083038186803b15801561049257600080fd5b505afa1580156104a6573d6000803e3d6000fd5b5050505050565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610507575060408051601f3d908101601f1916820190925261050491810190610d0d565b60015b61053457604051634c9c8ce360e01b81526001600160a01b03831660048201526024015b60405180910390fd5b600080516020610da0833981519152811461056557604051632a87526960e21b81526004810182905260240161052b565b61056f83836107f7565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146104455760405163703e46dd60e11b815260040160405180910390fd5b6000838152600260205260409020548390156105ef576040516347f6332960e11b81526004810182905260240161052b565b6001546040516310e67a9d60e31b81526001600160a01b03808916600483015288928892911690638733d4e890602401602060405180830381865afa15801561063c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106609190610d26565b6001600160a01b0316816001600160a01b0316146106a45760405163cc41100960e01b81526001600160a01b0380841660048301528216602482015260440161052b565b600086815260026020526040908190204390555186907f3e21fe65ee16f151c8cda6e871883b2e0550f9c8511b4ea1d75c9c9e8d489f67906106eb908a9089908990610d43565b60405180910390a25050505050505050565b6040805160008082526020820180845287905260ff8616928201929092526060810184905260808101839052819060019060a0016020604051602081039080840390855afa158015610753573d6000803e3d6000fd5b505050602060405103519050806001600160a01b0316876001600160a01b0316146107a45760405163cc41100960e01b81526001600160a01b0380891660048301528216602482015260440161052b565b9695505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661044557604051631afcd79f60e31b815260040160405180910390fd5b6108008261084d565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a28051156108455761056f82826108b2565b6102e3610928565b806001600160a01b03163b60000361088357604051634c9c8ce360e01b81526001600160a01b038216600482015260240161052b565b600080516020610da083398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516108cf9190610d83565b600060405180830381855af49150503d806000811461090a576040519150601f19603f3d011682016040523d82523d6000602084013e61090f565b606091505b509150915061091f858383610947565b95945050505050565b34156104455760405163b398979f60e01b815260040160405180910390fd5b60608261095c57610957826109a6565b61099f565b815115801561097357506001600160a01b0384163b155b1561099c57604051639996b31560e01b81526001600160a01b038516600482015260240161052b565b50805b9392505050565b8051156109b65780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b6001600160a01b03811681146109cf57600080fd5b600080604083850312156109fa57600080fd5b8235610a05816109d2565b91506020830135610a15816109d2565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b60008060408385031215610a4957600080fd5b8235610a54816109d2565b9150602083013567ffffffffffffffff80821115610a7157600080fd5b818501915085601f830112610a8557600080fd5b813581811115610a9757610a97610a20565b604051601f8201601f19908116603f01168101908382118183101715610abf57610abf610a20565b81604052828152886020848701011115610ad857600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60008083601f840112610b0c57600080fd5b50813567ffffffffffffffff811115610b2457600080fd5b602083019150836020828501011115610b3c57600080fd5b9250929050565b60008060008060608587031215610b5957600080fd5b8435610b64816109d2565b935060208501359250604085013567ffffffffffffffff811115610b8757600080fd5b610b9387828801610afa565b95989497509550505050565b60005b83811015610bba578181015183820152602001610ba2565b50506000910152565b6020815260008251806020840152610be2816040850160208701610b9f565b601f01601f19169190910160400192915050565b600080600080600080600060c0888a031215610c1157600080fd5b8735610c1c816109d2565b9650602088013560ff81168114610c3257600080fd5b955060408801359450606088013593506080880135925060a088013567ffffffffffffffff811115610c6357600080fd5b610c6f8a828b01610afa565b989b979a50959850939692959293505050565b600060208284031215610c9457600080fd5b5035919050565b6001600160f81b03198881168252871660018201526bffffffffffffffffffffffff19606087811b8216600284015286901b1660168201526b637265617465536368656d6160a01b602a8201526036810184905260008284605684013750600091016056019081529695505050505050565b600060208284031215610d1f57600080fd5b5051919050565b600060208284031215610d3857600080fd5b815161099f816109d2565b6001600160a01b03841681526040602082018190528101829052818360608301376000818301606090810191909152601f909201601f1916010192915050565b60008251610d95818460208701610b9f565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca26469706673582212204a4fb68df29ffd4bbbd06a3c0b087236a2b91e6a775ec5d620b345da38d3139664736f6c63430008170033" }, "0x0000000000000000000000000000000000004444": { "comment": "Proxy: Smart contract to manage credential definitions", @@ -227,16 +189,16 @@ "code": "0x6080604052600a600c565b005b60186014601a565b6051565b565b6000604c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e808015606f573d6000f35b3d6000fdfea26469706673582212208de99705f21830b33bf2bd4a57ce70f27ec58ac48b2c88e1c96b59a11978ef8164736f6c63430008170033", "storage": { "0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000009999", - "0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000019999", + "0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000018888", "0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000005555", "f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00": "0x0000000000000000000000000000000000000000000000000000000000000001", - "360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000000000000000000000002c9e42514acaddd0a44e234b987c6b79aaebbc45" + "360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000ddbc94cbc03d53bdaff95115dacd7101805e2179" } }, - "0x2c9e42514acaddd0a44e234b987c6b79aaebbc45": { + "0xddbc94cbc03d53bdaff95115dacd7101805e2179": { "comment": "Implementation: Smart contract to manage credential definitions", "balance": "0", - "code": "0x6080604052600436106100555760003560e01c80634cc562d41461005a5780634f1ef2861461007c57806352d1902d1461008f5780636170c48a146100b7578063ad3cb1cc146100e4578063c0c53b8b14610122575b600080fd5b34801561006657600080fd5b5061007a610075366004610f27565b610142565b005b61007a61008a3660046110b6565b610514565b34801561009b57600080fd5b506100a4610533565b6040519081526020015b60405180910390f35b3480156100c357600080fd5b506100d76100d2366004611148565b610550565b6040516100ae91906111d9565b3480156100f057600080fd5b50610115604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100ae919061120c565b34801561012e57600080fd5b5061007a61013d36600461121f565b6106af565b87878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604051600392506101899150839061126a565b90815260405190819003602001902060010154156101c557806040516341d617b960e01b81526004016101bc919061120c565b60405180910390fd5b84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060025460405163bd7fc5eb60e01b81526001600160a01b03909116925063bd7fc5eb915061022b90849060040161120c565b6000604051808303816000875af115801561024a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526102729190810190611286565b5087878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506001546040516366874f2560e01b81526001600160a01b0390911692506366874f2591506102d990849060040161120c565b60a060405180830381865afa925050508015610312575060408051601f3d908101601f1916820190925261030f91810190611353565b60015b6103b7573d808015610340576040519150601f19603f3d011682016040523d82523d6000602084013e610345565b606091505b506103578163186a887560e11b6107c3565b156103775781604051634c92543b60e01b81526004016101bc919061120c565b61038881631859e3bb60e11b6107c3565b156103a8578160405163046cb69560e21b81526004016101bc919061120c565b6103b1816107f3565b5061042e565b80516001600160a01b031633148015906103e7575080602001516001600160a01b0316336001600160a01b031614155b1561040757604051632eaf165960e11b81523360048201526024016101bc565b80608001511561042c57816040516350943b5760e11b81526004016101bc919061120c565b505b610477898989898f8f8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092969594939250506107ff9050565b848460038d8d60405161048b9291906113df565b908152604051908190036020019020916104a6919083611471565b504260038c8c6040516104ba9291906113df565b908152604051908190036020018120600101919091557f4f0e13d45b6c20e62fb843b05270cf51d91c9cb535dbd5fe03abcc9bbd39d796906104ff908d908d90611530565b60405180910390a15050505050505050505050565b61051c6108bd565b61052582610964565b61052f82826109ca565b5050565b600061053d610a8c565b506000805160206115ea83398151915290565b610558610eb2565b82828080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040516003925061059f9150839061126a565b908152604051908190036020019020600101546000036105d457806040516305c96b5360e01b81526004016101bc919061120c565b600384846040516105e69291906113df565b908152602001604051809103902060405180604001604052908160008201805461060f906113ef565b80601f016020809104026020016040519081016040528092919081815260200182805461063b906113ef565b80156106885780601f1061065d57610100808354040283529160200191610688565b820191906000526020600020905b81548152906001019060200180831161066b57829003601f168201915b50505091835250506040805160208082019092526001939093015483520152949350505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460019190600160401b900460ff16806106f8575080546001600160401b03808416911610155b156107165760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff19166001600160401b03831617600160401b17815561074085610ad5565b600180546001600160a01b038681166001600160a01b0319928316179092556002805492861692909116919091179055805468ff0000000000000000191681556040516001600160401b03831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15050505050565b600080838060200190518101906107da919061155f565b6001600160e01b03198481169116149150505b92915050565b60208101815182018082fd5b600084846040518060400160405280601881526020017f2f616e6f6e63726564732f76302f434c41494d5f4445462f00000000000000008152508585604051806040016040528060018152602001602f60f81b81525060405160200161086a96959493929190611589565b604051602081830303815290604052905061089661088782610aff565b61089088610aff565b90610b0a565b6108b55785604051638ada824b60e01b81526004016101bc919061120c565b505050505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061094457507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166109386000805160206115ea833981519152546001600160a01b031690565b6001600160a01b031614155b156109625760405163703e46dd60e11b815260040160405180910390fd5b565b60005460405163574a81d760e01b81523060048201526001600160a01b0383811660248301529091169063574a81d79060440160006040518083038186803b1580156109af57600080fd5b505afa1580156109c3573d6000803e3d6000fd5b5050505050565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610a24575060408051601f3d908101601f19168201909252610a21918101906115d0565b60015b610a4c57604051634c9c8ce360e01b81526001600160a01b03831660048201526024016101bc565b6000805160206115ea8339815191528114610a7d57604051632a87526960e21b8152600481018290526024016101bc565b610a878383610b1d565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146109625760405163703e46dd60e11b815260040160405180910390fd5b610add610b73565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b60006107ed82610bbc565b6000610b168383610bd0565b9392505050565b610b2682610c1d565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115610b6b57610a878282610c82565b61052f610cf8565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661096257604051631afcd79f60e31b815260040160405180910390fd5b600080602083019050610b16818451610d17565b60006001600160801b0383811690831680821015610bf3576000925050506107ed565b8481831115610c0957610c068683610d23565b90505b610c138186610d76565b9695505050505050565b806001600160a01b03163b600003610c5357604051634c9c8ce360e01b81526001600160a01b03821660048201526024016101bc565b6000805160206115ea83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b031684604051610c9f919061126a565b600060405180830381855af49150503d8060008114610cda576040519150601f19603f3d011682016040523d82523d6000602084013e610cdf565b606091505b5091509150610cef858383610db8565b95945050505050565b34156109625760405163b398979f60e01b815260040160405180910390fd5b6000610b168383610e14565b60006001600160801b03831680831115610d50576040516365f4e9df60e01b815260040160405180910390fd5b610d6e610d5d8560801c90565b60801b6001600160801b0385161790565b949350505050565b60006001600160801b038381169083168114610d965760009150506107ed565b610d6e610da38560801c90565b610dad8560801c90565b839081902091201490565b606082610dcd57610dc882610e20565b610b16565b8151158015610de457506001600160a01b0384163b155b15610e0d57604051639996b31560e01b81526001600160a01b03851660048201526024016101bc565b5092915050565b6000610b168383610e4c565b805115610e305780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b60006001600160801b03831115610e765760405163fee7506f60e01b815260040160405180910390fd5b6001600160801b03821115610e9e57604051633b6b098d60e01b815260040160405180910390fd5b506001600160801b031660809190911b1790565b604051806040016040528060608152602001610eda6040518060200160405280600081525090565b905290565b60008083601f840112610ef157600080fd5b5081356001600160401b03811115610f0857600080fd5b602083019150836020828501011115610f2057600080fd5b9250929050565b6000806000806000806000806080898b031215610f4357600080fd5b88356001600160401b0380821115610f5a57600080fd5b610f668c838d01610edf565b909a50985060208b0135915080821115610f7f57600080fd5b610f8b8c838d01610edf565b909850965060408b0135915080821115610fa457600080fd5b610fb08c838d01610edf565b909650945060608b0135915080821115610fc957600080fd5b50610fd68b828c01610edf565b999c989b5096995094979396929594505050565b6001600160a01b0381168114610e4957600080fd5b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171561103757611037610fff565b60405290565b604051602081016001600160401b038111828210171561103757611037610fff565b604051601f8201601f191681016001600160401b038111828210171561108757611087610fff565b604052919050565b60006001600160401b038211156110a8576110a8610fff565b50601f01601f191660200190565b600080604083850312156110c957600080fd5b82356110d481610fea565b915060208301356001600160401b038111156110ef57600080fd5b8301601f8101851361110057600080fd5b803561111361110e8261108f565b61105f565b81815286602083850101111561112857600080fd5b816020840160208301376000602083830101528093505050509250929050565b6000806020838503121561115b57600080fd5b82356001600160401b0381111561117157600080fd5b61117d85828601610edf565b90969095509350505050565b60005b838110156111a457818101518382015260200161118c565b50506000910152565b600081518084526111c5816020860160208601611189565b601f01601f19169290920160200192915050565b6020815260008251604060208401526111f560608401826111ad565b905060208401515160408401528091505092915050565b602081526000610b1660208301846111ad565b60008060006060848603121561123457600080fd5b833561123f81610fea565b9250602084013561124f81610fea565b9150604084013561125f81610fea565b809150509250925092565b6000825161127c818460208701611189565b9190910192915050565b6000602080838503121561129957600080fd5b82516001600160401b03808211156112b057600080fd5b9084019081860360408112156112c557600080fd5b6112cd611015565b8351838111156112dc57600080fd5b84019250601f830188136112ef57600080fd5b82516112fd61110e8261108f565b818152898783870101111561131157600080fd5b61132082888301898801611189565b825250601f19820185131561133457600080fd5b61133c61103d565b938501518452938401929092525090949350505050565b600060a0828403121561136557600080fd5b60405160a081018181106001600160401b038211171561138757611387610fff565b604052825161139581610fea565b815260208301516113a581610fea565b806020830152506040830151604082015260608301516060820152608083015180151581146113d357600080fd5b60808201529392505050565b8183823760009101908152919050565b600181811c9082168061140357607f821691505b60208210810361142357634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610a87576000816000526020600020601f850160051c810160208610156114525750805b601f850160051c820191505b818110156108b55782815560010161145e565b6001600160401b0383111561148857611488610fff565b61149c8361149683546113ef565b83611429565b6000601f8411600181146114d057600085156114b85750838201355b600019600387901b1c1916600186901b1783556109c3565b600083815260209020601f19861690835b8281101561150157868501358255602094850194600190920191016114e1565b508682101561151e5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b60006020828403121561157157600080fd5b81516001600160e01b031981168114610b1657600080fd5b8587823760008682016000815286516115a6818360208b01611189565b0184868237600090850190815283516115c3818360208801611189565b0198975050505050505050565b6000602082840312156115e257600080fd5b505191905056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca2646970667358221220aa26bfab1ab319219524065305f4f784a33e05d33b950f30a436dcb96b58605664736f6c63430008170033" + "code": "0x60806040526004361061007b5760003560e01c8063bbc742411161004e578063bbc742411461013a578063c0c53b8b1461015a578063eaa760c21461017a578063f062236b146101a757600080fd5b80634f1ef2861461008057806352d1902d146100955780638b963e9d146100bd578063ad3cb1cc146100fc575b600080fd5b61009361008e366004610aa8565b6101c7565b005b3480156100a157600080fd5b506100aa6101e6565b6040519081526020015b60405180910390f35b3480156100c957600080fd5b506100ec6100d8366004610b6c565b600090815260036020526040902054151590565b60405190151581526020016100b4565b34801561010857600080fd5b5061012d604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100b49190610ba9565b34801561014657600080fd5b50610093610155366004610c25565b610203565b34801561016657600080fd5b50610093610175366004610c8f565b610218565b34801561018657600080fd5b506100aa610195366004610b6c565b60036020526000908152604090205481565b3480156101b357600080fd5b506100936101c2366004610cda565b61032f565b6101cf610392565b6101d882610439565b6101e28282610498565b5050565b60006101f061055f565b50600080516020610eaf83398151915290565b6102118533868686866105a8565b5050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460019190600160401b900460ff16806102625750805467ffffffffffffffff808416911610155b156102805760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff191667ffffffffffffffff831617600160401b1781556102ab8561077e565b600180546001600160a01b038681166001600160a01b0319928316179092556002805492861692909116919091179055805468ff00000000000000001916815560405167ffffffffffffffff831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15050505050565b60405160009061035590601960f81b90839030908d908a908a908a908a90602001610d6f565b6040516020818303038152906040528051906020012090506103878961037e8b848c8c8c6107a8565b878787876105a8565b505050505050505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061041957507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661040d600080516020610eaf833981519152546001600160a01b031690565b6001600160a01b031614155b156104375760405163703e46dd60e11b815260040160405180910390fd5b565b60005460405163574a81d760e01b81523060048201526001600160a01b0383811660248301529091169063574a81d79060440160006040518083038186803b15801561048457600080fd5b505afa158015610211573d6000803e3d6000fd5b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156104f2575060408051601f3d908101601f191682019092526104ef91810190610dfa565b60015b61051f57604051634c9c8ce360e01b81526001600160a01b03831660048201526024015b60405180910390fd5b600080516020610eaf833981519152811461055057604051632a87526960e21b815260048101829052602401610516565b61055a8383610859565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146104375760405163703e46dd60e11b815260040160405180910390fd5b6000848152600360205260409020548490156105da5760405163b1a7a2af60e01b815260048101829052602401610516565b6001546040516310e67a9d60e31b81526001600160a01b03808a16600483015289928992911690638733d4e890602401602060405180830381865afa158015610627573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064b9190610e13565b6001600160a01b0316816001600160a01b03161461068f5760405163cc41100960e01b81526001600160a01b03808416600483015282166024820152604401610516565b60025460405163e8d7402960e01b81526004810188905287916001600160a01b03169063e8d74029906024016020604051808303816000875af11580156106da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106fe9190610e30565b15156000036107235760405163063de83560e21b815260048101829052602401610516565b600088815260036020526040908190204390555188907fb244582b6218e1202021c674f5f9ba330f9393f8359101bb96445efeedff3db39061076a908c908a908a90610e52565b60405180910390a250505050505050505050565b6107866108af565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6040805160008082526020820180845287905260ff8616928201929092526060810184905260808101839052819060019060a0016020604051602081039080840390855afa1580156107fe573d6000803e3d6000fd5b505050602060405103519050806001600160a01b0316876001600160a01b03161461084f5760405163cc41100960e01b81526001600160a01b03808916600483015282166024820152604401610516565b9695505050505050565b610862826108f8565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a28051156108a75761055a828261095d565b6101e26109d3565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661043757604051631afcd79f60e31b815260040160405180910390fd5b806001600160a01b03163b60000361092e57604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610516565b600080516020610eaf83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b03168460405161097a9190610e92565b600060405180830381855af49150503d80600081146109b5576040519150601f19603f3d011682016040523d82523d6000602084013e6109ba565b606091505b50915091506109ca8583836109f2565b95945050505050565b34156104375760405163b398979f60e01b815260040160405180910390fd5b606082610a0757610a0282610a51565b610a4a565b8151158015610a1e57506001600160a01b0384163b155b15610a4757604051639996b31560e01b81526001600160a01b0385166004820152602401610516565b50805b9392505050565b805115610a615780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b6001600160a01b0381168114610a7a57600080fd5b634e487b7160e01b600052604160045260246000fd5b60008060408385031215610abb57600080fd5b8235610ac681610a7d565b9150602083013567ffffffffffffffff80821115610ae357600080fd5b818501915085601f830112610af757600080fd5b813581811115610b0957610b09610a92565b604051601f8201601f19908116603f01168101908382118183101715610b3157610b31610a92565b81604052828152886020848701011115610b4a57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b600060208284031215610b7e57600080fd5b5035919050565b60005b83811015610ba0578181015183820152602001610b88565b50506000910152565b6020815260008251806020840152610bc8816040850160208701610b85565b601f01601f19169190910160400192915050565b60008083601f840112610bee57600080fd5b50813567ffffffffffffffff811115610c0657600080fd5b602083019150836020828501011115610c1e57600080fd5b9250929050565b600080600080600060808688031215610c3d57600080fd5b8535610c4881610a7d565b94506020860135935060408601359250606086013567ffffffffffffffff811115610c7257600080fd5b610c7e88828901610bdc565b969995985093965092949392505050565b600080600060608486031215610ca457600080fd5b8335610caf81610a7d565b92506020840135610cbf81610a7d565b91506040840135610ccf81610a7d565b809150509250925092565b60008060008060008060008060e0898b031215610cf657600080fd5b8835610d0181610a7d565b9750602089013560ff81168114610d1757600080fd5b965060408901359550606089013594506080890135935060a0890135925060c089013567ffffffffffffffff811115610d4f57600080fd5b610d5b8b828c01610bdc565b999c989b5096995094979396929594505050565b6001600160f81b03198981168252881660018201526bffffffffffffffffffffffff19606088811b8216600284015287901b1660168201527f63726561746543726564656e7469616c446566696e6974696f6e000000000000602a82015260448101859052606481018490526000828460848401375060009101608401908152979650505050505050565b600060208284031215610e0c57600080fd5b5051919050565b600060208284031215610e2557600080fd5b8151610a4a81610a7d565b600060208284031215610e4257600080fd5b81518015158114610a4a57600080fd5b6001600160a01b03841681526040602082018190528101829052818360608301376000818301606090810191909152601f909201601f1916010192915050565b60008251610ea4818460208701610b85565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca26469706673582212201f00954ebf639fab6f5f5c206581348f7c25f754c1b3e5049cc5d0dce01f676864736f6c63430008170033" } } } diff --git a/network/config/nodes/validator5/key b/network/config/nodes/validator5/key index f5de401c..2607ffb5 100644 --- a/network/config/nodes/validator5/key +++ b/network/config/nodes/validator5/key @@ -1 +1 @@ -0x69829d80fd48789dfd5cff0b0a66cad4a4f9dfc53a8a0fb8ccb597ea92f22467 \ No newline at end of file +0x52bd45e5975ae4945094e5bc0444bb40527674204a03b09807d436db91590dcd \ No newline at end of file diff --git a/smart_contracts/README.md b/smart_contracts/README.md index 77503813..c6983704 100644 --- a/smart_contracts/README.md +++ b/smart_contracts/README.md @@ -76,7 +76,8 @@ You can find sample scripts demonstrating the usage of deployed contracts in the * `genesis` - helper scripts to generate genesis blocks for injecting contracts. - > Find more details regarding the scripts in the [genesis section](#inject-contracts-into-network-genesis) of this document. + > Find more details regarding the scripts in the [genesis section](#inject-contracts-into-network-genesis) of this + document. ## Inject contracts into network genesis @@ -93,12 +94,12 @@ This section describes how to inject smart contracts into the genesis state of t 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 dd455d97..cd86820d 100644 --- a/smart_contracts/contracts-ts/CredentialDefinitionRegistry.ts +++ b/smart_contracts/contracts-ts/CredentialDefinitionRegistry.ts @@ -1,5 +1,6 @@ +import { getBytes, keccak256, Signature, toUtf8Bytes, toUtf8String } from 'ethers' +import { CredentialDefinitionCreatedEvent } from '../typechain-types/contracts/cl/CredentialDefinitionRegistry' import { Contract } from '../utils/contract' -import { CredentialDefinitionRecord, mapCredentialDefinitionRecord } from './types' export class CredentialDefinitionRegistry extends Contract { public static readonly defaultAddress = '0x0000000000000000000000000000000000004444' @@ -8,13 +9,42 @@ export class CredentialDefinitionRegistry extends Contract { super(CredentialDefinitionRegistry.name, sender) } - public async createCredentialDefinition(id: string, issuerId: string, schemaId: string, credDef: string) { - const tx = await this.instance.createCredentialDefinition(id, issuerId, schemaId, credDef) + public async createCredentialDefinition(identity: string, id: string, schemaId: string, credDef: string) { + const tx = await this.instance.createCredentialDefinition( + identity, + keccak256(toUtf8Bytes(id)), + keccak256(toUtf8Bytes(schemaId)), + toUtf8Bytes(credDef), + ) return tx.wait() } - public async resolveCredentialDefinition(id: string): Promise { - const result = await this.instance.resolveCredentialDefinition(id) - return mapCredentialDefinitionRecord(result) + public async createCredentialDefinitionSigned( + identity: string, + id: string, + schemaId: string, + credDef: string, + signature: Signature, + ) { + const tx = await this.instance.createCredentialDefinitionSigned( + identity, + signature.v, + signature.r, + signature.s, + keccak256(toUtf8Bytes(id)), + 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 filer = await this.instance.filters.CredentialDefinitionCreated(keccak256(toUtf8Bytes(id))) + const events = await this.instance.queryFilter(filer) + return toUtf8String(getBytes(events[0].args[2])) } } diff --git a/smart_contracts/contracts-ts/EthereumDIDRegistry.ts b/smart_contracts/contracts-ts/EthereumExtDidRegistry.ts similarity index 83% rename from smart_contracts/contracts-ts/EthereumDIDRegistry.ts rename to smart_contracts/contracts-ts/EthereumExtDidRegistry.ts index ea36fe43..02d3f68d 100644 --- a/smart_contracts/contracts-ts/EthereumDIDRegistry.ts +++ b/smart_contracts/contracts-ts/EthereumExtDidRegistry.ts @@ -1,16 +1,21 @@ +import { encodeBytes32String, toUtf8Bytes } from 'ethers' import { Contract } from '../utils/contract' -export class EthereumDIDRegistry extends Contract { +export class EthereumExtDidRegistry extends Contract { public static readonly defaultAddress = '0x0000000000000000000000000000000000018888' constructor(sender?: any) { - super(EthereumDIDRegistry.name, sender) + super(EthereumExtDidRegistry.name, sender) } public async identityOwner(identity: string): Promise { return await this.instance.identityOwner(identity) } + public async changed(identity: string) { + return await this.instance.changed(identity) + } + public async changeOwner(identity: string, newOwner: string) { const tx = await this.instance.changeOwner(identity, newOwner) return tx.wait() @@ -30,13 +35,13 @@ export class EthereumDIDRegistry extends Contract { return tx.wait() } - public async setAttribute(identity: string, name: string, value: Uint8Array, validity: number) { - const tx = await this.instance.setAttribute(identity, name, value, validity) + public async setAttribute(identity: string, name: string, value: string, validity: number) { + const tx = await this.instance.setAttribute(identity, encodeBytes32String(name), toUtf8Bytes(value), validity) return tx.wait() } - public async revokeAttribute(identity: string, name: string, value: Uint8Array) { - const tx = await this.instance.revokeAttribute(identity, name, value) + public async revokeAttribute(identity: string, name: string, value: string) { + const tx = await this.instance.revokeAttribute(identity, encodeBytes32String(name), toUtf8Bytes(value)) return tx.wait() } diff --git a/smart_contracts/contracts-ts/SchemaRegistry.ts b/smart_contracts/contracts-ts/SchemaRegistry.ts index fb017ad5..41b5fba7 100644 --- a/smart_contracts/contracts-ts/SchemaRegistry.ts +++ b/smart_contracts/contracts-ts/SchemaRegistry.ts @@ -1,5 +1,6 @@ +import { getBytes, keccak256, Signature, toUtf8Bytes, toUtf8String } from 'ethers' +import { SchemaCreatedEvent } from '../typechain-types/contracts/cl/SchemaRegistryInterface' import { Contract } from '../utils/contract' -import { mapSchemaRecord, SchemaRecord } from './types' export class SchemaRegistry extends Contract { public static readonly defaultAddress = '0x0000000000000000000000000000000000005555' @@ -8,13 +9,30 @@ export class SchemaRegistry extends Contract { super(SchemaRegistry.name, sender) } - public async createSchema(id: string, issuerId: string, schema: string) { - const tx = await this.instance.createSchema(id, issuerId, schema) + public async createSchema(identity: string, id: string, schema: string) { + const tx = await this.instance.createSchema(identity, keccak256(toUtf8Bytes(id)), toUtf8Bytes(schema)) return tx.wait() } - public async resolveSchema(id: string): Promise { - const result = await this.instance.resolveSchema(id) - return mapSchemaRecord(result) + public async createSchemaSigned(identity: string, id: string, schema: string, signature: Signature) { + const tx = await this.instance.createSchemaSigned( + identity, + signature.v, + signature.r, + signature.s, + keccak256(toUtf8Bytes(id)), + toUtf8Bytes(schema), + ) + return tx.wait() + } + + public async created(id: string): Promise { + return this.instance.created(keccak256(toUtf8Bytes(id))) + } + + 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])) } } diff --git a/smart_contracts/contracts-ts/index.ts b/smart_contracts/contracts-ts/index.ts index e322b9bf..5666ab2c 100644 --- a/smart_contracts/contracts-ts/index.ts +++ b/smart_contracts/contracts-ts/index.ts @@ -1,10 +1,7 @@ export * from './AccountControl' export * from './CredentialDefinitionRegistry' -export * from './IndyDidRegistry' -export * from './EthereumDIDRegistry' +export * from './EthereumExtDidRegistry' export * from './RoleControl' export * from './SchemaRegistry' -export * from './UniversalDidReolver' export * from './UpgradeControl' export * from './ValidatorControl' -export * from './types' diff --git a/smart_contracts/contracts/cl/CLRegistry.sol b/smart_contracts/contracts/cl/CLRegistry.sol index 8692d595..5e098a6f 100644 --- a/smart_contracts/contracts/cl/CLRegistry.sol +++ b/smart_contracts/contracts/cl/CLRegistry.sol @@ -1,34 +1,33 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.20; -import { DidNotFound, IncorrectDid } 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, UnauthorizedIssuer } from "./ClErrors.sol"; +import { UnauthorizedIssuer } from "./ClErrors.sol"; +import { EthereumExtDidRegistry } from "../did/EthereumExtDidRegistry.sol"; contract CLRegistry { /** - * @dev Reference to the contract that resolves DIDs + * @dev Reference to the DID registry contract */ - UniversalDidResolverInterface internal _didResolver; + EthereumExtDidRegistry internal _didRegistry; - /** - * @dev Check that the Issuer DID exist, authorized for sender, and active. - * @param id The Issuer's DID. - */ - modifier _validIssuer(string memory id) { - try _didResolver.resolveMetadata(id) returns (DidMetadata memory metadata) { - if (msg.sender != metadata.owner && msg.sender != metadata.sender) { - revert UnauthorizedIssuer(msg.sender); - } - if (metadata.deactivated) revert IssuerHasBeenDeactivated(id); - } catch (bytes memory reason) { - if (Errors.equals(reason, DidNotFound.selector)) revert IssuerNotFound(id); - if (Errors.equals(reason, IncorrectDid.selector)) revert InvalidIssuerId(id); - - Errors.rethrow(reason); + modifier _validIssuer(address identity, address actor) { + if (actor != _didRegistry.identityOwner(identity)) { + revert UnauthorizedIssuer(identity, actor); } _; } + + function _checkSignature( + 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); + } + return signer; + } } diff --git a/smart_contracts/contracts/cl/ClErrors.sol b/smart_contracts/contracts/cl/ClErrors.sol index 76371fe4..d01b6324 100644 --- a/smart_contracts/contracts/cl/ClErrors.sol +++ b/smart_contracts/contracts/cl/ClErrors.sol @@ -1,66 +1,36 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.20; -/** - * @notice Error that occurs when the specified issuer is not found. - * @param id Issuer ID. - */ -error IssuerNotFound(string id); - -/** - * @notice Error that occurs when the provided issuer ID is invalid. - * @param id Issuer ID. - */ -error InvalidIssuerId(string id); - -/** - * @notice Error that occurs when attempting to perform an operation on a deactivated issuer. - * @param id Issuer ID. - */ -error IssuerHasBeenDeactivated(string id); - // Schema errors -/** - * @notice Error that occurs when the provided schema ID is invalid. - * @param id Schema ID. - */ -error InvalidSchemaId(string id); - /** * @notice Error that occurs when trying to create an already existing schema. * @param id Schema ID. */ -error SchemaAlreadyExist(string id); +error SchemaAlreadyExist(bytes32 id); /** * @notice Error that occurs when the specified schema is not found. * @param id Schema ID. */ -error SchemaNotFound(string id); +error SchemaNotFound(bytes32 id); // CredDef errors -/** - * @notice Error that occurs when the provided credential definition ID is invalid. - * @param id Credential definition ID. - */ -error InvalidCredentialDefinitionId(string id); - /** * @notice Error that occurs when trying to create an existing credential definition. * @param id Credential definition ID. */ -error CredentialDefinitionAlreadyExist(string id); +error CredentialDefinitionAlreadyExist(bytes32 id); /** * @notice Error that occurs when the specified credential definition is not found. * @param id Credential definition ID. */ -error CredentialDefinitionNotFound(string 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); +error UnauthorizedIssuer(address sender, address owner); diff --git a/smart_contracts/contracts/cl/CredentialDefinitionRegistry.sol b/smart_contracts/contracts/cl/CredentialDefinitionRegistry.sol index 91a60c62..854d9da3 100644 --- a/smart_contracts/contracts/cl/CredentialDefinitionRegistry.sol +++ b/smart_contracts/contracts/cl/CredentialDefinitionRegistry.sol @@ -1,17 +1,13 @@ // 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 { CredentialDefinitionValidator } from "./CredentialDefinitionValidator.sol"; -import { CredentialDefinitionAlreadyExist, CredentialDefinitionNotFound } from "./ClErrors.sol"; +import { CredentialDefinitionAlreadyExist, SchemaNotFound } from "./ClErrors.sol"; import { CLRegistry } from "./CLRegistry.sol"; import { SchemaRegistryInterface } from "./SchemaRegistryInterface.sol"; - -using CredentialDefinitionValidator for string; +import { EthereumExtDidRegistry } from "../did/EthereumExtDidRegistry.sol"; contract CredentialDefinitionRegistry is CredentialDefinitionRegistryInterface, ControlledUpgradeable, CLRegistry { /** @@ -20,63 +16,79 @@ contract CredentialDefinitionRegistry is CredentialDefinitionRegistryInterface, SchemaRegistryInterface private _schemaRegistry; /** - * Mapping Credential Definition ID to its Credential Definition Details and Metadata. + * Mapping to track created created credential definitions by their id to block number. */ - mapping(string id => CredentialDefinitionRecord credentialDefinitionRecord) private _credDefs; + mapping(bytes32 id => uint block) public created; /** * Checks the uniqueness of the credential definition ID */ - modifier _uniqueCredDefId(string memory id) { - if (_credDefs[id].metadata.created != 0) revert CredentialDefinitionAlreadyExist(id); - _; - } - - /** - * Checks that the credential definition exist - */ - modifier _credDefExist(string memory id) { - if (_credDefs[id].metadata.created == 0) revert CredentialDefinitionNotFound(id); + modifier _uniqueCredDefId(bytes32 id) { + if (created[id] != 0) revert CredentialDefinitionAlreadyExist(id); _; } /** - * Сhecks that the schema exist + * Checks that the schema exist */ - modifier _schemaExist(string memory id) { - _schemaRegistry.resolveSchema(id); + modifier _schemaExist(bytes32 id) { + if (_schemaRegistry.created(id) == 0) revert SchemaNotFound(id); _; } function initialize( address upgradeControlAddress, - address didResolverAddress, + address ethereumExtDidRegistry, address schemaRegistryAddress ) public reinitializer(1) { _initializeUpgradeControl(upgradeControlAddress); - _didResolver = UniversalDidResolverInterface(didResolverAddress); + _didRegistry = EthereumExtDidRegistry(ethereumExtDidRegistry); _schemaRegistry = SchemaRegistryInterface(schemaRegistryAddress); } /// @inheritdoc CredentialDefinitionRegistryInterface function createCredentialDefinition( - string calldata id, - string calldata issuerId, - string calldata schemaId, - string calldata credDef - ) public virtual _uniqueCredDefId(id) _schemaExist(schemaId) _validIssuer(issuerId) { - id.validateIdSyntax(issuerId, schemaId); - - _credDefs[id].credDef = credDef; - _credDefs[id].metadata.created = block.timestamp; - - emit CredentialDefinitionCreated(id); + address identity, + bytes32 id, + bytes32 schemaId, + bytes calldata credDef + ) public virtual { + _createCredentialDefinition(identity, msg.sender, id, schemaId, credDef); } /// @inheritdoc CredentialDefinitionRegistryInterface - function resolveCredentialDefinition( - string calldata id - ) public view virtual _credDefExist(id) returns (CredentialDefinitionRecord memory credentialDefinitionRecord) { - return _credDefs[id]; + function createCredentialDefinitionSigned( + address identity, + uint8 sigV, + bytes32 sigR, + bytes32 sigS, + bytes32 id, + bytes32 schemaId, + bytes calldata credDef + ) public virtual { + bytes32 hash = keccak256( + abi.encodePacked( + bytes1(0x19), + bytes1(0), + address(this), + identity, + "createCredentialDefinition", + id, + schemaId, + credDef + ) + ); + _createCredentialDefinition(identity, _checkSignature(identity, hash, sigV, sigR, sigS), id, schemaId, credDef); + } + + function _createCredentialDefinition( + address identity, + address actor, + bytes32 id, + bytes32 schemaId, + bytes calldata credDef + ) internal _uniqueCredDefId(id) _validIssuer(identity, actor) _schemaExist(schemaId) { + created[id] = block.number; + emit CredentialDefinitionCreated(id, actor, credDef); } } diff --git a/smart_contracts/contracts/cl/CredentialDefinitionRegistryInterface.sol b/smart_contracts/contracts/cl/CredentialDefinitionRegistryInterface.sol index 37497641..18e5248b 100644 --- a/smart_contracts/contracts/cl/CredentialDefinitionRegistryInterface.sol +++ b/smart_contracts/contracts/cl/CredentialDefinitionRegistryInterface.sol @@ -1,15 +1,15 @@ // 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 credentialDefinitionId ID of created credential definition + * @param id KECCAK256 hash of credential definition id. + * @param identity Account address of credential definition issuer. + * @param credDef AnonCreds credential definition object as bytes. */ - event CredentialDefinitionCreated(string credentialDefinitionId); + event CredentialDefinitionCreated(bytes32 indexed id, address identity, bytes credDef); /** * @dev Creates a new Credential Definition. @@ -20,33 +20,53 @@ interface CredentialDefinitionRegistryInterface { * 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. - * - `IssuerNotFound`: Raised if the associated issuer doesn't exist. - * - `IssuerHasBeenDeactivated`: Raised if the associated issuer is not active. - * - `InvalidCredentialDefinitionId`: Raised if the Credential Definition ID syntax is invalid. * - `UnauthorizedIssuer`: Raised when an issuer DID specified in CredentialDefinition is not owned by sender * - * @param id Id of credential definition to be created. - * @param issuerId Id of credential definition issuer. - * @param schemaId Id of credential definition schema. - * @param credDef AnonCreds credential definition as JSON string. + * @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. */ function createCredentialDefinition( - string calldata id, - string calldata issuerId, - string calldata schemaId, - string calldata credDef + address identity, + bytes32 id, + bytes32 schemaId, + bytes calldata credDef ) external; /** - * @dev Resolve the Credential Definition associated with the given ID. + * @dev Endorse a new Credential Definition. + * + * Once the Credential Definition is created, this function emits a `CredentialDefinitionCreated` event + * with the new Credential Definition's ID. * - * If no matching Credential Definition is found, the function revert with `CredentialDefinitionNotFound` error + * 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 * - * @param id The ID of the Credential Definition to be resolved. + * @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. + */ + function createCredentialDefinitionSigned( + address identity, + uint8 sigV, + bytes32 sigR, + bytes32 sigS, + bytes32 id, + bytes32 schemaId, + bytes calldata credDef + ) external; + + /** + * @dev Get the block number when a schema was created. * - * @return credentialDefinitionRecord Returns the credential definition with metadata. + * @param id KECCAK256 hash of credential definition id. */ - function resolveCredentialDefinition( - string calldata id - ) external returns (CredentialDefinitionRecord memory credentialDefinitionRecord); + function created(bytes32 id) external returns (uint256 block); } diff --git a/smart_contracts/contracts/cl/CredentialDefinitionTypes.sol b/smart_contracts/contracts/cl/CredentialDefinitionTypes.sol deleted file mode 100644 index 6811749d..00000000 --- a/smart_contracts/contracts/cl/CredentialDefinitionTypes.sol +++ /dev/null @@ -1,25 +0,0 @@ -// 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 as a JSON string. - * @param metadata - Additional metadata associated with the credential definition. - */ -struct CredentialDefinitionRecord { - string 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/CredentialDefinitionValidator.sol b/smart_contracts/contracts/cl/CredentialDefinitionValidator.sol deleted file mode 100644 index a311f0c8..00000000 --- a/smart_contracts/contracts/cl/CredentialDefinitionValidator.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.20; - -import { InvalidCredentialDefinitionId } from "./ClErrors.sol"; - -import { toSlice } from "@dk1a/solidity-stringutils/src/StrSlice.sol"; - -using { toSlice } for string; - -library CredentialDefinitionValidator { - string private constant _DELIMITER = "/"; - string private constant _CRED_DEF_ID_MIDDLE_PART = "/anoncreds/v0/CLAIM_DEF/"; - string private constant _ANONCREDS_TYPE = "CL"; - - /** - * @dev Validates the Credential Definition ID syntax - */ - function validateIdSyntax(string memory self, string calldata issuerId, string calldata schemaId) internal pure { - string memory credDefId = string.concat(issuerId, _CRED_DEF_ID_MIDDLE_PART, schemaId, _DELIMITER); - - if (!self.toSlice().startsWith(credDefId.toSlice())) revert InvalidCredentialDefinitionId(self); - } -} diff --git a/smart_contracts/contracts/cl/SchemaRegistry.sol b/smart_contracts/contracts/cl/SchemaRegistry.sol index a60f7106..dae52e7d 100644 --- a/smart_contracts/contracts/cl/SchemaRegistry.sol +++ b/smart_contracts/contracts/cl/SchemaRegistry.sol @@ -1,62 +1,59 @@ // 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, SchemaNotFound } from "./ClErrors.sol"; +import { SchemaAlreadyExist } from "./ClErrors.sol"; import { SchemaRegistryInterface } from "./SchemaRegistryInterface.sol"; -import { SchemaRecord } from "./SchemaTypes.sol"; -import { SchemaValidator } from "./SchemaValidator.sol"; import { CLRegistry } from "./CLRegistry.sol"; - -using SchemaValidator for string; +import { EthereumExtDidRegistry } from "../did/EthereumExtDidRegistry.sol"; contract SchemaRegistry is SchemaRegistryInterface, ControlledUpgradeable, CLRegistry { /** - * Mapping Schema ID to its Schema Details and Metadata. + * Mapping to track created schemas by their id to the block number when it was created. */ - mapping(string id => SchemaRecord SchemaRecord) private _schemas; + mapping(bytes32 id => uint block) public created; /** * Checks the uniqueness of the Schema ID */ - modifier _uniqueSchemaId(string memory id) { - if (_schemas[id].metadata.created != 0) revert SchemaAlreadyExist(id); - _; - } - - /** - * Checks that the Schema exist - */ - modifier _schemaExist(string memory id) { - if (_schemas[id].metadata.created == 0) revert SchemaNotFound(id); + modifier _uniqueSchemaId(bytes32 id) { + if (created[id] != 0) revert SchemaAlreadyExist(id); _; } - function initialize(address upgradeControlAddress, address didResolverAddress) public reinitializer(1) { + function initialize(address upgradeControlAddress, address ethereumExtDidRegistry) public reinitializer(1) { _initializeUpgradeControl(upgradeControlAddress); - _didResolver = UniversalDidResolverInterface(didResolverAddress); + _didRegistry = EthereumExtDidRegistry(ethereumExtDidRegistry); } /// @inheritdoc SchemaRegistryInterface - function createSchema( - string calldata id, - string calldata issuerId, - string calldata schema - ) public virtual _uniqueSchemaId(id) _validIssuer(issuerId) { - id.validateIdSyntax(issuerId); - - _schemas[id].schema = schema; - _schemas[id].metadata.created = block.timestamp; - - emit SchemaCreated(id); + function createSchema(address identity, bytes32 id, bytes calldata schema) public virtual { + _createSchema(identity, msg.sender, id, schema); } /// @inheritdoc SchemaRegistryInterface - function resolveSchema( - string calldata id - ) public view virtual _schemaExist(id) returns (SchemaRecord memory schemaRecord) { - return _schemas[id]; + function createSchemaSigned( + address identity, + uint8 sigV, + bytes32 sigR, + bytes32 sigS, + bytes32 id, + bytes calldata schema + ) public virtual { + bytes32 hash = keccak256( + abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createSchema", id, schema) + ); + _createSchema(identity, _checkSignature(identity, hash, sigV, sigR, sigS), id, schema); + } + + function _createSchema( + address identity, + address actor, + bytes32 id, + bytes calldata schema + ) internal _uniqueSchemaId(id) _validIssuer(identity, actor) { + created[id] = block.number; + emit SchemaCreated(id, actor, schema); } } diff --git a/smart_contracts/contracts/cl/SchemaRegistryInterface.sol b/smart_contracts/contracts/cl/SchemaRegistryInterface.sol index 2a9ba4d4..c1c8f5cf 100644 --- a/smart_contracts/contracts/cl/SchemaRegistryInterface.sol +++ b/smart_contracts/contracts/cl/SchemaRegistryInterface.sol @@ -1,15 +1,15 @@ // 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 schemaId Created Schema ID + * @param id KECCAK256 hash of created schema id. + * @param identity Account address of schema issuer . + * @param schema AnonCreds schema object as bytes. */ - event SchemaCreated(string schemaId); + event SchemaCreated(bytes32 indexed id, address identity, bytes schema); /** * @dev Creates a new Schema. @@ -19,24 +19,44 @@ interface SchemaRegistryInterface { * * This function can revert with following errors: * - `SchemaAlreadyExist`: Raised if Schema with provided ID already exist. - * - `IssuerNotFound`: Raised if the associated issuer doesn't exist. - * - `IssuerHasBeenDeactivated`: Raised if the associated issuer is not active. * - `UnauthorizedIssuer`: Raised when an issuer DID specified in Schema is not owned by sender * - * @param id Id of schema to be created. - * @param issuerId Id of schema issuer. - * @param schema AnonCreds schema as JSON string. + * @param identity Account address of schema issuer. + * @param id KECCAK256 hash of schema id to be created. + * @param schema AnonCreds schema object as bytes. */ - function createSchema(string calldata id, string calldata issuerId, string calldata schema) external; + function createSchema(address identity, bytes32 id, bytes calldata schema) external; /** - * @dev Resolve the Schema associated with the given ID. + * @dev Endorse a new Schema. * - * If no matching Schema is found, the function revert with `SchemaNotFound` error + * Once the Schema is created, this function emits a `SchemaCreated` event + * with the new Schema ID. + * + * 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 * - * @param id The ID of the Schema to be resolved. + * @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. + */ + function createSchemaSigned( + address identity, + uint8 sigV, + bytes32 sigR, + bytes32 sigS, + bytes32 id, + bytes calldata schema + ) external; + + /** + * @dev Get the block number when a schema was created. * - * @return schemaRecord Returns the Schema with Metadata. + * @param id KECCAK256 hash of schema id. */ - function resolveSchema(string calldata id) external returns (SchemaRecord memory schemaRecord); + function created(bytes32 id) external returns (uint256 block); } diff --git a/smart_contracts/contracts/cl/SchemaTypes.sol b/smart_contracts/contracts/cl/SchemaTypes.sol deleted file mode 100644 index 56688e0e..00000000 --- a/smart_contracts/contracts/cl/SchemaTypes.sol +++ /dev/null @@ -1,25 +0,0 @@ -// 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 as a JSON string. - * @param metadata - Additional metadata associated with the schema. - */ -struct SchemaRecord { - string 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/cl/SchemaValidator.sol b/smart_contracts/contracts/cl/SchemaValidator.sol deleted file mode 100644 index 7be6215d..00000000 --- a/smart_contracts/contracts/cl/SchemaValidator.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.20; - -import { InvalidSchemaId } from "./ClErrors.sol"; - -import { toSlice } from "@dk1a/solidity-stringutils/src/StrSlice.sol"; - -using { toSlice } for string; - -library SchemaValidator { - string private constant _DELIMITER = "/"; - string private constant _SCHEMA_ID_MIDDLE_PART = "/anoncreds/v0/SCHEMA/"; - - /** - * @dev Validates the Schema ID syntax - */ - function validateIdSyntax(string memory self, string calldata issuerId) internal pure { - string memory schemaId = string.concat(issuerId, _SCHEMA_ID_MIDDLE_PART); - - if (!self.toSlice().startsWith(schemaId.toSlice())) revert InvalidSchemaId(self); - } -} diff --git a/smart_contracts/contracts/did/DidErrors.sol b/smart_contracts/contracts/did/DidErrors.sol deleted file mode 100644 index 4c0a5ae2..00000000 --- a/smart_contracts/contracts/did/DidErrors.sol +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.20; - -/** - * @dev Error that occurs when the specified DID is not found. - */ -error DidNotFound(string did); - -/** - * @dev Error that occurs when trying to create an already existing DID. - */ -error DidAlreadyExist(string did); - -/** - * @dev Error that occurs when trying to perform an operation with a deactivated DID. - */ -error DidHasBeenDeactivated(string did); - -/** - * @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); diff --git a/smart_contracts/contracts/did/DidTypes.sol b/smart_contracts/contracts/did/DidTypes.sol deleted file mode 100644 index 6e6ede82..00000000 --- a/smart_contracts/contracts/did/DidTypes.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.20; - -/** - * @dev DidRecord holds the DID Document and its associated metadata - */ -struct DidRecord { - string document; - DidMetadata metadata; -} - -/** - * @dev DidMetadata holds additional properties associated with the DID - */ -struct DidMetadata { - address owner; - address sender; - uint256 created; - uint256 updated; - bool deactivated; -} diff --git a/smart_contracts/contracts/did/IndyDidRegistry.sol b/smart_contracts/contracts/did/IndyDidRegistry.sol deleted file mode 100644 index ff581359..00000000 --- a/smart_contracts/contracts/did/IndyDidRegistry.sol +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.20; - -import { ControlledUpgradeable } from "../upgrade/ControlledUpgradeable.sol"; - -import { DidAlreadyExist, DidHasBeenDeactivated, DidNotFound, UnauthorizedSender } from "./DidErrors.sol"; -import { IndyDidRegistryInterface } from "./IndyDidRegistryInterface.sol"; -import { DidRecord } from "./DidTypes.sol"; -import { IndyDidValidator } from "./IndyDidValidator.sol"; - -contract IndyDidRegistry is IndyDidRegistryInterface, ControlledUpgradeable { - /** - * @dev Mapping DID to its corresponding DID Document/Metadata. - */ - mapping(string did => DidRecord didRecord) private _dids; - - /** - * Checks that DID already exists - */ - modifier _didExist(string memory did) { - if (_dids[did].metadata.created == 0) revert DidNotFound(did); - _; - } - - /** - * Checks that the DID has not yet been added - */ - modifier _didNotExist(string memory did) { - if (_dids[did].metadata.created != 0) revert DidAlreadyExist(did); - _; - } - - /** - * Checks that the DID has not been deactivated - */ - modifier _didIsActive(string memory did) { - if (_dids[did].metadata.deactivated) revert DidHasBeenDeactivated(did); - _; - } - - /** - * Checks that method was called either by did owner or sender - */ - modifier _senderIsAuthorized(string memory did) { - // FIXME: once we add strict role and endorsement, the check here should be either owner or Trustee - if (msg.sender != _dids[did].metadata.owner && msg.sender != _dids[did].metadata.sender) - revert UnauthorizedSender(msg.sender); - _; - } - - function initialize(address upgradeControlAddress) public reinitializer(1) { - _initializeUpgradeControl(upgradeControlAddress); - } - - /// @inheritdoc IndyDidRegistryInterface - function createDid(address identity, string calldata did, string calldata document) public _didNotExist(did) { - IndyDidValidator.validateDidSyntax(did); - - _dids[did].document = document; - _dids[did].metadata.owner = identity; - _dids[did].metadata.sender = msg.sender; - _dids[did].metadata.created = block.timestamp; - _dids[did].metadata.updated = block.timestamp; - - emit DIDCreated(did); - } - - /// @inheritdoc IndyDidRegistryInterface - function updateDid( - string calldata did, - string calldata document - ) public _didExist(did) _didIsActive(did) _senderIsAuthorized(did) { - _dids[did].document = document; - _dids[did].metadata.updated = block.timestamp; - - emit DIDUpdated(did); - } - - /// @inheritdoc IndyDidRegistryInterface - function deactivateDid(string calldata did) public _didExist(did) _didIsActive(did) _senderIsAuthorized(did) { - _dids[did].metadata.deactivated = true; - - emit DIDDeactivated(did); - } - - /// @inheritdoc IndyDidRegistryInterface - function resolveDid(string calldata did) public view virtual _didExist(did) returns (DidRecord memory didRecord) { - return _dids[did]; - } -} diff --git a/smart_contracts/contracts/did/IndyDidRegistryInterface.sol b/smart_contracts/contracts/did/IndyDidRegistryInterface.sol deleted file mode 100644 index 3e8765eb..00000000 --- a/smart_contracts/contracts/did/IndyDidRegistryInterface.sol +++ /dev/null @@ -1,83 +0,0 @@ -// 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 did Created DID. - */ - event DIDCreated(string did); - - /** - * @dev Event that is sent when a DID Document is updated. - * - * @param did Updated DID. - */ - event DIDUpdated(string did); - - /** - * @dev Event that is sent when a DID Document is deactivated. - * - * @param did Deactivated DID. - */ - event DIDDeactivated(string did); - - /** - * @dev Creates a new DID. - * - * @param identity Address of DID owner. - * @param did The new DID. - * @param document The new DID Document as JSON string. - */ - function createDid(address identity, string calldata did, string calldata document) external; - - /** - * @dev Updates an existing DID. - * - * Restrictions: - * - * - DID must not already exist; otherwise, will revert with a `DidAlreadyExist` 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. - * - * Events: - * - On successful DID update, will emit a `DIDUpdated` event. - * - * @param did The DID to update. - * @param document The updated DID Document as JSON string. - */ - function updateDid(string calldata did, string calldata document) external; - - /** - * @dev Deactivates a 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. - * - * Events: - * - On successful DID deactivation, will emit a `DIDDeactivated` event. - * - * @param did The DID to be deactivated. - */ - function deactivateDid(string calldata did) external; - - /** - * @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 didRecord The resolved DID document associated with provided DID. - */ - function resolveDid(string calldata did) external view returns (DidRecord memory didRecord); -} diff --git a/smart_contracts/contracts/did/IndyDidValidator.sol b/smart_contracts/contracts/did/IndyDidValidator.sol deleted file mode 100644 index 2caa5ad5..00000000 --- a/smart_contracts/contracts/did/IndyDidValidator.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.20; - -import { StringUtils } from "../utils/StringUtils.sol"; -import { DidUtils, ParsedDid } from "../utils/DidUtils.sol"; -import { IncorrectDid } from "./DidErrors.sol"; - -using StringUtils for string; - -library IndyDidValidator { - function validateDidSyntax(string memory did) public view { - ParsedDid memory parsedDid = DidUtils.parseDid(did); - - if (!DidUtils.isIndyMethod(parsedDid.method)) revert IncorrectDid(did); - - uint256 identifierLength = parsedDid.identifier.length(); - if (identifierLength != 21 && identifierLength != 22) revert IncorrectDid(did); - } -} diff --git a/smart_contracts/contracts/did/UniversalDidResolver.sol b/smart_contracts/contracts/did/UniversalDidResolver.sol deleted file mode 100644 index 9752a8f0..00000000 --- a/smart_contracts/contracts/did/UniversalDidResolver.sol +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.20; - -import { ControlledUpgradeable } from "../upgrade/ControlledUpgradeable.sol"; -import { UnsupportedOperation } from "../utils/Errors.sol"; -import { DidUtils, ParsedDid } from "../utils/DidUtils.sol"; -import { IncorrectDid } from "./DidErrors.sol"; -import { IndyDidRegistryInterface } from "./IndyDidRegistryInterface.sol"; -import { EthereumExtDidRegistry } from "./EthereumExtDidRegistry.sol"; -import { DidMetadata } from "./DidTypes.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 (string memory document) { - ParsedDid memory parsedDid = DidUtils.parseDid(did); - - if (DidUtils.isIndyMethod(parsedDid.method)) { - return _indyDidRegistry.resolveDid(did).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); - - if (DidUtils.isEthereumMethod(parsedDid.method)) { - address identity = DidUtils.convertEthereumIdentifierToAddress(parsedDid.identifier); - - if (identity == address(0)) revert IncorrectDid(did); - - address identityOwner = _ethereumDIDRegistry.identityOwner(identity); - return DidMetadata(identityOwner, address(0), 0, 0, false); - } else if (DidUtils.isIndyMethod(parsedDid.method)) { - return _indyDidRegistry.resolveDid(did).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 deleted file mode 100644 index 8306a05a..00000000 --- a/smart_contracts/contracts/did/UniversalDidResolverInterface.sol +++ /dev/null @@ -1,33 +0,0 @@ -// 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 memory did) external view returns (string 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 memory did) external view returns (DidMetadata memory metadata); -} diff --git a/smart_contracts/contracts/network/ValidatorControlInterface.sol b/smart_contracts/contracts/network/ValidatorControlInterface.sol index fbf04b74..89d54aa3 100644 --- a/smart_contracts/contracts/network/ValidatorControlInterface.sol +++ b/smart_contracts/contracts/network/ValidatorControlInterface.sol @@ -66,12 +66,6 @@ interface ValidatorControlInterface { */ error ValidatorNotFound(address validator); - /** - * @dev Gets the list of active validators. - * @return A array of the active validators. - */ - function getValidators() external view returns (address[] memory); - /** * @dev Adds a new validator to the list. * @@ -104,4 +98,10 @@ interface ValidatorControlInterface { * - On successful validator removal, will emit a `ValidatorRemoved` event. */ function removeValidator(address validator) external; + + /** + * @dev Gets the list of active validators. + * @return A array of the active validators. + */ + function getValidators() external view returns (address[] memory); } diff --git a/smart_contracts/contracts/utils/DidUtils.sol b/smart_contracts/contracts/utils/DidUtils.sol deleted file mode 100644 index 88fc4b63..00000000 --- a/smart_contracts/contracts/utils/DidUtils.sol +++ /dev/null @@ -1,88 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.20; - -import { StrSlice, toSlice } from "@dk1a/solidity-stringutils/src/StrSlice.sol"; -import { IncorrectDid } from "../did/DidErrors.sol"; -import { StringUtils } from "./StringUtils.sol"; - -string constant DID_ETHR_METHOD = "ethr"; -string constant DID_INDY_METHOD = "indy"; -string constant DID_INDY_2_METHOD = "indy2"; -string constant DID_SOV_METHOD = "sov"; - -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 identifier, `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 any of the Indy method identifiers. - * @param method The method string to check. - * @return Returns `true` if the method string matches any of the Indy method identifiers, `false` otherwise. - */ - function isIndyMethod(string memory method) internal pure returns (bool) { - StrSlice methodSlice = method.toSlice(); - return - methodSlice.eq(DID_INDY_METHOD.toSlice()) || - methodSlice.eq(DID_INDY_2_METHOD.toSlice()) || - methodSlice.eq(DID_SOV_METHOD.toSlice()); - } -} diff --git a/smart_contracts/contracts/utils/Errors.sol b/smart_contracts/contracts/utils/Errors.sol index c0f892ea..2fbb5bc7 100644 --- a/smart_contracts/contracts/utils/Errors.sol +++ b/smart_contracts/contracts/utils/Errors.sol @@ -1,25 +1,6 @@ // 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. diff --git a/smart_contracts/contracts/utils/StringUtils.sol b/smart_contracts/contracts/utils/StringUtils.sol index befad2ff..a03610c0 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 { StrSlice, toSlice } from "@dk1a/solidity-stringutils/src/StrSlice.sol"; +import { toSlice } from "@dk1a/solidity-stringutils/src/StrSlice.sol"; using { toSlice } for string; @@ -51,46 +51,4 @@ library StringUtils { function hasHexPrefix(string memory str) internal pure returns (bool) { return str.toSlice().startsWith(_HEX_PREFIX.toSlice()); } - - /** - * @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; - } - - /** - * 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 deleted file mode 100644 index dca26e7e..00000000 --- a/smart_contracts/demos/flow-with-did-ethr.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { encodeBytes32String, toUtf8Bytes } from 'ethers' -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, - encodeBytes32String('did/svc/did-communication'), - toUtf8Bytes('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, - encodeBytes32String('did/svc/did-communication'), - toUtf8Bytes('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(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( - 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 9567aff0..b102a9ce 100644 --- a/smart_contracts/demos/flow.ts +++ b/smart_contracts/demos/flow.ts @@ -2,6 +2,7 @@ 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 @@ -9,59 +10,71 @@ 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. Faber creates DID Document') - receipt = await faber.didRegistry.createDid(faber.address, faber.did, faber.didDocument) - console.log(`Did Document created for DID ${faber.did}. 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('3. Faber creates Test Schema') - const { id: schemaId, schema } = createSchemaObject({ issuerId: faber.did }) - receipt = await faber.schemaRegistry.createSchema(schemaId, faber.did, schema) + 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(`Schema created for id ${schemaId}. Receipt: ${JSON.stringify(receipt)}`) - 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('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('5. Faber create Test Credential Definition') + 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.did, + issuer: faber.address, 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('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.did) - console.log(`Did Document resolved for ${faber.did}. DID Document: ${faberDidDocument?.document}`) + 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('8. Alice resolves Test Schema') - const testSchema = await alice.schemaRegistry.resolveSchema(schemaId) - console.log(`Schema resolved for ${schemaId}. Schema: ${testSchema.schema}`) + const testResolvedSchema = await alice.schemaRegistry.resolveSchema(schemaId) + console.log(`Schema resolved for ${schemaId}. Schema: ${testResolvedSchema}`) console.log('9. Alice resolves Test Credential Definition') - const testCredentialDefinition = await alice.credentialDefinitionRegistry.resolveCredentialDefinition( + const testResolvedCredDef = await alice.credentialDefinitionRegistry.resolveCredentialDefinition( credentialDefinitionId, ) console.log( - `Credential Definition resolved for ${credentialDefinitionId}. Credential Definition: ${testCredentialDefinition.credDef}`, + `Credential Definition resolved for ${credentialDefinitionId}. Credential Definition: ${testResolvedCredDef}`, ) } diff --git a/smart_contracts/demos/utils/actor.ts b/smart_contracts/demos/utils/actor.ts index bdb7f59b..c1df3607 100644 --- a/smart_contracts/demos/utils/actor.ts +++ b/smart_contracts/demos/utils/actor.ts @@ -1,11 +1,10 @@ import { RoleControl, - IndyDidRegistry, SchemaRegistry, CredentialDefinitionRegistry, ValidatorControl, UpgradeControl, - EthereumDIDRegistry, + EthereumExtDidRegistry, } from '../../contracts-ts' import { Account, AccountInfo } from '../../utils' @@ -13,8 +12,7 @@ export class Actor { public account: Account public roleControl!: RoleControl public validatorControl!: ValidatorControl - public didRegistry!: IndyDidRegistry - public ethereumDIDRegistry!: EthereumDIDRegistry + public ethereumDIDRegistry!: EthereumExtDidRegistry public schemaRegistry!: SchemaRegistry public credentialDefinitionRegistry!: CredentialDefinitionRegistry public upgradeControl!: UpgradeControl @@ -26,9 +24,8 @@ 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 EthereumDIDRegistry(this.account).getInstance( - EthereumDIDRegistry.defaultAddress, + this.ethereumDIDRegistry = await new EthereumExtDidRegistry(this.account).getInstance( + EthereumExtDidRegistry.defaultAddress, ) this.schemaRegistry = await new SchemaRegistry(this.account).getInstance(SchemaRegistry.defaultAddress) this.credentialDefinitionRegistry = await new CredentialDefinitionRegistry(this.account).getInstance( diff --git a/smart_contracts/package.json b/smart_contracts/package.json index 03461d3c..f4e34834 100644 --- a/smart_contracts/package.json +++ b/smart_contracts/package.json @@ -18,7 +18,6 @@ "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 163057ce..45974daf 100644 --- a/smart_contracts/scripts/genesis/config.ts +++ b/smart_contracts/scripts/genesis/config.ts @@ -2,11 +2,8 @@ import { AccountControlConfig, CredentialDefinitionsConfig, EthereumDidRegistryConfig, - IndyDidRegistryConfig, - IndyDidValidatorConfig, RolesConfig, SchemasConfig, - UniversalDidResolverConfig, ValidatorsConfig, } from './contracts' import { UpgradeControlConfig } from './contracts/upgradeControl' @@ -18,27 +15,21 @@ export const outFile = 'ContractsGenesis.json' export interface Config { accountControl: AccountControlConfig credentialDefinitionRegistry: CredentialDefinitionsConfig - indyDidValidator: IndyDidValidatorConfig - indyDidRegistry: IndyDidRegistryConfig ethereumDidRegistry: EthereumDidRegistryConfig roleControl: RolesConfig schemaRegistry: SchemasConfig - universalDidResolver: UniversalDidResolverConfig upgradeControl: UpgradeControlConfig validatorControl: ValidatorsConfig } const contractsAddresses = { - didValidator: '0x0000000000000000000000000000000000002222', - didRegistry: '0x0000000000000000000000000000000000003333', credentialDefinitionRegistry: '0x0000000000000000000000000000000000004444', schemas: '0x0000000000000000000000000000000000005555', roles: '0x0000000000000000000000000000000000006666', validators: '0x0000000000000000000000000000000000007777', accountControl: '0x0000000000000000000000000000000000008888', upgradeControl: '0x0000000000000000000000000000000000009999', - universalDidResolver: '0x000000000000000000000000000000000019999', - ethereumDIDRegistry: '0x0000000000000000000000000000000000018888', + ethereumDidRegistry: '0x0000000000000000000000000000000000018888', } export const config: Config = { @@ -57,29 +48,14 @@ export const config: Config = { description: 'Smart contract to manage credential definitions', data: { credentialDefinitions: [], - universalDidResolverAddress: contractsAddresses.universalDidResolver, + ethereumDidRegistry: contractsAddresses.ethereumDidRegistry, schemaRegistryAddress: contractsAddresses.schemas, upgradeControlAddress: contractsAddresses.upgradeControl, }, }, - indyDidValidator: { - name: 'IndyDidValidator', - address: contractsAddresses.didValidator, - description: 'Library to validate DID', - }, - indyDidRegistry: { - name: 'IndyDidRegistry', - address: contractsAddresses.didRegistry, - description: 'Smart contract to manage DIDs', - libraries: { 'contracts/did/IndyDidValidator.sol:IndyDidValidator': contractsAddresses.didValidator }, - data: { - dids: [], - upgradeControlAddress: contractsAddresses.upgradeControl, - }, - }, ethereumDidRegistry: { name: 'EthereumExtDidRegistry', - address: contractsAddresses.ethereumDIDRegistry, + address: contractsAddresses.ethereumDidRegistry, description: 'Ethereum registry for ERC-1056 ethr did methods', }, roleControl: { @@ -123,17 +99,7 @@ export const config: Config = { description: 'Smart contract to manage schemas', data: { schemas: [], - 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, + ethereumDidRegistry: contractsAddresses.ethereumDidRegistry, upgradeControlAddress: contractsAddresses.upgradeControl, }, }, diff --git a/smart_contracts/scripts/genesis/contracts/credentialDefinitionRegistry.ts b/smart_contracts/scripts/genesis/contracts/credentialDefinitionRegistry.ts index 5a989ae1..bd3cd55a 100644 --- a/smart_contracts/scripts/genesis/contracts/credentialDefinitionRegistry.ts +++ b/smart_contracts/scripts/genesis/contracts/credentialDefinitionRegistry.ts @@ -6,7 +6,7 @@ import { buildProxySection, slots } from '../helpers' export interface CredentialDefinitionsConfig extends ContractConfig { data: { credentialDefinitions: Array<{ id: string; data: { name: string } }> - universalDidResolverAddress: string + ethereumDidRegistry: string schemaRegistryAddress: string upgradeControlAddress: string } @@ -19,7 +19,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.universalDidResolverAddress, 64) + storage[slots['1']] = padLeft(data.ethereumDidRegistry, 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/index.ts b/smart_contracts/scripts/genesis/contracts/index.ts index 58c83a6b..d9d9ba09 100644 --- a/smart_contracts/scripts/genesis/contracts/index.ts +++ b/smart_contracts/scripts/genesis/contracts/index.ts @@ -1,10 +1,7 @@ export * from './accountControl' export * from './credentialDefinitionRegistry' -export * from './indyDidRegistry' -export * from './indyDidValidator' 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 deleted file mode 100644 index aef6b6db..00000000 --- a/smart_contracts/scripts/genesis/contracts/indyDidRegistry.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { padLeft } from 'web3-utils' -import { config } from '../config' -import { ContractConfig } from '../contractConfig' -import { buildProxySection, slots } from '../helpers' - -export interface IndyDidRegistryConfig extends ContractConfig { - libraries: { [libraryName: string]: string } - data: { - dids: Array<{ id: string; data: any }> - upgradeControlAddress: string - } -} - -export function indyDidRegistry() { - const { name, address, description, libraries, data } = config.indyDidRegistry - const storage: any = {} - - storage[slots['0']] = padLeft(data.upgradeControlAddress, 64) - return buildProxySection(name, address, description, storage, libraries) -} diff --git a/smart_contracts/scripts/genesis/contracts/indyDidValidator.ts b/smart_contracts/scripts/genesis/contracts/indyDidValidator.ts deleted file mode 100644 index 4072121c..00000000 --- a/smart_contracts/scripts/genesis/contracts/indyDidValidator.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { config } from '../config' -import { ContractConfig } from '../contractConfig' -import { buildSection } from '../helpers' - -export interface IndyDidValidatorConfig extends ContractConfig {} - -export function indyDidValidator() { - const { name, address, description } = config.indyDidValidator - const storage: any = {} - return buildSection(name, address, description, storage) -} diff --git a/smart_contracts/scripts/genesis/contracts/schemaRegistry.ts b/smart_contracts/scripts/genesis/contracts/schemaRegistry.ts index 1e751142..187f2d9c 100644 --- a/smart_contracts/scripts/genesis/contracts/schemaRegistry.ts +++ b/smart_contracts/scripts/genesis/contracts/schemaRegistry.ts @@ -6,7 +6,7 @@ import { buildProxySection, slots } from '../helpers' export interface SchemasConfig extends ContractConfig { data: { schemas: Array<{ id: string; data: { name: string } }> - universalDidResolverAddress: string + ethereumDidRegistry: string upgradeControlAddress: string } } @@ -18,6 +18,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.universalDidResolverAddress, 64) + storage[slots['1']] = padLeft(data.ethereumDidRegistry, 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 deleted file mode 100644 index 9f9bcdb3..00000000 --- a/smart_contracts/scripts/genesis/contracts/universalDidResolver.ts +++ /dev/null @@ -1,25 +0,0 @@ -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 a0abfcba..93d5737f 100644 --- a/smart_contracts/scripts/genesis/generate.ts +++ b/smart_contracts/scripts/genesis/generate.ts @@ -4,11 +4,8 @@ import { accountControl, credentialDefinitionRegistry, ethereumDidRegistry, - indyDidRegistry, - indyDidValidator, roleControl, schemaRegistry, - universalDidResolver, upgradeControl, validatorControl, } from './contracts' @@ -19,10 +16,7 @@ function main() { ...roleControl(), ...validatorControl(), ...upgradeControl(), - ...indyDidValidator(), - ...indyDidRegistry(), ...ethereumDidRegistry(), - ...universalDidResolver(), ...schemaRegistry(), ...credentialDefinitionRegistry(), } diff --git a/smart_contracts/test/cl/CredentialDefinitionRegistry.spec.ts b/smart_contracts/test/cl/CredentialDefinitionRegistry.spec.ts index 6fe07670..2e623d1f 100644 --- a/smart_contracts/test/cl/CredentialDefinitionRegistry.spec.ts +++ b/smart_contracts/test/cl/CredentialDefinitionRegistry.spec.ts @@ -1,37 +1,46 @@ import { expect } from 'chai' -import { IndyDidRegistry } from '../../contracts-ts' +import { keccak256, toUtf8Bytes } from 'ethers' +import { EthereumExtDidRegistry } from '../../contracts-ts' import { createCredentialDefinitionObject } from '../../utils' import { createDid, createSchema, + createSchemaSigned, deployCredentialDefinitionRegistry, + signCredDefEndorsementData, TestableCredentialDefinitionRegistry, TestableSchemaRegistry, + testActorAddress, + testActorPrivateKey, } from '../utils/contract-helpers' import { ClErrors } from '../utils/errors' import { TestAccounts } from '../utils/test-entities' describe('CredentialDefinitionRegistry', function () { - let didRegistry: IndyDidRegistry + let didRegistry: EthereumExtDidRegistry let schemaRegistry: TestableSchemaRegistry let credentialDefinitionRegistry: TestableCredentialDefinitionRegistry let testAccounts: TestAccounts let schemaId: string - const issuerId = 'did:indy2:mainnet:SEp33q43PsdP7nDATyySSH' + let issuer: string beforeEach(async function () { const { - indyDidRegistry: didRegistryInit, + didRegistry: 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, issuerId) + + const { id } = await createSchema(schemaRegistryInit, issuer) didRegistry = didRegistryInit testAccounts = testAccountsInit @@ -42,116 +51,132 @@ describe('CredentialDefinitionRegistry', function () { describe('Add/Resolve Credential Definition', function () { it('Should create and resolve Credential Definition', async function () { - const { id, credDef } = createCredentialDefinitionObject({ issuerId, schemaId }) + const { id, credDef } = createCredentialDefinitionObject({ issuer, schemaId }) - await credentialDefinitionRegistry.createCredentialDefinition(id, issuerId, schemaId, credDef) - const result = await credentialDefinitionRegistry.resolveCredentialDefinition(id) + await credentialDefinitionRegistry.createCredentialDefinition(issuer, id, schemaId, credDef) - expect(result.credDef).to.be.deep.equal(credDef) + const created = await credentialDefinitionRegistry.created(id) + expect(created).to.be.not.equal(0) }) it('Should fail if resolving Credential Definition does not exist', async function () { - const { id } = createCredentialDefinitionObject({ issuerId, schemaId }) + const { id } = createCredentialDefinitionObject({ issuer, schemaId }) - await expect(credentialDefinitionRegistry.resolveCredentialDefinition(id)) - .to.be.revertedWithCustomError(credentialDefinitionRegistry.baseInstance, ClErrors.CredentialDefinitionNotFound) - .withArgs(id) + const created = await credentialDefinitionRegistry.created(id) + expect(created).to.be.equal(0) }) it('Should fail if Credential Definition is being already exists', async function () { - const { id, credDef } = createCredentialDefinitionObject({ issuerId, schemaId }) + const { id, credDef } = createCredentialDefinitionObject({ issuer, schemaId }) - await credentialDefinitionRegistry.createCredentialDefinition(id, issuerId, schemaId, credDef) + await credentialDefinitionRegistry.createCredentialDefinition(issuer, id, schemaId, credDef) - await expect(credentialDefinitionRegistry.createCredentialDefinition(id, issuerId, schemaId, credDef)) + await expect(credentialDefinitionRegistry.createCredentialDefinition(issuer, id, schemaId, credDef)) .to.be.revertedWithCustomError( credentialDefinitionRegistry.baseInstance, ClErrors.CredentialDefinitionAlreadyExist, ) - .withArgs(id) - }) - - it('Should fail if Credential Definition is being created with non-existing Issuer', async function () { - const unknownIssuerId = 'did:indy2:mainnet:GEzcdDLhCpGCYRHW82kjHd' - const { id, credDef } = createCredentialDefinitionObject({ issuerId: unknownIssuerId, schemaId }) - - await expect(credentialDefinitionRegistry.createCredentialDefinition(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 () { - didRegistry.deactivateDid(issuerId) - - const { id, credDef } = createCredentialDefinitionObject({ issuerId, schemaId }) - - await expect(credentialDefinitionRegistry.createCredentialDefinition(id, issuerId, schemaId, credDef)) - .to.be.revertedWithCustomError(credentialDefinitionRegistry.baseInstance, ClErrors.IssuerHasBeenDeactivated) - .withArgs(issuerId) + .withArgs(keccak256(toUtf8Bytes(id))) }) 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({ issuerId, schemaId: unknownSchemaId }) + const { id, credDef } = createCredentialDefinitionObject({ issuer, schemaId: unknownSchemaId }) - await expect(credentialDefinitionRegistry.createCredentialDefinition(id, issuerId, unknownSchemaId, credDef)) - .to.be.revertedWithCustomError(schemaRegistry.baseInstance, ClErrors.SchemaNotFound) - .withArgs(unknownSchemaId) + await expect(credentialDefinitionRegistry.createCredentialDefinition(issuer, id, unknownSchemaId, credDef)) + .to.be.revertedWithCustomError(credentialDefinitionRegistry.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({ issuerId, schemaId }) - - didRegistry.connect(testAccounts.trustee2.account) - credentialDefinitionRegistry.connect(testAccounts.trustee2.account) - - await createDid(didRegistry, testAccounts.trustee2.account.address, issuerId2) - await expect(credentialDefinitionRegistry.createCredentialDefinition(id, issuerId, schemaId, credDef)) + const { id, credDef } = createCredentialDefinitionObject({ issuer, schemaId }) + + await expect( + credentialDefinitionRegistry.createCredentialDefinition( + testAccounts.trustee2.account.address, + id, + schemaId, + credDef, + ), + ) .to.be.revertedWithCustomError(credentialDefinitionRegistry.baseInstance, ClErrors.UnauthorizedIssuer) - .withArgs(testAccounts.trustee2.account.address) - }) - - it('Should fail if Credential Definition is being with invalid ID', async function () { - const { credDef } = createCredentialDefinitionObject({ issuerId, schemaId }) - const id = 'Gs6cQcvrtWoZKsbBhD3dQJ:3:CL:140384:mctc' - - await expect(credentialDefinitionRegistry.createCredentialDefinition(id, issuerId, schemaId, credDef)) - .to.be.revertedWithCustomError( - credentialDefinitionRegistry.baseInstance, - ClErrors.InvalidCredentialDefinitionId, - ) - .withArgs(id) + .withArgs(testAccounts.trustee2.account.address, testAccounts.trustee.account.address) }) }) - describe('Add/Resolve Credential Definition with did:ethr Issuer', function () { - it('Should create and resolve Credential Definition', async function () { - const ethrIssuerId = `did:ethr:${testAccounts.trustee.account.address}` - const { id, credDef } = createCredentialDefinitionObject({ issuerId: ethrIssuerId, schemaId }) - - await credentialDefinitionRegistry.createCredentialDefinition(id, ethrIssuerId, schemaId, credDef) - const result = await credentialDefinitionRegistry.resolveCredentialDefinition(id) - - expect(result.credDef).to.be.deep.equal(credDef) + 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) + + const { id, credDef } = createCredentialDefinitionObject({ issuer: testActorAddress, schemaId: ethSchemaId }) + const signature = await signCredDefEndorsementData( + credentialDefinitionRegistry, + testActorAddress, + testActorPrivateKey, + id, + ethSchemaId, + credDef, + ) + + await credentialDefinitionRegistry.createCredentialDefinitionSigned( + testActorAddress, + id, + ethSchemaId, + credDef, + signature, + ) + + const created = await credentialDefinitionRegistry.created(id) + expect(created).to.be.not.equal(0) }) - 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(id, ethrIssuerId, schemaId, credDef)) - .to.be.revertedWithCustomError(credentialDefinitionRegistry.baseInstance, ClErrors.UnauthorizedIssuer) - .withArgs(testAccounts.trustee.account.address) + 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 signature = await signCredDefEndorsementData( + credentialDefinitionRegistry, + testAccounts.trustee2.account.address, + testActorPrivateKey, + id, + ethSchemaId, + credDef, + ) + await expect( + credentialDefinitionRegistry.createCredentialDefinitionSigned( + testAccounts.trustee2.account.address, + id, + ethSchemaId, + credDef, + signature, + ), + ) + .to.be.revertedWithCustomError(schemaRegistry.baseInstance, ClErrors.UnauthorizedIssuer) + .withArgs(testAccounts.trustee2.account.address, testActorAddress) }) - 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(id, invalidIssuerId, schemaId, credDef)) - .to.be.revertedWithCustomError(schemaRegistry.baseInstance, ClErrors.InvalidIssuerId) - .withArgs(invalidIssuerId) + 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 signature = await signCredDefEndorsementData( + credentialDefinitionRegistry, + testActorAddress, + testActorPrivateKey, + 'different id passed into signature', + ethSchemaId, + credDef, + ) + await expect( + credentialDefinitionRegistry.createCredentialDefinitionSigned( + testActorAddress, + id, + schemaId, + credDef, + signature, + ), + ).to.be.revertedWithCustomError(schemaRegistry.baseInstance, ClErrors.UnauthorizedIssuer) }) }) }) diff --git a/smart_contracts/test/cl/SchemaRegistry.spec.ts b/smart_contracts/test/cl/SchemaRegistry.spec.ts index 0316eee1..1a49cc7d 100644 --- a/smart_contracts/test/cl/SchemaRegistry.spec.ts +++ b/smart_contracts/test/cl/SchemaRegistry.spec.ts @@ -1,25 +1,36 @@ import { expect } from 'chai' -import { IndyDidRegistry, SchemaRegistry } from '../../contracts-ts' +import { keccak256, toUtf8Bytes } from 'ethers' +import { EthereumExtDidRegistry, SchemaRegistry } from '../../contracts-ts' import { createSchemaObject } from '../../utils' -import { createDid, deploySchemaRegistry, TestableSchemaRegistry } from '../utils/contract-helpers' +import { + createDid, + deploySchemaRegistry, + signSchemaEndorsementData, + TestableSchemaRegistry, + testActorAddress, + testActorPrivateKey, +} from '../utils/contract-helpers' import { ClErrors } from '../utils/errors' import { TestAccounts } from '../utils/test-entities' describe('SchemaRegistry', function () { - let didRegistry: IndyDidRegistry + let didRegistry: EthereumExtDidRegistry let schemaRegistry: TestableSchemaRegistry let testAccounts: TestAccounts - const issuerId = 'did:indy2:mainnet:SEp33q43PsdP7nDATyySSH' + let issuer: string beforeEach(async function () { const { - indyDidRegistry: didRegistryInit, + didRegistry: 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) didRegistry = didRegistryInit @@ -29,103 +40,80 @@ describe('SchemaRegistry', function () { describe('Add/Resolve Schema', function () { it('Should create and resolve Schema', async function () { - const { id, schema } = createSchemaObject({ issuerId }) + const { id, schema } = createSchemaObject({ issuer }) - await schemaRegistry.createSchema(id, issuerId, schema) - const result = await schemaRegistry.resolveSchema(id) + await schemaRegistry.createSchema(issuer, id, schema) - expect(result.schema).to.be.deep.equal(schema) + const created = await schemaRegistry.created(id) + expect(created).to.be.not.equal(0) }) it('Should fail if resolving a non-existing schema', async function () { - const { id, schema } = createSchemaObject({ issuerId }) + const { id } = createSchemaObject({ issuer }) - await expect(schemaRegistry.resolveSchema(id)) - .to.be.revertedWithCustomError(schemaRegistry.baseInstance, ClErrors.SchemaNotFound) - .withArgs(id) + const created = await schemaRegistry.created(id) + expect(created).to.be.equal(0) }) it('Should fail if Schema is being created already exists', async function () { - const { id, schema } = createSchemaObject({ issuerId }) + const { id, schema } = createSchemaObject({ issuer }) - await schemaRegistry.createSchema(id, issuerId, schema) + await schemaRegistry.createSchema(issuer, id, schema) - await expect(schemaRegistry.createSchema(id, issuerId, schema)) + await expect(schemaRegistry.createSchema(issuer, id, schema)) .to.be.revertedWithCustomError(schemaRegistry.baseInstance, ClErrors.SchemaAlreadyExist) - .withArgs(id) - }) - - it('Should fail if Schema is being created with non-existing Issuer', async function () { - const unknownIssuerId = 'did:indy2:mainnet:GEzcdDLhCpGCYRHW82kjHd' - const { id, schema } = createSchemaObject({ issuerId: unknownIssuerId }) - - await expect(schemaRegistry.createSchema(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 () { - didRegistry.deactivateDid(issuerId) - - const { id, schema } = createSchemaObject({ issuerId }) - - await expect(schemaRegistry.createSchema(id, issuerId, schema)) - .to.be.revertedWithCustomError(schemaRegistry.baseInstance, ClErrors.IssuerHasBeenDeactivated) - .withArgs(issuerId) - }) - - it('Should fail if Schema is being created with invalid Schema ID', async function () { - const { schema } = createSchemaObject({ issuerId }) - const id = 'SEp33q43PsdP7nDATyySSH:2:BasicSchema:1.0.0' - - await expect(schemaRegistry.createSchema(id, issuerId, schema)) - .to.be.revertedWithCustomError(schemaRegistry.baseInstance, ClErrors.InvalidSchemaId) - .withArgs(id) + .withArgs(keccak256(toUtf8Bytes(id))) }) it('Should fail if Schema is being created with not owned Issuer DID', async function () { - const issuerId2 = 'did:indy2:mainnet:SEp33q43PsdP7nDATyyDDA' - const { id, schema } = createSchemaObject({ issuerId }) - - didRegistry.connect(testAccounts.trustee2.account) - schemaRegistry.connect(testAccounts.trustee2.account) + const { id, schema } = createSchemaObject({ issuer }) - await createDid(didRegistry, testAccounts.trustee2.account.address, issuerId2) - await expect(schemaRegistry.createSchema(id, issuerId, schema)) + await expect(schemaRegistry.createSchema(testAccounts.trustee2.account.address, id, schema)) .to.be.revertedWithCustomError(schemaRegistry.baseInstance, ClErrors.UnauthorizedIssuer) - .withArgs(testAccounts.trustee2.account.address) + .withArgs(testAccounts.trustee2.account.address, testAccounts.trustee.account.address) }) }) - 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 }) + describe('Endorse/Resolve Schema with did:ethr Issuer', function () { + it('Should endorse and resolve Schema', async function () { + const { id, schema } = createSchemaObject({ issuer: testActorAddress }) - await schemaRegistry.createSchema(id, ethrIssuerId, schema) - const result = await schemaRegistry.resolveSchema(id) + const sig = await signSchemaEndorsementData(schemaRegistry, testActorAddress, testActorPrivateKey, id, schema) - expect(result.schema).to.be.deep.equal(schema) + await schemaRegistry.createSchemaSigned(testActorAddress, id, schema, sig) + const created = await schemaRegistry.created(id) + expect(created).to.be.not.equal(0) }) - 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(id, ethrIssuerId, 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 sig = await signSchemaEndorsementData( + schemaRegistry, + testAccounts.trustee2.account.address, + testActorPrivateKey, + id, + schema, + ) + await expect(schemaRegistry.createSchemaSigned(testAccounts.trustee2.account.address, id, schema, sig)) .to.be.revertedWithCustomError(schemaRegistry.baseInstance, ClErrors.UnauthorizedIssuer) - .withArgs(testAccounts.trustee.account.address) + .withArgs(testAccounts.trustee2.account.address, testActorAddress) }) - 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(id, invalidIssuerId, schema)) - .to.be.revertedWithCustomError(schemaRegistry.baseInstance, ClErrors.InvalidIssuerId) - .withArgs(invalidIssuerId) + it('Should fail if Schema is being endorsed with invalid signature', async function () { + const { id, schema } = createSchemaObject({ issuer: testActorAddress }) + + const sig = await signSchemaEndorsementData( + schemaRegistry, + testActorAddress, + testActorPrivateKey, + 'different id passed into signature', + schema, + ) + await expect(schemaRegistry.createSchemaSigned(testActorAddress, id, schema, sig)).to.be.revertedWithCustomError( + schemaRegistry.baseInstance, + ClErrors.UnauthorizedIssuer, + ) }) }) }) diff --git a/smart_contracts/test/did/DidRegistry.spec.ts b/smart_contracts/test/did/DidRegistry.spec.ts index ea4996c8..9a3aece3 100644 --- a/smart_contracts/test/did/DidRegistry.spec.ts +++ b/smart_contracts/test/did/DidRegistry.spec.ts @@ -1,181 +1,25 @@ import { expect } from 'chai' -import { createBaseDidDocument } from '../../utils/entity-factories' -import { deployIndyDidRegistry, TestableIndyDidRegistry } from '../utils/contract-helpers' -import { IndyDidValidator } from '../utils/contract-helpers' -import { DidError } from '../utils/errors' +import { deployDidRegistry, TestableDidRegistry } from '../utils/contract-helpers' import { TestAccounts } from '../utils/test-entities' describe('DIDContract', function () { - let didRegistry: TestableIndyDidRegistry - let didValidator: IndyDidValidator + let didRegistry: TestableDidRegistry let testAccounts: TestAccounts beforeEach(async function () { - const { - indyDidRegistry: didRegistryInit, - indyDidValidator: didValidatorInit, - testAccounts: testAccountsInit, - } = await deployIndyDidRegistry() + const { didRegistry: didRegistryInit, testAccounts: testAccountsInit } = await deployDidRegistry() didRegistry = didRegistryInit - didValidator = didValidatorInit testAccounts = testAccountsInit didRegistry.connect(testAccounts.trustee.account) }) describe('Create DID', function () { - it('Should create and resolve DID document', async function () { - const did: string = 'did:indy2:testnet:SEp33q43PsdP7nDATyySSH' - const didDocument = createBaseDidDocument(did) - - await didRegistry.createDid(testAccounts.noRole.account.address, did, didDocument) - - const { document } = await didRegistry.resolveDid(did) - - expect(document).to.be.deep.equal(didDocument) - }) - - it('Should fail if resolving DID does not exist', async function () { - const did: string = 'did:indy2:testnet:SEp33q43PsdP7nDATyySSH' - - await expect(didRegistry.resolveDid(did)) - .to.revertedWithCustomError(didRegistry.baseInstance, DidError.DidNotFound) - .withArgs(did) - }) - - it('Should fail if the DID being created already exists', async function () { - const did: string = 'did:indy2:testnet:SEp33q43PsdP7nDATyySSH' - const didDocument = createBaseDidDocument(did) - - await didRegistry.createDid(testAccounts.noRole.account.address, did, didDocument) - - await expect(didRegistry.createDid(testAccounts.noRole2.account.address, did, didDocument)) - .to.be.revertedWithCustomError(didRegistry.baseInstance, DidError.DidAlreadyExist) - .withArgs(did) - }) - - it('Should fail if an incorrect schema is provided for the DID', async function () { - const did: string = 'indy:indy2:testnet:SEp33q43PsdP7nDATyySSH' - const didDocument = createBaseDidDocument(did) - - await expect(didRegistry.createDid(testAccounts.noRole.account.address, did, didDocument)) - .to.be.revertedWithCustomError(didValidator.baseInstance, DidError.IncorrectDid) - .withArgs(did) - }) - - it('Should fail if an unsupported DID method is provided', async function () { - const did: string = 'did:indy3:testnet:SEp33q43PsdP7nDATyySSH' - const didDocument = createBaseDidDocument(did) - - await expect(didRegistry.createDid(testAccounts.noRole.account.address, did, didDocument)) - .to.be.revertedWithCustomError(didValidator.baseInstance, DidError.IncorrectDid) - .withArgs(did) - }) - - it('Should fail if an incorrect DID method-specific-id is provided', async function () { - const did: string = 'did:indy3:testnet:123456789' - const didDocument = createBaseDidDocument(did) - - await expect(didRegistry.createDid(testAccounts.noRole.account.address, did, didDocument)) - .revertedWithCustomError(didValidator.baseInstance, DidError.IncorrectDid) - .withArgs(did) - }) - }) - - describe('Update DID', function () { - it('Should update DID document', async function () { - const did: string = 'did:indy2:testnet:SEp33q43PsdP7nDATyySSH' - const didDocument = createBaseDidDocument(did) - - await didRegistry.createDid(testAccounts.noRole.account.address, did, didDocument) - - await didRegistry.updateDid(did, didDocument) - - const { document } = await didRegistry.resolveDid(did) - - expect(document).to.be.deep.equal(didDocument) - }) - - it('Should fail if the DID creator is not an update txn sender', async function () { - const did: string = 'did:indy2:testnet:SEp33q43PsdP7nDATyySSH' - const didDocument = createBaseDidDocument(did) - - await didRegistry.createDid(testAccounts.noRole.account.address, did, didDocument) - - didRegistry.connect(testAccounts.trustee2.account) - await expect(didRegistry.updateDid(did, didDocument)).to.revertedWithCustomError( - didRegistry.baseInstance, - DidError.UnauthorizedSender, - ) - }) - - it('Should fail if the DID being updated does not exists', async function () { - const did: string = 'did:indy2:testnet:SEp33q43PsdP7nDATyySSH' - const didDocument = createBaseDidDocument(did) - - await expect(didRegistry.updateDid(did, didDocument)) - .to.revertedWithCustomError(didRegistry.baseInstance, DidError.DidNotFound) - .withArgs(did) - }) - - it('Should fail if the DID being updated is deactivated', async function () { - const did: string = 'did:indy2:testnet:SEp33q43PsdP7nDATyySSH' - const didDocument = createBaseDidDocument(did) - - await didRegistry.createDid(testAccounts.noRole.account.address, did, didDocument) - await didRegistry.deactivateDid(did) - - await expect(didRegistry.updateDid(did, didDocument)) - .to.revertedWithCustomError(didRegistry.baseInstance, DidError.DidHasBeenDeactivated) - .withArgs(did) - }) - }) - - describe('Deactivate DID', function () { - it('Should deactivate DID document', async function () { - const did: string = 'did:indy2:testnet:SEp33q43PsdP7nDATyySSH' - const didDocument = createBaseDidDocument(did) - - await didRegistry.createDid(testAccounts.noRole.account.address, did, didDocument) - await didRegistry.deactivateDid(did) - - const didStorage = await didRegistry.resolveDid(did) - - expect(didStorage.metadata.deactivated).is.true - }) - - it('Should fail if the DID has already been deactivated', async function () { - const did: string = 'did:indy2:testnet:SEp33q43PsdP7nDATyySSH' - const didDocument = createBaseDidDocument(did) - - await didRegistry.createDid(testAccounts.noRole.account.address, did, didDocument) - await didRegistry.deactivateDid(did) - - await expect(didRegistry.deactivateDid(did)) - .to.revertedWithCustomError(didRegistry.baseInstance, DidError.DidHasBeenDeactivated) - .withArgs(did) - }) - - it('Should fail if the DID being deactivated does not exists', async function () { - const did: string = 'did:indy2:testnet:SEp33q43PsdP7nDATyySSH' - - await expect(didRegistry.deactivateDid(did)) - .to.revertedWithCustomError(didRegistry.baseInstance, DidError.DidNotFound) - .withArgs(did) - }) - - it('Should fail if the DID creator is not an deactivate txn sender', async function () { - const did: string = 'did:indy2:testnet:SEp33q43PsdP7nDATyySSH' - const didDocument = createBaseDidDocument(did) - - await didRegistry.createDid(testAccounts.noRole.account.address, did, didDocument) - - didRegistry.connect(testAccounts.trustee2.account) - await expect(didRegistry.deactivateDid(did)).to.revertedWithCustomError( - didRegistry.baseInstance, - DidError.UnauthorizedSender, - ) + 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) }) }) }) diff --git a/smart_contracts/test/did/UniversalDidResolver.spec.ts b/smart_contracts/test/did/UniversalDidResolver.spec.ts deleted file mode 100644 index c875c6c5..00000000 --- a/smart_contracts/test/did/UniversalDidResolver.spec.ts +++ /dev/null @@ -1,73 +0,0 @@ -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 () { - const did = 'did:indy2:testnet:SEp33q43PsdP7nDATyySSH' - const indy2DidDocument = createBaseDidDocument(did) - - let universalDidResolver: TestableUniversalDidResolver - let testAccounts: TestAccounts - - async function deployUniversalDidResolverFixture() { - const { - universalDidReolver: universalDidReolverInit, - indyDidRegistry, - testAccounts: testAccountsInit, - } = await deployUniversalDidResolver() - - indyDidRegistry.connect(testAccountsInit.trustee.account) - await indyDidRegistry.createDid(testAccountsInit.trustee.account.address, did, indy2DidDocument) - - return { universalDidReolverInit, testAccountsInit } - } - - beforeEach(async function () { - const { universalDidReolverInit, testAccountsInit } = await loadFixture(deployUniversalDidResolverFixture) - - universalDidResolver = universalDidReolverInit - testAccounts = testAccountsInit - - universalDidResolver.connect(testAccounts.trustee.account) - }) - - describe('Resolve did:indy2', function () { - it('Should resolve DID document', async function () { - const document = await universalDidResolver.resolveDocument(did) - - expect(document).to.be.deep.equal(indy2DidDocument) - }) - - 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 e8ba3083..13927b0a 100644 --- a/smart_contracts/test/utils/contract-helpers.ts +++ b/smart_contracts/test/utils/contract-helpers.ts @@ -1,26 +1,17 @@ +import { concat, getAddress, getBytes, keccak256, SigningKey, toUtf8Bytes } from 'ethers' import { CredentialDefinitionRegistry, - IndyDidRegistry, + EthereumExtDidRegistry, RoleControl, SchemaRegistry, - UniversalDidResolver, UpgradeControl, ValidatorControl, } from '../../contracts-ts' -import { Contract, createBaseDidDocument, createSchemaObject } from '../../utils' +import { Contract, createSchemaObject } from '../../utils' import { getTestAccounts, ZERO_ADDRESS } from './test-entities' -export class EthereumDIDRegistry extends testableContractMixin(Contract) { - constructor() { - super(EthereumDIDRegistry.name) - } -} - -export class IndyDidValidator extends testableContractMixin(Contract) { - constructor() { - super(IndyDidValidator.name) - } -} +export const testActorAddress = '0x2036C6CD85692F0Fb2C26E6c6B2ECed9e4478Dfd' +export const testActorPrivateKey = getBytes('0xa285ab66393c5fdda46d6fbad9e27fafd438254ab72ad5acb681a0e9f20f5d7b') export class UpgradablePrototype extends testableContractMixin(Contract) { public get version(): Promise { @@ -28,7 +19,7 @@ export class UpgradablePrototype extends testableContractMixin(Contract) { } } -export class TestableIndyDidRegistry extends testableContractMixin(IndyDidRegistry) {} +export class TestableDidRegistry extends testableContractMixin(EthereumExtDidRegistry) {} export class TestableSchemaRegistry extends testableContractMixin(SchemaRegistry) {} @@ -40,7 +31,13 @@ export class TestableValidatorControl extends testableContractMixin(ValidatorCon export class TestableUpgradeControl extends testableContractMixin(UpgradeControl) {} -export class TestableUniversalDidResolver extends testableContractMixin(UniversalDidResolver) {} +function testableContractMixin Contract>(Base: T) { + return class extends Base { + public get baseInstance() { + return this.instance + } + } +} export async function deployRoleControl() { const roleControl = await new RoleControl().deployProxy({ params: [ZERO_ADDRESS] }) @@ -49,63 +46,88 @@ export async function deployRoleControl() { return { roleControl, testAccounts } } -export async function deployIndyDidRegistry() { +export async function deployDidRegistry() { const { testAccounts } = await deployRoleControl() - const indyDidValidator = await new IndyDidValidator().deploy() - const indyDidRegistry = await new TestableIndyDidRegistry().deployProxy({ + const didRegistry = await new TestableDidRegistry().deployProxy({ params: [ZERO_ADDRESS], - libraries: [indyDidValidator], - }) - - return { indyDidRegistry, indyDidValidator, 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 } + return { didRegistry, testAccounts } } export async function deploySchemaRegistry() { - const { universalDidReolver, indyDidRegistry, testAccounts } = await deployUniversalDidResolver() + const { didRegistry, testAccounts } = await deployDidRegistry() const schemaRegistry = await new TestableSchemaRegistry().deployProxy({ - params: [ZERO_ADDRESS, universalDidReolver.address], + params: [ZERO_ADDRESS, didRegistry.address], }) - return { universalDidReolver, indyDidRegistry, schemaRegistry, testAccounts } + return { didRegistry, schemaRegistry, testAccounts } } export async function deployCredentialDefinitionRegistry() { - const { universalDidReolver, indyDidRegistry, schemaRegistry, testAccounts } = await deploySchemaRegistry() + const { didRegistry, schemaRegistry, testAccounts } = await deploySchemaRegistry() const credentialDefinitionRegistry = await new TestableCredentialDefinitionRegistry().deployProxy({ - params: [ZERO_ADDRESS, universalDidReolver.address, schemaRegistry.address], + params: [ZERO_ADDRESS, didRegistry.address, schemaRegistry.address], }) - return { credentialDefinitionRegistry, universalDidReolver, indyDidRegistry, schemaRegistry, testAccounts } + return { credentialDefinitionRegistry, didRegistry, 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, did, 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 createSchema(schemaRegistry: SchemaRegistry, issuerId: string) { - const { id, schema } = createSchemaObject({ issuerId }) - await schemaRegistry.createSchema(id, issuerId, schema) +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) return { id, schema } } -function testableContractMixin Contract>(Base: T) { - return class extends Base { - public get baseInstance() { - return this.instance - } - } +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) + 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), + ]), + ) } diff --git a/smart_contracts/test/utils/errors.ts b/smart_contracts/test/utils/errors.ts index b4e79d43..681f02c6 100644 --- a/smart_contracts/test/utils/errors.ts +++ b/smart_contracts/test/utils/errors.ts @@ -8,33 +8,17 @@ export namespace AuthErrors { } export namespace ClErrors { - export const IssuerNotFound = 'IssuerNotFound' - export const IssuerHasBeenDeactivated = 'IssuerHasBeenDeactivated' - export const InvalidIssuerId = 'InvalidIssuerId' export const UnauthorizedIssuer = 'UnauthorizedIssuer' // Schema errors - export const InvalidSchemaId = 'InvalidSchemaId' export const SchemaAlreadyExist = 'SchemaAlreadyExist' export const SchemaNotFound = 'SchemaNotFound' // CredDef errors - export const InvalidCredentialDefinitionId = 'InvalidCredentialDefinitionId' - export const UnsupportedCredentialDefinitionType = 'UnsupportedCredentialDefinitionType' export const CredentialDefinitionAlreadyExist = 'CredentialDefinitionAlreadyExist' export const CredentialDefinitionNotFound = 'CredentialDefinitionNotFound' } -export namespace DidError { - export const AuthenticationKeyRequired = 'AuthenticationKeyRequired' - export const AuthenticationKeyNotFound = 'AuthenticationKeyNotFound' - export const DidNotFound = 'DidNotFound' - export const DidAlreadyExist = 'DidAlreadyExist' - export const DidHasBeenDeactivated = 'DidHasBeenDeactivated' - export const IncorrectDid = 'IncorrectDid' - export const UnauthorizedSender = 'UnauthorizedSender' -} - export namespace ProxyError { export const ERC1967InvalidImplementation = 'ERC1967InvalidImplementation' } diff --git a/smart_contracts/utils/contract.ts b/smart_contracts/utils/contract.ts index fbfbc8b1..0b60425e 100644 --- a/smart_contracts/utils/contract.ts +++ b/smart_contracts/utils/contract.ts @@ -4,10 +4,10 @@ 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 diff --git a/smart_contracts/utils/entity-factories.ts b/smart_contracts/utils/entity-factories.ts index 38e741b5..6065054d 100644 --- a/smart_contracts/utils/entity-factories.ts +++ b/smart_contracts/utils/entity-factories.ts @@ -23,18 +23,19 @@ export function createBaseDidDocument(did: string) { } interface CreateSchemaParams { - issuerId: string + issuer: string name?: string version?: string attrNames?: string[] } export function createSchemaObject({ - issuerId, + issuer, 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, @@ -49,7 +50,7 @@ export function createSchemaObject({ } interface CreateCredentialDefinitionParams { - issuerId: string + issuer: string schemaId: string credDefType?: string tag?: string @@ -57,7 +58,7 @@ interface CreateCredentialDefinitionParams { } export function createCredentialDefinitionObject({ - issuerId, + issuer, schemaId, credDefType = 'CL', tag = 'BasicIdentity', @@ -68,6 +69,7 @@ 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 0513578d..d3201661 100644 --- a/vdr/src/client/client.rs +++ b/vdr/src/client/client.rs @@ -209,7 +209,6 @@ pub mod test { pub const CHAIN_ID: u64 = 1337; pub const CONTRACTS_SPEC_BASE_PATH: &str = "../smart_contracts/artifacts/contracts/"; - pub const DID_REGISTRY_SPEC_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"; @@ -225,9 +224,7 @@ pub mod test { "http://127.0.0.1:21004", ]; pub const DEFAULT_NONCE: u64 = 0; - - pub static DID_REGISTRY_ADDRESS: Lazy
    = - Lazy::new(|| Address::from("0x0000000000000000000000000000000000003333")); + pub const TEST_NETWORK: &str = "test"; pub static SCHEMA_REGISTRY_ADDRESS: Lazy
    = Lazy::new(|| Address::from("0x0000000000000000000000000000000000005555")); @@ -263,11 +260,11 @@ pub mod test { fn contracts() -> Vec { vec![ - ContractConfig { - address: DID_REGISTRY_ADDRESS.to_string(), - spec_path: Some(build_contract_path(DID_REGISTRY_SPEC_PATH)), - spec: None, - }, + // ContractConfig { + // address: DID_REGISTRY_ADDRESS.to_string(), + // spec_path: Some(build_contract_path(DID_REGISTRY_SPEC_PATH)), + // spec: None, + // }, ContractConfig { address: SCHEMA_REGISTRY_ADDRESS.to_string(), spec_path: Some(build_contract_path(SCHEMA_REGISTRY_SPEC_PATH)), diff --git a/vdr/src/contracts/cl/credential_definition_registry.rs b/vdr/src/contracts/cl/credential_definition_registry.rs index bbd52467..f7779b7d 100644 --- a/vdr/src/contracts/cl/credential_definition_registry.rs +++ b/vdr/src/contracts/cl/credential_definition_registry.rs @@ -3,16 +3,22 @@ use log_derive::{logfn, logfn_inputs}; use crate::{ client::LedgerClient, contracts::cl::types::{ - credential_definition::{CredentialDefinition, CredentialDefinitionRecord}, + credential_definition::{CredentialDefinition, CredentialDefinitionCreatedEvent}, credential_definition_id::CredentialDefinitionId, }, error::VdrResult, - types::{Address, Transaction, TransactionBuilder, TransactionParser, TransactionType}, + types::{ + Address, EventParser, EventQueryBuilder, MethodParam, Transaction, TransactionBuilder, + TransactionEndorsingDataBuilder, TransactionParser, TransactionType, + }, + Block, EventLog, EventQuery, SignatureData, TransactionEndorsingData, VdrError, }; const CONTRACT_NAME: &str = "CredentialDefinitionRegistry"; const METHOD_CREATE_CREDENTIAL_DEFINITION: &str = "createCredentialDefinition"; -const METHOD_RESOLVE_CREDENTIAL_DEFINITION: &str = "resolveCredentialDefinition"; +const METHOD_CREATE_CREDENTIAL_DEFINITION_SIGNED: &str = "createCredentialDefinitionSigned"; +const METHOD_CREDENTIAL_DEFINITION_CREATED: &str = "created"; +const EVENT_CREDENTIAL_DEFINITION_CREATED: &str = "CredentialDefinitionCreated"; /// Build transaction to execute CredentialDefinitionRegistry.createCredentialDefinition contract /// method to create a new Credential Definition @@ -34,11 +40,12 @@ pub async fn build_create_credential_definition_transaction( credential_definition: &CredentialDefinition, ) -> VdrResult { // TODO: validate credential definition + let identity = Address::try_from(&credential_definition.issuer_id)?; TransactionBuilder::new() .set_contract(CONTRACT_NAME) .set_method(METHOD_CREATE_CREDENTIAL_DEFINITION) + .add_param(&identity)? .add_param(id)? - .add_param(&credential_definition.issuer_id)? .add_param(&credential_definition.schema_id)? .add_param(credential_definition)? .set_type(TransactionType::Write) @@ -47,59 +54,201 @@ pub async fn build_create_credential_definition_transaction( .await } -/// Build transaction to execute CredentialDefinitionRegistry.resolveCredentialDefinition contract -/// method to retrieve an existing Credential Definition by the given id +/// 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 resolve +/// #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 -/// Read transaction to submit +/// #Returns +/// data: TransactionEndorsingData - transaction endorsement data to sign +#[logfn(Info)] +#[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)?; + 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(&credential_definition.schema_id)? + .add_param(credential_definition)? + .build(client) + .await +} + +/// Build transaction to execute CredentialDefinitionRegistry.createCredentialDefinitionSigned contract method to +/// endorse a new Credential Definition +/// 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 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 +/// +/// #Returns +/// transaction: Transaction - prepared write transaction object to sign and submit #[logfn(Info)] #[logfn_inputs(Debug)] -pub async fn build_resolve_credential_definition_transaction( +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)?; TransactionBuilder::new() .set_contract(CONTRACT_NAME) - .set_method(METHOD_RESOLVE_CREDENTIAL_DEFINITION) + .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(&credential_definition.schema_id)? + .add_param(credential_definition)? + .set_type(TransactionType::Write) + .set_from(from) + .build(client) + .await +} + +/// Build transaction to execute CredentialDefinitionRegistry.credDefs contract method to get +/// block number when a Credential Definition was created +/// +/// #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 +#[logfn(Info)] +#[logfn_inputs(Debug)] +pub async fn build_get_credential_definition_created_transaction( + client: &LedgerClient, + id: &CredentialDefinitionId, +) -> VdrResult { + TransactionBuilder::new() + .set_contract(CONTRACT_NAME) + .set_method(METHOD_CREDENTIAL_DEFINITION_CREATED) .add_param(id)? .set_type(TransactionType::Read) .build(client) .await } -/// Parse the result of execution CredentialDefinitionRegistry.resolveCredentialDefinition contract -/// method to receive a Credential Definition associated with the id +/// 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 /// /// # Params /// - `client` client connected to the network where contract will be executed /// - `bytes` result bytes returned from the ledger /// /// # Returns -/// parsed Credential Definition +/// Block when the credential definition was created #[logfn(Info)] #[logfn_inputs(Debug)] -pub fn parse_resolve_credential_definition_result( +pub fn parse_credential_definition_created_result( client: &LedgerClient, bytes: &[u8], -) -> VdrResult { - // TODO: validate credential definition - Ok(TransactionParser::new() +) -> VdrResult { + TransactionParser::new() .set_contract(CONTRACT_NAME) - .set_method(METHOD_RESOLVE_CREDENTIAL_DEFINITION) - .parse::(client, bytes)? - .credential_definition) + .set_method(METHOD_CREDENTIAL_DEFINITION_CREATED) + .parse::(client, bytes) } -pub fn resolve_credential_definition( - _client: &LedgerClient, - _id: &CredentialDefinitionId, +/// 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) +} + +/// 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 +/// +/// # Returns +/// Resolved Credential Definition object +#[logfn(Info)] +#[logfn_inputs(Debug)] +pub async fn resolve_credential_definition( + client: &LedgerClient, + id: &CredentialDefinitionId, ) -> VdrResult { - unimplemented!() + let transaction = build_get_credential_definition_created_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) + )); + } + + let cred_def = parse_credential_definition_created_event(client, &events[0])?.cred_def; + Ok(cred_def) } #[cfg(test)] @@ -148,50 +297,31 @@ pub mod test { nonce: Some(DEFAULT_NONCE.clone()), chain_id: CHAIN_ID, data: vec![ - 76, 197, 98, 212, 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, 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, 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, 1, 160, 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, 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, 151, 100, 105, 100, 58, 105, 110, 100, 121, 50, 58, - 116, 101, 115, 116, 110, 101, 116, 58, 51, 76, 112, 106, 115, 122, 107, 103, - 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, 119, 47, 97, 110, 111, - 110, 99, 114, 101, 100, 115, 47, 118, 48, 47, 67, 76, 65, 73, 77, 95, 68, 69, - 70, 47, 100, 105, 100, 58, 105, 110, 100, 121, 50, 58, 116, 101, 115, 116, 110, - 101, 116, 58, 51, 76, 112, 106, 115, 122, 107, 103, 84, 109, 69, 51, 113, 84, - 104, 103, 101, 50, 53, 70, 90, 119, 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, 47, 100, 101, 102, 97, 117, 108, - 116, 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, 40, 100, 105, 100, 58, 105, 110, - 100, 121, 50, 58, 116, 101, 115, 116, 110, 101, 116, 58, 51, 76, 112, 106, 115, - 122, 107, 103, 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, 119, 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, 79, 100, 105, 100, 58, 105, 110, 100, 121, 50, 58, 116, 101, 115, 116, - 110, 101, 116, 58, 51, 76, 112, 106, 115, 122, 107, 103, 84, 109, 69, 51, 113, - 84, 104, 103, 101, 50, 53, 70, 90, 119, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 187, 199, 66, 65, 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, 73, 77, + 222, 144, 79, 39, 191, 53, 141, 180, 7, 174, 32, 255, 241, 133, 79, 137, 100, + 14, 222, 118, 247, 141, 252, 216, 221, 232, 25, 32, 232, 199, 79, 65, 37, 166, + 217, 193, 224, 92, 150, 117, 26, 77, 108, 102, 77, 6, 238, 63, 247, 212, 122, + 19, 86, 115, 119, 131, 17, 47, 17, 46, 238, 182, 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, 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, 4, 123, 34, 99, 114, 101, 100, 68, 101, - 102, 84, 121, 112, 101, 34, 58, 34, 67, 76, 34, 44, 34, 105, 115, 115, 117, - 101, 114, 73, 100, 34, 58, 34, 100, 105, 100, 58, 105, 110, 100, 121, 50, 58, - 116, 101, 115, 116, 110, 101, 116, 58, 51, 76, 112, 106, 115, 122, 107, 103, - 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, 119, 34, 44, 34, 115, - 99, 104, 101, 109, 97, 73, 100, 34, 58, 34, 100, 105, 100, 58, 105, 110, 100, - 121, 50, 58, 116, 101, 115, 116, 110, 101, 116, 58, 51, 76, 112, 106, 115, 122, - 107, 103, 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, 119, 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, 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, 0, - 0, 0, 0, 0, 0, + 1, 23, 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, 105, 110, 100, 121, 50, 58, 116, 101, 115, 116, 110, 101, + 116, 58, 51, 76, 112, 106, 115, 122, 107, 103, 84, 109, 69, 51, 113, 84, 104, + 103, 101, 50, 53, 70, 90, 119, 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, ], signature: RwLock::new(None), hash: None, @@ -204,7 +334,7 @@ pub mod test { use super::*; #[async_std::test] - async fn build_resolve_credential_definition_transaction_test() { + async fn build_get_credential_definition_query_test() { init_env_logger(); let client = mock_client(); let (id, _) = credential_definition( @@ -212,73 +342,59 @@ pub mod test { &SchemaId::from(SCHEMA_ID), Some(CREDENTIAL_DEFINITION_TAG), ); - let transaction = build_resolve_credential_definition_transaction(&client, &id) + let query = build_get_credential_definition_query(&client, &id, None, None) .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![ - 97, 112, 196, 138, 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, 151, 100, 105, 100, 58, 105, - 110, 100, 121, 50, 58, 116, 101, 115, 116, 110, 101, 116, 58, 51, 76, 112, 106, - 115, 122, 107, 103, 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, - 119, 47, 97, 110, 111, 110, 99, 114, 101, 100, 115, 47, 118, 48, 47, 67, 76, - 65, 73, 77, 95, 68, 69, 70, 47, 100, 105, 100, 58, 105, 110, 100, 121, 50, 58, - 116, 101, 115, 116, 110, 101, 116, 58, 51, 76, 112, 106, 115, 122, 107, 103, - 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, 119, 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, 47, - 100, 101, 102, 97, 117, 108, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - signature: RwLock::new(None), - hash: None, + let expected_query = EventQuery { + address: CRED_DEF_REGISTRY_ADDRESS.clone(), + from_block: None, + to_block: None, + event_signature: None, + event_filter: Some( + "494dde904f27bf358db407ae20fff1854f89640ede76f78dfcd8dde81920e8c7".to_string(), + ), }; - assert_eq!(expected_transaction, transaction); + assert_eq!(expected_query, query); } } - mod parse_resolve_credential_definition_result { - use super::*; - - #[test] - fn parse_resolve_credential_definition_result_test() { - init_env_logger(); - let client = mock_client(); - 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, 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, 101, 166, 63, 232, 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, 4, 123, 34, 99, 114, - 101, 100, 68, 101, 102, 84, 121, 112, 101, 34, 58, 34, 67, 76, 34, 44, 34, 105, - 115, 115, 117, 101, 114, 73, 100, 34, 58, 34, 100, 105, 100, 58, 105, 110, 100, - 121, 50, 58, 116, 101, 115, 116, 110, 101, 116, 58, 51, 76, 112, 106, 115, 122, - 107, 103, 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, 119, 34, 44, 34, - 115, 99, 104, 101, 109, 97, 73, 100, 34, 58, 34, 100, 105, 100, 58, 105, 110, 100, - 121, 50, 58, 116, 101, 115, 116, 110, 101, 116, 58, 51, 76, 112, 106, 115, 122, - 107, 103, 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, 119, 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, 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, 0, 0, 0, 0, 0, 0, - ]; - let parsed_cred_def = - parse_resolve_credential_definition_result(&client, &data).unwrap(); - let (_, expected_cred_def) = credential_definition( - &DID::from(ISSUER_ID), - &SchemaId::from(SCHEMA_ID), - Some(CREDENTIAL_DEFINITION_TAG), - ); - assert_eq!(expected_cred_def, parsed_cred_def); - } - } + // mod parse_resolve_credential_definition_result { + // use super::*; + // + // #[test] + // fn parse_resolve_credential_definition_result_test() { + // init_env_logger(); + // let client = mock_client(); + // 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, 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, 101, 166, 63, 232, 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, 4, 123, 34, 99, 114, + // 101, 100, 68, 101, 102, 84, 121, 112, 101, 34, 58, 34, 67, 76, 34, 44, 34, 105, + // 115, 115, 117, 101, 114, 73, 100, 34, 58, 34, 100, 105, 100, 58, 105, 110, 100, + // 121, 50, 58, 116, 101, 115, 116, 110, 101, 116, 58, 51, 76, 112, 106, 115, 122, + // 107, 103, 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, 119, 34, 44, 34, + // 115, 99, 104, 101, 109, 97, 73, 100, 34, 58, 34, 100, 105, 100, 58, 105, 110, 100, + // 121, 50, 58, 116, 101, 115, 116, 110, 101, 116, 58, 51, 76, 112, 106, 115, 122, + // 107, 103, 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, 119, 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, 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, 0, 0, 0, 0, 0, 0, + // ]; + // let parsed_cred_def = + // parse_resolve_credential_definition_result(&client, &data).unwrap(); + // let (_, expected_cred_def) = credential_definition( + // &DID::from(ISSUER_ID), + // &SchemaId::from(SCHEMA_ID), + // Some(CREDENTIAL_DEFINITION_TAG), + // ); + // assert_eq!(expected_cred_def, parsed_cred_def); + // } + // } } diff --git a/vdr/src/contracts/cl/mod.rs b/vdr/src/contracts/cl/mod.rs index cedf4949..c7603490 100644 --- a/vdr/src/contracts/cl/mod.rs +++ b/vdr/src/contracts/cl/mod.rs @@ -2,8 +2,12 @@ pub mod credential_definition_registry; pub mod schema_registry; pub mod types; -pub use types::{schema::Schema, schema_id::SchemaId}; +pub use types::{ + schema::{Schema, SchemaCreatedEvent}, + schema_id::SchemaId, +}; pub use types::{ - credential_definition::CredentialDefinition, credential_definition_id::CredentialDefinitionId, + credential_definition::{CredentialDefinition, CredentialDefinitionCreatedEvent}, + credential_definition_id::CredentialDefinitionId, }; diff --git a/vdr/src/contracts/cl/schema_registry.rs b/vdr/src/contracts/cl/schema_registry.rs index 007ba768..007ea124 100644 --- a/vdr/src/contracts/cl/schema_registry.rs +++ b/vdr/src/contracts/cl/schema_registry.rs @@ -3,16 +3,22 @@ use log_derive::{logfn, logfn_inputs}; use crate::{ client::LedgerClient, contracts::cl::types::{ - schema::{Schema, SchemaRecord}, + schema::{Schema, SchemaCreatedEvent}, schema_id::SchemaId, }, error::VdrResult, - types::{Address, Transaction, TransactionBuilder, TransactionParser, TransactionType}, + types::{ + Address, EventParser, EventQueryBuilder, MethodParam, Transaction, TransactionBuilder, + TransactionEndorsingDataBuilder, TransactionParser, TransactionType, + }, + Block, EventLog, EventQuery, SignatureData, TransactionEndorsingData, VdrError, }; const CONTRACT_NAME: &str = "SchemaRegistry"; const METHOD_CREATE_SCHEMA: &str = "createSchema"; -const METHOD_RESOLVE_SCHEMA: &str = "resolveSchema"; +const METHOD_CREATE_SCHEMA_SIGNED: &str = "createSchemaSigned"; +const METHOD_SCHEMA_CREATED: &str = "created"; +const EVENT_SCHEMA_CREATED: &str = "SchemaCreated"; /// Build transaction to execute SchemaRegistry.createSchema contract method to create a new Schema /// @@ -33,11 +39,12 @@ pub async fn build_create_schema_transaction( schema: &Schema, ) -> VdrResult { // TODO: validate schema + let identity = Address::try_from(&schema.issuer_id)?; TransactionBuilder::new() .set_contract(CONTRACT_NAME) .set_method(METHOD_CREATE_SCHEMA) + .add_param(&identity)? .add_param(id)? - .add_param(&schema.issuer_id)? .add_param(schema)? .set_type(TransactionType::Write) .set_from(from) @@ -45,50 +52,195 @@ pub async fn build_create_schema_transaction( .await } -/// Build transaction to execute SchemaRegistry.resolveSchema contract method to retrieve an existing Schema by the given id +/// 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 resolve +/// #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 -/// Read transaction to submit +/// #Returns +/// data: TransactionEndorsingData - transaction endorsement data to sign +#[logfn(Info)] +#[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)?; + TransactionEndorsingDataBuilder::new() + .set_contract(CONTRACT_NAME) + .set_identity(&identity) + .add_param(&identity)? + .add_param(MethodParam::from(METHOD_CREATE_SCHEMA))? + .add_param(id)? + .add_param(schema)? + .build(client) + .await +} + +/// 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 +#[logfn(Info)] +#[logfn_inputs(Debug)] +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)?; + 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(schema)? + .set_type(TransactionType::Write) + .set_from(sender) + .build(client) + .await +} + +/// Build transaction to execute SchemaRegistry.schemasCreated contract method to get +/// block number when Schema was created +/// +/// #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 #[logfn(Info)] #[logfn_inputs(Debug)] -pub async fn build_resolve_schema_transaction( +pub async fn build_get_schema_created_transaction( client: &LedgerClient, id: &SchemaId, ) -> VdrResult { TransactionBuilder::new() .set_contract(CONTRACT_NAME) - .set_method(METHOD_RESOLVE_SCHEMA) + .set_method(METHOD_SCHEMA_CREATED) .add_param(id)? .set_type(TransactionType::Read) .build(client) .await } -/// Parse the result of execution SchemaRegistry.resolveSchema contract method to receive a Schema associated with the id +/// 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. /// /// # Params /// - `client` client connected to the network where contract will be executed /// - `bytes` result bytes returned from the ledger /// /// # Returns -/// parsed Schema +/// Parsed Schema object #[logfn(Info)] #[logfn_inputs(Debug)] -pub fn parse_resolve_schema_result(client: &LedgerClient, bytes: &[u8]) -> VdrResult { +pub fn parse_schema_created_event( + client: &LedgerClient, + log: &EventLog, +) -> VdrResult { // TODO: validate schema - Ok(TransactionParser::new() + EventParser::new() .set_contract(CONTRACT_NAME) - .set_method(METHOD_RESOLVE_SCHEMA) - .parse::(client, bytes)? - .schema) + .set_event(EVENT_SCHEMA_CREATED) + .parse(client, log) } -pub fn resolve_schema(_client: &LedgerClient, _id: &SchemaId) -> VdrResult { - unimplemented!() +/// Single step function to resolve a Schema for the given ID +/// +/// # Params +/// - `client` client connected to the network where contract will be executed +/// - `id` id of schema to resolve +/// +/// # Returns +/// Resolved Schema object +#[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 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.len() == 0 { + 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) } #[cfg(test)] @@ -124,31 +276,22 @@ pub mod test { nonce: Some(DEFAULT_NONCE.clone()), chain_id: CHAIN_ID, data: vec![ - 54, 206, 23, 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, 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, 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, 1, 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, 0, 79, 100, 105, 100, 58, 105, 110, 100, 121, 50, 58, 116, 101, 115, 116, - 110, 101, 116, 58, 51, 76, 112, 106, 115, 122, 107, 103, 84, 109, 69, 51, 113, - 84, 104, 103, 101, 50, 53, 70, 90, 119, 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, 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, 40, 100, 105, 100, 58, 105, 110, 100, - 121, 50, 58, 116, 101, 115, 116, 110, 101, 116, 58, 51, 76, 112, 106, 115, 122, - 107, 103, 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, 119, 0, 0, + 89, 21, 183, 104, 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, 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, 134, 123, 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, 44, 34, 76, 97, 115, 116, 32, 78, - 97, 109, 101, 34, 93, 44, 34, 105, 115, 115, 117, 101, 114, 73, 100, 34, 58, - 34, 100, 105, 100, 58, 105, 110, 100, 121, 50, 58, 116, 101, 115, 116, 110, - 101, 116, 58, 51, 76, 112, 106, 115, 122, 107, 103, 84, 109, 69, 51, 113, 84, - 104, 103, 101, 50, 53, 70, 90, 119, 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, 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, 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, 70, 105, 114, 115, 116, 32, 78, 97, 109, + 101, 34, 44, 34, 76, 97, 115, 116, 32, 78, 97, 109, 101, 34, 93, 125, 0, 0, 0, + 0, 0, 0, 0, ], signature: RwLock::new(None), hash: None, @@ -157,67 +300,57 @@ pub mod test { } } - mod build_resolve_schema_transaction { + mod build_get_schema_query { use super::*; #[async_std::test] - async fn build_resolve_schema_transaction_test() { + async fn build_get_schema_query_test() { init_env_logger(); let client = mock_client(); let (id, _) = schema(&DID::from(ISSUER_ID), Some(SCHEMA_NAME)); - let transaction = build_resolve_schema_transaction(&client, &id) + let query = build_get_schema_query(&client, &id, None, None) .await .unwrap(); - let expected_transaction = Transaction { - type_: TransactionType::Read, - from: None, - to: SCHEMA_REGISTRY_ADDRESS.clone(), - nonce: None, - chain_id: CHAIN_ID, - data: vec![ - 189, 127, 197, 235, 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, 79, 100, 105, 100, 58, 105, - 110, 100, 121, 50, 58, 116, 101, 115, 116, 110, 101, 116, 58, 51, 76, 112, 106, - 115, 122, 107, 103, 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, - 119, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - signature: RwLock::new(None), - hash: None, + let expected_query = EventQuery { + address: SCHEMA_REGISTRY_ADDRESS.clone(), + from_block: None, + to_block: None, + event_signature: None, + event_filter: Some( + "221b17828fe3035e930eb93f0a32917347686a91e8be7b54f040d95ea7347798".to_string(), + ), }; - assert_eq!(expected_transaction, transaction); - } - } - - mod parse_resolve_schema_result { - use super::*; - use crate::contracts::did::types::did::DID; - - #[test] - fn parse_resolve_schema_result_test() { - init_env_logger(); - let client = mock_client(); - 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, 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, 101, 166, 63, 62, 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, 134, 123, 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, 44, 34, 76, 97, 115, 116, 32, 78, 97, 109, 101, 34, 93, 44, 34, - 105, 115, 115, 117, 101, 114, 73, 100, 34, 58, 34, 100, 105, 100, 58, 105, 110, - 100, 121, 50, 58, 116, 101, 115, 116, 110, 101, 116, 58, 51, 76, 112, 106, 115, - 122, 107, 103, 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, 119, 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, 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, - ]; - 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); + assert_eq!(expected_query, query); } } + // + // mod parse_resolve_schema_result { + // use super::*; + // use crate::contracts::did::types::did::DID; + // + // #[test] + // fn parse_resolve_schema_result_test() { + // init_env_logger(); + // let client = mock_client(); + // 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, 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, 101, 166, 63, 62, 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, 134, 123, 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, 44, 34, 76, 97, 115, 116, 32, 78, 97, 109, 101, 34, 93, 44, 34, + // 105, 115, 115, 117, 101, 114, 73, 100, 34, 58, 34, 100, 105, 100, 58, 105, 110, + // 100, 121, 50, 58, 116, 101, 115, 116, 110, 101, 116, 58, 51, 76, 112, 106, 115, + // 122, 107, 103, 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, 119, 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, 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, + // ]; + // 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); + // } + // } } diff --git a/vdr/src/contracts/cl/types/credential_definition.rs b/vdr/src/contracts/cl/types/credential_definition.rs index ea4d5723..e401b17f 100644 --- a/vdr/src/contracts/cl/types/credential_definition.rs +++ b/vdr/src/contracts/cl/types/credential_definition.rs @@ -1,18 +1,10 @@ +use crate::{error::VdrError, types::ContractParam, Address}; + use crate::{ - error::VdrError, - types::{ContractOutput, ContractParam}, + contracts::{cl::types::schema_id::SchemaId, did::types::did::DID}, + types::ContractEvent, }; - -use crate::contracts::{cl::types::schema_id::SchemaId, did::types::did::DID}; use serde_derive::{Deserialize, Serialize}; -use serde_json::json; - -#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct CredentialDefinitionRecord { - pub credential_definition: CredentialDefinition, - pub metadata: CredentialDefinitionMetadata, -} #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct CredentialDefinition { @@ -40,57 +32,42 @@ impl AsRef for CredentialDefinitionTypes { } } -#[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize)] -pub struct CredentialDefinitionMetadata { - pub created: u64, -} - impl TryFrom<&CredentialDefinition> for ContractParam { type Error = VdrError; fn try_from(value: &CredentialDefinition) -> Result { - Ok(ContractParam::String(json!(value).to_string())) + serde_json::to_vec(value) + .map(ContractParam::Bytes) + .map_err(|_| VdrError::ContractInvalidInputData) } } -impl TryFrom<&ContractOutput> for CredentialDefinition { +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +pub struct CredentialDefinitionCreatedEvent { + pub id_hash: String, + pub identity: Address, + pub cred_def: CredentialDefinition, +} + +impl TryFrom for CredentialDefinitionCreatedEvent { type Error = VdrError; - fn try_from(value: &ContractOutput) -> Result { - serde_json::from_str(&value.get_string(0)?).map_err(|err| { + 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| { VdrError::ContractInvalidResponseData(format!( - "Unable to parse CredentialDefinition from the response. Err: {:?}", + "Unable to parse credential definition from contract event. Err: {:?}", err )) - }) - } -} - -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) + Ok(CredentialDefinitionCreatedEvent { + id_hash: hex::encode(&id), + identity, + cred_def, + }) } } @@ -152,7 +129,7 @@ pub mod test { &SchemaId::from(SCHEMA_ID), Some(CREDENTIAL_DEFINITION_TAG), ); - ContractParam::String(json!(cred_def).to_string()) + ContractParam::Bytes(serde_json::to_vec(&cred_def).unwrap()) } mod convert_into_contract_param { @@ -169,20 +146,4 @@ 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 cfb7292d..7c5ae697 100644 --- a/vdr/src/contracts/cl/types/credential_definition_id.rs +++ b/vdr/src/contracts/cl/types/credential_definition_id.rs @@ -1,5 +1,7 @@ use crate::{contracts::did::types::did::DID, types::ContractParam, VdrError}; + use serde_derive::{Deserialize, Serialize}; +use sha3::Digest; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct CredentialDefinitionId(String); @@ -19,13 +21,21 @@ impl CredentialDefinitionId { .as_str(), ) } + + 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 { type Error = VdrError; fn try_from(value: &CredentialDefinitionId) -> Result { - Ok(ContractParam::String(value.to_string())) + Ok(ContractParam::FixedBytes(value.hash())) } } diff --git a/vdr/src/contracts/cl/types/schema.rs b/vdr/src/contracts/cl/types/schema.rs index a0f7902d..e0f08810 100644 --- a/vdr/src/contracts/cl/types/schema.rs +++ b/vdr/src/contracts/cl/types/schema.rs @@ -1,18 +1,11 @@ use crate::{ error::VdrError, types::{ContractOutput, ContractParam}, + Address, }; -use crate::contracts::did::types::did::DID; +use crate::{contracts::did::types::did::DID, types::ContractEvent}; use serde_derive::{Deserialize, Serialize}; -use serde_json::json; - -#[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 { @@ -24,16 +17,13 @@ pub struct Schema { pub attr_names: Vec, } -#[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize)] -pub struct SchemaMetadata { - pub created: u64, -} - impl TryFrom<&Schema> for ContractParam { type Error = VdrError; fn try_from(value: &Schema) -> Result { - Ok(ContractParam::String(json!(value).to_string())) + serde_json::to_vec(value) + .map(ContractParam::Bytes) + .map_err(|_| VdrError::ContractInvalidInputData) } } @@ -50,31 +40,32 @@ impl TryFrom<&ContractOutput> for 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) - } +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +pub struct SchemaCreatedEvent { + pub id_hash: String, + pub identity: Address, + pub schema: Schema, } -impl TryFrom for SchemaRecord { +impl TryFrom for SchemaCreatedEvent { type Error = VdrError; - 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)?; + 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 + )) + })?; - let schema_with_meta = SchemaRecord { + Ok(SchemaCreatedEvent { + id_hash: hex::encode(&id), + identity, schema, - metadata: SchemaMetadata::try_from(metadata)?, - }; - Ok(schema_with_meta) + }) } } @@ -114,7 +105,7 @@ pub mod test { fn schema_param() -> ContractParam { let (_, schema) = schema(&DID::from(ISSUER_ID), Some(SCHEMA_NAME)); - ContractParam::String(json!(schema).to_string()) + ContractParam::Bytes(serde_json::to_vec(&schema).unwrap()) } mod convert_into_contract_param { @@ -127,16 +118,4 @@ pub mod test { 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 5855edbd..0a1dfc48 100644 --- a/vdr/src/contracts/cl/types/schema_id.rs +++ b/vdr/src/contracts/cl/types/schema_id.rs @@ -1,5 +1,7 @@ use crate::{contracts::did::types::did::DID, types::ContractParam, VdrError}; + use serde_derive::{Deserialize, Serialize}; +use sha3::Digest; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct SchemaId(String); @@ -19,13 +21,21 @@ impl SchemaId { .as_str(), ) } + + 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 { type Error = VdrError; fn try_from(value: &SchemaId) -> Result { - Ok(ContractParam::String(value.to_string())) + Ok(ContractParam::FixedBytes(value.hash())) } } diff --git a/vdr/src/contracts/did/did_ethr_registry.rs b/vdr/src/contracts/did/did_ethr_registry.rs index 18a51bc0..fd141a4f 100644 --- a/vdr/src/contracts/did/did_ethr_registry.rs +++ b/vdr/src/contracts/did/did_ethr_registry.rs @@ -9,7 +9,8 @@ use crate::{ did_doc_attribute::{DelegateType, DidDocAttribute, PublicKeyPurpose, Validity}, did_events::{DidAttributeChanged, DidDelegateChanged, DidEvents, DidOwnerChanged}, }, - DidMetadata, DidResolutionMetadata, DidResolutionOptions, KEYS_CONTEXT, SECPK_CONTEXT, + DidDocumentBuilder, DidMetadata, DidResolutionMetadata, DidResolutionOptions, + KEYS_CONTEXT, SECPK_CONTEXT, }, DidDocumentWithMeta, }, @@ -19,8 +20,7 @@ use crate::{ TransactionBuilder, TransactionEndorsingDataBuilder, TransactionParser, TransactionType, UintBytesParam, }, - Block, DidDocumentBuilder, SignatureData, TransactionEndorsingData, VdrError, - VerificationKeyType, DID, + Block, Nonce, SignatureData, TransactionEndorsingData, VdrError, VerificationKeyType, DID, }; const CONTRACT_NAME: &str = "EthereumExtDidRegistry"; @@ -43,6 +43,8 @@ const EVENT_DID_ATTRIBUTE_CHANGED: &str = "DIDAttributeChanged"; const EVENT_DID_DELEGATE_CHANGED: &str = "DIDDelegateChanged"; const EVENT_DID_OWNER_CHANGED: &str = "DIDOwnerChanged"; +pub const ETHR_DID_METHOD: &str = "ethr"; + // TODO: In current implementation all methods accept DID but contract API accept identity account address // Should we change it? @@ -94,9 +96,11 @@ pub async fn build_did_change_owner_endorsing_data( new_owner: &Address, ) -> VdrResult { let identity = Address::try_from(did)?; + let nonce = resolve_identity_nonce(client, &identity).await?; TransactionEndorsingDataBuilder::new() .set_contract(CONTRACT_NAME) .set_identity(&identity) + .add_param(&nonce)? .add_param(&identity)? .add_param(MethodParam::from(METHOD_CHANGE_OWNER))? .add_param(new_owner)? @@ -199,9 +203,11 @@ pub async fn build_did_add_delegate_endorsing_data( validity: &Validity, ) -> VdrResult { let identity = Address::try_from(did)?; + let nonce = resolve_identity_nonce(client, &identity).await?; TransactionEndorsingDataBuilder::new() .set_contract(CONTRACT_NAME) .set_identity(&identity) + .add_param(&nonce)? .add_param(&identity)? .add_param(MethodParam::from(METHOD_ADD_DELEGATE))? .add_param(delegate_type)? @@ -308,9 +314,11 @@ pub async fn build_did_revoke_delegate_endorsing_data( delegate: &Address, ) -> VdrResult { let identity = Address::try_from(did)?; + let nonce = resolve_identity_nonce(client, &identity).await?; TransactionEndorsingDataBuilder::new() .set_contract(CONTRACT_NAME) .set_identity(&identity) + .add_param(&nonce)? .add_param(&identity)? .add_param(MethodParam::from(METHOD_REVOKE_DELEGATE))? .add_param(delegate_type)? @@ -416,9 +424,10 @@ pub async fn build_did_set_attribute_endorsing_data( validity: &Validity, ) -> VdrResult { let identity = Address::try_from(did)?; + let nonce = resolve_identity_nonce(client, &identity).await?; TransactionEndorsingDataBuilder::new() .set_contract(CONTRACT_NAME) - .set_identity(&identity) + .add_param(&nonce)? .add_param(&identity)? .add_param(MethodParam::from(METHOD_SET_ATTRIBUTE))? .add_param(&attribute.name()?)? @@ -523,9 +532,11 @@ pub async fn build_did_revoke_attribute_endorsing_data( attribute: &DidDocAttribute, ) -> VdrResult { let identity = Address::try_from(did)?; + let nonce = resolve_identity_nonce(client, &identity).await?; TransactionEndorsingDataBuilder::new() .set_contract(CONTRACT_NAME) .set_identity(&identity) + .add_param(&nonce)? .add_param(&identity)? .add_param(MethodParam::from(METHOD_REVOKE_ATTRIBUTE))? .add_param(&attribute.name()?)? @@ -723,12 +734,11 @@ pub fn parse_did_owner_result(client: &LedgerClient, bytes: &[u8]) -> VdrResult< /// Nonce to use for endorsing #[logfn(Info)] #[logfn_inputs(Debug)] -pub fn parse_did_nonce_result(client: &LedgerClient, bytes: &[u8]) -> VdrResult { - Ok(TransactionParser::new() +pub fn parse_did_nonce_result(client: &LedgerClient, bytes: &[u8]) -> VdrResult { + TransactionParser::new() .set_contract(CONTRACT_NAME) .set_method(METHOD_DID_NONCE) - .parse::(client, bytes)? - .value()) + .parse::(client, bytes) } /// Parse DidAttributeChangedEvent from the event log. @@ -836,13 +846,13 @@ pub fn parse_did_event_response(client: &LedgerClient, event: &EventLog) -> VdrR #[logfn(Info)] #[logfn_inputs(Debug)] -pub async fn resolve_identity_nonce(client: &LedgerClient, identity: &Address) -> VdrResult { +pub async fn resolve_identity_nonce(client: &LedgerClient, identity: &Address) -> VdrResult { let transaction = build_get_identity_nonce_transaction(client, identity).await?; let response = client.submit_transaction(&transaction).await?; parse_did_nonce_result(client, &response) } -/// Single step function to resolve a DidDocument with metadata for teh given 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 diff --git a/vdr/src/contracts/did/did_indy_registry.rs b/vdr/src/contracts/did/did_indy_registry.rs deleted file mode 100644 index a7e2632e..00000000 --- a/vdr/src/contracts/did/did_indy_registry.rs +++ /dev/null @@ -1,438 +0,0 @@ -use log_derive::{logfn, logfn_inputs}; - -use crate::{ - client::LedgerClient, - contracts::did::types::{ - did::DID, - did_doc::{DidDocument, DidRecord}, - }, - error::VdrResult, - types::{Address, Transaction, TransactionBuilder, TransactionParser, TransactionType}, -}; - -const CONTRACT_NAME: &str = "IndyDidRegistry"; -const METHOD_CREATE_DID: &str = "createDid"; -const METHOD_UPDATE_DID: &str = "updateDid"; -const METHOD_DEACTIVATE_DID: &str = "deactivateDid"; -const METHOD_RESOLVE_DID: &str = "resolveDid"; - -/// 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 -/// - `identity` DID owner account address -/// - `did` DID to be created -/// - `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, - identity: &Address, - did: &DID, - did_doc: &DidDocument, -) -> VdrResult { - TransactionBuilder::new() - .set_contract(CONTRACT_NAME) - .set_method(METHOD_CREATE_DID) - .add_param(identity)? - .add_param(did)? - .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 be updated -/// - `did_doc` new 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 { - TransactionBuilder::new() - .set_contract(CONTRACT_NAME) - .set_method(METHOD_UPDATE_DID) - .add_param(did)? - .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 { - TransactionBuilder::new() - .set_contract(CONTRACT_NAME) - .set_method(METHOD_DEACTIVATE_DID) - .add_param(did)? - .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` target DID to receive DID Document -/// -/// # Returns -/// Read transaction to submit -#[logfn(Info)] -#[logfn_inputs(Debug)] -pub async fn build_resolve_did_transaction( - client: &LedgerClient, - did: &DID, -) -> VdrResult { - TransactionBuilder::new() - .set_contract(CONTRACT_NAME) - .set_method(METHOD_RESOLVE_DID) - .add_param(did)? - .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 Document -#[logfn(Info)] -#[logfn_inputs(Debug)] -pub fn parse_resolve_did_result(client: &LedgerClient, bytes: &[u8]) -> VdrResult { - Ok(TransactionParser::new() - .set_contract(CONTRACT_NAME) - .set_method(METHOD_RESOLVE_DID) - .parse::(client, bytes)? - .document) -} - -#[cfg(test)] -pub mod test { - use super::*; - use crate::{ - client::client::test::{ - mock_client, CHAIN_ID, DEFAULT_NONCE, DID_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, IDENTITY_ACC}, - contracts::{ - did::types::did_doc::test::service, StringOrVector, VerificationMethod, - VerificationMethodOrReference, - }, - VerificationKeyType, - }; - - #[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(Some(ISSUER_ID)); - let transaction = - build_create_did_transaction(&client, &TRUSTEE_ACC, &IDENTITY_ACC, &did, &did_doc) - .await - .unwrap(); - let expected_transaction = Transaction { - type_: TransactionType::Write, - from: Some(TRUSTEE_ACC.clone()), - to: DID_REGISTRY_ADDRESS.clone(), - nonce: Some(DEFAULT_NONCE.clone()), - chain_id: CHAIN_ID, - data: vec![ - 30, 113, 85, 17, 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, 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, - 0, 0, 0, 0, 0, 0, 192, 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, 40, 100, 105, 100, 58, 105, 110, 100, 121, - 50, 58, 116, 101, 115, 116, 110, 101, 116, 58, 51, 76, 112, 106, 115, 122, 107, - 103, 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, 119, 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, 51, 76, 112, - 106, 115, 122, 107, 103, 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, - 90, 119, 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, 51, 76, 112, 106, 115, 122, 107, 103, 84, 109, 69, 51, 113, 84, 104, 103, - 101, 50, 53, 70, 90, 119, 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, 51, 76, 112, 106, - 115, 122, 107, 103, 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, - 119, 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, 51, 76, 112, 106, 115, 122, 107, - 103, 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, 119, 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, - ], - signature: RwLock::new(None), - hash: None, - }; - assert_eq!(expected_transaction, transaction); - } - - #[async_std::test] - async fn build_create_did_transaction_with_two_keys_and_service_test() { - init_env_logger(); - let client = mock_client(); - - let did = DID::from("did:indy2:testnet:3LpjszkgTmE3qThge25FZw"); - let did_doc = DidDocument { - context: StringOrVector::Vector(vec!["https://www.w3.org/ns/did/v1".to_string()]), - id: DID::from("did:indy2:testnet:3LpjszkgTmE3qThge25FZw"), - controller: None, - verification_method: vec![ - VerificationMethod { - id: "did:indy2:testnet:3LpjszkgTmE3qThge25FZw#KEY-1".to_string(), - type_: VerificationKeyType::Ed25519VerificationKey2018, - controller: "did:indy2:testnet:3LpjszkgTmE3qThge25FZw".to_string(), - blockchain_account_id: None, - public_key_multibase: Some("8rnQ4gvtEYi59DMAzN7FyCVatVATkFo7wPXVMy38WmvG".to_string()), - public_key_hex: None, - public_key_base58: None, - public_key_base64: None, - }, - VerificationMethod { - id: "did:indy2:testnet:3LpjszkgTmE3qThge25FZw#KEY-2".to_string(), - type_: VerificationKeyType::EcdsaSecp256k1VerificationKey2019, - controller: "did:indy2:testnet:3LpjszkgTmE3qThge25FZw".to_string(), - blockchain_account_id: None, - public_key_multibase: Some("NaqS2qSLZTJcuKLvFAoBSeRFXeivDfyoUqvSs8DQ4ajydz4KbUvT6vdJyz8i9gJEqGjFkCN27niZhoAbQLgk3imn".to_string()), - public_key_hex: None, - public_key_base58: None, - public_key_base64: None, - }, - ], - authentication: vec![ - VerificationMethodOrReference::String("did:indy2:testnet:3LpjszkgTmE3qThge25FZw#KEY-1".to_string()), - VerificationMethodOrReference::String("did:indy2:testnet:3LpjszkgTmE3qThge25FZw#KEY-2".to_string()), - ], - assertion_method: vec![], - capability_invocation: vec![], - capability_delegation: vec![], - key_agreement: vec![], - service: vec![ - service("did:indy2:testnet:3LpjszkgTmE3qThge25FZw#SERVICE-1") - ], - also_known_as: Some(vec![]), - }; - let transaction = - build_create_did_transaction(&client, &TRUSTEE_ACC, &IDENTITY_ACC, &did, &did_doc) - .await - .unwrap(); - let expected_transaction = Transaction { - type_: TransactionType::Write, - from: Some(TRUSTEE_ACC.clone()), - to: DID_REGISTRY_ADDRESS.clone(), - nonce: Some(DEFAULT_NONCE.clone()), - chain_id: CHAIN_ID, - data: vec![ - 30, 113, 85, 17, 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, 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, - 0, 0, 0, 0, 0, 0, 192, 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, 40, 100, 105, 100, 58, 105, 110, 100, 121, - 50, 58, 116, 101, 115, 116, 110, 101, 116, 58, 51, 76, 112, 106, 115, 122, 107, - 103, 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, 119, 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, 3, 96, - 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, 51, 76, 112, - 106, 115, 122, 107, 103, 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, - 90, 119, 35, 75, 69, 89, 45, 49, 34, 44, 34, 100, 105, 100, 58, 105, 110, 100, - 121, 50, 58, 116, 101, 115, 116, 110, 101, 116, 58, 51, 76, 112, 106, 115, 122, - 107, 103, 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, 119, 35, 75, - 69, 89, 45, 50, 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, 51, 76, 112, 106, - 115, 122, 107, 103, 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, - 119, 34, 44, 34, 115, 101, 114, 118, 105, 99, 101, 34, 58, 91, 123, 34, 105, - 100, 34, 58, 34, 100, 105, 100, 58, 105, 110, 100, 121, 50, 58, 116, 101, 115, - 116, 110, 101, 116, 58, 51, 76, 112, 106, 115, 122, 107, 103, 84, 109, 69, 51, - 113, 84, 104, 103, 101, 50, 53, 70, 90, 119, 35, 83, 69, 82, 86, 73, 67, 69, - 45, 49, 34, 44, 34, 115, 101, 114, 118, 105, 99, 101, 69, 110, 100, 112, 111, - 105, 110, 116, 34, 58, 34, 49, 50, 55, 46, 48, 46, 48, 46, 49, 58, 53, 53, 53, - 53, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 68, 73, 68, 67, 111, 109, 109, - 83, 101, 114, 118, 105, 99, 101, 34, 125, 93, 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, 51, 76, - 112, 106, 115, 122, 107, 103, 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, - 70, 90, 119, 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, 51, 76, 112, 106, 115, - 122, 107, 103, 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, 119, - 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, 56, 114, 110, 81, 52, - 103, 118, 116, 69, 89, 105, 53, 57, 68, 77, 65, 122, 78, 55, 70, 121, 67, 86, - 97, 116, 86, 65, 84, 107, 70, 111, 55, 119, 80, 88, 86, 77, 121, 51, 56, 87, - 109, 118, 71, 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, 44, 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, 51, 76, 112, 106, 115, 122, 107, 103, 84, 109, 69, - 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, 119, 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, 51, 76, 112, 106, 115, 122, 107, 103, 84, 109, 69, 51, 113, 84, - 104, 103, 101, 50, 53, 70, 90, 119, 35, 75, 69, 89, 45, 50, 34, 44, 34, 112, - 117, 98, 108, 105, 99, 75, 101, 121, 77, 117, 108, 116, 105, 98, 97, 115, 101, - 34, 58, 34, 78, 97, 113, 83, 50, 113, 83, 76, 90, 84, 74, 99, 117, 75, 76, 118, - 70, 65, 111, 66, 83, 101, 82, 70, 88, 101, 105, 118, 68, 102, 121, 111, 85, - 113, 118, 83, 115, 56, 68, 81, 52, 97, 106, 121, 100, 122, 52, 75, 98, 85, 118, - 84, 54, 118, 100, 74, 121, 122, 56, 105, 57, 103, 74, 69, 113, 71, 106, 70, - 107, 67, 78, 50, 55, 110, 105, 90, 104, 111, 65, 98, 81, 76, 103, 107, 51, 105, - 109, 110, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 69, 99, 100, 115, 97, 83, - 101, 99, 112, 50, 53, 54, 107, 49, 86, 101, 114, 105, 102, 105, 99, 97, 116, - 105, 111, 110, 75, 101, 121, 50, 48, 49, 57, 34, 125, 93, 125, - ], - 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: DID_REGISTRY_ADDRESS.clone(), - nonce: None, - chain_id: CHAIN_ID, - data: vec![ - 54, 51, 133, 44, 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, 40, 100, 105, 100, 58, 105, - 110, 100, 121, 50, 58, 116, 101, 115, 116, 110, 101, 116, 58, 51, 76, 112, 106, - 115, 122, 107, 103, 84, 109, 69, 51, 113, 84, 104, 103, 101, 50, 53, 70, 90, - 119, 0, 0, 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, - }; - 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:indy2: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(Some(issuer_did)), parsed_did_doc); - } - } -} diff --git a/vdr/src/contracts/did/mod.rs b/vdr/src/contracts/did/mod.rs index 749afcf5..ab442dd9 100644 --- a/vdr/src/contracts/did/mod.rs +++ b/vdr/src/contracts/did/mod.rs @@ -1,7 +1,6 @@ pub mod did_ethr_registry; -pub mod did_indy_registry; pub mod types; pub use did_ethr_registry::*; -pub use did_indy_registry::*; -pub use types::{did::DID, did_doc::*, did_doc_builder::DidDocumentBuilder}; +pub(crate) use types::did_doc_builder::DidDocumentBuilder; +pub use types::{did::DID, did_doc::*}; diff --git a/vdr/src/contracts/did/types/did_doc.rs b/vdr/src/contracts/did/types/did_doc.rs index c6d4f278..d98ee921 100644 --- a/vdr/src/contracts/did/types/did_doc.rs +++ b/vdr/src/contracts/did/types/did_doc.rs @@ -274,7 +274,7 @@ pub mod test { use super::*; use crate::utils::rand_bytes; - pub const ISSUER_ID: &str = "did:indy2:testnet:3LpjszkgTmE3qThge25FZw"; + pub const ISSUER_ID: &str = "did:ethr:testnet:0xf0e2db6c8dc6c681bb5d6ad121a107f300e9b2b5"; pub const CONTEXT: &str = "https://www.w3.org/ns/did/v1"; pub const MULTIBASE_KEY: &str = "zAKJP3f7BD6W4iWEQ9jwndVTCBq8ua2Utt8EEjJ6Vxsf"; pub const SERVICE_ENDPOINT: &str = "127.0.0.1:5555"; diff --git a/vdr/src/contracts/mod.rs b/vdr/src/contracts/mod.rs index a955e4e0..1554237b 100644 --- a/vdr/src/contracts/mod.rs +++ b/vdr/src/contracts/mod.rs @@ -6,7 +6,8 @@ pub mod network; pub use auth::{role_control, Role}; pub use cl::{credential_definition_registry, schema_registry, CredentialDefinition, Schema}; pub use did::{ - did_indy_registry, DidDocument, DidDocumentWithMeta, Service, ServiceEndpoint, StringOrVector, + did_ethr_registry, DidDocument, DidDocumentWithMeta, DidMetadata, DidResolutionMetadata, + Service, ServiceEndpoint, ServiceEndpointObject, StringOrVector, VerificationKeyType, VerificationMethod, VerificationMethodOrReference, }; pub use network::validator_control; diff --git a/vdr/src/lib.rs b/vdr/src/lib.rs index 88c68333..707d2f3a 100644 --- a/vdr/src/lib.rs +++ b/vdr/src/lib.rs @@ -21,12 +21,14 @@ pub use contracts::{ cl::{ credential_definition_registry, schema_registry, types::{ - credential_definition::CredentialDefinition, - credential_definition_id::CredentialDefinitionId, schema::Schema, schema_id::SchemaId, + credential_definition::{CredentialDefinition, CredentialDefinitionCreatedEvent}, + credential_definition_id::CredentialDefinitionId, + schema::{Schema, SchemaCreatedEvent}, + schema_id::SchemaId, }, }, did::{ - did_ethr_registry, did_indy_registry, + did_ethr_registry, types::{ did::DID, did_doc::{DidDocument, DidResolutionOptions, VerificationKeyType}, diff --git a/vdr/src/test.rs b/vdr/src/test.rs index 1e0a8ae8..a6d6439d 100644 --- a/vdr/src/test.rs +++ b/vdr/src/test.rs @@ -1,15 +1,10 @@ use crate::{ - client::client::test::{client, IDENTITY_ACC}, + client::client::test::{client, TEST_NETWORK}, contracts::{ auth::Role, - cl::{ - schema_registry, - types::{credential_definition::test::credential_definition, schema::test::schema}, - CredentialDefinition, Schema, SchemaId, - }, - did::{types::did_doc::test::did_doc, DidDocument, DID}, + cl::types::{credential_definition::test::credential_definition, schema::test::schema}, + did::ETHR_DID_METHOD, }, - did_indy_registry, error::VdrResult, signer::basic_signer::{ test::{basic_signer, TRUSTEE_ACC}, @@ -19,45 +14,6 @@ use crate::{ LedgerClient, }; -async fn create_did(client: &LedgerClient, signer: &crate::BasicSigner) -> DidDocument { - let did_doc = did_doc(None); - let transaction = did_indy_registry::build_create_did_transaction( - &client, - &TRUSTEE_ACC, - &IDENTITY_ACC, - &did_doc.id, - &did_doc, - ) - .await - .unwrap(); - - let sign_bytes = transaction.get_signing_bytes().unwrap(); - let signature = signer.sign(&sign_bytes, TRUSTEE_ACC.as_ref()).unwrap(); - transaction.set_signature(signature); - - client.submit_transaction(&transaction).await.unwrap(); - did_doc -} - -pub async fn create_schema( - client: &LedgerClient, - issuer_id: &DID, - signer: &crate::BasicSigner, -) -> (SchemaId, Schema) { - let (id, schema) = schema(issuer_id, None); - let transaction = - schema_registry::build_create_schema_transaction(&client, &TRUSTEE_ACC, &id, &schema) - .await - .unwrap(); - - let sign_bytes = transaction.get_signing_bytes().unwrap(); - let signature = signer.sign(&sign_bytes, TRUSTEE_ACC.as_ref()).unwrap(); - transaction.set_signature(signature); - - client.submit_transaction(&transaction).await.unwrap(); - (id, schema) -} - async fn sign_and_submit_transaction( client: &LedgerClient, transaction: Transaction, @@ -77,56 +33,22 @@ mod did { did_ethr_registry, did_ethr_registry::test::{public_key, service, validity}, types::did_doc_attribute::DidDocAttribute, + DID, }, - did_indy_registry, DID, + Address, }; - pub(crate) async fn build_and_submit_create_did_doc_transaction( - client: &LedgerClient, - did_doc: &DidDocument, - signer: &BasicSigner, - ) -> String { - let transaction = did_indy_registry::build_create_did_transaction( - &client, - &TRUSTEE_ACC, - &IDENTITY_ACC, - &did_doc.id, - did_doc, - ) - .await - .unwrap(); - sign_and_submit_transaction(client, transaction, signer).await - } - - #[async_std::test] - async fn demo_build_and_submit_did_transaction_test() -> VdrResult<()> { - let signer = basic_signer(); - let client = client(); - - // write - let did_doc = did_doc(None); - let receipt = build_and_submit_create_did_doc_transaction(&client, &did_doc, &signer).await; - println!("Receipt: {}", receipt); - - // read - let transaction = did_indy_registry::build_resolve_did_transaction(&client, &did_doc.id) - .await - .unwrap(); - let result = client.submit_transaction(&transaction).await.unwrap(); - let resolved_did_doc = - did_indy_registry::parse_resolve_did_result(&client, &result).unwrap(); - assert_eq!(did_doc, resolved_did_doc); - - Ok(()) + pub(crate) fn did(address: &Address) -> DID { + DID::build(ETHR_DID_METHOD, TEST_NETWORK, address.as_ref()) } #[async_std::test] - async fn demo_build_and_submit_did_ethr_transaction_test() -> VdrResult<()> { + async fn demo_create_did_ethr() -> VdrResult<()> { let signer = basic_signer(); let client = client(); // write - let did = DID::from(format!("did:ethr:{}", TRUSTEE_ACC.clone().as_ref()).as_str()); + let did = super::did::did(&TRUSTEE_ACC.clone()); let transaction = did_ethr_registry::build_did_set_attribute_transaction( &client, &TRUSTEE_ACC, @@ -136,8 +58,7 @@ mod did { ) .await .unwrap(); - let receipt = sign_and_submit_transaction(&client, transaction, &signer).await; - println!("Receipt: {}", receipt); + let _receipt = sign_and_submit_transaction(&client, transaction, &signer).await; // read event let transaction = did_ethr_registry::build_get_did_events_query(&client, &did, None, None) @@ -165,8 +86,7 @@ mod did { ) .await .unwrap(); - let receipt = sign_and_submit_transaction(&client, transaction, &signer).await; - println!("Receipt: {}", receipt); + let _receipt = sign_and_submit_transaction(&client, transaction, &signer).await; let did_doc = did_ethr_registry::resolve_did(&client, &did, None) .await @@ -178,14 +98,14 @@ mod did { } #[async_std::test] - async fn demo_endorse_did_ethr_transaction_test() -> VdrResult<()> { + async fn demo_endorse_did_ethr() -> VdrResult<()> { let mut signer = basic_signer(); let client = client(); - let (identity, _) = signer.create_key(None)?; // write - let did = DID::from(format!("did:ethr:{}", identity.to_string()).as_str()); + let did = super::did::did(&identity); + let service = service(); let validity = validity(); @@ -224,42 +144,84 @@ mod did { mod schema { use super::*; - use crate::{schema_registry, SchemaId}; + use crate::{schema_registry, Address, LedgerClient, Schema, SchemaId, DID}; - pub(crate) async fn build_and_submit_create_schema_transaction( + pub(crate) async fn endorse_schema( client: &LedgerClient, - id: &SchemaId, - schema: &Schema, + did: &DID, signer: &BasicSigner, - ) -> String { - let transaction = - schema_registry::build_create_schema_transaction(&client, &TRUSTEE_ACC, id, schema) + ) -> (SchemaId, Schema) { + let identity = Address::try_from(did).unwrap(); + let (schema_id, schema) = schema(did, None); + let transaction_endorsing_data = + schema_registry::build_create_schema_endorsing_data(client, &schema_id, &schema) .await .unwrap(); - sign_and_submit_transaction(client, transaction, signer).await + + let endorsing_sign_bytes = transaction_endorsing_data.get_signing_bytes().unwrap(); + let signature = signer + .sign(&endorsing_sign_bytes, &identity.to_string()) + .unwrap(); + + let transaction = schema_registry::build_create_schema_signed_transaction( + client, + &TRUSTEE_ACC.clone(), + &schema_id, + &schema, + &signature, + ) + .await + .unwrap(); + let _receipt = sign_and_submit_transaction(client, transaction, signer).await; + (schema_id, schema) } #[async_std::test] - async fn demo_build_and_submit_transaction_test() -> VdrResult<()> { + async fn demo_create_schema() -> VdrResult<()> { let signer = basic_signer(); let client = client(); // create DID Document - let did_doc = create_did(&client, &signer).await; + let did = super::did::did(&TRUSTEE_ACC.clone()); // write - let (schema_id, schema) = schema(&did_doc.id, None); - let receipt = - build_and_submit_create_schema_transaction(&client, &schema_id, &schema, &signer).await; + let (schema_id, schema) = schema(&did, None); + let transaction = schema_registry::build_create_schema_transaction( + &client, + &TRUSTEE_ACC.clone(), + &schema_id, + &schema, + ) + .await + .unwrap(); + let receipt = sign_and_submit_transaction(&client, transaction, &signer).await; println!("Receipt: {}", receipt); // read - let transaction = schema_registry::build_resolve_schema_transaction(&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<()> { + let mut signer = basic_signer(); + let client = client(); + let (identity, _) = signer.create_key(None)?; + + // create DID Document + let did = super::did::did(&identity); + + // endorse schema + let (schema_id, schema) = endorse_schema(&client, &did, &signer).await; + + // read + let resolved_schema = schema_registry::resolve_schema(&client, &schema_id) .await .unwrap(); - let result = client.submit_transaction(&transaction).await.unwrap(); - let resolved_schema = - schema_registry::parse_resolve_schema_result(&client, &result).unwrap(); assert_eq!(schema, resolved_schema); Ok(()) @@ -268,60 +230,105 @@ mod schema { mod credential_definition { use super::*; - use crate::{credential_definition_registry, CredentialDefinitionId}; + use crate::{credential_definition_registry, schema_registry}; - pub(crate) async fn build_and_submit_create_cred_def_transaction( - client: &LedgerClient, - id: &CredentialDefinitionId, - cred_def: &CredentialDefinition, - signer: &BasicSigner, - ) -> String { + #[async_std::test] + async fn demo_create_credential_definition() -> VdrResult<()> { + let signer = basic_signer(); + let client = client(); + + // create DID + let did = super::did::did(&TRUSTEE_ACC.clone()); + + // 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(); + let receipt = sign_and_submit_transaction(&client, transaction, &signer).await; + println!("Schema Receipt: {}", receipt); + + // write + let (credential_definition_id, credential_definition) = + credential_definition(&did, &schema_id, None); let transaction = credential_definition_registry::build_create_credential_definition_transaction( &client, &TRUSTEE_ACC, - id, - cred_def, + &credential_definition_id, + &credential_definition, ) .await .unwrap(); - sign_and_submit_transaction(client, transaction, signer).await + let receipt = sign_and_submit_transaction(&client, transaction, &signer).await; + println!("CredDef Receipt: {}", receipt); + + // read + let resolved_credential_definition = + credential_definition_registry::resolve_credential_definition( + &client, + &credential_definition_id, + ) + .await + .unwrap(); + assert_eq!(credential_definition, resolved_credential_definition); + + Ok(()) } #[async_std::test] - async fn demo_build_and_submit_transaction_test() -> VdrResult<()> { - let signer = basic_signer(); + async fn demo_endorse_credential_definition() -> VdrResult<()> { + let mut signer = basic_signer(); let client = client(); + let (identity, _) = signer.create_key(None)?; + + // create DID Document + let did = super::did::did(&identity); - // create DID Document and Schema - let did_doc = create_did(&client, &signer).await; - let (schema_id, _) = create_schema(&client, &did_doc.id, &signer).await; + // create Schema + let (schema_id, _) = super::schema::endorse_schema(&client, &did, &signer).await; // write let (credential_definition_id, credential_definition) = - credential_definition(&did_doc.id, &schema_id, None); - let receipt = build_and_submit_create_cred_def_transaction( - &client, - &credential_definition_id, - &credential_definition, - &signer, - ) - .await; - println!("Receipt: {}", receipt); + 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 endorsing_sign_bytes = transaction_endorsing_data.get_signing_bytes()?; + let signature = signer + .sign(&endorsing_sign_bytes, &identity.to_string()) + .unwrap(); - // read let transaction = - credential_definition_registry::build_resolve_credential_definition_transaction( + credential_definition_registry::build_create_credential_definition_signed_transaction( &client, + &TRUSTEE_ACC.clone(), &credential_definition_id, + &credential_definition, + &signature, ) .await .unwrap(); - let result = client.submit_transaction(&transaction).await.unwrap(); + let _receipt = sign_and_submit_transaction(&client, transaction, &signer).await; + + // read let resolved_credential_definition = - credential_definition_registry::parse_resolve_credential_definition_result( - &client, &result, + credential_definition_registry::resolve_credential_definition( + &client, + &credential_definition_id, ) + .await .unwrap(); assert_eq!(credential_definition, resolved_credential_definition); diff --git a/vdr/src/types/mod.rs b/vdr/src/types/mod.rs index 918c701b..bbba55e3 100644 --- a/vdr/src/types/mod.rs +++ b/vdr/src/types/mod.rs @@ -11,7 +11,7 @@ pub use event_query::{EventLog, EventQuery}; pub use signature::SignatureData; pub use status::{PingStatus, Status}; pub use transaction::{ - Block, Transaction, TransactionEndorsingData, TransactionSignature, TransactionType, + Block, Nonce, Transaction, TransactionEndorsingData, TransactionSignature, TransactionType, }; pub(crate) use contract::{ diff --git a/vdr/src/types/transaction.rs b/vdr/src/types/transaction.rs index bb9c9a03..b404d8fe 100644 --- a/vdr/src/types/transaction.rs +++ b/vdr/src/types/transaction.rs @@ -12,7 +12,6 @@ use std::{fmt::Debug, str::FromStr, sync::RwLock}; use crate::{ client::{GAS_LIMIT, GAS_PRICE}, - did_ethr_registry::resolve_identity_nonce, error::{VdrError, VdrResult}, types::{ contract::UintBytesParam, signature::SignatureData, Address, ContractOutput, ContractParam, @@ -354,7 +353,6 @@ impl TransactionParser { pub struct TransactionEndorsingData { pub to: Address, pub from: Address, - pub nonce: u64, pub params: Vec, } @@ -369,7 +367,6 @@ impl TransactionEndorsingData { ContractParam::Uint(Uint::from(Self::PREFIX)), ContractParam::FixedBytes(vec![Self::VERSION]), (&self.to).try_into()?, - UintBytesParam::from(self.nonce).try_into()?, ]; tokens.extend_from_slice(self.params.as_slice()); @@ -421,12 +418,10 @@ impl TransactionEndorsingDataBuilder { #[logfn_inputs(Trace)] pub async fn build(self, client: &LedgerClient) -> VdrResult { let contract = client.contract(&self.contract)?; - let nonce: u64 = resolve_identity_nonce(client, &self.identity).await?; Ok(TransactionEndorsingData { to: contract.address().to_owned(), from: self.identity.to_owned(), params: self.params, - nonce, }) } } @@ -463,3 +458,34 @@ impl From<&Block> for ContractParam { ContractParam::Uint(Uint::from(value.0)) } } + +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +pub struct Nonce(u64); + +impl Nonce { + pub fn value(&self) -> u64 { + self.0 + } +} + +impl From for Nonce { + fn from(value: u64) -> Self { + Nonce(value) + } +} + +impl TryFrom for Nonce { + type Error = VdrError; + + fn try_from(value: ContractOutput) -> Result { + Ok(Nonce::from(value.get_u64(0)?)) + } +} + +impl TryFrom<&Nonce> for ContractParam { + type Error = VdrError; + + fn try_from(value: &Nonce) -> Result { + UintBytesParam::from(value.0).try_into() + } +} diff --git a/vdr/uniffi/src/ffi/contracts/credential_definition_registry.rs b/vdr/uniffi/src/ffi/contracts/credential_definition_registry.rs index bd871b68..53999de2 100644 --- a/vdr/uniffi/src/ffi/contracts/credential_definition_registry.rs +++ b/vdr/uniffi/src/ffi/contracts/credential_definition_registry.rs @@ -1,9 +1,13 @@ use crate::ffi::{ client::LedgerClient, error::{VdrError, VdrResult}, - transaction::Transaction, + event_query::{EventLog, EventQuery}, + transaction::{Transaction, TransactionEndorsingData}, + types::SignatureData, +}; +use indy2_vdr::{ + credential_definition_registry, Address, Block, CredentialDefinitionId, }; -use indy2_vdr::{credential_definition_registry, Address, CredentialDefinitionId}; use serde_json::json; #[uniffi::export(async_runtime = "tokio")] @@ -29,27 +33,111 @@ pub async fn build_create_credential_definition_transaction( } #[uniffi::export(async_runtime = "tokio")] -pub async fn build_resolve_credential_definition_transaction( +pub async fn build_create_credential_definition_endorsing_data( client: &LedgerClient, id: &str, + credential_definition: &str, +) -> VdrResult { + let credential_definition = + serde_json::from_str(credential_definition).map_err(|err| VdrError::CommonInvalidData { + msg: format!("Unable to parse credential definition. Err: {:?}", err), + })?; + credential_definition_registry::build_create_credential_definition_endorsing_data( + &client.client, + &CredentialDefinitionId::from(id), + &credential_definition, + ) + .await + .map(TransactionEndorsingData::from) + .map_err(VdrError::from) +} + +#[uniffi::export(async_runtime = "tokio")] +pub async fn build_create_credential_definition_signed_transaction( + client: &LedgerClient, + from: &str, + id: &str, + credential_definition: &str, + signature: SignatureData, ) -> VdrResult { - let transaction = - credential_definition_registry::build_resolve_credential_definition_transaction( - &client.client, - &CredentialDefinitionId::from(id), - ) - .await?; - Ok(Transaction { transaction }) + let credential_definition = + serde_json::from_str(credential_definition).map_err(|err| VdrError::CommonInvalidData { + msg: format!("Unable to parse credential definition. Err: {:?}", err), + })?; + credential_definition_registry::build_create_credential_definition_signed_transaction( + &client.client, + &Address::from(from), + &CredentialDefinitionId::from(id), + &credential_definition, + &signature.into(), + ) + .await + .map(Transaction::from) + .map_err(VdrError::from) +} + +#[uniffi::export(async_runtime = "tokio")] +pub async fn build_get_credential_definition_created_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) } #[uniffi::export] -pub fn parse_resolve_credential_definition_result( +pub fn parse_credential_definition_created_result( client: &LedgerClient, bytes: Vec, -) -> VdrResult { - let cred_def = credential_definition_registry::parse_resolve_credential_definition_result( +) -> 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( + &client.client, + &log.into(), + )?; + Ok(json!(event).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( + &client.client, + &CredentialDefinitionId::from(id), + ) + .await?; Ok(json!(cred_def).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 07a06769..b1cee60e 100644 --- a/vdr/uniffi/src/ffi/contracts/did_ethr_registry.rs +++ b/vdr/uniffi/src/ffi/contracts/did_ethr_registry.rs @@ -1,11 +1,9 @@ -use crate::{ - ffi::{ - client::LedgerClient, - error::{VdrError, VdrResult}, - transaction::{Transaction, TransactionEndorsingData}, - types::SignatureData, - }, - EventLog, EventQuery, +use crate::ffi::{ + client::LedgerClient, + error::{VdrError, VdrResult}, + event_query::{EventLog, EventQuery}, + transaction::{Transaction, TransactionEndorsingData}, + types::SignatureData, }; use indy2_vdr::{ did_ethr_registry, Address, Block, DelegateType, DidAttributeChanged as DidAttributeChanged_, @@ -442,7 +440,7 @@ pub fn parse_did_event_response(client: &LedgerClient, log: EventLog) -> VdrResu .map_err(VdrError::from) } -#[uniffi::export] +#[uniffi::export(async_runtime = "tokio")] pub async fn resolve_did( client: &LedgerClient, did: &str, diff --git a/vdr/uniffi/src/ffi/contracts/did_indy_registry.rs b/vdr/uniffi/src/ffi/contracts/did_indy_registry.rs deleted file mode 100644 index b24390f4..00000000 --- a/vdr/uniffi/src/ffi/contracts/did_indy_registry.rs +++ /dev/null @@ -1,80 +0,0 @@ -use crate::ffi::{ - client::LedgerClient, - error::{VdrError, VdrResult}, - transaction::Transaction, -}; -use indy2_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, - identity: &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), - &Address::from(identity), - &DID::from(did), - &did_doc, - ) - .await?; - Ok(Transaction { transaction }) -} - -#[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_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_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_doc = did_indy_registry::parse_resolve_did_result(&client.client, &bytes)?; - Ok(json!(did_doc).to_string()) -} diff --git a/vdr/uniffi/src/ffi/contracts/mod.rs b/vdr/uniffi/src/ffi/contracts/mod.rs index bb4ed263..f7e7e433 100644 --- a/vdr/uniffi/src/ffi/contracts/mod.rs +++ b/vdr/uniffi/src/ffi/contracts/mod.rs @@ -1,6 +1,5 @@ pub mod credential_definition_registry; pub mod did_ethr_registry; -pub mod did_indy_registry; 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 b19af315..1a78c64f 100644 --- a/vdr/uniffi/src/ffi/contracts/schema_registry.rs +++ b/vdr/uniffi/src/ffi/contracts/schema_registry.rs @@ -1,9 +1,11 @@ use crate::ffi::{ client::LedgerClient, error::{VdrError, VdrResult}, - transaction::Transaction, + event_query::{EventLog, EventQuery}, + transaction::{Transaction, TransactionEndorsingData}, + types::SignatureData, }; -use indy2_vdr::{schema_registry, Address, SchemaId}; +use indy2_vdr::{schema_registry, Address, Block, SchemaId}; use serde_json::json; #[uniffi::export(async_runtime = "tokio")] @@ -27,18 +29,90 @@ pub async fn build_create_schema_transaction( } #[uniffi::export(async_runtime = "tokio")] -pub async fn build_resolve_schema_transaction( +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) +} + +#[uniffi::export(async_runtime = "tokio")] +pub async fn build_create_schema_signed_transaction( + client: &LedgerClient, + from: &str, + id: &str, + schema: &str, + signature: SignatureData, ) -> VdrResult { - let transaction = - schema_registry::build_resolve_schema_transaction(&client.client, &SchemaId::from(id)) - .await?; - Ok(Transaction { transaction }) + 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_signed_transaction( + &client.client, + &Address::from(from), + &SchemaId::from(id), + &schema, + &signature.into(), + ) + .await + .map(Transaction::from) + .map_err(VdrError::from) +} + +#[uniffi::export(async_runtime = "tokio")] +pub async fn build_get_schema_created_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_resolve_schema_result(client: &LedgerClient, bytes: Vec) -> VdrResult { - let schema = schema_registry::parse_resolve_schema_result(&client.client, &bytes)?; +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()) +} + +#[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()) +} + +#[uniffi::export(async_runtime = "tokio")] +pub async fn resolve_schema(client: &LedgerClient, id: &str) -> VdrResult { + let schema = schema_registry::resolve_schema(&client.client, &SchemaId::from(id)).await?; Ok(json!(schema).to_string()) } diff --git a/vdr/wasm/demo/node/src/main.ts b/vdr/wasm/demo/node/src/main.ts index 120d9b42..07b897b3 100644 --- a/vdr/wasm/demo/node/src/main.ts +++ b/vdr/wasm/demo/node/src/main.ts @@ -1,92 +1,60 @@ import fs from "fs"; import secp256k1 from "secp256k1"; -import bs58 from "bs58"; -import { randomBytes } from 'crypto' -import { LedgerClient, IndyDidRegistry, EthrDidRegistry } from "indy2-vdr"; +import { LedgerClient, EthrDidRegistry } from "indy2-vdr"; const chainId = 1337 const nodeAddress = 'http://127.0.0.1:8545' // set path to the compiled contract -const didIndyRegistryConfig = { - address: '0x0000000000000000000000000000000000003333', - specPath: '/Users/user/indy-besu/smart_contracts/artifacts/contracts/did/IndyDidRegistry.sol/IndyDidRegistry.json' -} const didEthrRegistryConfig = { address: '0x0000000000000000000000000000000000018888', - specPath: '/Users/user/indy-besu/smart_contracts/artifacts/contracts/did/EthereumExtDidRegistry.sol/EthereumExtDidRegistry.json' + specPath: '/Users/indy-besu/smart_contracts/artifacts/contracts/did/EthereumExtDidRegistry.sol/EthereumExtDidRegistry.json' } -const account = '0xf0e2db6c8dc6c681bb5d6ad121a107f300e9b2b5' -const identity = '0xb9059400dcd05158ffd8ca092937989dd27b3bdc' -const secret = Uint8Array.from([ 139, 187, 177, 179, 69, 175, 86, 181, 96, 165, 178, 11, 212, 176, 237, 28, 216, 204, 153, 88, 161, 98, 98, 188, 117, 17, 132, 83, 203, 84, 109, 247 ]) - -async function didIndyDemo(client: LedgerClient) { - console.log('2. Publish DID Document') - const did = 'did:indy2:' + bs58.encode(randomBytes(16)) - const kid = did + '#KEY-1' - const didDoc = { - "@context": [ "https://www.w3.org/ns/did/v1" ], - "id": did, - "verificationMethod": [ - { - "controller": did, - "id": kid, - "publicKeyMultibase": "zAKJP3f7BD6W4iWEQ9jwndVTCBq8ua2Utt8EEjJ6Vxsf", - "type": "Ed25519VerificationKey2018" - } - ], - "authentication": [ kid ] - } - console.log('DID Document: ' + JSON.stringify(didDoc, null, 2)) - let transaction = await IndyDidRegistry.buildCreateDidTransaction(client, account, identity, did, didDoc) - const bytesToSign = transaction.getSigningBytes() - const signature = secp256k1.ecdsaSign(bytesToSign, secret) - transaction.setSignature({ - recovery_id: signature.recid, - signature: signature.signature - }) - - const txnHash = await client.submitTransaction(transaction) - console.log('Transaction hash: ' + txnHash) - - const receipt = await client.getReceipt(txnHash) - console.log('Transaction receipt: ' + receipt) - - console.log('3. Resolve DID Document') - transaction = await IndyDidRegistry.buildResolveDidTransaction(client, didDoc.id) - const response = await client.submitTransaction(transaction) - const resolvedDidDoc = IndyDidRegistry.parseResolveDidResult(client, response) - console.log('Resolved DID Document: ' + JSON.stringify(resolvedDidDoc, null, 2)) +const trustee = { + address: '0xf0e2db6c8dc6c681bb5d6ad121a107f300e9b2b5', + secret: Uint8Array.from([ 139, 187, 177, 179, 69, 175, 86, 181, 96, 165, 178, 11, 212, 176, 237, 28, 216, 204, 153, 88, 161, 98, 98, 188, 117, 17, 132, 83, 203, 84, 109, 247 ]) +} +const identity = { + address: '0xf0e2db6c8dc6c681bb5d6ad121a107f300e9b2b5', + secret: Uint8Array.from([17, 230, 90, 7, 166, 132, 10, 84, 177, 140, 139, 18, 254, 94, 235, 200, 171, 63, 41, 29, 76, 110, 166, 107, 86, 7, 198, 74, 34, 146, 157, 66]) } -async function didEthrDemo(client: LedgerClient) { - const did = 'did:ethr:' + account +async function demo() { + console.log('1. Init client') + const contractConfigs = [ + { + "address": didEthrRegistryConfig.address, + "spec": JSON.parse(fs.readFileSync(didEthrRegistryConfig.specPath, 'utf8')), + } + ] + const client = new LedgerClient(chainId, nodeAddress, contractConfigs, null) + const status = await client.ping() + console.log('Status: ' + JSON.stringify(status, null, 2)) + + console.log('2. Publish and Modify DID') - console.log('2. Publish Sevice DID Attribute') + console.log('2.1 Publish Service DID Attribute') + const did = 'did:ethr:' + identity.address const serviceAttribute = {"serviceEndpoint":"http://10.0.0.2","type":"TestService"} - let transaction = await EthrDidRegistry.buildDidSetAttributeTransaction(client, account, did, serviceAttribute, BigInt(100000)) - let bytesToSign = transaction.getSigningBytes() - let signature = secp256k1.ecdsaSign(bytesToSign, secret) - transaction.setSignature({ + let endorsingData = await EthrDidRegistry.buildDidSetAttributeEndorsingData(client, did, serviceAttribute, BigInt(100000)) + let endorsingBytesToSign = endorsingData.getSigningBytes() + let signature = secp256k1.ecdsaSign(endorsingBytesToSign, identity.secret) + let authorSignature = { recovery_id: signature.recid, signature: signature.signature - }) - let txnHash = await client.submitTransaction(transaction) - let receipt = await client.getReceipt(txnHash) - console.log('Transaction receipt: ' + receipt) + } - console.log('2. Publish Key DID Attribute') - const keyAttribute = {"publicKeyBase58":"FbQWLPRhTH95MCkQUeFYdiSoQt8zMwetqfWoxqPgaq7x","purpose":"enc","type":"X25519KeyAgreementKey2020"} - transaction = await EthrDidRegistry.buildDidSetAttributeTransaction(client, account, did, keyAttribute, BigInt(100000)) - bytesToSign = transaction.getSigningBytes() - signature = secp256k1.ecdsaSign(bytesToSign, secret) - transaction.setSignature({ + let transaction = await EthrDidRegistry.buildDidSetAttributeSignedTransaction(client, trustee.address, did, serviceAttribute, BigInt(100000), authorSignature) + let bytesToSign = transaction.getSigningBytes() + signature = secp256k1.ecdsaSign(bytesToSign, trustee.secret) + let transactionSignature = { recovery_id: signature.recid, signature: signature.signature - }) - txnHash = await client.submitTransaction(transaction) - receipt = await client.getReceipt(txnHash) + } + transaction.setSignature(transactionSignature) + let txnHash = await client.submitTransaction(transaction) + let receipt = await client.getReceipt(txnHash) console.log('Transaction receipt: ' + receipt) console.log('3. Resolve DID Document') @@ -95,26 +63,7 @@ async function didEthrDemo(client: LedgerClient) { } async function main() { - console.log('1. Init client') - const contractConfigs = [ - { - "address": didIndyRegistryConfig.address, - "spec": JSON.parse(fs.readFileSync(didIndyRegistryConfig.specPath, 'utf8')), - }, - { - "address": didEthrRegistryConfig.address, - "spec": JSON.parse(fs.readFileSync(didEthrRegistryConfig.specPath, 'utf8')), - } - ] - const client = new LedgerClient(chainId, nodeAddress, contractConfigs, null) - const status = await client.ping() - console.log('Status: ' + JSON.stringify(status, null, 2)) - - console.log('DID Indy demo') - await didIndyDemo(client) - - console.log('DID Ethr demo') - await didEthrDemo(client) + await demo() } main() diff --git a/vdr/wasm/src/contracts/credential_definition_registry.rs b/vdr/wasm/src/contracts/credential_definition_registry.rs index 293103bb..addc30b3 100644 --- a/vdr/wasm/src/contracts/credential_definition_registry.rs +++ b/vdr/wasm/src/contracts/credential_definition_registry.rs @@ -1,5 +1,6 @@ use indy2_vdr::{ - credential_definition_registry, Address, CredentialDefinition, CredentialDefinitionId, + credential_definition_registry, Address, Block, CredentialDefinition, CredentialDefinitionId, + EventLog, SignatureData, }; use std::rc::Rc; use wasm_bindgen::prelude::*; @@ -7,7 +8,8 @@ use wasm_bindgen::prelude::*; use crate::{ client::LedgerClientWrapper, error::{JsResult, Result}, - transaction::TransactionWrapper, + event_query::EventQueryWrapper, + transaction::{TransactionEndorsingDataWrapper, TransactionWrapper}, }; #[wasm_bindgen(js_name = CredentialDefinitionRegistry)] @@ -35,14 +37,57 @@ impl CredentialDefinitionRegistry { Ok(TransactionWrapper(Rc::new(transaction))) } - #[wasm_bindgen(js_name = buildResolveCredentialDefinitionTransaction)] - pub async fn build_resolve_credential_definition_transaction( + #[wasm_bindgen(js_name = buildCreateSchemaEndorsingData)] + pub async fn build_create_schema_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, + ) + .await + .as_js()?; + Ok(TransactionEndorsingDataWrapper(Rc::new(data))) + } + + #[wasm_bindgen(js_name = buildCreateCredentialDefinitionSignedTransaction)] + 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_resolve_credential_definition_transaction( + credential_definition_registry::build_create_credential_definition_signed_transaction( + &client, + &address, + &id, + &cred_def, + &signature_data, + ) + .await + .as_js()?; + Ok(TransactionWrapper(Rc::new(transaction))) + } + + #[wasm_bindgen(js_name = buildGetCredentialDefinitionCreatedTransaction)] + pub async fn build_get_credential_definition_created_transaction( + client: &LedgerClientWrapper, + id: &str, + ) -> Result { + let id = CredentialDefinitionId::from(id); + let transaction = + credential_definition_registry::build_get_credential_definition_created_transaction( &client.0, &id, ) .await @@ -50,15 +95,63 @@ impl CredentialDefinitionRegistry { Ok(TransactionWrapper(Rc::new(transaction))) } - #[wasm_bindgen(js_name = parseResolveCredentialDefinitionResult)] - pub fn parse_resolve_credential_definition_result( + #[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( client: &LedgerClientWrapper, bytes: Vec, - ) -> Result { - let cred_def = credential_definition_registry::parse_resolve_credential_definition_result( + ) -> 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, + ) + .as_js()?; + let result: JsValue = serde_wasm_bindgen::to_value(&event)?; + Ok(result) + } + + #[wasm_bindgen(js_name = resolveCredentialDefinition)] + pub async fn resolve_credential_definition( + client: &LedgerClientWrapper, + id: &str, + ) -> Result { + let id = CredentialDefinitionId::from(id); + let cred_def = + credential_definition_registry::resolve_credential_definition(&client.0, &id) + .await + .as_js()?; let result: JsValue = serde_wasm_bindgen::to_value(&cred_def)?; Ok(result) } diff --git a/vdr/wasm/src/contracts/did_indy_registry.rs b/vdr/wasm/src/contracts/did_indy_registry.rs deleted file mode 100644 index 9aed0f67..00000000 --- a/vdr/wasm/src/contracts/did_indy_registry.rs +++ /dev/null @@ -1,89 +0,0 @@ -use indy2_vdr::{did_indy_registry, Address, DidDocument, DID}; -use std::rc::Rc; -use wasm_bindgen::prelude::*; - -use crate::{ - client::LedgerClientWrapper, - error::{JsResult, Result}, - transaction::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, - identity: &str, - did: &str, - did_doc: JsValue, - ) -> Result { - let did_doc: DidDocument = serde_wasm_bindgen::from_value(did_doc)?; - let address = Address::from(from); - let identity = Address::from(identity); - let did = DID::from(did); - let transaction = did_indy_registry::build_create_did_transaction( - &client.0, &address, &identity, &did, &did_doc, - ) - .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 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_update_did_transaction(&client.0, &address, &did, &did_doc) - .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 = 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/mod.rs b/vdr/wasm/src/contracts/mod.rs index bb4ed263..f7e7e433 100644 --- a/vdr/wasm/src/contracts/mod.rs +++ b/vdr/wasm/src/contracts/mod.rs @@ -1,6 +1,5 @@ pub mod credential_definition_registry; pub mod did_ethr_registry; -pub mod did_indy_registry; 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 b7cc98ee..c7eec7ff 100644 --- a/vdr/wasm/src/contracts/schema_registry.rs +++ b/vdr/wasm/src/contracts/schema_registry.rs @@ -1,11 +1,12 @@ -use indy2_vdr::{schema_registry, Address, Schema, SchemaId}; +use indy2_vdr::{schema_registry, Address, Block, EventLog, Schema, SchemaId, SignatureData}; use std::rc::Rc; use wasm_bindgen::prelude::*; use crate::{ client::LedgerClientWrapper, error::{JsResult, Result}, - transaction::TransactionWrapper, + event_query::EventQueryWrapper, + transaction::{TransactionEndorsingDataWrapper, TransactionWrapper}, }; #[wasm_bindgen(js_name = SchemaRegistry)] @@ -30,24 +31,103 @@ impl SchemaRegistry { Ok(TransactionWrapper(Rc::new(transaction))) } - #[wasm_bindgen(js_name = buildResolveSchemaTransaction)] - pub async fn build_resolve_schema_transaction( + #[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) + .await + .as_js()?; + Ok(TransactionEndorsingDataWrapper(Rc::new(data))) + } + + #[wasm_bindgen(js_name = buildCreateSchemaSignedTransaction)] + 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, + ) + .await + .as_js()?; + Ok(TransactionWrapper(Rc::new(transaction))) + } + + #[wasm_bindgen(js_name = buildGetSchemaCreatedTransaction)] + pub async fn build_get_schema_created_transaction( client: &LedgerClientWrapper, id: &str, ) -> Result { let id = SchemaId::from(id); - let transaction = schema_registry::build_resolve_schema_transaction(&client.0, &id) + let transaction = schema_registry::build_get_schema_created_transaction(&client.0, &id) .await .as_js()?; Ok(TransactionWrapper(Rc::new(transaction))) } - #[wasm_bindgen(js_name = parseResolveSchemaResult)] - pub fn parse_resolve_schema_result( + #[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( 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 schema = schema_registry::parse_resolve_schema_result(&client.0, &bytes).as_js()?; + 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)?; + Ok(result) + } + + #[wasm_bindgen(js_name = resolveSchema)] + pub async fn resolve_schema(client: &LedgerClientWrapper, id: &str) -> Result { + let id = SchemaId::from(id); + let schema = schema_registry::resolve_schema(&client.0, &id) + .await + .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 68d04430..28fb55c1 100644 --- a/vdr/wrappers/python/demo/test.py +++ b/vdr/wrappers/python/demo/test.py @@ -1,10 +1,6 @@ import asyncio import json -import os from eth_keys import keys - -import base58 - from indy2_vdr import * # chain id of the running network @@ -12,14 +8,25 @@ # address of an RPC node connected to the network node_address = 'http://127.0.0.1:8545' # address of deployed IndyDidRegistry smart contract -did_contact_address = '0x0000000000000000000000000000000000003333' +did_contact_address = '0x0000000000000000000000000000000000018888' # Path to the compiled IndyDidRegistry smart contract -did_contact_spec_path = '/Users/indy-besu/smart_contracts/artifacts/contracts/did/IndyDidRegistry.sol/IndyDidRegistry.json' +did_contact_spec_path = '/Users/indy-besu/smart_contracts/artifacts/contracts/did/EthereumExtDidRegistry.sol/EthereumExtDidRegistry.json' # Account address to use for sending transactions -account = '0xf0e2db6c8dc6c681bb5d6ad121a107f300e9b2b5' -identity = '0xb9059400dcd05158ffd8ca092937989dd27b3bdc' -# Account private key -account_key = '8bbbb1b345af56b560a5b20bd4b0ed1cd8cc9958a16262bc75118453cb546df7' +trustee = { + "address": '0xf0e2db6c8dc6c681bb5d6ad121a107f300e9b2b5', + "secret": '8bbbb1b345af56b560a5b20bd4b0ed1cd8cc9958a16262bc75118453cb546df7' +} +identity = { + "address": '0xf0e2db6c8dc6c681bb5d6ad121a107f300e9b2b5', + "secret": '11e65a07a6840a54b18c8b12fe5eebc8ab3f291d4c6ea66b5607c64a22929d42' +} + + +def sign(secret: str, data: bytes): + signature = keys.PrivateKey(bytearray.fromhex(secret)).sign_msg_hash(data) + rec_id = int(signature[-1:][0]) + sig = signature[0:-1] + return SignatureData(rec_id, sig) async def demo(): @@ -31,49 +38,23 @@ async def demo(): status = await client.ping() print('Status: ' + str(status)) - print("2. Publish DID Document") - did = 'did:indy2:testnet:' + str(base58.b58encode(os.urandom(16)).decode()) - kid = did + '#KEY-1' - did_doc = { - "@context": ["https://www.w3.org/ns/did/v1"], - "id": did, - "controller": [], - "verificationMethod": [ - { - "id": kid, - "type": "EcdsaSecp256k1VerificationKey2019", - "controller": did, - "publicKeyMultibase": "zQ3shnKp9QFbmV6Xj4YkoCg23DryaxNMTCJikSezYwLibafef" - } - ], - "authentication": [kid], - "assertionMethod": [], - "capabilityInvocation": [], - "capabilityDelegation": [], - "keyAgreement": [], - "service": [], - "alsoKnownAs": [] - } - - print('DID Document: ' + json.dumps(did_doc)) - - transaction = await build_create_did_transaction(client, account, identity, did, json.dumps(did_doc)) - bytes_to_sign = transaction.get_signing_bytes() - - signature = keys.PrivateKey(bytearray.fromhex(account_key)).sign_msg_hash(bytes_to_sign) - rec_id = int(signature[-1:][0]) - sig = signature[0:-1] - transaction.set_signature(SignatureData(rec_id, sig)) - + print("2. Publish and Modify DID") + did = 'did:ethr:' + identity['address'] + service_attribute = {"serviceEndpoint": "http://10.0.0.2", "type": "TestService"} + endorsing_data = await build_did_set_attribute_endorsing_data(client, did, json.dumps(service_attribute), 1000) + identity_signature = sign(identity["secret"], endorsing_data.get_signing_bytes()) + transaction = await build_did_set_attribute_signed_transaction(client, trustee["address"], did, + json.dumps(service_attribute), 1000, + identity_signature) + trustee_signature = sign(trustee["secret"], transaction.get_signing_bytes()) + transaction.set_signature(trustee_signature) txn_hash = await client.submit_transaction(transaction) print('Transaction hash: ' + bytes(txn_hash).hex()) receipt = await client.get_receipt(txn_hash) print('Transaction receipt: ' + str(receipt)) print("3. Resolve DID Document") - transaction = await build_resolve_did_transaction(client, did) - response = await client.submit_transaction(transaction) - resolved_did_doc = parse_resolve_did_result(client, response) + resolved_did_doc = await resolve_did(client, did, None) print('Resolved DID Document:' + resolved_did_doc) diff --git a/vdr/wrappers/python/indy2_vdr/__init__.py b/vdr/wrappers/python/indy2_vdr/__init__.py index e314c891..e7197587 100644 --- a/vdr/wrappers/python/indy2_vdr/__init__.py +++ b/vdr/wrappers/python/indy2_vdr/__init__.py @@ -24,7 +24,6 @@ build_add_validator_transaction, build_assign_role_transaction, build_create_credential_definition_transaction, - build_create_did_transaction, build_did_change_owner_transaction, build_did_change_owner_signed_transaction, build_did_change_owner_endorsing_data, @@ -52,22 +51,29 @@ parse_did_event_response, resolve_did, build_create_schema_transaction, - build_deactivate_did_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_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, 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 ) __all__ = ( @@ -95,7 +101,6 @@ "build_add_validator_transaction", "build_assign_role_transaction", "build_create_credential_definition_transaction", - "build_create_did_transaction", "build_did_change_owner_transaction", "build_did_change_owner_signed_transaction", "build_did_change_owner_endorsing_data", @@ -123,20 +128,27 @@ "parse_did_event_response", "resolve_did", "build_create_schema_transaction", - "build_deactivate_did_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_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", "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/indy2_vdr/indy2_vdr.py b/vdr/wrappers/python/indy2_vdr/indy2_vdr.py index 84f57f30..2a8209db 100644 --- a/vdr/wrappers/python/indy2_vdr/indy2_vdr.py +++ b/vdr/wrappers/python/indy2_vdr/indy2_vdr.py @@ -491,13 +491,17 @@ def _uniffi_check_api_checksums(lib): raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_assign_role_transaction() != 3167: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_credential_definition_endorsing_data() != 1444: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_credential_definition_signed_transaction() != 26456: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_credential_definition_transaction() != 61090: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_did_transaction() != 17862: + if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_schema_endorsing_data() != 41486: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_schema_transaction() != 1461: + if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_schema_signed_transaction() != 25892: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_deactivate_did_transaction() != 51668: + if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_schema_transaction() != 1461: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_add_delegate_endorsing_data() != 16808: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") @@ -529,6 +533,10 @@ def _uniffi_check_api_checksums(lib): raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_set_attribute_transaction() != 15287: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_credential_definition_created_transaction() != 11334: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_credential_definition_query() != 41617: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_did_changed_transaction() != 5297: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_did_events_query() != 59834: @@ -539,21 +547,21 @@ def _uniffi_check_api_checksums(lib): raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_role_transaction() != 23366: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_schema_created_transaction() != 53318: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_schema_query() != 10119: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_validators_transaction() != 18706: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_has_role_transaction() != 6703: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_remove_validator_transaction() != 7091: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_resolve_credential_definition_transaction() != 45980: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_resolve_did_transaction() != 61414: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_resolve_schema_transaction() != 35418: - raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_revoke_role_transaction() != 18761: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_update_did_transaction() != 42568: + if lib.uniffi_indy2_vdr_uniffi_checksum_func_parse_credential_definition_created_event() != 25117: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_indy2_vdr_uniffi_checksum_func_parse_credential_definition_created_result() != 31850: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy2_vdr_uniffi_checksum_func_parse_did_attribute_changed_event_response() != 53460: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") @@ -573,14 +581,16 @@ def _uniffi_check_api_checksums(lib): raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy2_vdr_uniffi_checksum_func_parse_has_role_result() != 45027: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_parse_resolve_credential_definition_result() != 24172: + if lib.uniffi_indy2_vdr_uniffi_checksum_func_parse_schema_created_event() != 48161: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_parse_resolve_did_result() != 23936: + if lib.uniffi_indy2_vdr_uniffi_checksum_func_parse_schema_created_result() != 21869: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_parse_resolve_schema_result() != 779: + if lib.uniffi_indy2_vdr_uniffi_checksum_func_resolve_credential_definition() != 53835: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy2_vdr_uniffi_checksum_func_resolve_did() != 38549: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_indy2_vdr_uniffi_checksum_func_resolve_schema() != 54438: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy2_vdr_uniffi_checksum_method_ledgerclient_get_receipt() != 16895: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_indy2_vdr_uniffi_checksum_method_ledgerclient_ping() != 3979: @@ -731,34 +741,48 @@ def _uniffi_check_api_checksums(lib): _UniffiRustBuffer, ) _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_assign_role_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_credential_definition_transaction.argtypes = ( +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_credential_definition_endorsing_data.argtypes = ( + ctypes.c_void_p, + _UniffiRustBuffer, + _UniffiRustBuffer, +) +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_credential_definition_endorsing_data.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_credential_definition_signed_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, + _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_credential_definition_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_did_transaction.argtypes = ( +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_credential_definition_signed_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_credential_definition_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, +) +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_credential_definition_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_schema_endorsing_data.argtypes = ( + ctypes.c_void_p, + _UniffiRustBuffer, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_did_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_schema_transaction.argtypes = ( +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_schema_endorsing_data.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_schema_signed_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, + _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_schema_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_deactivate_did_transaction.argtypes = ( +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_schema_signed_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_schema_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, + _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_deactivate_did_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_schema_transaction.restype = ctypes.c_void_p _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_add_delegate_endorsing_data.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, @@ -876,6 +900,18 @@ def _uniffi_check_api_checksums(lib): ctypes.c_uint64, ) _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_set_attribute_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_credential_definition_created_transaction.argtypes = ( + ctypes.c_void_p, + _UniffiRustBuffer, +) +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_credential_definition_created_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_credential_definition_query.argtypes = ( + ctypes.c_void_p, + _UniffiRustBuffer, + _UniffiRustBuffer, + _UniffiRustBuffer, +) +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_credential_definition_query.restype = ctypes.c_void_p _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_did_changed_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, @@ -903,6 +939,18 @@ def _uniffi_check_api_checksums(lib): _UniffiRustBuffer, ) _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_role_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_schema_created_transaction.argtypes = ( + ctypes.c_void_p, + _UniffiRustBuffer, +) +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_schema_created_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_schema_query.argtypes = ( + ctypes.c_void_p, + _UniffiRustBuffer, + _UniffiRustBuffer, + _UniffiRustBuffer, +) +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_schema_query.restype = ctypes.c_void_p _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_validators_transaction.argtypes = ( ctypes.c_void_p, ) @@ -919,21 +967,6 @@ def _uniffi_check_api_checksums(lib): _UniffiRustBuffer, ) _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_remove_validator_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_resolve_credential_definition_transaction.argtypes = ( - ctypes.c_void_p, - _UniffiRustBuffer, -) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_resolve_credential_definition_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_resolve_did_transaction.argtypes = ( - ctypes.c_void_p, - _UniffiRustBuffer, -) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_resolve_did_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_resolve_schema_transaction.argtypes = ( - ctypes.c_void_p, - _UniffiRustBuffer, -) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_resolve_schema_transaction.restype = ctypes.c_void_p _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_revoke_role_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, @@ -941,13 +974,18 @@ def _uniffi_check_api_checksums(lib): _UniffiRustBuffer, ) _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_revoke_role_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_update_did_transaction.argtypes = ( +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_credential_definition_created_event.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_credential_definition_created_event.restype = _UniffiRustBuffer +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_credential_definition_created_result.argtypes = ( + ctypes.c_void_p, _UniffiRustBuffer, - _UniffiRustBuffer, + ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_update_did_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_credential_definition_created_result.restype = ctypes.c_uint64 _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_did_attribute_changed_event_response.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, @@ -1002,30 +1040,34 @@ def _uniffi_check_api_checksums(lib): ctypes.POINTER(_UniffiRustCallStatus), ) _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_has_role_result.restype = ctypes.c_int8 -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_resolve_credential_definition_result.argtypes = ( +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_schema_created_event.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_resolve_credential_definition_result.restype = _UniffiRustBuffer -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_resolve_did_result.argtypes = ( +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_schema_created_event.restype = _UniffiRustBuffer +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_schema_created_result.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_resolve_did_result.restype = _UniffiRustBuffer -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_resolve_schema_result.argtypes = ( +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_schema_created_result.restype = ctypes.c_uint64 +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_resolve_credential_definition.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, - ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_resolve_schema_result.restype = _UniffiRustBuffer +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_resolve_credential_definition.restype = ctypes.c_void_p _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_resolve_did.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, ) _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_resolve_did.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_resolve_schema.argtypes = ( + ctypes.c_void_p, + _UniffiRustBuffer, +) +_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_resolve_schema.restype = ctypes.c_void_p _UniffiLib.ffi_indy2_vdr_uniffi_rustbuffer_alloc.argtypes = ( ctypes.c_int32, ctypes.POINTER(_UniffiRustCallStatus), @@ -1300,18 +1342,24 @@ def _uniffi_check_api_checksums(lib): _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_assign_role_transaction.argtypes = ( ) _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_assign_role_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_credential_definition_endorsing_data.argtypes = ( +) +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_credential_definition_endorsing_data.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_credential_definition_signed_transaction.argtypes = ( +) +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_credential_definition_signed_transaction.restype = ctypes.c_uint16 _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_credential_definition_transaction.argtypes = ( ) _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_credential_definition_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_did_transaction.argtypes = ( +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_schema_endorsing_data.argtypes = ( +) +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_schema_endorsing_data.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_schema_signed_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_did_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_schema_signed_transaction.restype = ctypes.c_uint16 _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_schema_transaction.argtypes = ( ) _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_schema_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_deactivate_did_transaction.argtypes = ( -) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_deactivate_did_transaction.restype = ctypes.c_uint16 _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_add_delegate_endorsing_data.argtypes = ( ) _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_add_delegate_endorsing_data.restype = ctypes.c_uint16 @@ -1357,6 +1405,12 @@ def _uniffi_check_api_checksums(lib): _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_set_attribute_transaction.argtypes = ( ) _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_set_attribute_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_credential_definition_created_transaction.argtypes = ( +) +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_credential_definition_created_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_credential_definition_query.argtypes = ( +) +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_credential_definition_query.restype = ctypes.c_uint16 _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_did_changed_transaction.argtypes = ( ) _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_did_changed_transaction.restype = ctypes.c_uint16 @@ -1372,6 +1426,12 @@ def _uniffi_check_api_checksums(lib): _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_role_transaction.argtypes = ( ) _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_role_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_schema_created_transaction.argtypes = ( +) +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_schema_created_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_schema_query.argtypes = ( +) +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_schema_query.restype = ctypes.c_uint16 _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_validators_transaction.argtypes = ( ) _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_validators_transaction.restype = ctypes.c_uint16 @@ -1381,21 +1441,15 @@ def _uniffi_check_api_checksums(lib): _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_remove_validator_transaction.argtypes = ( ) _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_remove_validator_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_resolve_credential_definition_transaction.argtypes = ( -) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_resolve_credential_definition_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_resolve_did_transaction.argtypes = ( -) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_resolve_did_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_resolve_schema_transaction.argtypes = ( -) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_resolve_schema_transaction.restype = ctypes.c_uint16 _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_revoke_role_transaction.argtypes = ( ) _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_revoke_role_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_update_did_transaction.argtypes = ( +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_credential_definition_created_event.argtypes = ( +) +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_credential_definition_created_event.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_credential_definition_created_result.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_update_did_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_credential_definition_created_result.restype = ctypes.c_uint16 _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_did_attribute_changed_event_response.argtypes = ( ) _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_did_attribute_changed_event_response.restype = ctypes.c_uint16 @@ -1423,18 +1477,21 @@ def _uniffi_check_api_checksums(lib): _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_has_role_result.argtypes = ( ) _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_has_role_result.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_resolve_credential_definition_result.argtypes = ( +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_schema_created_event.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_resolve_credential_definition_result.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_resolve_did_result.argtypes = ( +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_schema_created_event.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_schema_created_result.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_resolve_did_result.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_resolve_schema_result.argtypes = ( +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_schema_created_result.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_resolve_credential_definition.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_resolve_schema_result.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_resolve_credential_definition.restype = ctypes.c_uint16 _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_resolve_did.argtypes = ( ) _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_resolve_did.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_resolve_schema.argtypes = ( +) +_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_resolve_schema.restype = ctypes.c_uint16 _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_method_ledgerclient_get_receipt.argtypes = ( ) _UniffiLib.uniffi_indy2_vdr_uniffi_checksum_method_ledgerclient_get_receipt.restype = ctypes.c_uint16 @@ -3446,7 +3503,28 @@ def build_assign_role_transaction(client: "LedgerClient",_from: "str",role: "int _UniffiConverterTypeVdrError, ) -def build_create_credential_definition_transaction(client: "LedgerClient",_from: "str",id: "str",credential_definition: "str"): +def build_create_credential_definition_endorsing_data(client: "LedgerClient",id: "str",credential_definition: "str"): + _UniffiConverterTypeLedgerClient.check_lower(client) + + _UniffiConverterString.check_lower(id) + + _UniffiConverterString.check_lower(credential_definition) + + return _uniffi_rust_call_async( + _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_credential_definition_endorsing_data( + _UniffiConverterTypeLedgerClient.lower(client), + _UniffiConverterString.lower(id), + _UniffiConverterString.lower(credential_definition)), + _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, + _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, + _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + # lift function + _UniffiConverterTypeTransactionEndorsingData.lift, + # Error FFI converter + _UniffiConverterTypeVdrError, + ) + +def build_create_credential_definition_signed_transaction(client: "LedgerClient",_from: "str",id: "str",credential_definition: "str",signature: "SignatureData"): _UniffiConverterTypeLedgerClient.check_lower(client) _UniffiConverterString.check_lower(_from) @@ -3455,12 +3533,15 @@ def build_create_credential_definition_transaction(client: "LedgerClient",_from: _UniffiConverterString.check_lower(credential_definition) + _UniffiConverterTypeSignatureData.check_lower(signature) + return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_credential_definition_transaction( + _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_credential_definition_signed_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(_from), _UniffiConverterString.lower(id), - _UniffiConverterString.lower(credential_definition)), + _UniffiConverterString.lower(credential_definition), + _UniffiConverterTypeSignatureData.lower(signature)), _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, @@ -3470,24 +3551,21 @@ def build_create_credential_definition_transaction(client: "LedgerClient",_from: _UniffiConverterTypeVdrError, ) -def build_create_did_transaction(client: "LedgerClient",_from: "str",identity: "str",did: "str",did_doc: "str"): +def build_create_credential_definition_transaction(client: "LedgerClient",_from: "str",id: "str",credential_definition: "str"): _UniffiConverterTypeLedgerClient.check_lower(client) _UniffiConverterString.check_lower(_from) - _UniffiConverterString.check_lower(identity) - - _UniffiConverterString.check_lower(did) + _UniffiConverterString.check_lower(id) - _UniffiConverterString.check_lower(did_doc) + _UniffiConverterString.check_lower(credential_definition) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_did_transaction( + _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_credential_definition_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(_from), - _UniffiConverterString.lower(identity), - _UniffiConverterString.lower(did), - _UniffiConverterString.lower(did_doc)), + _UniffiConverterString.lower(id), + _UniffiConverterString.lower(credential_definition)), _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, @@ -3497,7 +3575,28 @@ def build_create_did_transaction(client: "LedgerClient",_from: "str",identity: " _UniffiConverterTypeVdrError, ) -def build_create_schema_transaction(client: "LedgerClient",_from: "str",id: "str",schema: "str"): +def build_create_schema_endorsing_data(client: "LedgerClient",id: "str",schema: "str"): + _UniffiConverterTypeLedgerClient.check_lower(client) + + _UniffiConverterString.check_lower(id) + + _UniffiConverterString.check_lower(schema) + + return _uniffi_rust_call_async( + _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_schema_endorsing_data( + _UniffiConverterTypeLedgerClient.lower(client), + _UniffiConverterString.lower(id), + _UniffiConverterString.lower(schema)), + _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, + _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, + _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + # lift function + _UniffiConverterTypeTransactionEndorsingData.lift, + # Error FFI converter + _UniffiConverterTypeVdrError, + ) + +def build_create_schema_signed_transaction(client: "LedgerClient",_from: "str",id: "str",schema: "str",signature: "SignatureData"): _UniffiConverterTypeLedgerClient.check_lower(client) _UniffiConverterString.check_lower(_from) @@ -3506,12 +3605,15 @@ def build_create_schema_transaction(client: "LedgerClient",_from: "str",id: "str _UniffiConverterString.check_lower(schema) + _UniffiConverterTypeSignatureData.check_lower(signature) + return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_schema_transaction( + _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_schema_signed_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(_from), _UniffiConverterString.lower(id), - _UniffiConverterString.lower(schema)), + _UniffiConverterString.lower(schema), + _UniffiConverterTypeSignatureData.lower(signature)), _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, @@ -3521,18 +3623,21 @@ def build_create_schema_transaction(client: "LedgerClient",_from: "str",id: "str _UniffiConverterTypeVdrError, ) -def build_deactivate_did_transaction(client: "LedgerClient",_from: "str",did: "str"): +def build_create_schema_transaction(client: "LedgerClient",_from: "str",id: "str",schema: "str"): _UniffiConverterTypeLedgerClient.check_lower(client) _UniffiConverterString.check_lower(_from) - _UniffiConverterString.check_lower(did) + _UniffiConverterString.check_lower(id) + + _UniffiConverterString.check_lower(schema) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_deactivate_did_transaction( + _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_schema_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(_from), - _UniffiConverterString.lower(did)), + _UniffiConverterString.lower(id), + _UniffiConverterString.lower(schema)), _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, @@ -3938,6 +4043,48 @@ def build_did_set_attribute_transaction(client: "LedgerClient",_from: "str",did: _UniffiConverterTypeVdrError, ) +def build_get_credential_definition_created_transaction(client: "LedgerClient",id: "str"): + _UniffiConverterTypeLedgerClient.check_lower(client) + + _UniffiConverterString.check_lower(id) + + return _uniffi_rust_call_async( + _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_credential_definition_created_transaction( + _UniffiConverterTypeLedgerClient.lower(client), + _UniffiConverterString.lower(id)), + _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, + _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, + _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + # lift function + _UniffiConverterTypeTransaction.lift, + # Error FFI converter + _UniffiConverterTypeVdrError, + ) + +def build_get_credential_definition_query(client: "LedgerClient",id: "str",from_block: "typing.Optional[int]",to_block: "typing.Optional[int]"): + _UniffiConverterTypeLedgerClient.check_lower(client) + + _UniffiConverterString.check_lower(id) + + _UniffiConverterOptionalUInt64.check_lower(from_block) + + _UniffiConverterOptionalUInt64.check_lower(to_block) + + return _uniffi_rust_call_async( + _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_credential_definition_query( + _UniffiConverterTypeLedgerClient.lower(client), + _UniffiConverterString.lower(id), + _UniffiConverterOptionalUInt64.lower(from_block), + _UniffiConverterOptionalUInt64.lower(to_block)), + _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, + _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, + _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + # lift function + _UniffiConverterTypeEventQuery.lift, + # Error FFI converter + _UniffiConverterTypeVdrError, + ) + def build_get_did_changed_transaction(client: "LedgerClient",did: "str"): _UniffiConverterTypeLedgerClient.check_lower(client) @@ -4034,33 +4181,15 @@ def build_get_role_transaction(client: "LedgerClient",account: "str"): _UniffiConverterTypeVdrError, ) -def build_get_validators_transaction(client: "LedgerClient"): - _UniffiConverterTypeLedgerClient.check_lower(client) - - return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_validators_transaction( - _UniffiConverterTypeLedgerClient.lower(client)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, - # lift function - _UniffiConverterTypeTransaction.lift, - # Error FFI converter - _UniffiConverterTypeVdrError, - ) - -def build_has_role_transaction(client: "LedgerClient",role: "int",account: "str"): +def build_get_schema_created_transaction(client: "LedgerClient",id: "str"): _UniffiConverterTypeLedgerClient.check_lower(client) - _UniffiConverterUInt8.check_lower(role) - - _UniffiConverterString.check_lower(account) + _UniffiConverterString.check_lower(id) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_has_role_transaction( + _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_schema_created_transaction( _UniffiConverterTypeLedgerClient.lower(client), - _UniffiConverterUInt8.lower(role), - _UniffiConverterString.lower(account)), + _UniffiConverterString.lower(id)), _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, @@ -4070,36 +4199,36 @@ 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_get_schema_query(client: "LedgerClient",id: "str",from_block: "typing.Optional[int]",to_block: "typing.Optional[int]"): _UniffiConverterTypeLedgerClient.check_lower(client) - _UniffiConverterString.check_lower(_from) + _UniffiConverterString.check_lower(id) - _UniffiConverterString.check_lower(validator_address) + _UniffiConverterOptionalUInt64.check_lower(from_block) + + _UniffiConverterOptionalUInt64.check_lower(to_block) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_remove_validator_transaction( + _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_schema_query( _UniffiConverterTypeLedgerClient.lower(client), - _UniffiConverterString.lower(_from), - _UniffiConverterString.lower(validator_address)), + _UniffiConverterString.lower(id), + _UniffiConverterOptionalUInt64.lower(from_block), + _UniffiConverterOptionalUInt64.lower(to_block)), _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, # lift function - _UniffiConverterTypeTransaction.lift, + _UniffiConverterTypeEventQuery.lift, # Error FFI converter _UniffiConverterTypeVdrError, ) -def build_resolve_credential_definition_transaction(client: "LedgerClient",id: "str"): +def build_get_validators_transaction(client: "LedgerClient"): _UniffiConverterTypeLedgerClient.check_lower(client) - _UniffiConverterString.check_lower(id) - return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_resolve_credential_definition_transaction( - _UniffiConverterTypeLedgerClient.lower(client), - _UniffiConverterString.lower(id)), + _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_validators_transaction( + _UniffiConverterTypeLedgerClient.lower(client)), _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, @@ -4109,15 +4238,18 @@ def build_resolve_credential_definition_transaction(client: "LedgerClient",id: " _UniffiConverterTypeVdrError, ) -def build_resolve_did_transaction(client: "LedgerClient",did: "str"): +def build_has_role_transaction(client: "LedgerClient",role: "int",account: "str"): _UniffiConverterTypeLedgerClient.check_lower(client) - _UniffiConverterString.check_lower(did) + _UniffiConverterUInt8.check_lower(role) + + _UniffiConverterString.check_lower(account) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_resolve_did_transaction( + _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_has_role_transaction( _UniffiConverterTypeLedgerClient.lower(client), - _UniffiConverterString.lower(did)), + _UniffiConverterUInt8.lower(role), + _UniffiConverterString.lower(account)), _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, @@ -4127,15 +4259,18 @@ def build_resolve_did_transaction(client: "LedgerClient",did: "str"): _UniffiConverterTypeVdrError, ) -def build_resolve_schema_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_indy2_vdr_uniffi_fn_func_build_resolve_schema_transaction( + _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_remove_validator_transaction( _UniffiConverterTypeLedgerClient.lower(client), - _UniffiConverterString.lower(id)), + _UniffiConverterString.lower(_from), + _UniffiConverterString.lower(validator_address)), _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, @@ -4169,29 +4304,25 @@ def build_revoke_role_transaction(client: "LedgerClient",_from: "str",role: "int _UniffiConverterTypeVdrError, ) -def build_update_did_transaction(client: "LedgerClient",_from: "str",did: "str",did_doc: "str"): +def parse_credential_definition_created_event(client: "LedgerClient",log: "EventLog") -> "str": _UniffiConverterTypeLedgerClient.check_lower(client) - _UniffiConverterString.check_lower(_from) + _UniffiConverterTypeEventLog.check_lower(log) - _UniffiConverterString.check_lower(did) + return _UniffiConverterString.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_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_doc) + _UniffiConverterBytes.check_lower(bytes) - return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_update_did_transaction( + return _UniffiConverterUInt64.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_credential_definition_created_result, _UniffiConverterTypeLedgerClient.lower(client), - _UniffiConverterString.lower(_from), - _UniffiConverterString.lower(did), - _UniffiConverterString.lower(did_doc)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, - # lift function - _UniffiConverterTypeTransaction.lift, - # Error FFI converter - _UniffiConverterTypeVdrError, - ) + _UniffiConverterBytes.lower(bytes))) + def parse_did_attribute_changed_event_response(client: "LedgerClient",log: "EventLog") -> "DidAttributeChanged": _UniffiConverterTypeLedgerClient.check_lower(client) @@ -4283,35 +4414,43 @@ def parse_has_role_result(client: "LedgerClient",bytes: "bytes") -> "bool": _UniffiConverterBytes.lower(bytes))) -def parse_resolve_credential_definition_result(client: "LedgerClient",bytes: "bytes") -> "str": +def parse_schema_created_event(client: "LedgerClient",log: "EventLog") -> "str": _UniffiConverterTypeLedgerClient.check_lower(client) - _UniffiConverterBytes.check_lower(bytes) + _UniffiConverterTypeEventLog.check_lower(log) - return _UniffiConverterString.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_resolve_credential_definition_result, + return _UniffiConverterString.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_schema_created_event, _UniffiConverterTypeLedgerClient.lower(client), - _UniffiConverterBytes.lower(bytes))) + _UniffiConverterTypeEventLog.lower(log))) -def parse_resolve_did_result(client: "LedgerClient",bytes: "bytes") -> "str": +def parse_schema_created_result(client: "LedgerClient",bytes: "bytes") -> "int": _UniffiConverterTypeLedgerClient.check_lower(client) _UniffiConverterBytes.check_lower(bytes) - return _UniffiConverterString.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_resolve_did_result, + return _UniffiConverterUInt64.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_schema_created_result, _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterBytes.lower(bytes))) -def parse_resolve_schema_result(client: "LedgerClient",bytes: "bytes") -> "str": +def resolve_credential_definition(client: "LedgerClient",id: "str"): _UniffiConverterTypeLedgerClient.check_lower(client) - _UniffiConverterBytes.check_lower(bytes) + _UniffiConverterString.check_lower(id) - return _UniffiConverterString.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_resolve_schema_result, + return _uniffi_rust_call_async( + _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_resolve_credential_definition( _UniffiConverterTypeLedgerClient.lower(client), - _UniffiConverterBytes.lower(bytes))) - + _UniffiConverterString.lower(id)), + _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_rust_buffer, + _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_rust_buffer, + _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_rust_buffer, + # lift function + _UniffiConverterString.lift, + # Error FFI converter + _UniffiConverterTypeVdrError, + ) def resolve_did(client: "LedgerClient",did: "str",options: "typing.Optional[DidResolutionOptions]"): _UniffiConverterTypeLedgerClient.check_lower(client) @@ -4334,6 +4473,24 @@ def resolve_did(client: "LedgerClient",did: "str",options: "typing.Optional[DidR _UniffiConverterTypeVdrError, ) +def resolve_schema(client: "LedgerClient",id: "str"): + _UniffiConverterTypeLedgerClient.check_lower(client) + + _UniffiConverterString.check_lower(id) + + return _uniffi_rust_call_async( + _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_resolve_schema( + _UniffiConverterTypeLedgerClient.lower(client), + _UniffiConverterString.lower(id)), + _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_rust_buffer, + _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_rust_buffer, + _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_rust_buffer, + # lift function + _UniffiConverterString.lift, + # Error FFI converter + _UniffiConverterTypeVdrError, + ) + __all__ = [ "InternalError", "DidEvents", @@ -4353,10 +4510,12 @@ def resolve_did(client: "LedgerClient",did: "str",options: "typing.Optional[DidR "TransactionSignature", "build_add_validator_transaction", "build_assign_role_transaction", + "build_create_credential_definition_endorsing_data", + "build_create_credential_definition_signed_transaction", "build_create_credential_definition_transaction", - "build_create_did_transaction", + "build_create_schema_endorsing_data", + "build_create_schema_signed_transaction", "build_create_schema_transaction", - "build_deactivate_did_transaction", "build_did_add_delegate_endorsing_data", "build_did_add_delegate_signed_transaction", "build_did_add_delegate_transaction", @@ -4372,19 +4531,21 @@ def resolve_did(client: "LedgerClient",did: "str",options: "typing.Optional[DidR "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", - "build_update_did_transaction", + "parse_credential_definition_created_event", + "parse_credential_definition_created_result", "parse_did_attribute_changed_event_response", "parse_did_changed_result", "parse_did_delegate_changed_event_response", @@ -4394,10 +4555,11 @@ def resolve_did(client: "LedgerClient",did: "str",options: "typing.Optional[DidR "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", + "parse_schema_created_event", + "parse_schema_created_result", + "resolve_credential_definition", "resolve_did", + "resolve_schema", "EventQuery", "LedgerClient", "Transaction", From ef330f60d245a982146e034e5d826176246fa769 Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Tue, 30 Jan 2024 10:21:59 +0300 Subject: [PATCH 2/5] Added schema publishing to samples Signed-off-by: artem.ivanov --- .../cl/CredentialDefinitionRegistry.spec.ts | 4 +- .../test/cl/SchemaRegistry.spec.ts | 6 +- vdr/wasm/demo/node/src/main.ts | 62 +++++++++++++------ vdr/wrappers/python/demo/test.py | 46 +++++++++++--- 4 files changed, 87 insertions(+), 31 deletions(-) diff --git a/smart_contracts/test/cl/CredentialDefinitionRegistry.spec.ts b/smart_contracts/test/cl/CredentialDefinitionRegistry.spec.ts index 2e623d1f..7faeb5b8 100644 --- a/smart_contracts/test/cl/CredentialDefinitionRegistry.spec.ts +++ b/smart_contracts/test/cl/CredentialDefinitionRegistry.spec.ts @@ -50,7 +50,7 @@ describe('CredentialDefinitionRegistry', function () { }) describe('Add/Resolve Credential Definition', function () { - it('Should create and resolve Credential Definition', async function () { + it('Should create Credential Definition', async function () { const { id, credDef } = createCredentialDefinitionObject({ issuer, schemaId }) await credentialDefinitionRegistry.createCredentialDefinition(issuer, id, schemaId, credDef) @@ -59,7 +59,7 @@ describe('CredentialDefinitionRegistry', function () { expect(created).to.be.not.equal(0) }) - it('Should fail if resolving Credential Definition does not exist', async function () { + it('Should return zero created block a non-existing credential definition', async function () { const { id } = createCredentialDefinitionObject({ issuer, schemaId }) const created = await credentialDefinitionRegistry.created(id) diff --git a/smart_contracts/test/cl/SchemaRegistry.spec.ts b/smart_contracts/test/cl/SchemaRegistry.spec.ts index 1a49cc7d..9a11f2a7 100644 --- a/smart_contracts/test/cl/SchemaRegistry.spec.ts +++ b/smart_contracts/test/cl/SchemaRegistry.spec.ts @@ -39,7 +39,7 @@ describe('SchemaRegistry', function () { }) describe('Add/Resolve Schema', function () { - it('Should create and resolve Schema', async function () { + it('Should create Schema', async function () { const { id, schema } = createSchemaObject({ issuer }) await schemaRegistry.createSchema(issuer, id, schema) @@ -48,7 +48,7 @@ describe('SchemaRegistry', function () { expect(created).to.be.not.equal(0) }) - it('Should fail if resolving a non-existing schema', async function () { + it('Should return zero created block a non-existing schema', async function () { const { id } = createSchemaObject({ issuer }) const created = await schemaRegistry.created(id) @@ -75,7 +75,7 @@ describe('SchemaRegistry', function () { }) describe('Endorse/Resolve Schema with did:ethr Issuer', function () { - it('Should endorse and resolve Schema', async function () { + it('Should endorse Schema', async function () { const { id, schema } = createSchemaObject({ issuer: testActorAddress }) const sig = await signSchemaEndorsementData(schemaRegistry, testActorAddress, testActorPrivateKey, id, schema) diff --git a/vdr/wasm/demo/node/src/main.ts b/vdr/wasm/demo/node/src/main.ts index 07b897b3..a0af1d6f 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 } from "indy2-vdr"; +import { LedgerClient, EthrDidRegistry, SchemaRegistry } from "indy2-vdr"; const chainId = 1337 const nodeAddress = 'http://127.0.0.1:8545' @@ -10,14 +10,27 @@ const didEthrRegistryConfig = { address: '0x0000000000000000000000000000000000018888', specPath: '/Users/indy-besu/smart_contracts/artifacts/contracts/did/EthereumExtDidRegistry.sol/EthereumExtDidRegistry.json' } +const schemaRegistryConfig = { + address: '0x0000000000000000000000000000000000005555', + specPath: '/Users/indy-besu/smart_contracts/artifacts/contracts/cl/SchemaRegistry.sol/SchemaRegistry.json' +} + const trustee = { address: '0xf0e2db6c8dc6c681bb5d6ad121a107f300e9b2b5', secret: Uint8Array.from([ 139, 187, 177, 179, 69, 175, 86, 181, 96, 165, 178, 11, 212, 176, 237, 28, 216, 204, 153, 88, 161, 98, 98, 188, 117, 17, 132, 83, 203, 84, 109, 247 ]) } const identity = { - address: '0xf0e2db6c8dc6c681bb5d6ad121a107f300e9b2b5', - secret: Uint8Array.from([17, 230, 90, 7, 166, 132, 10, 84, 177, 140, 139, 18, 254, 94, 235, 200, 171, 63, 41, 29, 76, 110, 166, 107, 86, 7, 198, 74, 34, 146, 157, 66]) + address: '0xce70ce892768d46caf120b600dec29ed20198982', + secret: Uint8Array.from([126, 218, 51, 235, 106, 56, 168, 226, 49, 234, 92, 61, 233, 13, 242, 75, 137, 130, 228, 222, 148, 239, 14, 63, 135, 13, 140, 163, 134, 166, 49, 50]) +} + +function sign(message: Uint8Array, key: Uint8Array) { + let signature = secp256k1.ecdsaSign(message, key) + return { + recovery_id: signature.recid, + signature: signature.signature + } } async function demo() { @@ -26,6 +39,10 @@ async function demo() { { "address": didEthrRegistryConfig.address, "spec": JSON.parse(fs.readFileSync(didEthrRegistryConfig.specPath, 'utf8')), + }, + { + "address": schemaRegistryConfig.address, + "spec": JSON.parse(fs.readFileSync(schemaRegistryConfig.specPath, 'utf8')), } ] const client = new LedgerClient(chainId, nodeAddress, contractConfigs, null) @@ -33,25 +50,12 @@ async function demo() { console.log('Status: ' + JSON.stringify(status, null, 2)) console.log('2. Publish and Modify DID') - - console.log('2.1 Publish Service DID Attribute') 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)) - let endorsingBytesToSign = endorsingData.getSigningBytes() - let signature = secp256k1.ecdsaSign(endorsingBytesToSign, identity.secret) - let authorSignature = { - recovery_id: signature.recid, - signature: signature.signature - } - + let authorSignature = sign(endorsingData.getSigningBytes(), identity.secret) let transaction = await EthrDidRegistry.buildDidSetAttributeSignedTransaction(client, trustee.address, did, serviceAttribute, BigInt(100000), authorSignature) - let bytesToSign = transaction.getSigningBytes() - signature = secp256k1.ecdsaSign(bytesToSign, trustee.secret) - let transactionSignature = { - recovery_id: signature.recid, - signature: signature.signature - } + let transactionSignature = sign(transaction.getSigningBytes(), trustee.secret) transaction.setSignature(transactionSignature) let txnHash = await client.submitTransaction(transaction) let receipt = await client.getReceipt(txnHash) @@ -60,6 +64,28 @@ async function demo() { console.log('3. Resolve DID Document') const didWithMeta = await EthrDidRegistry.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 schema = { + "attrNames": [ "First Name", "Last Name" ], + "issuerId": `did:ethr:test:${identity.address}`, + "name": name, + "version": "1.0.0" + } + let schemaEndorsingData = await SchemaRegistry.buildCreateSchemaEndorsingData(client, schemaId, schema) + authorSignature = sign(schemaEndorsingData.getSigningBytes(), identity.secret) + transaction = await SchemaRegistry.buildCreateSchemaSignedTransaction(client, trustee.address, schemaId, schema, authorSignature) + transactionSignature = sign(transaction.getSigningBytes(), trustee.secret) + transaction.setSignature(transactionSignature) + txnHash = await client.submitTransaction(transaction) + receipt = await client.getReceipt(txnHash) + console.log(' Schema Transaction receipt: ' + receipt) + + console.log('5. Resolve Schema') + const resolvedSchema = await SchemaRegistry.resolveSchema(client, schemaId) + console.log(' Resolved Schema: ' + JSON.stringify(resolvedSchema, null, 2)) } async function main() { diff --git a/vdr/wrappers/python/demo/test.py b/vdr/wrappers/python/demo/test.py index 28fb55c1..a3643bc8 100644 --- a/vdr/wrappers/python/demo/test.py +++ b/vdr/wrappers/python/demo/test.py @@ -1,5 +1,8 @@ import asyncio import json +import secrets +import string + from eth_keys import keys from indy2_vdr import * @@ -9,16 +12,18 @@ node_address = 'http://127.0.0.1:8545' # address of deployed IndyDidRegistry smart contract did_contact_address = '0x0000000000000000000000000000000000018888' +schema_contact_address = '0x0000000000000000000000000000000000005555' # Path to the compiled IndyDidRegistry smart contract did_contact_spec_path = '/Users/indy-besu/smart_contracts/artifacts/contracts/did/EthereumExtDidRegistry.sol/EthereumExtDidRegistry.json' +schema_contact_spec_path = '/Users/indy-besu/smart_contracts/artifacts/contracts/cl/SchemaRegistry.sol/SchemaRegistry.json' # Account address to use for sending transactions trustee = { "address": '0xf0e2db6c8dc6c681bb5d6ad121a107f300e9b2b5', "secret": '8bbbb1b345af56b560a5b20bd4b0ed1cd8cc9958a16262bc75118453cb546df7' } identity = { - "address": '0xf0e2db6c8dc6c681bb5d6ad121a107f300e9b2b5', - "secret": '11e65a07a6840a54b18c8b12fe5eebc8ab3f291d4c6ea66b5607c64a22929d42' + "address": '0xce70ce892768d46caf120b600dec29ed20198982', + "secret": '7eda33eb6a38a8e231ea5c3de90df24b8982e4de94ef0e3f870d8ca386a63132' } @@ -32,13 +37,14 @@ def sign(secret: str, data: bytes): async def demo(): print("1. Init client") contract_configs = [ - ContractConfig(did_contact_address, did_contact_spec_path, None) + ContractConfig(did_contact_address, did_contact_spec_path, None), + ContractConfig(schema_contact_address, schema_contact_spec_path, None), ] client = LedgerClient(chain_id, node_address, contract_configs, None) status = await client.ping() - print('Status: ' + str(status)) + print(' Status: ' + str(status)) - print("2. Publish and Modify DID") + print("2. Publish DID") did = 'did:ethr:' + identity['address'] service_attribute = {"serviceEndpoint": "http://10.0.0.2", "type": "TestService"} endorsing_data = await build_did_set_attribute_endorsing_data(client, did, json.dumps(service_attribute), 1000) @@ -49,14 +55,38 @@ async def demo(): trustee_signature = sign(trustee["secret"], transaction.get_signing_bytes()) transaction.set_signature(trustee_signature) txn_hash = await client.submit_transaction(transaction) - print('Transaction hash: ' + bytes(txn_hash).hex()) + print(' Transaction hash: ' + bytes(txn_hash).hex()) receipt = await client.get_receipt(txn_hash) - print('Transaction receipt: ' + str(receipt)) + print(' Transaction receipt: ' + str(receipt)) print("3. Resolve DID Document") resolved_did_doc = await resolve_did(client, did, None) - print('Resolved DID Document:' + resolved_did_doc) + print(' Resolved DID Document:' + resolved_did_doc) + + 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 = { + "attrNames": ["First Name", "Last Name"], + "issuerId": 'did:ethr:test:' + identity["address"], + "name": name, + "version": "1.0.0" + } + endorsing_data = await build_create_schema_endorsing_data(client, schema_id, 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, + json.dumps(schema), + identity_signature) + trustee_signature = sign(trustee["secret"], transaction.get_signing_bytes()) + transaction.set_signature(trustee_signature) + txn_hash = await client.submit_transaction(transaction) + print(' Transaction hash: ' + bytes(txn_hash).hex()) + receipt = await client.get_receipt(txn_hash) + print(' Transaction receipt: ' + str(receipt)) + print("5. Resolve Schema") + resolved_schema = await resolve_schema(client, schema_id) + print(' Resolved Schema:' + resolved_schema) if __name__ == "__main__": asyncio.get_event_loop().run_until_complete(demo()) From dbf6e7c627ba822d436bdb3d21c1739cd39926eb Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Tue, 30 Jan 2024 14:44:21 +0300 Subject: [PATCH 3/5] Documentation clean up Signed-off-by: artem.ivanov --- README.md | 5 ++ docs/README.md | 23 ++++++-- docs/design/legacy-identifiers-support.md | 71 +++++++++++++++++++++++ smart_contracts/README.md | 37 +++++------- vdr/README.md | 6 +- 5 files changed, 111 insertions(+), 31 deletions(-) create mode 100644 docs/design/legacy-identifiers-support.md diff --git a/README.md b/README.md index fdf192b2..2d74b10b 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,11 @@ _Resources_ section. The [Docker for Mac](https://docs.docker.com/docker-for-mac See [README.md](/smart_contracts/README.md). +## Client library + +[Rust library](./vdr/README.md) representing a convenient client for connecting to an Indy-Besu node, building and +executing transactions and queries. + ## Contributing Pull requests are welcome! Please read our [contributions guide](./CONTRIBUTING.md) diff --git a/docs/README.md b/docs/README.md index 058f8058..d65db3b6 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,5 +1,11 @@ ## Design documents +### Diagrams + +- [Components Overview](./design/conmponents.png) +- [Deployed Smart Contracts](./design/contracts.png) +- [Flow](./design/flow.png) + ### Modules - Network Permission modules: @@ -8,12 +14,19 @@ - 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 -- [DID Methods](design/did-registry.md) - Supported DID methods -- Registries: - - [DID Document Registry](design/did-registry.md) +- Identity: + - [DID Method](design/did-method.md) - Supported DID method - [CL Registry](design/cl-registry.md) -- [VDR](design/vdr.md) - design of VDR library +- [Client](design/vdr.md) - design of VDR library -## Migration documents +### Migration documents - [Indy Migration](migrtion/migration.md) + +### Development designs + +- [Roadmap](./roadmap.md) +- [DID and CL registers approach](./design/registry.md) +- [Transaction Endorsement](./design/endorsement.md) +- [Contract upgradability](./design/upgradability.md) +- [Legacy identifiers support](./design/legacy-identifiers-support.md) diff --git a/docs/design/legacy-identifiers-support.md b/docs/design/legacy-identifiers-support.md new file mode 100644 index 00000000..296569b8 --- /dev/null +++ b/docs/design/legacy-identifiers-support.md @@ -0,0 +1,71 @@ +## 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. +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; + + // legacy formated ids of schemas and cred defs -> new id + mapping(string => string) public clMappings; + + function createDidMapping(string legacyDid, bytes32 key, bytes32 ed25518Signature) { + // check signature + // check legacyDid is derived from key + didMappings[legacyDid] = msg.sender; + } + + function endorseDidMapping(address identity, string legacyDid, bytes32 key, bytes32 ed25518Signature, bytes32 ecdsaSignature) { + // check signatures + didMappings[legacyDid] = identity; + } + + // resolve mapping done through `didMappings(string)` function available after contract compilation + + function createClMapping(string legacyId, string id, bytes32 key, bytes32 signature) { + // fetch issuer did from legacy schema/credDef id + // check issuer did is derived from key + // check msg.sender is owner of issuer did + // check identity is owner of schema / cred def + // check signature + clMappings[legacyId] = id; + } + + function endorseClMapping(address identity, string legacyId, string id, bytes32 key, bytes32 ed25518Signature, bytes32 ecdsaSignature) { + // fetch issuer did from legacy schema/credDef id + // check issuer did is derived from key + // check identity is owner of issuer did + // check identity is owner of schema / cred def + // check signatures + clMappings[legacyId] = id; + } + + // resolve mapping done through `clMappings(string)` function available after contract compilation + } + ``` + * Note, that user must pass signature over identifier to prove ownership +* On migration, DID owners willing to preserve resolving of legacy formatted DIDs and id's must do: + * add mapping between legacy + identifier and ethereum account representing `did:ethr` identifier by + executing `LegacyIdMappingRegistry.createDidMapping(...)` method where he must pass: + * DID identifier itself + * Associated public key + * Ed25519 signature owner identifier proving ownership + * Signature must be done over the following hash value: `keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), msg.sender, "createDidMapping", legacyDid, identity, key))` + * add mapping between legacy schema/credDef id's and new ones executing `LegacyIdMappingRegistry.createClMapping()` method he must pass: + * Legacy schema/credDef id + * New id of corresponding schema/credDef + * Associated public key + * Ed25519 signature owner identifier proving ownership + * Signature must be done over the following hash value: `keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), msg.sender, "createClMapping", legacyId, id, key))` +* After migration, clients in order to resolve legacy identifiers: + * for DID document firstly must resolve ethereum account + using `LegacyIdMappingRegistry.didMappings(identifier)`, and next resolve DID ether document as it described in the + corresponding specification. + * 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/smart_contracts/README.md b/smart_contracts/README.md index c6983704..ff1f593b 100644 --- a/smart_contracts/README.md +++ b/smart_contracts/README.md @@ -30,18 +30,20 @@ The following folders should be generated as the result: ### Main Contracts -* `contracts/auth/AccountControl.sol` - contract to manage permissions for account transactions +* [AccountControl](./contracts/auth/AccountControlInterface.sol) - contract to manage permissions for transactions and new contracts deployment * [AccountControl TS contract wrapper class](./contracts-ts/AccountControl.ts) -* `contracts/auth/RoleControl.sol` - contract to manage (assign/revoke) account roles. +* [RoleControl](./contracts/auth/RoleControlInterface.sol) - contract to manage (assign/revoke) account roles. * [RoleControl TS contract wrapper class](./contracts-ts/RoleControl.ts) -* `contracts/cl/CredentialDefinitionRegistry` - contract to manage (create/resolve) credential definitions - * [CredentialDefinitionRegistry TS contract wrapper class](./contracts-ts/CredentialDefinitionRegistry.ts) -* `contracts/cl/SchemaRegistry` - contract to manager (create/resolve) schemas +* [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) +* [SchemaRegistry](./contracts/cl/SchemaRegistryInterface.sol) - contract to manage Schemas * [SchemaRegistry TS contract wrapper class](./contracts-ts/SchemaRegistry.ts) -* `contracts/did/DidRegistry` - contract to manage (create/update/deactivate/resolve) DID doucments - * [DidRegistry TS contract wrapper class](./contracts-ts/DidRegistry.ts) -* `contracts/network/ValidatorControl.sol` - contract to manage network validator nodes. +* [CredentialDefinitionRegistry](./contracts/cl/CredentialDefinitionRegistryInterface.sol) - contract to manage CL Credential Definitions + * [CredentialDefinitionRegistry TS contract wrapper class](./contracts-ts/CredentialDefinitionRegistry.ts) +* [ValidatorControl](./contracts/network/ValidatorControlInterface.sol) - contract to manage network validator nodes. * [ValidatorControl TS contract wrapper class](./contracts-ts/ValidatorControl.ts) +* [UpgradeControl](./contracts/upgrade/UpgradeControlInterface.sol) - contract to control deployed smart contracts and their versions (proposing and approving new versions). + * [Upgrading TS contract wrapper class](./contracts-ts/UpgradeControl.ts) ### Demos @@ -51,14 +53,10 @@ 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 using `did:indy2` method. +* [Demo flow](./demos/flow.ts) - create/resolve DID/Schema/Credential Definition. ``` > 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 @@ -74,18 +72,11 @@ You can find sample scripts demonstrating the usage of deployed contracts in the ### Helper Scripts -* `genesis` - helper scripts to generate genesis blocks for injecting contracts. - - > Find more details regarding the scripts in the [genesis section](#inject-contracts-into-network-genesis) of this - document. - -## Inject contracts into network genesis - -### Prerequisites +* [Genesis](./scripts/genesis) - helper scripts to generate genesis state for injecting smart contracts. -* `socl` tool must be installed on the machine. +> `socl` tool must be installed on the machine. -This section describes how to inject smart contracts into the genesis state of the network. +#### Steps 1. Prepare the [input file](scripts/genesis/config.ts) with the initial state of each contract. diff --git a/vdr/README.md b/vdr/README.md index b3ad3104..0fc26ea8 100644 --- a/vdr/README.md +++ b/vdr/README.md @@ -67,11 +67,11 @@ cargo +nightly fmt RUST_TEST_THREADS=1 cargo test --features "ledger_test" ``` -# Logging +## Logging - To see the logs, please set `RUST_LOG` environment variable to desired log level: `info`, `debug`, `trace` etc. -## FFI +## Wrappers ### Kotlin, Python, Swift @@ -83,4 +83,4 @@ See instructions [here](./uniffi/README.md). `Indy-VDR` library uses [wasm-bindgen](https://rustwasm.github.io/wasm-bindgen/) to generate bindings for JavaScript, NodeJs, WebAssembly. -See instructions [here](./wasm/README.md). \ No newline at end of file +See instructions [here](./wasm/README.md). From 4952bd3698a4d9e9d60964b2bc35d56137798257 Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Tue, 30 Jan 2024 17:07:32 +0300 Subject: [PATCH 4/5] Processed review comments + renamed VDR library Signed-off-by: artem.ivanov --- docs/design/cl-registry.md | 6 +- docs/design/endorsement.md | 176 +-- network/config/besu/genesis.json | 12 +- network/config/nodes/validator5/key | 2 +- .../cl/CredentialDefinitionRegistry.sol | 2 +- vdr/Cargo.lock | 2 +- vdr/Cargo.toml | 4 +- vdr/README.md | 2 +- vdr/src/client/client.rs | 5 - .../cl/credential_definition_registry.rs | 41 +- .../cl/types/credential_definition.rs | 2 +- vdr/src/contracts/cl/types/schema.rs | 2 +- vdr/src/contracts/did/did_ethr_registry.rs | 82 +- vdr/src/contracts/did/types/did_doc.rs | 8 +- vdr/uniffi.toml | 2 +- vdr/uniffi/Cargo.toml | 6 +- vdr/uniffi/README.md | 2 +- vdr/uniffi/build.rs | 2 +- vdr/uniffi/src/ffi/client.rs | 2 +- .../credential_definition_registry.rs | 4 +- .../src/ffi/contracts/did_ethr_registry.rs | 2 +- vdr/uniffi/src/ffi/contracts/role_control.rs | 2 +- .../src/ffi/contracts/schema_registry.rs | 2 +- .../src/ffi/contracts/validator_control.rs | 2 +- vdr/uniffi/src/ffi/error.rs | 2 +- vdr/uniffi/src/ffi/event_query.rs | 2 +- vdr/uniffi/src/ffi/transaction.rs | 2 +- vdr/uniffi/src/ffi/types.rs | 2 +- .../src/{indy2_vdr.udl => indy_besu_vdr.udl} | 2 +- vdr/uniffi/src/lib.rs | 2 +- vdr/wasm/Cargo.toml | 6 +- vdr/wasm/demo/node/package.json | 6 +- vdr/wasm/demo/node/src/main.ts | 2 +- vdr/wasm/src/client.rs | 2 +- .../credential_definition_registry.rs | 2 +- vdr/wasm/src/contracts/did_ethr_registry.rs | 2 +- vdr/wasm/src/contracts/role_control.rs | 2 +- vdr/wasm/src/contracts/schema_registry.rs | 2 +- vdr/wasm/src/contracts/validator_control.rs | 2 +- vdr/wasm/src/error.rs | 2 +- vdr/wasm/src/event_query.rs | 2 +- vdr/wasm/src/transaction.rs | 2 +- vdr/wrappers/python/README.md | 4 +- vdr/wrappers/python/demo/test.py | 2 +- .../{indy2_vdr => indy_besu_vdr}/__init__.py | 2 +- .../indy_besu_vdr.py} | 1288 ++++++++--------- .../{indy2_vdr => indy_besu_vdr}/version.py | 0 vdr/wrappers/python/setup.py | 8 +- 48 files changed, 810 insertions(+), 910 deletions(-) rename vdr/uniffi/src/{indy2_vdr.udl => indy_besu_vdr.udl} (67%) rename vdr/wrappers/python/{indy2_vdr => indy_besu_vdr}/__init__.py (99%) rename vdr/wrappers/python/{indy2_vdr/indy2_vdr.py => indy_besu_vdr/indy_besu_vdr.py} (69%) rename vdr/wrappers/python/{indy2_vdr => indy_besu_vdr}/version.py (100%) diff --git a/docs/design/cl-registry.md b/docs/design/cl-registry.md index 54b1575a..5461ef30 100644 --- a/docs/design/cl-registry.md +++ b/docs/design/cl-registry.md @@ -51,11 +51,11 @@ Contract name: **SchemaRegistry** #### Create a new schema * Method: `createSchema` - * Description: Transaction to create a new AnonCreds Schema + * Description: Transaction to create a new AnonCreds Schema matching to the [specification](https://hyperledger.github.io/anoncreds-spec/#schema-publisher-publish-schema-object) * Parameters: * `identity` - Account address of schema issuer * `id` - KECCAK256 hash of schema id to be created - * `schema` - AnonCreds schema object as bytes + * `schema` - AnonCreds Schema object as bytes * Restrictions: * Schema id must be unique. * Corresponding issuer account must exist and owned by sender. @@ -172,7 +172,7 @@ Contract name: **CredentialDefinitionRegistry** #### Create a new credential definition * Method: `createCredentialDefinition` - * Description: Transaction to create a new AnonCreds Credential Definition + * 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) * Parameters: * `identity` - Account address of credential definition issuer * `id` - KECCAK256 hash of credential definition id to be created diff --git a/docs/design/endorsement.md b/docs/design/endorsement.md index ed1b60f7..b5bdba0d 100644 --- a/docs/design/endorsement.md +++ b/docs/design/endorsement.md @@ -4,103 +4,6 @@ Not all identity owners may have permissions for writing transactions on the led 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. -### DID Indy registry - -#### Flow - -* Author steps: - * Step 1: Prepares a DID Document object - * Step 2: Queries `nonce` from the ledger: `IndyDidRegistry.nonce(identity)` - * Step 3: 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), nonce[identity], identity, "createDid", did, 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-8: Application specific data - // nonce - nonce to prevent reply attack - // identity - author account address - // `createDid` original contract method - added to be aligned with did:ethr contract - // did - DID to be created - // document - DID document as JSON string - ``` - * Step 4: Performs EcDSA signing using his ethereum identity account keys - * Step 5: Passes DID Document and Signature to Endorser -* Endorser steps: - * Step 1: Endorser builds transaction to endorse - DID: `endorseDid(address identity, string did, string document, uint8 sigV, bytes32 sigR, bytes32 sigS)` - > Optionally: `identity` can be derived from DidDocument.id instead of passing explicitly - * Step 2: Endorser does regular EcDSA signing of the **Transaction** - * Step 3: Endorser submit the signed transaction to the ledger which executes deployed `IndyDidRegistry.endorseDid` - contract method -* Ethereum: - * Checks the validity of the transaction level signature (Endorser's signature) -* Contract: - * Step 1: Get current nonce value of identity - * Step 2: Calculate the hash of signed data: same as for Author Step 3 - * Step 3: 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; - -// identity - ethereum address of DID owner -// document - did document -// identitySignature - identity owner signatures (EcDSA and optionally ED25519) ower serialized DID Document -function endorseDid(address identity, string calldata did, string calldata document, uint8 sigV, bytes32 sigR, bytes32 sigS) { - // sender is endorser when it's not equal to identity - if (msg.sender == identity) { - revert InvalidmethodExecution; - } - - // calculate the hash of DiDocument - // this hash will be checked agains signatures to verify ownership - bytes32 hash = keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), nonce[identity], identity, "createDid", did, document)); - - // verify EcDSA identity owner signature ower DID + DidDocument - checkEcDsaSignature(identity, hash, identitySignature); - - nonce[identity]++; - record[didDocument.did].didDocument = didDocument - record[didDocument.did].metadata.owner = identity - record[didDocument.did].metadata.sender = msg.sender -} - -function checkEcDsaSignature(address identity, bytes32 hash, EcDSASignature signature) { - address signer = ecrecover(hash, signature.v, signature.r, signature.s); - if (signer == address(0)) { - revert InvalidSignature("Invalid signature provided"); - } - if (identity != signer) { - revert InvalidSignature("Signature does not match to the target identity"); - } -} -``` - -#### VDR - -```rust -// Prepare endorsing bytes which need to be signed by an identity owner -fn prepare_endorse_did_data( - client: &LedgerClient, - identity: &Address, - did_doc: DidDocument -) -> Vec; - -// Build transaction to endorse DID -fn build_endorse_did_transaction( - client: &LedgerClient, - sender: &Address, - identity: &Address, - did_doc: &DidDocument, - signature: &Signature -) -> VdrResult {} -``` - ### DID Ethr registry `did:ethr` allows using Ethereum addresses as identifier without prior its registration on the network. @@ -133,6 +36,8 @@ TO BE defined later. **Schema endorsing steps** +Endorsing for schemas and credential definition is designed to match existing `did:ethr` API. + > In case of Schema and Credential Definition we do not need to add `nonce` as we do not have an update operation. * Author steps: @@ -140,23 +45,22 @@ TO BE defined later. * 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, issuerId, schema)) + keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createSchema", id, 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-8: Application specific data + // 4-7: 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 - id of schema issuer // schema - schema as JSON string ``` * 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, string id, string issuerId, string schema)` + DID: `endorseSchema(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` @@ -178,16 +82,15 @@ TO BE defined later. * 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, issuerId, schemaId, credDef)) + keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createCredentialDefinition", id, 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-9: 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 - // issuerId - id of issuer // schemaId - id of schema // credDef - credential definition as JSON string ``` @@ -198,39 +101,38 @@ TO BE defined later. #### Contracts ``` -function endorseSchema( +function createSchemaSigned( address identity, - string calldata id, - string calldata issuerId, - string calldata schema, uint8 sigV, bytes32 sigR, bytes32 sigS + bytes32 id, + bytes schema, + ) public virtual { // validate identity signature - bytes32 hash = keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createSchema", id, issuerId, schema)); + bytes32 hash = keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createSchema", id, schema)); checkSignature(identity, hash, sigV, sigR, sigS); // store schema - createSchema(identity, id, issuerId, schema); + createSchema(identity, id, schema); } function endorseCredentialDefinition( address identity, - string memory id, - string calldata issuerId, - string calldata schemaId, - string memory credDef, uint8 sigV, bytes32 sigR, - bytes32 sigS + bytes32 sigS, + byets32 id, + byets32 schemaId, + byets credDef ) public virtual { // validate identity signature - bytes32 hash = keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createCredentialDefinition", id, issuerId, schemaId, credDef)); + bytes32 hash = keccak256(abi.encodePacked(bytes1(0x19), bytes1(0), address(this), identity, "createCredentialDefinition", id, schemaId, credDef)); checkSignature(identity, hash, sigV, sigR, sigS); // store credential definition - createCredentialDefinition_(identity, id, issuerId, schemaId, credDef); + createCredentialDefinition_(identity, id, schemaId, credDef); } ``` @@ -238,45 +140,35 @@ function endorseCredentialDefinition( ```rust // Prepare schema endorsing bytes which need to be signed by an identity owner -fn prepare_endorse_schema_data( +pub async fn build_create_schema_endorsing_data( client: &LedgerClient, - identity: &Address, id: &SchemaId, - issuer_id: &DID, schema: &Schema, -) -> Vec; +) -> VdrResult; // Build transaction to endorse Schema -fn build_endorse_schema_transaction( +pub async fn build_create_schema_signed_transaction( client: &LedgerClient, sender: &Address, - identity: &Address, id: &SchemaId, - issuer_id: &DID, schema: &Schema, - signature: &Signature -) -> VdrResult {} + signature: &SignatureData, +) -> VdrResult; // Prepare credential definition endorsing bytes which need to be signed by an identity owner -fn prepare_endorse_credential_definition_data( +pub async fn build_create_credential_definition_endorsing_data( client: &LedgerClient, - identity: &Address, - id: &SchemaId, - issuer_id: &DID, - schema_id: &SchemaId, - cred_def: &CredentialDefinition, -) -> Vec; + id: &CredentialDefinitionId, + credential_definition: &CredentialDefinition, +) -> VdrResult; // Build transaction to endorse CredentialDefinition -fn build_endorse_credential_definition_transaction( +pub async fn build_create_credential_definition_signed_transaction( client: &LedgerClient, - sender: &Address, - identity: &Address, - id: &SchemaId, - issuer_id: &DID, - schema_id: &SchemaId, - cred_def: &CredentialDefinition, - signature: &Signature -) -> VdrResult {} + from: &Address, + id: &CredentialDefinitionId, + credential_definition: &CredentialDefinition, + signature: &SignatureData, +) -> VdrResult; ``` diff --git a/network/config/besu/genesis.json b/network/config/besu/genesis.json index 9ffdbb7f..29c74459 100644 --- a/network/config/besu/genesis.json +++ b/network/config/besu/genesis.json @@ -175,13 +175,13 @@ "0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000009999", "0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000018888", "f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00": "0x0000000000000000000000000000000000000000000000000000000000000001", - "360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000a3f794638578ed0b3abcea8482f5a4454ebd7293" + "360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000000000000000000000002d8ef83a48caa0366b27021d47d8bb9f7d02016d" } }, - "0xa3f794638578ed0b3abcea8482f5a4454ebd7293": { + "0x2d8ef83a48caa0366b27021d47d8bb9f7d02016d": { "comment": "Implementation: Smart contract to manage schemas", "balance": "0", - "code": "0x60806040526004361061007b5760003560e01c8063ad3cb1cc1161004e578063ad3cb1cc146100fd578063bdd23ccb1461013b578063e8d740291461015b578063eaa760c21461019a57600080fd5b8063485cc955146100805780634f1ef286146100a257806352d1902d146100b55780635915b768146100dd575b600080fd5b34801561008c57600080fd5b506100a061009b3660046109e7565b6101c7565b005b6100a06100b0366004610a36565b6102c8565b3480156100c157600080fd5b506100ca6102e7565b6040519081526020015b60405180910390f35b3480156100e957600080fd5b506100a06100f8366004610b43565b610304565b34801561010957600080fd5b5061012e604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100d49190610bc3565b34801561014757600080fd5b506100a0610156366004610bf6565b610317565b34801561016757600080fd5b5061018a610176366004610c82565b600090815260026020526040902054151590565b60405190151581526020016100d4565b3480156101a657600080fd5b506100ca6101b5366004610c82565b60026020526000908152604090205481565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460019190600160401b900460ff16806102115750805467ffffffffffffffff808416911610155b1561022f5760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff191667ffffffffffffffff831617600160401b17815561025a84610376565b600180546001600160a01b0319166001600160a01b038516179055805468ff00000000000000001916815560405167ffffffffffffffff831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a150505050565b6102d06103a0565b6102d982610447565b6102e382826104ad565b5050565b60006102f1610574565b50600080516020610da083398151915290565b61031184338585856105bd565b50505050565b60405160009061033b90601960f81b90839030908c90899089908990602001610c9b565b60405160208183030381529060405280519060200120905061036c886103648a848b8b8b6106fd565b8686866105bd565b5050505050505050565b61037e6107ae565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061042757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661041b600080516020610da0833981519152546001600160a01b031690565b6001600160a01b031614155b156104455760405163703e46dd60e11b815260040160405180910390fd5b565b60005460405163574a81d760e01b81523060048201526001600160a01b0383811660248301529091169063574a81d79060440160006040518083038186803b15801561049257600080fd5b505afa1580156104a6573d6000803e3d6000fd5b5050505050565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610507575060408051601f3d908101601f1916820190925261050491810190610d0d565b60015b61053457604051634c9c8ce360e01b81526001600160a01b03831660048201526024015b60405180910390fd5b600080516020610da0833981519152811461056557604051632a87526960e21b81526004810182905260240161052b565b61056f83836107f7565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146104455760405163703e46dd60e11b815260040160405180910390fd5b6000838152600260205260409020548390156105ef576040516347f6332960e11b81526004810182905260240161052b565b6001546040516310e67a9d60e31b81526001600160a01b03808916600483015288928892911690638733d4e890602401602060405180830381865afa15801561063c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106609190610d26565b6001600160a01b0316816001600160a01b0316146106a45760405163cc41100960e01b81526001600160a01b0380841660048301528216602482015260440161052b565b600086815260026020526040908190204390555186907f3e21fe65ee16f151c8cda6e871883b2e0550f9c8511b4ea1d75c9c9e8d489f67906106eb908a9089908990610d43565b60405180910390a25050505050505050565b6040805160008082526020820180845287905260ff8616928201929092526060810184905260808101839052819060019060a0016020604051602081039080840390855afa158015610753573d6000803e3d6000fd5b505050602060405103519050806001600160a01b0316876001600160a01b0316146107a45760405163cc41100960e01b81526001600160a01b0380891660048301528216602482015260440161052b565b9695505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661044557604051631afcd79f60e31b815260040160405180910390fd5b6108008261084d565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a28051156108455761056f82826108b2565b6102e3610928565b806001600160a01b03163b60000361088357604051634c9c8ce360e01b81526001600160a01b038216600482015260240161052b565b600080516020610da083398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516108cf9190610d83565b600060405180830381855af49150503d806000811461090a576040519150601f19603f3d011682016040523d82523d6000602084013e61090f565b606091505b509150915061091f858383610947565b95945050505050565b34156104455760405163b398979f60e01b815260040160405180910390fd5b60608261095c57610957826109a6565b61099f565b815115801561097357506001600160a01b0384163b155b1561099c57604051639996b31560e01b81526001600160a01b038516600482015260240161052b565b50805b9392505050565b8051156109b65780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b6001600160a01b03811681146109cf57600080fd5b600080604083850312156109fa57600080fd5b8235610a05816109d2565b91506020830135610a15816109d2565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b60008060408385031215610a4957600080fd5b8235610a54816109d2565b9150602083013567ffffffffffffffff80821115610a7157600080fd5b818501915085601f830112610a8557600080fd5b813581811115610a9757610a97610a20565b604051601f8201601f19908116603f01168101908382118183101715610abf57610abf610a20565b81604052828152886020848701011115610ad857600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60008083601f840112610b0c57600080fd5b50813567ffffffffffffffff811115610b2457600080fd5b602083019150836020828501011115610b3c57600080fd5b9250929050565b60008060008060608587031215610b5957600080fd5b8435610b64816109d2565b935060208501359250604085013567ffffffffffffffff811115610b8757600080fd5b610b9387828801610afa565b95989497509550505050565b60005b83811015610bba578181015183820152602001610ba2565b50506000910152565b6020815260008251806020840152610be2816040850160208701610b9f565b601f01601f19169190910160400192915050565b600080600080600080600060c0888a031215610c1157600080fd5b8735610c1c816109d2565b9650602088013560ff81168114610c3257600080fd5b955060408801359450606088013593506080880135925060a088013567ffffffffffffffff811115610c6357600080fd5b610c6f8a828b01610afa565b989b979a50959850939692959293505050565b600060208284031215610c9457600080fd5b5035919050565b6001600160f81b03198881168252871660018201526bffffffffffffffffffffffff19606087811b8216600284015286901b1660168201526b637265617465536368656d6160a01b602a8201526036810184905260008284605684013750600091016056019081529695505050505050565b600060208284031215610d1f57600080fd5b5051919050565b600060208284031215610d3857600080fd5b815161099f816109d2565b6001600160a01b03841681526040602082018190528101829052818360608301376000818301606090810191909152601f909201601f1916010192915050565b60008251610d95818460208701610b9f565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca26469706673582212204a4fb68df29ffd4bbbd06a3c0b087236a2b91e6a775ec5d620b345da38d3139664736f6c63430008170033" + "code": "0x6080604052600436106100705760003560e01c80635915b7681161004e5780635915b768146100d2578063ad3cb1cc146100f2578063bdd23ccb14610130578063eaa760c21461015057600080fd5b8063485cc955146100755780634f1ef2861461009757806352d1902d146100aa575b600080fd5b34801561008157600080fd5b5061009561009036600461099d565b61017d565b005b6100956100a53660046109ec565b61027e565b3480156100b657600080fd5b506100bf61029d565b6040519081526020015b60405180910390f35b3480156100de57600080fd5b506100956100ed366004610af9565b6102ba565b3480156100fe57600080fd5b50610123604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100c99190610b79565b34801561013c57600080fd5b5061009561014b366004610bac565b6102cd565b34801561015c57600080fd5b506100bf61016b366004610c38565b60026020526000908152604090205481565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460019190600160401b900460ff16806101c75750805467ffffffffffffffff808416911610155b156101e55760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff191667ffffffffffffffff831617600160401b1781556102108461032c565b600180546001600160a01b0319166001600160a01b038516179055805468ff00000000000000001916815560405167ffffffffffffffff831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a150505050565b610286610356565b61028f826103fd565b6102998282610463565b5050565b60006102a761052a565b50600080516020610d5683398151915290565b6102c78433858585610573565b50505050565b6040516000906102f190601960f81b90839030908c90899089908990602001610c51565b6040516020818303038152906040528051906020012090506103228861031a8a848b8b8b6106b3565b868686610573565b5050505050505050565b610334610764565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806103dd57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166103d1600080516020610d56833981519152546001600160a01b031690565b6001600160a01b031614155b156103fb5760405163703e46dd60e11b815260040160405180910390fd5b565b60005460405163574a81d760e01b81523060048201526001600160a01b0383811660248301529091169063574a81d79060440160006040518083038186803b15801561044857600080fd5b505afa15801561045c573d6000803e3d6000fd5b5050505050565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156104bd575060408051601f3d908101601f191682019092526104ba91810190610cc3565b60015b6104ea57604051634c9c8ce360e01b81526001600160a01b03831660048201526024015b60405180910390fd5b600080516020610d56833981519152811461051b57604051632a87526960e21b8152600481018290526024016104e1565b61052583836107ad565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103fb5760405163703e46dd60e11b815260040160405180910390fd5b6000838152600260205260409020548390156105a5576040516347f6332960e11b8152600481018290526024016104e1565b6001546040516310e67a9d60e31b81526001600160a01b03808916600483015288928892911690638733d4e890602401602060405180830381865afa1580156105f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106169190610cdc565b6001600160a01b0316816001600160a01b03161461065a5760405163cc41100960e01b81526001600160a01b038084166004830152821660248201526044016104e1565b600086815260026020526040908190204390555186907f3e21fe65ee16f151c8cda6e871883b2e0550f9c8511b4ea1d75c9c9e8d489f67906106a1908a9089908990610cf9565b60405180910390a25050505050505050565b6040805160008082526020820180845287905260ff8616928201929092526060810184905260808101839052819060019060a0016020604051602081039080840390855afa158015610709573d6000803e3d6000fd5b505050602060405103519050806001600160a01b0316876001600160a01b03161461075a5760405163cc41100960e01b81526001600160a01b038089166004830152821660248201526044016104e1565b9695505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff166103fb57604051631afcd79f60e31b815260040160405180910390fd5b6107b682610803565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a28051156107fb576105258282610868565b6102996108de565b806001600160a01b03163b60000361083957604051634c9c8ce360e01b81526001600160a01b03821660048201526024016104e1565b600080516020610d5683398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516108859190610d39565b600060405180830381855af49150503d80600081146108c0576040519150601f19603f3d011682016040523d82523d6000602084013e6108c5565b606091505b50915091506108d58583836108fd565b95945050505050565b34156103fb5760405163b398979f60e01b815260040160405180910390fd5b6060826109125761090d8261095c565b610955565b815115801561092957506001600160a01b0384163b155b1561095257604051639996b31560e01b81526001600160a01b03851660048201526024016104e1565b50805b9392505050565b80511561096c5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b6001600160a01b038116811461098557600080fd5b600080604083850312156109b057600080fd5b82356109bb81610988565b915060208301356109cb81610988565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156109ff57600080fd5b8235610a0a81610988565b9150602083013567ffffffffffffffff80821115610a2757600080fd5b818501915085601f830112610a3b57600080fd5b813581811115610a4d57610a4d6109d6565b604051601f8201601f19908116603f01168101908382118183101715610a7557610a756109d6565b81604052828152886020848701011115610a8e57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60008083601f840112610ac257600080fd5b50813567ffffffffffffffff811115610ada57600080fd5b602083019150836020828501011115610af257600080fd5b9250929050565b60008060008060608587031215610b0f57600080fd5b8435610b1a81610988565b935060208501359250604085013567ffffffffffffffff811115610b3d57600080fd5b610b4987828801610ab0565b95989497509550505050565b60005b83811015610b70578181015183820152602001610b58565b50506000910152565b6020815260008251806020840152610b98816040850160208701610b55565b601f01601f19169190910160400192915050565b600080600080600080600060c0888a031215610bc757600080fd5b8735610bd281610988565b9650602088013560ff81168114610be857600080fd5b955060408801359450606088013593506080880135925060a088013567ffffffffffffffff811115610c1957600080fd5b610c258a828b01610ab0565b989b979a50959850939692959293505050565b600060208284031215610c4a57600080fd5b5035919050565b6001600160f81b03198881168252871660018201526bffffffffffffffffffffffff19606087811b8216600284015286901b1660168201526b637265617465536368656d6160a01b602a8201526036810184905260008284605684013750600091016056019081529695505050505050565b600060208284031215610cd557600080fd5b5051919050565b600060208284031215610cee57600080fd5b815161095581610988565b6001600160a01b03841681526040602082018190528101829052818360608301376000818301606090810191909152601f909201601f1916010192915050565b60008251610d4b818460208701610b55565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca264697066735822122004327f7acb789b0212fc0886f4f174a5f4b4b46a13dbbb20db5383f95211b15d64736f6c63430008170033" }, "0x0000000000000000000000000000000000004444": { "comment": "Proxy: Smart contract to manage credential definitions", @@ -192,13 +192,13 @@ "0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000018888", "0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000005555", "f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00": "0x0000000000000000000000000000000000000000000000000000000000000001", - "360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000ddbc94cbc03d53bdaff95115dacd7101805e2179" + "360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x00000000000000000000000097fa08cd747ea254194e6ed783126688b7b955d7" } }, - "0xddbc94cbc03d53bdaff95115dacd7101805e2179": { + "0x97fa08cd747ea254194e6ed783126688b7b955d7": { "comment": "Implementation: Smart contract to manage credential definitions", "balance": "0", - "code": "0x60806040526004361061007b5760003560e01c8063bbc742411161004e578063bbc742411461013a578063c0c53b8b1461015a578063eaa760c21461017a578063f062236b146101a757600080fd5b80634f1ef2861461008057806352d1902d146100955780638b963e9d146100bd578063ad3cb1cc146100fc575b600080fd5b61009361008e366004610aa8565b6101c7565b005b3480156100a157600080fd5b506100aa6101e6565b6040519081526020015b60405180910390f35b3480156100c957600080fd5b506100ec6100d8366004610b6c565b600090815260036020526040902054151590565b60405190151581526020016100b4565b34801561010857600080fd5b5061012d604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100b49190610ba9565b34801561014657600080fd5b50610093610155366004610c25565b610203565b34801561016657600080fd5b50610093610175366004610c8f565b610218565b34801561018657600080fd5b506100aa610195366004610b6c565b60036020526000908152604090205481565b3480156101b357600080fd5b506100936101c2366004610cda565b61032f565b6101cf610392565b6101d882610439565b6101e28282610498565b5050565b60006101f061055f565b50600080516020610eaf83398151915290565b6102118533868686866105a8565b5050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460019190600160401b900460ff16806102625750805467ffffffffffffffff808416911610155b156102805760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff191667ffffffffffffffff831617600160401b1781556102ab8561077e565b600180546001600160a01b038681166001600160a01b0319928316179092556002805492861692909116919091179055805468ff00000000000000001916815560405167ffffffffffffffff831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15050505050565b60405160009061035590601960f81b90839030908d908a908a908a908a90602001610d6f565b6040516020818303038152906040528051906020012090506103878961037e8b848c8c8c6107a8565b878787876105a8565b505050505050505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061041957507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661040d600080516020610eaf833981519152546001600160a01b031690565b6001600160a01b031614155b156104375760405163703e46dd60e11b815260040160405180910390fd5b565b60005460405163574a81d760e01b81523060048201526001600160a01b0383811660248301529091169063574a81d79060440160006040518083038186803b15801561048457600080fd5b505afa158015610211573d6000803e3d6000fd5b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156104f2575060408051601f3d908101601f191682019092526104ef91810190610dfa565b60015b61051f57604051634c9c8ce360e01b81526001600160a01b03831660048201526024015b60405180910390fd5b600080516020610eaf833981519152811461055057604051632a87526960e21b815260048101829052602401610516565b61055a8383610859565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146104375760405163703e46dd60e11b815260040160405180910390fd5b6000848152600360205260409020548490156105da5760405163b1a7a2af60e01b815260048101829052602401610516565b6001546040516310e67a9d60e31b81526001600160a01b03808a16600483015289928992911690638733d4e890602401602060405180830381865afa158015610627573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064b9190610e13565b6001600160a01b0316816001600160a01b03161461068f5760405163cc41100960e01b81526001600160a01b03808416600483015282166024820152604401610516565b60025460405163e8d7402960e01b81526004810188905287916001600160a01b03169063e8d74029906024016020604051808303816000875af11580156106da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106fe9190610e30565b15156000036107235760405163063de83560e21b815260048101829052602401610516565b600088815260036020526040908190204390555188907fb244582b6218e1202021c674f5f9ba330f9393f8359101bb96445efeedff3db39061076a908c908a908a90610e52565b60405180910390a250505050505050505050565b6107866108af565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6040805160008082526020820180845287905260ff8616928201929092526060810184905260808101839052819060019060a0016020604051602081039080840390855afa1580156107fe573d6000803e3d6000fd5b505050602060405103519050806001600160a01b0316876001600160a01b03161461084f5760405163cc41100960e01b81526001600160a01b03808916600483015282166024820152604401610516565b9695505050505050565b610862826108f8565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a28051156108a75761055a828261095d565b6101e26109d3565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661043757604051631afcd79f60e31b815260040160405180910390fd5b806001600160a01b03163b60000361092e57604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610516565b600080516020610eaf83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b03168460405161097a9190610e92565b600060405180830381855af49150503d80600081146109b5576040519150601f19603f3d011682016040523d82523d6000602084013e6109ba565b606091505b50915091506109ca8583836109f2565b95945050505050565b34156104375760405163b398979f60e01b815260040160405180910390fd5b606082610a0757610a0282610a51565b610a4a565b8151158015610a1e57506001600160a01b0384163b155b15610a4757604051639996b31560e01b81526001600160a01b0385166004820152602401610516565b50805b9392505050565b805115610a615780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b6001600160a01b0381168114610a7a57600080fd5b634e487b7160e01b600052604160045260246000fd5b60008060408385031215610abb57600080fd5b8235610ac681610a7d565b9150602083013567ffffffffffffffff80821115610ae357600080fd5b818501915085601f830112610af757600080fd5b813581811115610b0957610b09610a92565b604051601f8201601f19908116603f01168101908382118183101715610b3157610b31610a92565b81604052828152886020848701011115610b4a57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b600060208284031215610b7e57600080fd5b5035919050565b60005b83811015610ba0578181015183820152602001610b88565b50506000910152565b6020815260008251806020840152610bc8816040850160208701610b85565b601f01601f19169190910160400192915050565b60008083601f840112610bee57600080fd5b50813567ffffffffffffffff811115610c0657600080fd5b602083019150836020828501011115610c1e57600080fd5b9250929050565b600080600080600060808688031215610c3d57600080fd5b8535610c4881610a7d565b94506020860135935060408601359250606086013567ffffffffffffffff811115610c7257600080fd5b610c7e88828901610bdc565b969995985093965092949392505050565b600080600060608486031215610ca457600080fd5b8335610caf81610a7d565b92506020840135610cbf81610a7d565b91506040840135610ccf81610a7d565b809150509250925092565b60008060008060008060008060e0898b031215610cf657600080fd5b8835610d0181610a7d565b9750602089013560ff81168114610d1757600080fd5b965060408901359550606089013594506080890135935060a0890135925060c089013567ffffffffffffffff811115610d4f57600080fd5b610d5b8b828c01610bdc565b999c989b5096995094979396929594505050565b6001600160f81b03198981168252881660018201526bffffffffffffffffffffffff19606088811b8216600284015287901b1660168201527f63726561746543726564656e7469616c446566696e6974696f6e000000000000602a82015260448101859052606481018490526000828460848401375060009101608401908152979650505050505050565b600060208284031215610e0c57600080fd5b5051919050565b600060208284031215610e2557600080fd5b8151610a4a81610a7d565b600060208284031215610e4257600080fd5b81518015158114610a4a57600080fd5b6001600160a01b03841681526040602082018190528101829052818360608301376000818301606090810191909152601f909201601f1916010192915050565b60008251610ea4818460208701610b85565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca26469706673582212201f00954ebf639fab6f5f5c206581348f7c25f754c1b3e5049cc5d0dce01f676864736f6c63430008170033" + "code": "0x6080604052600436106100705760003560e01c8063bbc742411161004e578063bbc74241146100f0578063c0c53b8b14610110578063eaa760c214610130578063f062236b1461015d57600080fd5b80634f1ef2861461007557806352d1902d1461008a578063ad3cb1cc146100b2575b600080fd5b610088610083366004610a5c565b61017d565b005b34801561009657600080fd5b5061009f61019c565b6040519081526020015b60405180910390f35b3480156100be57600080fd5b506100e3604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100a99190610b44565b3480156100fc57600080fd5b5061008861010b366004610bc0565b6101b9565b34801561011c57600080fd5b5061008861012b366004610c2a565b6101ce565b34801561013c57600080fd5b5061009f61014b366004610c75565b60036020526000908152604090205481565b34801561016957600080fd5b50610088610178366004610c8e565b6102e5565b610185610348565b61018e826103ef565b610198828261044e565b5050565b60006101a6610515565b50600080516020610e4183398151915290565b6101c785338686868661055e565b5050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460019190600160401b900460ff16806102185750805467ffffffffffffffff808416911610155b156102365760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff191667ffffffffffffffff831617600160401b17815561026185610732565b600180546001600160a01b038681166001600160a01b0319928316179092556002805492861692909116919091179055805468ff00000000000000001916815560405167ffffffffffffffff831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15050505050565b60405160009061030b90601960f81b90839030908d908a908a908a908a90602001610d23565b60405160208183030381529060405280519060200120905061033d896103348b848c8c8c61075c565b8787878761055e565b505050505050505050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806103cf57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166103c3600080516020610e41833981519152546001600160a01b031690565b6001600160a01b031614155b156103ed5760405163703e46dd60e11b815260040160405180910390fd5b565b60005460405163574a81d760e01b81523060048201526001600160a01b0383811660248301529091169063574a81d79060440160006040518083038186803b15801561043a57600080fd5b505afa1580156101c7573d6000803e3d6000fd5b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156104a8575060408051601f3d908101601f191682019092526104a591810190610dae565b60015b6104d557604051634c9c8ce360e01b81526001600160a01b03831660048201526024015b60405180910390fd5b600080516020610e41833981519152811461050657604051632a87526960e21b8152600481018290526024016104cc565b610510838361080d565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103ed5760405163703e46dd60e11b815260040160405180910390fd5b6000848152600360205260409020548490156105905760405163b1a7a2af60e01b8152600481018290526024016104cc565b6001546040516310e67a9d60e31b81526001600160a01b03808a16600483015289928992911690638733d4e890602401602060405180830381865afa1580156105dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106019190610dc7565b6001600160a01b0316816001600160a01b0316146106455760405163cc41100960e01b81526001600160a01b038084166004830152821660248201526044016104cc565b600254604051637553b06160e11b81526004810188905287916001600160a01b03169063eaa760c2906024016020604051808303816000875af1158015610690573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b49190610dae565b6000036106d75760405163063de83560e21b8152600481018290526024016104cc565b600088815260036020526040908190204390555188907fb244582b6218e1202021c674f5f9ba330f9393f8359101bb96445efeedff3db39061071e908c908a908a90610de4565b60405180910390a250505050505050505050565b61073a610863565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6040805160008082526020820180845287905260ff8616928201929092526060810184905260808101839052819060019060a0016020604051602081039080840390855afa1580156107b2573d6000803e3d6000fd5b505050602060405103519050806001600160a01b0316876001600160a01b0316146108035760405163cc41100960e01b81526001600160a01b038089166004830152821660248201526044016104cc565b9695505050505050565b610816826108ac565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a280511561085b576105108282610911565b610198610987565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff166103ed57604051631afcd79f60e31b815260040160405180910390fd5b806001600160a01b03163b6000036108e257604051634c9c8ce360e01b81526001600160a01b03821660048201526024016104cc565b600080516020610e4183398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b03168460405161092e9190610e24565b600060405180830381855af49150503d8060008114610969576040519150601f19603f3d011682016040523d82523d6000602084013e61096e565b606091505b509150915061097e8583836109a6565b95945050505050565b34156103ed5760405163b398979f60e01b815260040160405180910390fd5b6060826109bb576109b682610a05565b6109fe565b81511580156109d257506001600160a01b0384163b155b156109fb57604051639996b31560e01b81526001600160a01b03851660048201526024016104cc565b50805b9392505050565b805115610a155780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b6001600160a01b0381168114610a2e57600080fd5b634e487b7160e01b600052604160045260246000fd5b60008060408385031215610a6f57600080fd5b8235610a7a81610a31565b9150602083013567ffffffffffffffff80821115610a9757600080fd5b818501915085601f830112610aab57600080fd5b813581811115610abd57610abd610a46565b604051601f8201601f19908116603f01168101908382118183101715610ae557610ae5610a46565b81604052828152886020848701011115610afe57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b83811015610b3b578181015183820152602001610b23565b50506000910152565b6020815260008251806020840152610b63816040850160208701610b20565b601f01601f19169190910160400192915050565b60008083601f840112610b8957600080fd5b50813567ffffffffffffffff811115610ba157600080fd5b602083019150836020828501011115610bb957600080fd5b9250929050565b600080600080600060808688031215610bd857600080fd5b8535610be381610a31565b94506020860135935060408601359250606086013567ffffffffffffffff811115610c0d57600080fd5b610c1988828901610b77565b969995985093965092949392505050565b600080600060608486031215610c3f57600080fd5b8335610c4a81610a31565b92506020840135610c5a81610a31565b91506040840135610c6a81610a31565b809150509250925092565b600060208284031215610c8757600080fd5b5035919050565b60008060008060008060008060e0898b031215610caa57600080fd5b8835610cb581610a31565b9750602089013560ff81168114610ccb57600080fd5b965060408901359550606089013594506080890135935060a0890135925060c089013567ffffffffffffffff811115610d0357600080fd5b610d0f8b828c01610b77565b999c989b5096995094979396929594505050565b6001600160f81b03198981168252881660018201526bffffffffffffffffffffffff19606088811b8216600284015287901b1660168201527f63726561746543726564656e7469616c446566696e6974696f6e000000000000602a82015260448101859052606481018490526000828460848401375060009101608401908152979650505050505050565b600060208284031215610dc057600080fd5b5051919050565b600060208284031215610dd957600080fd5b81516109fe81610a31565b6001600160a01b03841681526040602082018190528101829052818360608301376000818301606090810191909152601f909201601f1916010192915050565b60008251610e36818460208701610b20565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca26469706673582212200e0babf8db311bee606a13b3bbbda0b81acf97f50dbe34a186627f036317833f64736f6c63430008170033" } } } diff --git a/network/config/nodes/validator5/key b/network/config/nodes/validator5/key index 2607ffb5..78967120 100644 --- a/network/config/nodes/validator5/key +++ b/network/config/nodes/validator5/key @@ -1 +1 @@ -0x52bd45e5975ae4945094e5bc0444bb40527674204a03b09807d436db91590dcd \ No newline at end of file +0x5db90911d0929e4b638b46f53c05b14c38c066ad57c63091f4fdbbaedc117d85 \ No newline at end of file diff --git a/smart_contracts/contracts/cl/CredentialDefinitionRegistry.sol b/smart_contracts/contracts/cl/CredentialDefinitionRegistry.sol index 854d9da3..5c03cb2f 100644 --- a/smart_contracts/contracts/cl/CredentialDefinitionRegistry.sol +++ b/smart_contracts/contracts/cl/CredentialDefinitionRegistry.sol @@ -16,7 +16,7 @@ contract CredentialDefinitionRegistry is CredentialDefinitionRegistryInterface, SchemaRegistryInterface private _schemaRegistry; /** - * Mapping to track created created credential definitions by their id to block number. + * Mapping to track created credential definitions by their id to block number. */ mapping(bytes32 id => uint block) public created; diff --git a/vdr/Cargo.lock b/vdr/Cargo.lock index a5ca3273..54a6490a 100644 --- a/vdr/Cargo.lock +++ b/vdr/Cargo.lock @@ -1232,7 +1232,7 @@ dependencies = [ ] [[package]] -name = "indy2_vdr" +name = "indy-besu-vdr" version = "0.0.1" dependencies = [ "async-std", diff --git a/vdr/Cargo.toml b/vdr/Cargo.toml index 4081439e..5414aca7 100644 --- a/vdr/Cargo.toml +++ b/vdr/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "indy2_vdr" +name = "indy-besu-vdr" description = "A client library for interacting with Indy Ledger 2.0." version = "0.0.1" authors = ["Artem Ivanov "] @@ -8,7 +8,7 @@ license = "Apache-2.0" readme = "./README.md" [lib] -name = "indy2_vdr" +name = "indy_besu_vdr" path = "src/lib.rs" crate-type = ["rlib", "cdylib"] diff --git a/vdr/README.md b/vdr/README.md index 0fc26ea8..f00409ee 100644 --- a/vdr/README.md +++ b/vdr/README.md @@ -35,7 +35,7 @@ To use vdr, add this to your `Cargo.toml`: ``` [dependencies] -indy2_vdr = { path = "../path/to/crate" } +indy_besu_vdr = { path = "../path/to/crate" } ``` ## Code formatting diff --git a/vdr/src/client/client.rs b/vdr/src/client/client.rs index d3201661..99cd1a41 100644 --- a/vdr/src/client/client.rs +++ b/vdr/src/client/client.rs @@ -260,11 +260,6 @@ pub mod test { fn contracts() -> Vec { vec![ - // ContractConfig { - // address: DID_REGISTRY_ADDRESS.to_string(), - // spec_path: Some(build_contract_path(DID_REGISTRY_SPEC_PATH)), - // spec: None, - // }, ContractConfig { address: SCHEMA_REGISTRY_ADDRESS.to_string(), spec_path: Some(build_contract_path(SCHEMA_REGISTRY_SPEC_PATH)), diff --git a/vdr/src/contracts/cl/credential_definition_registry.rs b/vdr/src/contracts/cl/credential_definition_registry.rs index f7779b7d..f624c169 100644 --- a/vdr/src/contracts/cl/credential_definition_registry.rs +++ b/vdr/src/contracts/cl/credential_definition_registry.rs @@ -298,30 +298,31 @@ pub mod test { 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, - 198, 198, 129, 187, 93, 106, 209, 33, 161, 7, 243, 0, 233, 178, 181, 73, 77, - 222, 144, 79, 39, 191, 53, 141, 180, 7, 174, 32, 255, 241, 133, 79, 137, 100, - 14, 222, 118, 247, 141, 252, 216, 221, 232, 25, 32, 232, 199, 79, 65, 37, 166, - 217, 193, 224, 92, 150, 117, 26, 77, 108, 102, 77, 6, 238, 63, 247, 212, 122, - 19, 86, 115, 119, 131, 17, 47, 17, 46, 238, 182, 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, 0, + 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, 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, 23, 123, 34, 105, 115, 115, 117, 101, 114, 73, 100, 34, 58, 34, 100, 105, + 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, 105, 110, 100, 121, 50, 58, 116, 101, 115, 116, 110, 101, - 116, 58, 51, 76, 112, 106, 115, 122, 107, 103, 84, 109, 69, 51, 113, 84, 104, - 103, 101, 50, 53, 70, 90, 119, 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, + 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, ], signature: RwLock::new(None), hash: None, @@ -351,7 +352,7 @@ pub mod test { to_block: None, event_signature: None, event_filter: Some( - "494dde904f27bf358db407ae20fff1854f89640ede76f78dfcd8dde81920e8c7".to_string(), + "6d471a95e8a387eb6d6889553e8dd19c0921695ec8fe4777bec3f811118defb1".to_string(), ), }; assert_eq!(expected_query, query); diff --git a/vdr/src/contracts/cl/types/credential_definition.rs b/vdr/src/contracts/cl/types/credential_definition.rs index e401b17f..a2457871 100644 --- a/vdr/src/contracts/cl/types/credential_definition.rs +++ b/vdr/src/contracts/cl/types/credential_definition.rs @@ -85,7 +85,7 @@ pub mod test { }; use serde_json::json; - pub const _CREDENTIAL_DEFINITION_ID: &str = "did:indy2:testnet:3LpjszkgTmE3qThge25FZw/anoncreds/v0/CLAIM_DEF/did:indy2:testnet:3LpjszkgTmE3qThge25FZw/anoncreds/v0/SCHEMA/F1DClaFEzi3t/1.0.0/default"; + 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( diff --git a/vdr/src/contracts/cl/types/schema.rs b/vdr/src/contracts/cl/types/schema.rs index e0f08810..f67f05c6 100644 --- a/vdr/src/contracts/cl/types/schema.rs +++ b/vdr/src/contracts/cl/types/schema.rs @@ -78,7 +78,7 @@ pub mod test { }; pub const SCHEMA_ID: &str = - "did:indy2:testnet:3LpjszkgTmE3qThge25FZw/anoncreds/v0/SCHEMA/F1DClaFEzi3t/1.0.0"; + "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"; diff --git a/vdr/src/contracts/did/did_ethr_registry.rs b/vdr/src/contracts/did/did_ethr_registry.rs index fd141a4f..86626eff 100644 --- a/vdr/src/contracts/did/did_ethr_registry.rs +++ b/vdr/src/contracts/did/did_ethr_registry.rs @@ -893,9 +893,7 @@ pub async fn resolve_did( // TODO: support the case when DID identifier is public key // Query block number when DID was changed last time - let transaction = build_get_did_changed_transaction(client, &did).await?; - let response = client.submit_transaction(&transaction).await?; - let did_changed_block = parse_did_changed_result(client, &response)?; + 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() { @@ -911,38 +909,11 @@ pub async fn resolve_did( let now = Utc::now().timestamp() as u64; // request events for a specific block until previous exists - let mut history: Vec = Vec::new(); - let mut previous_block: Option = Some(did_changed_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 - let events = logs - .iter() - .rev() - .map(|log| parse_did_event_response(client, log)) - .collect::>>()?; - - history.extend_from_slice(&events); - - previous_block = events.last().map(|event| event.previous_change()) - } + let did_history: Vec = 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 history_item in history.iter().rev() { + for history_item in did_history.iter().rev() { match history_item { DidEvents::OwnerChanged(_event) => { // TODO: Handle DID Owner changes event as described: @@ -1009,6 +980,48 @@ pub async fn resolve_did( Ok(did_with_meta) } +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) +} + +async fn receive_did_history( + client: &LedgerClient, + did: &DID, + first_block: Block, +) -> VdrResult> { + let mut history: Vec = 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 + let events = logs + .iter() + .rev() + .map(|log| parse_did_event_response(client, log)) + .collect::>>()?; + + history.extend_from_slice(&events); + + previous_block = events.last().map(|event| event.previous_change()) + } + Ok(history) +} + #[cfg(test)] pub mod test { use super::*; @@ -1020,6 +1033,7 @@ pub mod test { contracts::{ did::types::{ did::DID, + did_doc::test::{SERVICE_ENDPOINT, SERVICE_TYPE}, did_doc_attribute::{PublicKeyAttribute, PublicKeyType, ServiceAttribute}, }, ServiceEndpoint, @@ -1034,8 +1048,8 @@ pub mod test { pub fn service() -> DidDocAttribute { DidDocAttribute::Service(ServiceAttribute { - type_: "Service".to_string(), - service_endpoint: ServiceEndpoint::String("http://example.com".to_string()), + type_: SERVICE_TYPE.to_string(), + service_endpoint: ServiceEndpoint::String(SERVICE_ENDPOINT.to_string()), }) } diff --git a/vdr/src/contracts/did/types/did_doc.rs b/vdr/src/contracts/did/types/did_doc.rs index d98ee921..5c36b446 100644 --- a/vdr/src/contracts/did/types/did_doc.rs +++ b/vdr/src/contracts/did/types/did_doc.rs @@ -277,8 +277,8 @@ pub mod test { pub const ISSUER_ID: &str = "did:ethr:testnet:0xf0e2db6c8dc6c681bb5d6ad121a107f300e9b2b5"; pub const CONTEXT: &str = "https://www.w3.org/ns/did/v1"; pub const MULTIBASE_KEY: &str = "zAKJP3f7BD6W4iWEQ9jwndVTCBq8ua2Utt8EEjJ6Vxsf"; - pub const SERVICE_ENDPOINT: &str = "127.0.0.1:5555"; - pub const SERVICE_TYPE: &str = "DIDCommService"; + pub const SERVICE_ENDPOINT: &str = "http://example.com"; + pub const SERVICE_TYPE: &str = "Service"; pub const KEY_1: &str = "KEY-1"; pub fn verification_method(id: &str) -> VerificationMethod { @@ -298,7 +298,7 @@ pub mod test { VerificationMethodOrReference::String(format!("{}#{}", id, KEY_1)) } - pub fn service(id: &str) -> Service { + pub fn _service(id: &str) -> Service { Service { id: id.to_string(), type_: SERVICE_TYPE.to_string(), @@ -308,7 +308,7 @@ pub mod test { pub fn new_id() -> String { format!( - "did:indy2:testnet:{}", + "did:ethr:testnet:{}", &bs58::encode(rand_bytes()).into_string() ) } diff --git a/vdr/uniffi.toml b/vdr/uniffi.toml index b1c0d19f..2048895e 100644 --- a/vdr/uniffi.toml +++ b/vdr/uniffi.toml @@ -1,2 +1,2 @@ [bindings.kotlin] -cdylib_name = "indy2_vdr_uniffi" \ No newline at end of file +cdylib_name = "indy_besu_vdr_uniffi" \ No newline at end of file diff --git a/vdr/uniffi/Cargo.toml b/vdr/uniffi/Cargo.toml index b932c089..26914252 100644 --- a/vdr/uniffi/Cargo.toml +++ b/vdr/uniffi/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "indy2-vdr-uniffi" +name = "indy-besu-vdr-uniffi" description = "Uni-FFI bindings for Indy 2.0 VDR" version = "0.1.0" authors = [ @@ -10,7 +10,7 @@ license = "Apache-2.0" readme = "./README.md" [lib] -name = "indy2_vdr_uniffi" +name = "indy_besu_vdr_uniffi" path = "src/lib.rs" crate-type = ["rlib", "cdylib"] @@ -22,7 +22,7 @@ path = "src/bin.rs" default = [] [dependencies] -indy2_vdr = { path = ".." } +indy-besu-vdr = { path = ".." } serde = "1.0.188" serde_derive = "1.0.188" serde_json = "1.0.107" diff --git a/vdr/uniffi/README.md b/vdr/uniffi/README.md index 5e291de6..cdba8ab5 100644 --- a/vdr/uniffi/README.md +++ b/vdr/uniffi/README.md @@ -13,7 +13,7 @@ language ``: ``` cargo build --release -cargo run --bin uniffi-bindgen generate --library target/release/libindy2_vdr_uniffi.dylib --language --out-dir out +cargo run --bin uniffi-bindgen generate --library target/release/libindy_besu_vdr_uniffi.dylib --language --out-dir out ``` The check `out` directory which will contain generated bindings. diff --git a/vdr/uniffi/build.rs b/vdr/uniffi/build.rs index c01f70f5..9c9a00e4 100644 --- a/vdr/uniffi/build.rs +++ b/vdr/uniffi/build.rs @@ -1,3 +1,3 @@ fn main() { - uniffi::generate_scaffolding("src/indy2_vdr.udl").unwrap(); + uniffi::generate_scaffolding("src/indy_besu_vdr.udl").unwrap(); } diff --git a/vdr/uniffi/src/ffi/client.rs b/vdr/uniffi/src/ffi/client.rs index cbc3207c..f17de2ed 100644 --- a/vdr/uniffi/src/ffi/client.rs +++ b/vdr/uniffi/src/ffi/client.rs @@ -7,7 +7,7 @@ use crate::{ }, VdrError, }; -use indy2_vdr::{ContractConfig as ContractConfig_, LedgerClient as LedgerClient_}; +use indy_besu_vdr::{ContractConfig as ContractConfig_, LedgerClient as LedgerClient_}; #[derive(uniffi::Object)] pub struct LedgerClient { diff --git a/vdr/uniffi/src/ffi/contracts/credential_definition_registry.rs b/vdr/uniffi/src/ffi/contracts/credential_definition_registry.rs index 53999de2..6f2f5009 100644 --- a/vdr/uniffi/src/ffi/contracts/credential_definition_registry.rs +++ b/vdr/uniffi/src/ffi/contracts/credential_definition_registry.rs @@ -5,9 +5,7 @@ use crate::ffi::{ transaction::{Transaction, TransactionEndorsingData}, types::SignatureData, }; -use indy2_vdr::{ - credential_definition_registry, Address, Block, CredentialDefinitionId, -}; +use indy_besu_vdr::{credential_definition_registry, Address, Block, CredentialDefinitionId}; use serde_json::json; #[uniffi::export(async_runtime = "tokio")] diff --git a/vdr/uniffi/src/ffi/contracts/did_ethr_registry.rs b/vdr/uniffi/src/ffi/contracts/did_ethr_registry.rs index b1cee60e..60f2192e 100644 --- a/vdr/uniffi/src/ffi/contracts/did_ethr_registry.rs +++ b/vdr/uniffi/src/ffi/contracts/did_ethr_registry.rs @@ -5,7 +5,7 @@ use crate::ffi::{ transaction::{Transaction, TransactionEndorsingData}, types::SignatureData, }; -use indy2_vdr::{ +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, diff --git a/vdr/uniffi/src/ffi/contracts/role_control.rs b/vdr/uniffi/src/ffi/contracts/role_control.rs index c91c9524..970548b9 100644 --- a/vdr/uniffi/src/ffi/contracts/role_control.rs +++ b/vdr/uniffi/src/ffi/contracts/role_control.rs @@ -3,7 +3,7 @@ use crate::ffi::{ error::{VdrError, VdrResult}, transaction::Transaction, }; -use indy2_vdr::{role_control, Address, Role}; +use indy_besu_vdr::{role_control, Address, Role}; #[uniffi::export(async_runtime = "tokio")] pub async fn build_assign_role_transaction( diff --git a/vdr/uniffi/src/ffi/contracts/schema_registry.rs b/vdr/uniffi/src/ffi/contracts/schema_registry.rs index 1a78c64f..16f7befd 100644 --- a/vdr/uniffi/src/ffi/contracts/schema_registry.rs +++ b/vdr/uniffi/src/ffi/contracts/schema_registry.rs @@ -5,7 +5,7 @@ use crate::ffi::{ transaction::{Transaction, TransactionEndorsingData}, types::SignatureData, }; -use indy2_vdr::{schema_registry, Address, Block, SchemaId}; +use indy_besu_vdr::{schema_registry, Address, Block, SchemaId}; use serde_json::json; #[uniffi::export(async_runtime = "tokio")] diff --git a/vdr/uniffi/src/ffi/contracts/validator_control.rs b/vdr/uniffi/src/ffi/contracts/validator_control.rs index c43ae73e..9fdab119 100644 --- a/vdr/uniffi/src/ffi/contracts/validator_control.rs +++ b/vdr/uniffi/src/ffi/contracts/validator_control.rs @@ -1,5 +1,5 @@ use crate::ffi::{client::LedgerClient, error::VdrResult, transaction::Transaction}; -use indy2_vdr::{validator_control, Address}; +use indy_besu_vdr::{validator_control, Address}; use serde_json::json; #[uniffi::export(async_runtime = "tokio")] diff --git a/vdr/uniffi/src/ffi/error.rs b/vdr/uniffi/src/ffi/error.rs index bea3eb47..dd210c10 100644 --- a/vdr/uniffi/src/ffi/error.rs +++ b/vdr/uniffi/src/ffi/error.rs @@ -1,4 +1,4 @@ -use indy2_vdr::VdrError as VdrError_; +use indy_besu_vdr::VdrError as VdrError_; #[derive(thiserror::Error, Debug, uniffi::Error)] pub enum VdrError { diff --git a/vdr/uniffi/src/ffi/event_query.rs b/vdr/uniffi/src/ffi/event_query.rs index 68866eee..d9ff393a 100644 --- a/vdr/uniffi/src/ffi/event_query.rs +++ b/vdr/uniffi/src/ffi/event_query.rs @@ -1,4 +1,4 @@ -use indy2_vdr::{Address, Block, EventLog as EventLog_, EventQuery as EventQuery_}; +use indy_besu_vdr::{Address, Block, EventLog as EventLog_, EventQuery as EventQuery_}; #[derive(uniffi::Object)] pub struct EventQuery { diff --git a/vdr/uniffi/src/ffi/transaction.rs b/vdr/uniffi/src/ffi/transaction.rs index e6c1d5de..1595697e 100644 --- a/vdr/uniffi/src/ffi/transaction.rs +++ b/vdr/uniffi/src/ffi/transaction.rs @@ -2,7 +2,7 @@ use crate::ffi::{ error::{VdrError, VdrResult}, types::{SignatureData, TransactionSignature, TransactionType}, }; -use indy2_vdr::{ +use indy_besu_vdr::{ Address, Transaction as Transaction_, TransactionEndorsingData as TransactionEndorsingData_, }; diff --git a/vdr/uniffi/src/ffi/types.rs b/vdr/uniffi/src/ffi/types.rs index 6ac676ac..d174e655 100644 --- a/vdr/uniffi/src/ffi/types.rs +++ b/vdr/uniffi/src/ffi/types.rs @@ -1,5 +1,5 @@ use crate::JsonValue; -use indy2_vdr::{ +use indy_besu_vdr::{ ContractConfig as ContractConfig_, ContractSpec as ContractSpec_, PingStatus as PingStatus_, QuorumConfig as QuorumConfig_, SignatureData as SignatureData_, Status as Status_, TransactionSignature as TransactionSignature_, TransactionType as TransactionType_, diff --git a/vdr/uniffi/src/indy2_vdr.udl b/vdr/uniffi/src/indy_besu_vdr.udl similarity index 67% rename from vdr/uniffi/src/indy2_vdr.udl rename to vdr/uniffi/src/indy_besu_vdr.udl index 706bbea2..c09fef34 100644 --- a/vdr/uniffi/src/indy2_vdr.udl +++ b/vdr/uniffi/src/indy_besu_vdr.udl @@ -1,3 +1,3 @@ // This file is required for UNI-FFI binding generation -namespace indy2_vdr {}; +namespace indy_besu_vdr {}; diff --git a/vdr/uniffi/src/lib.rs b/vdr/uniffi/src/lib.rs index 375abbd9..b072beeb 100644 --- a/vdr/uniffi/src/lib.rs +++ b/vdr/uniffi/src/lib.rs @@ -18,4 +18,4 @@ impl UniffiCustomTypeConverter for JsonValue { } uniffi::custom_type!(JsonValue, String); -uniffi::include_scaffolding!("indy2_vdr"); +uniffi::include_scaffolding!("indy_besu_vdr"); diff --git a/vdr/wasm/Cargo.toml b/vdr/wasm/Cargo.toml index 8860b59b..c497e323 100644 --- a/vdr/wasm/Cargo.toml +++ b/vdr/wasm/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "indy2-vdr-wasm" +name = "indy-besu-vdr-wasm" description = "JavaScript bindings for Indy 2.0 VDR" version = "0.1.0" authors = [ @@ -11,14 +11,14 @@ readme = "./README.md" [lib] crate-type = ["cdylib", "rlib"] -name = "indy2_vdr_wasm" +name = "indy_besu_vdr_wasm" path = "src/lib.rs" [features] default = [] [dependencies] -indy2_vdr = { path = "..", default-features = false, features = ['wasm'] } +indy-besu-vdr = { path = "..", default-features = false, features = ['wasm'] } wasm-bindgen = "0.2.87" wasm-bindgen-futures = "0.4.37" js-sys = "0.3.64" diff --git a/vdr/wasm/demo/node/package.json b/vdr/wasm/demo/node/package.json index 33cf03a8..c2050fbe 100644 --- a/vdr/wasm/demo/node/package.json +++ b/vdr/wasm/demo/node/package.json @@ -1,7 +1,7 @@ { - "name": "indy2-vdr-wasm-demo", + "name": "indy-besu-vdr-wasm-demo", "version": "0.1.0", - "description": "NodeJS demo for indy2-vdr wasm bindings", + "description": "NodeJS demo for indy-besu-vdr wasm bindings", "scripts": { "start": "ts-node src/main.ts", "check": "tslint -c tslint.json 'src/**/*.ts'" @@ -11,7 +11,7 @@ "dependencies": { "@types/bs58": "^4.0.4", "bs58": "^5.0.0", - "indy2-vdr": "file:../../pkg", + "indy-besu-vdr": "file:../../pkg", "secp256k1": "5.0.0", "typescript": "^4.5.2" }, diff --git a/vdr/wasm/demo/node/src/main.ts b/vdr/wasm/demo/node/src/main.ts index a0af1d6f..993598dd 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 "indy2-vdr"; +import { LedgerClient, EthrDidRegistry, SchemaRegistry } from "indy-besu-vdr"; const chainId = 1337 const nodeAddress = 'http://127.0.0.1:8545' diff --git a/vdr/wasm/src/client.rs b/vdr/wasm/src/client.rs index cfb8dd99..e4834c5c 100644 --- a/vdr/wasm/src/client.rs +++ b/vdr/wasm/src/client.rs @@ -3,7 +3,7 @@ use std::rc::Rc; use wasm_bindgen::prelude::*; use wasm_bindgen_futures::future_to_promise; -use indy2_vdr::{ContractConfig, LedgerClient, QuorumConfig}; +use indy_besu_vdr::{ContractConfig, LedgerClient, QuorumConfig}; use crate::{ error::{JsResult, Result}, diff --git a/vdr/wasm/src/contracts/credential_definition_registry.rs b/vdr/wasm/src/contracts/credential_definition_registry.rs index addc30b3..d1bca190 100644 --- a/vdr/wasm/src/contracts/credential_definition_registry.rs +++ b/vdr/wasm/src/contracts/credential_definition_registry.rs @@ -1,4 +1,4 @@ -use indy2_vdr::{ +use indy_besu_vdr::{ credential_definition_registry, Address, Block, CredentialDefinition, CredentialDefinitionId, EventLog, SignatureData, }; diff --git a/vdr/wasm/src/contracts/did_ethr_registry.rs b/vdr/wasm/src/contracts/did_ethr_registry.rs index fbe17d3e..5eef7241 100644 --- a/vdr/wasm/src/contracts/did_ethr_registry.rs +++ b/vdr/wasm/src/contracts/did_ethr_registry.rs @@ -1,4 +1,4 @@ -use indy2_vdr::{ +use indy_besu_vdr::{ did_ethr_registry, Address, Block, DelegateType, DidDocAttribute, DidResolutionOptions, EventLog, SignatureData, Validity, DID, }; diff --git a/vdr/wasm/src/contracts/role_control.rs b/vdr/wasm/src/contracts/role_control.rs index 14365bef..905e98e0 100644 --- a/vdr/wasm/src/contracts/role_control.rs +++ b/vdr/wasm/src/contracts/role_control.rs @@ -1,4 +1,4 @@ -use indy2_vdr::{role_control, Address, Role}; +use indy_besu_vdr::{role_control, Address, Role}; use std::rc::Rc; use wasm_bindgen::prelude::*; diff --git a/vdr/wasm/src/contracts/schema_registry.rs b/vdr/wasm/src/contracts/schema_registry.rs index c7eec7ff..e103ffaa 100644 --- a/vdr/wasm/src/contracts/schema_registry.rs +++ b/vdr/wasm/src/contracts/schema_registry.rs @@ -1,4 +1,4 @@ -use indy2_vdr::{schema_registry, Address, Block, EventLog, Schema, SchemaId, SignatureData}; +use indy_besu_vdr::{schema_registry, Address, Block, EventLog, Schema, SchemaId, SignatureData}; use std::rc::Rc; use wasm_bindgen::prelude::*; diff --git a/vdr/wasm/src/contracts/validator_control.rs b/vdr/wasm/src/contracts/validator_control.rs index d5f806a0..34935328 100644 --- a/vdr/wasm/src/contracts/validator_control.rs +++ b/vdr/wasm/src/contracts/validator_control.rs @@ -1,4 +1,4 @@ -use indy2_vdr::{validator_control, Address}; +use indy_besu_vdr::{validator_control, Address}; use std::rc::Rc; use wasm_bindgen::prelude::*; diff --git a/vdr/wasm/src/error.rs b/vdr/wasm/src/error.rs index 724414c1..de9c1a80 100644 --- a/vdr/wasm/src/error.rs +++ b/vdr/wasm/src/error.rs @@ -1,4 +1,4 @@ -use indy2_vdr::VdrResult; +use indy_besu_vdr::VdrResult; use js_sys::Error as JsError; use wasm_bindgen::JsValue; diff --git a/vdr/wasm/src/event_query.rs b/vdr/wasm/src/event_query.rs index f27debbb..88056202 100644 --- a/vdr/wasm/src/event_query.rs +++ b/vdr/wasm/src/event_query.rs @@ -1,4 +1,4 @@ -use indy2_vdr::EventQuery; +use indy_besu_vdr::EventQuery; use std::rc::Rc; use wasm_bindgen::prelude::*; diff --git a/vdr/wasm/src/transaction.rs b/vdr/wasm/src/transaction.rs index 853b04be..7ca00ed5 100644 --- a/vdr/wasm/src/transaction.rs +++ b/vdr/wasm/src/transaction.rs @@ -1,4 +1,4 @@ -use indy2_vdr::{SignatureData, Transaction, TransactionEndorsingData}; +use indy_besu_vdr::{SignatureData, Transaction, TransactionEndorsingData}; use std::rc::Rc; use wasm_bindgen::prelude::*; diff --git a/vdr/wrappers/python/README.md b/vdr/wrappers/python/README.md index 9f5a5af5..cdcc0dc3 100644 --- a/vdr/wrappers/python/README.md +++ b/vdr/wrappers/python/README.md @@ -10,8 +10,8 @@ This is thin python package created on top of Indy Besu bindings generated using 1. Bindings building: * Build bindings as describe in uniffi [README.md](../../uniffi/README.md). - * Copy `uniffi/out/indy2_vdr` file and put into `wrappers/python/indy2_vdr` folder. - * Copy `uniffi/target/release/libindy2_vdr_uniffi.dylib` file and put into `wrappers/python/indy2_vdr` folder. + * Copy `uniffi/out/indy_besu_vdr` file and put into `wrappers/python/indy_besu_vdr` folder. + * Copy `uniffi/target/release/libindy_besu_vdr_uniffi.dylib` file and put into `wrappers/python/indy_besu_vdr` folder. 2. Package building: * Run the following commands: ``` diff --git a/vdr/wrappers/python/demo/test.py b/vdr/wrappers/python/demo/test.py index a3643bc8..d41a0abd 100644 --- a/vdr/wrappers/python/demo/test.py +++ b/vdr/wrappers/python/demo/test.py @@ -4,7 +4,7 @@ import string from eth_keys import keys -from indy2_vdr import * +from indy_besu_vdr import * # chain id of the running network chain_id = 1337 diff --git a/vdr/wrappers/python/indy2_vdr/__init__.py b/vdr/wrappers/python/indy_besu_vdr/__init__.py similarity index 99% rename from vdr/wrappers/python/indy2_vdr/__init__.py rename to vdr/wrappers/python/indy_besu_vdr/__init__.py index e7197587..5c18d229 100644 --- a/vdr/wrappers/python/indy2_vdr/__init__.py +++ b/vdr/wrappers/python/indy_besu_vdr/__init__.py @@ -1,5 +1,5 @@ """Indy2 VDR Python wrapper""" -from .indy2_vdr import ( +from .indy_besu_vdr import ( InternalError, Status, TransactionType, diff --git a/vdr/wrappers/python/indy2_vdr/indy2_vdr.py b/vdr/wrappers/python/indy_besu_vdr/indy_besu_vdr.py similarity index 69% rename from vdr/wrappers/python/indy2_vdr/indy2_vdr.py rename to vdr/wrappers/python/indy_besu_vdr/indy_besu_vdr.py index 2a8209db..b2c377f0 100644 --- a/vdr/wrappers/python/indy2_vdr/indy2_vdr.py +++ b/vdr/wrappers/python/indy_besu_vdr/indy_besu_vdr.py @@ -39,14 +39,14 @@ class _UniffiRustBuffer(ctypes.Structure): @staticmethod def alloc(size): - return _rust_call(_UniffiLib.ffi_indy2_vdr_uniffi_rustbuffer_alloc, size) + return _rust_call(_UniffiLib.ffi_indy_besu_vdr_uniffi_rustbuffer_alloc, size) @staticmethod def reserve(rbuf, additional): - return _rust_call(_UniffiLib.ffi_indy2_vdr_uniffi_rustbuffer_reserve, rbuf, additional) + return _rust_call(_UniffiLib.ffi_indy_besu_vdr_uniffi_rustbuffer_reserve, rbuf, additional) def free(self): - return _rust_call(_UniffiLib.ffi_indy2_vdr_uniffi_rustbuffer_free, self) + return _rust_call(_UniffiLib.ffi_indy_besu_vdr_uniffi_rustbuffer_free, self) def __str__(self): return "_UniffiRustBuffer(capacity={}, len={}, data={})".format( @@ -473,7 +473,7 @@ def _uniffi_load_indirect(): # Anything else must be an ELF platform - Linux, *BSD, Solaris/illumos libname = "lib{}.so" - libname = libname.format("indy2_vdr_uniffi") + libname = libname.format("indy_besu_vdr_uniffi") path = os.path.join(os.path.dirname(__file__), libname) lib = ctypes.cdll.LoadLibrary(path) return lib @@ -482,134 +482,134 @@ def _uniffi_check_contract_api_version(lib): # Get the bindings contract version from our ComponentInterface bindings_contract_version = 25 # Get the scaffolding contract version by calling the into the dylib - scaffolding_contract_version = lib.ffi_indy2_vdr_uniffi_uniffi_contract_version() + scaffolding_contract_version = lib.ffi_indy_besu_vdr_uniffi_uniffi_contract_version() if bindings_contract_version != scaffolding_contract_version: raise InternalError("UniFFI contract version mismatch: try cleaning and rebuilding your project") def _uniffi_check_api_checksums(lib): - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_add_validator_transaction() != 21831: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_add_validator_transaction() != 2909: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_assign_role_transaction() != 3167: + 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_indy2_vdr_uniffi_checksum_func_build_create_credential_definition_endorsing_data() != 1444: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_credential_definition_endorsing_data() != 59949: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_credential_definition_signed_transaction() != 26456: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_credential_definition_signed_transaction() != 6216: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_credential_definition_transaction() != 61090: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_credential_definition_transaction() != 59923: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_schema_endorsing_data() != 41486: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_schema_endorsing_data() != 3325: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_schema_signed_transaction() != 25892: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_schema_signed_transaction() != 56271: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_schema_transaction() != 1461: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_schema_transaction() != 6657: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_add_delegate_endorsing_data() != 16808: + 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") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_add_delegate_signed_transaction() != 45029: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_add_delegate_signed_transaction() != 6684: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_add_delegate_transaction() != 344: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_add_delegate_transaction() != 5942: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_change_owner_endorsing_data() != 31381: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_change_owner_endorsing_data() != 21431: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_change_owner_signed_transaction() != 22827: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_change_owner_signed_transaction() != 25381: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_change_owner_transaction() != 16056: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_change_owner_transaction() != 41898: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_revoke_attribute_endorsing_data() != 54465: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_revoke_attribute_endorsing_data() != 24316: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_revoke_attribute_signed_transaction() != 61659: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_revoke_attribute_signed_transaction() != 59037: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_revoke_attribute_transaction() != 62078: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_revoke_attribute_transaction() != 59289: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_revoke_delegate_endorsing_data() != 15988: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_revoke_delegate_endorsing_data() != 14031: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_revoke_delegate_signed_transaction() != 39933: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_revoke_delegate_signed_transaction() != 7578: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_revoke_delegate_transaction() != 3109: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_revoke_delegate_transaction() != 55423: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_set_attribute_endorsing_data() != 39347: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_set_attribute_endorsing_data() != 8983: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_set_attribute_signed_transaction() != 17918: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_set_attribute_signed_transaction() != 64551: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_set_attribute_transaction() != 15287: + 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_indy2_vdr_uniffi_checksum_func_build_get_credential_definition_created_transaction() != 11334: + 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_indy2_vdr_uniffi_checksum_func_build_get_credential_definition_query() != 41617: + 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_indy2_vdr_uniffi_checksum_func_build_get_did_changed_transaction() != 5297: + 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_indy2_vdr_uniffi_checksum_func_build_get_did_events_query() != 59834: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_did_events_query() != 35752: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_did_owner_transaction() != 58749: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_did_owner_transaction() != 29722: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_identity_nonce_transaction() != 35175: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_identity_nonce_transaction() != 21686: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_role_transaction() != 23366: + 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_indy2_vdr_uniffi_checksum_func_build_get_schema_created_transaction() != 53318: + 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_indy2_vdr_uniffi_checksum_func_build_get_schema_query() != 10119: + 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_indy2_vdr_uniffi_checksum_func_build_get_validators_transaction() != 18706: + 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_indy2_vdr_uniffi_checksum_func_build_has_role_transaction() != 6703: + 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_indy2_vdr_uniffi_checksum_func_build_remove_validator_transaction() != 7091: + 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_indy2_vdr_uniffi_checksum_func_build_revoke_role_transaction() != 18761: + 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_indy2_vdr_uniffi_checksum_func_parse_credential_definition_created_event() != 25117: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_credential_definition_created_event() != 43712: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_parse_credential_definition_created_result() != 31850: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_credential_definition_created_result() != 43952: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_parse_did_attribute_changed_event_response() != 53460: + 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") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_parse_did_changed_result() != 27839: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_changed_result() != 11223: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_parse_did_delegate_changed_event_response() != 52991: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_delegate_changed_event_response() != 48798: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_parse_did_event_response() != 41707: + 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_indy2_vdr_uniffi_checksum_func_parse_did_owner_changed_event_response() != 27353: + 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_indy2_vdr_uniffi_checksum_func_parse_did_owner_result() != 16800: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_owner_result() != 11739: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_parse_get_role_result() != 48393: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_get_role_result() != 24565: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_parse_get_validators_result() != 64310: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_get_validators_result() != 34604: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_parse_has_role_result() != 45027: + 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_indy2_vdr_uniffi_checksum_func_parse_schema_created_event() != 48161: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_schema_created_event() != 39931: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_parse_schema_created_result() != 21869: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_schema_created_result() != 64564: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_resolve_credential_definition() != 53835: + 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") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_resolve_did() != 38549: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_resolve_did() != 9418: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_func_resolve_schema() != 54438: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_func_resolve_schema() != 37103: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_method_ledgerclient_get_receipt() != 16895: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_method_ledgerclient_get_receipt() != 56453: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_method_ledgerclient_ping() != 3979: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_method_ledgerclient_ping() != 64834: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_method_ledgerclient_query_events() != 56922: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_method_ledgerclient_query_events() != 44751: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_method_ledgerclient_submit_transaction() != 39684: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_method_ledgerclient_submit_transaction() != 37630: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_method_transaction_get_signing_bytes() != 46925: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_method_transaction_get_signing_bytes() != 1239: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_method_transaction_set_signature() != 11161: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_method_transaction_set_signature() != 39952: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_method_transactionendorsingdata_get_signing_bytes() != 31013: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_method_transactionendorsingdata_get_signing_bytes() != 64283: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_constructor_eventquery_new() != 62354: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_constructor_eventquery_new() != 57276: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_constructor_ledgerclient_new() != 12058: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_constructor_ledgerclient_new() != 17350: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") - if lib.uniffi_indy2_vdr_uniffi_checksum_constructor_transaction_new() != 55819: + if lib.uniffi_indy_besu_vdr_uniffi_checksum_constructor_transaction_new() != 38765: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") @@ -625,17 +625,17 @@ def _uniffi_check_api_checksums(lib): # This is an implementation detail which will be called internally by the public API. _UniffiLib = _uniffi_load_indirect() -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_clone_eventquery.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_clone_eventquery.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_clone_eventquery.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_free_eventquery.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_clone_eventquery.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_free_eventquery.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_free_eventquery.restype = None -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_constructor_eventquery_new.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_free_eventquery.restype = None +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_constructor_eventquery_new.argtypes = ( _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, @@ -643,55 +643,55 @@ def _uniffi_check_api_checksums(lib): _UniffiRustBuffer, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_constructor_eventquery_new.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_clone_ledgerclient.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_constructor_eventquery_new.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_clone_ledgerclient.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_clone_ledgerclient.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_free_ledgerclient.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_clone_ledgerclient.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_free_ledgerclient.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_free_ledgerclient.restype = None -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_constructor_ledgerclient_new.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_free_ledgerclient.restype = None +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_constructor_ledgerclient_new.argtypes = ( ctypes.c_uint64, _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_constructor_ledgerclient_new.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_method_ledgerclient_get_receipt.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_constructor_ledgerclient_new.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_method_ledgerclient_get_receipt.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_method_ledgerclient_get_receipt.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_method_ledgerclient_ping.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_method_ledgerclient_get_receipt.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_method_ledgerclient_ping.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_method_ledgerclient_ping.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_method_ledgerclient_query_events.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_method_ledgerclient_ping.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_method_ledgerclient_query_events.argtypes = ( ctypes.c_void_p, ctypes.c_void_p, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_method_ledgerclient_query_events.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_method_ledgerclient_submit_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_method_ledgerclient_query_events.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_method_ledgerclient_submit_transaction.argtypes = ( ctypes.c_void_p, ctypes.c_void_p, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_method_ledgerclient_submit_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_clone_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_method_ledgerclient_submit_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_clone_transaction.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_clone_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_free_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_clone_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_free_transaction.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_free_transaction.restype = None -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_constructor_transaction_new.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_free_transaction.restype = None +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_constructor_transaction_new.argtypes = ( _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, @@ -701,97 +701,97 @@ def _uniffi_check_api_checksums(lib): _UniffiRustBuffer, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_constructor_transaction_new.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_method_transaction_get_signing_bytes.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_constructor_transaction_new.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_method_transaction_get_signing_bytes.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_method_transaction_get_signing_bytes.restype = _UniffiRustBuffer -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_method_transaction_set_signature.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_method_transaction_get_signing_bytes.restype = _UniffiRustBuffer +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_method_transaction_set_signature.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_method_transaction_set_signature.restype = None -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_clone_transactionendorsingdata.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_method_transaction_set_signature.restype = None +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_clone_transactionendorsingdata.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_clone_transactionendorsingdata.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_free_transactionendorsingdata.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_clone_transactionendorsingdata.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_free_transactionendorsingdata.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_free_transactionendorsingdata.restype = None -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_method_transactionendorsingdata_get_signing_bytes.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_free_transactionendorsingdata.restype = None +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_method_transactionendorsingdata_get_signing_bytes.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_method_transactionendorsingdata_get_signing_bytes.restype = _UniffiRustBuffer -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_add_validator_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_method_transactionendorsingdata_get_signing_bytes.restype = _UniffiRustBuffer +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_add_validator_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_add_validator_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_assign_role_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_add_validator_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_assign_role_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, ctypes.c_uint8, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_assign_role_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_credential_definition_endorsing_data.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_assign_role_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_credential_definition_endorsing_data.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_credential_definition_endorsing_data.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_credential_definition_signed_transaction.argtypes = ( +_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 = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_credential_definition_signed_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_credential_definition_transaction.argtypes = ( +_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_indy2_vdr_uniffi_fn_func_build_create_credential_definition_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_schema_endorsing_data.argtypes = ( +_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 = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_schema_endorsing_data.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_schema_signed_transaction.argtypes = ( +_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 = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_schema_signed_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_schema_transaction.argtypes = ( +_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_indy2_vdr_uniffi_fn_func_build_create_schema_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_add_delegate_endorsing_data.argtypes = ( +_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_did_add_delegate_endorsing_data.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, ctypes.c_uint64, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_add_delegate_endorsing_data.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_add_delegate_signed_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_add_delegate_endorsing_data.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_add_delegate_signed_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, @@ -800,8 +800,8 @@ def _uniffi_check_api_checksums(lib): ctypes.c_uint64, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_add_delegate_signed_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_add_delegate_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_add_delegate_signed_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_add_delegate_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, @@ -809,57 +809,57 @@ def _uniffi_check_api_checksums(lib): _UniffiRustBuffer, ctypes.c_uint64, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_add_delegate_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_change_owner_endorsing_data.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_add_delegate_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_change_owner_endorsing_data.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_change_owner_endorsing_data.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_change_owner_signed_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_change_owner_endorsing_data.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_change_owner_signed_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_change_owner_signed_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_change_owner_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_change_owner_signed_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_change_owner_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_change_owner_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_revoke_attribute_endorsing_data.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_change_owner_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_revoke_attribute_endorsing_data.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_revoke_attribute_endorsing_data.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_revoke_attribute_signed_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_revoke_attribute_endorsing_data.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_revoke_attribute_signed_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_revoke_attribute_signed_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_revoke_attribute_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_revoke_attribute_signed_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_revoke_attribute_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_revoke_attribute_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_revoke_delegate_endorsing_data.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_revoke_attribute_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_revoke_delegate_endorsing_data.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_revoke_delegate_endorsing_data.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_revoke_delegate_signed_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_revoke_delegate_endorsing_data.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_revoke_delegate_signed_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, @@ -867,23 +867,23 @@ def _uniffi_check_api_checksums(lib): _UniffiRustBuffer, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_revoke_delegate_signed_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_revoke_delegate_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_revoke_delegate_signed_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_revoke_delegate_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_revoke_delegate_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_set_attribute_endorsing_data.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_revoke_delegate_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_set_attribute_endorsing_data.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, ctypes.c_uint64, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_set_attribute_endorsing_data.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_set_attribute_signed_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_set_attribute_endorsing_data.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_set_attribute_signed_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, @@ -891,640 +891,640 @@ def _uniffi_check_api_checksums(lib): ctypes.c_uint64, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_set_attribute_signed_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_set_attribute_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_set_attribute_signed_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_set_attribute_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, ctypes.c_uint64, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_set_attribute_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_credential_definition_created_transaction.argtypes = ( +_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_indy2_vdr_uniffi_fn_func_build_get_credential_definition_created_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_credential_definition_query.argtypes = ( +_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_indy2_vdr_uniffi_fn_func_build_get_credential_definition_query.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_did_changed_transaction.argtypes = ( +_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, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_did_changed_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_did_events_query.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_did_changed_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_did_events_query.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_did_events_query.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_did_owner_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_did_events_query.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_did_owner_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_did_owner_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_identity_nonce_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_did_owner_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_identity_nonce_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_identity_nonce_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_role_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_identity_nonce_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_role_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_role_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_schema_created_transaction.argtypes = ( +_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_indy2_vdr_uniffi_fn_func_build_get_schema_created_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_schema_query.argtypes = ( +_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_indy2_vdr_uniffi_fn_func_build_get_schema_query.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_validators_transaction.argtypes = ( +_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, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_validators_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_has_role_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_validators_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_has_role_transaction.argtypes = ( ctypes.c_void_p, ctypes.c_uint8, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_has_role_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_remove_validator_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_has_role_transaction.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_remove_validator_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_remove_validator_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_revoke_role_transaction.argtypes = ( +_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_revoke_role_transaction.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, ctypes.c_uint8, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_revoke_role_transaction.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_credential_definition_created_event.argtypes = ( +_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 = ( ctypes.c_void_p, _UniffiRustBuffer, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_credential_definition_created_event.restype = _UniffiRustBuffer -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_credential_definition_created_result.argtypes = ( +_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 = ( ctypes.c_void_p, _UniffiRustBuffer, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_credential_definition_created_result.restype = ctypes.c_uint64 -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_did_attribute_changed_event_response.argtypes = ( +_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_parse_did_attribute_changed_event_response.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_did_attribute_changed_event_response.restype = _UniffiRustBuffer -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_did_changed_result.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_attribute_changed_event_response.restype = _UniffiRustBuffer +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_changed_result.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_did_changed_result.restype = ctypes.c_uint64 -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_did_delegate_changed_event_response.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_changed_result.restype = ctypes.c_uint64 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_delegate_changed_event_response.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_did_delegate_changed_event_response.restype = _UniffiRustBuffer -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_did_event_response.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_delegate_changed_event_response.restype = _UniffiRustBuffer +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_event_response.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_did_event_response.restype = _UniffiRustBuffer -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_did_owner_changed_event_response.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_event_response.restype = _UniffiRustBuffer +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_owner_changed_event_response.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_did_owner_changed_event_response.restype = _UniffiRustBuffer -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_did_owner_result.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_owner_changed_event_response.restype = _UniffiRustBuffer +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_owner_result.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_did_owner_result.restype = _UniffiRustBuffer -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_get_role_result.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_owner_result.restype = _UniffiRustBuffer +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_get_role_result.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_get_role_result.restype = ctypes.c_uint8 -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_get_validators_result.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_get_role_result.restype = ctypes.c_uint8 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_get_validators_result.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_get_validators_result.restype = _UniffiRustBuffer -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_has_role_result.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_get_validators_result.restype = _UniffiRustBuffer +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_has_role_result.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_has_role_result.restype = ctypes.c_int8 -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_schema_created_event.argtypes = ( +_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 = ( ctypes.c_void_p, _UniffiRustBuffer, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_schema_created_event.restype = _UniffiRustBuffer -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_schema_created_result.argtypes = ( +_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 = ( ctypes.c_void_p, _UniffiRustBuffer, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_schema_created_result.restype = ctypes.c_uint64 -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_resolve_credential_definition.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_schema_created_result.restype = ctypes.c_uint64 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_resolve_credential_definition.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_resolve_credential_definition.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_resolve_did.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_resolve_credential_definition.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_resolve_did.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_resolve_did.restype = ctypes.c_void_p -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_resolve_schema.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_resolve_did.restype = ctypes.c_void_p +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_resolve_schema.argtypes = ( ctypes.c_void_p, _UniffiRustBuffer, ) -_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_resolve_schema.restype = ctypes.c_void_p -_UniffiLib.ffi_indy2_vdr_uniffi_rustbuffer_alloc.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_resolve_schema.restype = ctypes.c_void_p +_UniffiLib.ffi_indy_besu_vdr_uniffi_rustbuffer_alloc.argtypes = ( ctypes.c_int32, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.ffi_indy2_vdr_uniffi_rustbuffer_alloc.restype = _UniffiRustBuffer -_UniffiLib.ffi_indy2_vdr_uniffi_rustbuffer_from_bytes.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rustbuffer_alloc.restype = _UniffiRustBuffer +_UniffiLib.ffi_indy_besu_vdr_uniffi_rustbuffer_from_bytes.argtypes = ( _UniffiForeignBytes, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.ffi_indy2_vdr_uniffi_rustbuffer_from_bytes.restype = _UniffiRustBuffer -_UniffiLib.ffi_indy2_vdr_uniffi_rustbuffer_free.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rustbuffer_from_bytes.restype = _UniffiRustBuffer +_UniffiLib.ffi_indy_besu_vdr_uniffi_rustbuffer_free.argtypes = ( _UniffiRustBuffer, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.ffi_indy2_vdr_uniffi_rustbuffer_free.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rustbuffer_reserve.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rustbuffer_free.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rustbuffer_reserve.argtypes = ( _UniffiRustBuffer, ctypes.c_int32, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.ffi_indy2_vdr_uniffi_rustbuffer_reserve.restype = _UniffiRustBuffer -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_u8.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rustbuffer_reserve.restype = _UniffiRustBuffer +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_u8.argtypes = ( ctypes.c_void_p, UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, ctypes.c_size_t, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_u8.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_u8.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_u8.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_u8.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_u8.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_u8.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_u8.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_u8.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_u8.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_u8.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_u8.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_u8.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_u8.restype = ctypes.c_uint8 -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_i8.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_u8.restype = ctypes.c_uint8 +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_i8.argtypes = ( ctypes.c_void_p, UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, ctypes.c_size_t, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_i8.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_i8.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_i8.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_i8.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_i8.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_i8.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_i8.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_i8.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_i8.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_i8.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_i8.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_i8.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_i8.restype = ctypes.c_int8 -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_u16.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_i8.restype = ctypes.c_int8 +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_u16.argtypes = ( ctypes.c_void_p, UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, ctypes.c_size_t, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_u16.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_u16.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_u16.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_u16.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_u16.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_u16.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_u16.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_u16.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_u16.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_u16.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_u16.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_u16.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_u16.restype = ctypes.c_uint16 -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_i16.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_u16.restype = ctypes.c_uint16 +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_i16.argtypes = ( ctypes.c_void_p, UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, ctypes.c_size_t, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_i16.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_i16.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_i16.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_i16.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_i16.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_i16.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_i16.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_i16.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_i16.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_i16.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_i16.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_i16.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_i16.restype = ctypes.c_int16 -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_u32.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_i16.restype = ctypes.c_int16 +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_u32.argtypes = ( ctypes.c_void_p, UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, ctypes.c_size_t, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_u32.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_u32.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_u32.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_u32.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_u32.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_u32.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_u32.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_u32.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_u32.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_u32.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_u32.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_u32.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_u32.restype = ctypes.c_uint32 -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_i32.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_u32.restype = ctypes.c_uint32 +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_i32.argtypes = ( ctypes.c_void_p, UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, ctypes.c_size_t, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_i32.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_i32.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_i32.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_i32.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_i32.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_i32.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_i32.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_i32.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_i32.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_i32.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_i32.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_i32.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_i32.restype = ctypes.c_int32 -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_u64.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_i32.restype = ctypes.c_int32 +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_u64.argtypes = ( ctypes.c_void_p, UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, ctypes.c_size_t, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_u64.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_u64.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_u64.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_u64.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_u64.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_u64.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_u64.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_u64.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_u64.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_u64.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_u64.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_u64.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_u64.restype = ctypes.c_uint64 -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_i64.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_u64.restype = ctypes.c_uint64 +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_i64.argtypes = ( ctypes.c_void_p, UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, ctypes.c_size_t, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_i64.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_i64.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_i64.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_i64.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_i64.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_i64.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_i64.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_i64.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_i64.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_i64.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_i64.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_i64.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_i64.restype = ctypes.c_int64 -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_f32.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_i64.restype = ctypes.c_int64 +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_f32.argtypes = ( ctypes.c_void_p, UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, ctypes.c_size_t, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_f32.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_f32.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_f32.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_f32.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_f32.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_f32.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_f32.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_f32.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_f32.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_f32.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_f32.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_f32.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_f32.restype = ctypes.c_float -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_f64.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_f32.restype = ctypes.c_float +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_f64.argtypes = ( ctypes.c_void_p, UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, ctypes.c_size_t, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_f64.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_f64.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_f64.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_f64.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_f64.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_f64.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_f64.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_f64.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_f64.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_f64.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_f64.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_f64.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_f64.restype = ctypes.c_double -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_f64.restype = ctypes.c_double +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer.argtypes = ( ctypes.c_void_p, UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, ctypes.c_size_t, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_pointer.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_pointer.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_pointer.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_pointer.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_pointer.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_pointer.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_pointer.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer.restype = ctypes.c_void_p -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_rust_buffer.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_pointer.restype = ctypes.c_void_p +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_rust_buffer.argtypes = ( ctypes.c_void_p, UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, ctypes.c_size_t, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_rust_buffer.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_rust_buffer.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_rust_buffer.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_rust_buffer.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_rust_buffer.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_rust_buffer.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_rust_buffer.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_rust_buffer.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_rust_buffer.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_rust_buffer.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_rust_buffer.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_rust_buffer.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_rust_buffer.restype = _UniffiRustBuffer -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_void.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_rust_buffer.restype = _UniffiRustBuffer +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_void.argtypes = ( ctypes.c_void_p, UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK, ctypes.c_size_t, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_void.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_void.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_void.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_void.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_cancel_void.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_void.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_cancel_void.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_void.argtypes = ( ctypes.c_void_p, ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_void.restype = None -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_void.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_void.restype = None +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_void.argtypes = ( ctypes.c_void_p, ctypes.POINTER(_UniffiRustCallStatus), ) -_UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_void.restype = None -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_add_validator_transaction.argtypes = ( +_UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_void.restype = None +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_add_validator_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_add_validator_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_assign_role_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_add_validator_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_assign_role_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_assign_role_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_credential_definition_endorsing_data.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_assign_role_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_credential_definition_endorsing_data.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_credential_definition_endorsing_data.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_credential_definition_signed_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_credential_definition_endorsing_data.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_credential_definition_signed_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_credential_definition_signed_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_credential_definition_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_credential_definition_signed_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_credential_definition_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_credential_definition_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_schema_endorsing_data.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_schema_endorsing_data.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_schema_endorsing_data.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_schema_signed_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_schema_endorsing_data.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_schema_signed_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_schema_signed_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_schema_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_schema_signed_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_create_schema_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_create_schema_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_add_delegate_endorsing_data.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_did_add_delegate_endorsing_data.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_add_delegate_endorsing_data.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_add_delegate_signed_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_add_delegate_endorsing_data.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_add_delegate_signed_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_add_delegate_signed_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_add_delegate_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_add_delegate_signed_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_add_delegate_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_add_delegate_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_change_owner_endorsing_data.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_add_delegate_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_change_owner_endorsing_data.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_change_owner_endorsing_data.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_change_owner_signed_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_change_owner_endorsing_data.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_change_owner_signed_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_change_owner_signed_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_change_owner_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_change_owner_signed_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_change_owner_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_change_owner_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_revoke_attribute_endorsing_data.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_change_owner_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_revoke_attribute_endorsing_data.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_revoke_attribute_endorsing_data.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_revoke_attribute_signed_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_revoke_attribute_endorsing_data.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_revoke_attribute_signed_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_revoke_attribute_signed_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_revoke_attribute_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_revoke_attribute_signed_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_revoke_attribute_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_revoke_attribute_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_revoke_delegate_endorsing_data.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_revoke_attribute_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_revoke_delegate_endorsing_data.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_revoke_delegate_endorsing_data.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_revoke_delegate_signed_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_revoke_delegate_endorsing_data.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_revoke_delegate_signed_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_revoke_delegate_signed_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_revoke_delegate_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_revoke_delegate_signed_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_revoke_delegate_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_revoke_delegate_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_set_attribute_endorsing_data.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_revoke_delegate_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_set_attribute_endorsing_data.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_set_attribute_endorsing_data.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_set_attribute_signed_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_set_attribute_endorsing_data.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_set_attribute_signed_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_set_attribute_signed_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_set_attribute_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_set_attribute_signed_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_did_set_attribute_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_did_set_attribute_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_credential_definition_created_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_indy2_vdr_uniffi_checksum_func_build_get_credential_definition_created_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_credential_definition_query.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_indy2_vdr_uniffi_checksum_func_build_get_credential_definition_query.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_did_changed_transaction.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_indy2_vdr_uniffi_checksum_func_build_get_did_changed_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_did_events_query.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_did_changed_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_did_events_query.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_did_events_query.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_did_owner_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_did_events_query.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_did_owner_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_did_owner_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_identity_nonce_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_did_owner_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_identity_nonce_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_identity_nonce_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_role_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_identity_nonce_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_role_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_role_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_schema_created_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_indy2_vdr_uniffi_checksum_func_build_get_schema_created_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_schema_query.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_indy2_vdr_uniffi_checksum_func_build_get_schema_query.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_get_validators_transaction.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_indy2_vdr_uniffi_checksum_func_build_get_validators_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_has_role_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_get_validators_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_has_role_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_has_role_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_remove_validator_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_has_role_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_build_remove_validator_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_remove_validator_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_revoke_role_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_revoke_role_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_build_revoke_role_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_credential_definition_created_event.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_indy2_vdr_uniffi_checksum_func_parse_credential_definition_created_event.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_credential_definition_created_result.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_indy2_vdr_uniffi_checksum_func_parse_credential_definition_created_result.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_did_attribute_changed_event_response.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_parse_did_attribute_changed_event_response.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_did_attribute_changed_event_response.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_did_changed_result.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_attribute_changed_event_response.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_changed_result.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_did_changed_result.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_did_delegate_changed_event_response.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_changed_result.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_delegate_changed_event_response.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_did_delegate_changed_event_response.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_did_event_response.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_delegate_changed_event_response.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_event_response.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_did_event_response.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_did_owner_changed_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_owner_changed_event_response.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_did_owner_changed_event_response.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_did_owner_result.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_owner_changed_event_response.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_owner_result.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_did_owner_result.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_get_role_result.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_did_owner_result.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_get_role_result.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_get_role_result.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_get_validators_result.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_get_role_result.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_get_validators_result.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_get_validators_result.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_has_role_result.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_get_validators_result.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_parse_has_role_result.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_has_role_result.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_schema_created_event.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_indy2_vdr_uniffi_checksum_func_parse_schema_created_event.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_parse_schema_created_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_indy2_vdr_uniffi_checksum_func_parse_schema_created_result.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_resolve_credential_definition.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_resolve_credential_definition.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_resolve_credential_definition.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_resolve_did.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_resolve_credential_definition.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_resolve_did.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_resolve_did.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_resolve_schema.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_resolve_did.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_resolve_schema.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_func_resolve_schema.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_method_ledgerclient_get_receipt.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_func_resolve_schema.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_method_ledgerclient_get_receipt.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_method_ledgerclient_get_receipt.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_method_ledgerclient_ping.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_method_ledgerclient_get_receipt.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_method_ledgerclient_ping.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_method_ledgerclient_ping.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_method_ledgerclient_query_events.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_method_ledgerclient_ping.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_method_ledgerclient_query_events.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_method_ledgerclient_query_events.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_method_ledgerclient_submit_transaction.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_method_ledgerclient_query_events.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_method_ledgerclient_submit_transaction.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_method_ledgerclient_submit_transaction.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_method_transaction_get_signing_bytes.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_method_ledgerclient_submit_transaction.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_method_transaction_get_signing_bytes.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_method_transaction_get_signing_bytes.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_method_transaction_set_signature.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_method_transaction_get_signing_bytes.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_method_transaction_set_signature.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_method_transaction_set_signature.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_method_transactionendorsingdata_get_signing_bytes.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_method_transaction_set_signature.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_method_transactionendorsingdata_get_signing_bytes.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_method_transactionendorsingdata_get_signing_bytes.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_constructor_eventquery_new.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_method_transactionendorsingdata_get_signing_bytes.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_constructor_eventquery_new.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_constructor_eventquery_new.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_constructor_ledgerclient_new.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_constructor_eventquery_new.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_constructor_ledgerclient_new.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_constructor_ledgerclient_new.restype = ctypes.c_uint16 -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_constructor_transaction_new.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_constructor_ledgerclient_new.restype = ctypes.c_uint16 +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_constructor_transaction_new.argtypes = ( ) -_UniffiLib.uniffi_indy2_vdr_uniffi_checksum_constructor_transaction_new.restype = ctypes.c_uint16 -_UniffiLib.ffi_indy2_vdr_uniffi_uniffi_contract_version.argtypes = ( +_UniffiLib.uniffi_indy_besu_vdr_uniffi_checksum_constructor_transaction_new.restype = ctypes.c_uint16 +_UniffiLib.ffi_indy_besu_vdr_uniffi_uniffi_contract_version.argtypes = ( ) -_UniffiLib.ffi_indy2_vdr_uniffi_uniffi_contract_version.restype = ctypes.c_uint32 +_UniffiLib.ffi_indy_besu_vdr_uniffi_uniffi_contract_version.restype = ctypes.c_uint32 _uniffi_check_contract_api_version(_UniffiLib) _uniffi_check_api_checksums(_UniffiLib) @@ -1689,7 +1689,7 @@ def __init__(self, address: "str",from_block: "typing.Optional[int]",to_block: " _UniffiConverterOptionalString.check_lower(event_filter) - self._pointer = _rust_call(_UniffiLib.uniffi_indy2_vdr_uniffi_fn_constructor_eventquery_new, + self._pointer = _rust_call(_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_constructor_eventquery_new, _UniffiConverterString.lower(address), _UniffiConverterOptionalUInt64.lower(from_block), _UniffiConverterOptionalUInt64.lower(to_block), @@ -1700,10 +1700,10 @@ def __del__(self): # In case of partial initialization of instances. pointer = getattr(self, "_pointer", None) if pointer is not None: - _rust_call(_UniffiLib.uniffi_indy2_vdr_uniffi_fn_free_eventquery, pointer) + _rust_call(_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_free_eventquery, pointer) def _uniffi_clone_pointer(self): - return _rust_call(_UniffiLib.uniffi_indy2_vdr_uniffi_fn_clone_eventquery, self._pointer) + return _rust_call(_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_clone_eventquery, self._pointer) # Used by alternative constructors or any methods which return this type. @classmethod @@ -1766,7 +1766,7 @@ def __init__(self, chain_id: "int",node_address: "str",contract_configs: "typing _UniffiConverterOptionalTypeQuorumConfig.check_lower(quorum_config) - self._pointer = _rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_vdr_uniffi_fn_constructor_ledgerclient_new, + self._pointer = _rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_constructor_ledgerclient_new, _UniffiConverterUInt64.lower(chain_id), _UniffiConverterString.lower(node_address), _UniffiConverterSequenceTypeContractConfig.lower(contract_configs), @@ -1776,10 +1776,10 @@ def __del__(self): # In case of partial initialization of instances. pointer = getattr(self, "_pointer", None) if pointer is not None: - _rust_call(_UniffiLib.uniffi_indy2_vdr_uniffi_fn_free_ledgerclient, pointer) + _rust_call(_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_free_ledgerclient, pointer) def _uniffi_clone_pointer(self): - return _rust_call(_UniffiLib.uniffi_indy2_vdr_uniffi_fn_clone_ledgerclient, self._pointer) + return _rust_call(_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_clone_ledgerclient, self._pointer) # Used by alternative constructors or any methods which return this type. @classmethod @@ -1795,13 +1795,13 @@ def get_receipt(self, hash: "bytes"): _UniffiConverterBytes.check_lower(hash) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_method_ledgerclient_get_receipt( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_method_ledgerclient_get_receipt( self._uniffi_clone_pointer(), _UniffiConverterBytes.lower(hash) ), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_rust_buffer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_rust_buffer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_rust_buffer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_rust_buffer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_rust_buffer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_rust_buffer, # lift function _UniffiConverterString.lift, # Error FFI converter @@ -1814,12 +1814,12 @@ def get_receipt(self, hash: "bytes"): def ping(self, ): return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_method_ledgerclient_ping( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_method_ledgerclient_ping( self._uniffi_clone_pointer(), ), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_rust_buffer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_rust_buffer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_rust_buffer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_rust_buffer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_rust_buffer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_rust_buffer, # lift function _UniffiConverterTypePingStatus.lift, # Error FFI converter @@ -1834,13 +1834,13 @@ def query_events(self, query: "EventQuery"): _UniffiConverterTypeEventQuery.check_lower(query) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_method_ledgerclient_query_events( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_method_ledgerclient_query_events( self._uniffi_clone_pointer(), _UniffiConverterTypeEventQuery.lower(query) ), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_rust_buffer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_rust_buffer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_rust_buffer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_rust_buffer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_rust_buffer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_rust_buffer, # lift function _UniffiConverterSequenceTypeEventLog.lift, # Error FFI converter @@ -1855,13 +1855,13 @@ def submit_transaction(self, transaction: "Transaction"): _UniffiConverterTypeTransaction.check_lower(transaction) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_method_ledgerclient_submit_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_method_ledgerclient_submit_transaction( self._uniffi_clone_pointer(), _UniffiConverterTypeTransaction.lower(transaction) ), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_rust_buffer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_rust_buffer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_rust_buffer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_rust_buffer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_rust_buffer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_rust_buffer, # lift function _UniffiConverterBytes.lift, # Error FFI converter @@ -1925,7 +1925,7 @@ def __init__(self, type: "TransactionType",_from: "typing.Optional[str]",to: "st _UniffiConverterOptionalTypeTransactionSignature.check_lower(signature) - self._pointer = _rust_call(_UniffiLib.uniffi_indy2_vdr_uniffi_fn_constructor_transaction_new, + self._pointer = _rust_call(_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_constructor_transaction_new, _UniffiConverterTypeTransactionType.lower(type), _UniffiConverterOptionalString.lower(_from), _UniffiConverterString.lower(to), @@ -1938,10 +1938,10 @@ def __del__(self): # In case of partial initialization of instances. pointer = getattr(self, "_pointer", None) if pointer is not None: - _rust_call(_UniffiLib.uniffi_indy2_vdr_uniffi_fn_free_transaction, pointer) + _rust_call(_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_free_transaction, pointer) def _uniffi_clone_pointer(self): - return _rust_call(_UniffiLib.uniffi_indy2_vdr_uniffi_fn_clone_transaction, self._pointer) + return _rust_call(_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_clone_transaction, self._pointer) # Used by alternative constructors or any methods which return this type. @classmethod @@ -1956,7 +1956,7 @@ def _make_instance_(cls, pointer): def get_signing_bytes(self, ) -> "bytes": return _UniffiConverterBytes.lift( _rust_call_with_error( - _UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_vdr_uniffi_fn_method_transaction_get_signing_bytes,self._uniffi_clone_pointer(),) + _UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_method_transaction_get_signing_bytes,self._uniffi_clone_pointer(),) ) @@ -1967,7 +1967,7 @@ def get_signing_bytes(self, ) -> "bytes": def set_signature(self, signature_data: "SignatureData"): _UniffiConverterTypeSignatureData.check_lower(signature_data) - _rust_call(_UniffiLib.uniffi_indy2_vdr_uniffi_fn_method_transaction_set_signature,self._uniffi_clone_pointer(), + _rust_call(_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_method_transaction_set_signature,self._uniffi_clone_pointer(), _UniffiConverterTypeSignatureData.lower(signature_data)) @@ -2017,10 +2017,10 @@ def __del__(self): # In case of partial initialization of instances. pointer = getattr(self, "_pointer", None) if pointer is not None: - _rust_call(_UniffiLib.uniffi_indy2_vdr_uniffi_fn_free_transactionendorsingdata, pointer) + _rust_call(_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_free_transactionendorsingdata, pointer) def _uniffi_clone_pointer(self): - return _rust_call(_UniffiLib.uniffi_indy2_vdr_uniffi_fn_clone_transactionendorsingdata, self._pointer) + return _rust_call(_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_clone_transactionendorsingdata, self._pointer) # Used by alternative constructors or any methods which return this type. @classmethod @@ -2035,7 +2035,7 @@ def _make_instance_(cls, pointer): def get_signing_bytes(self, ) -> "bytes": return _UniffiConverterBytes.lift( _rust_call_with_error( - _UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_vdr_uniffi_fn_method_transactionendorsingdata_get_signing_bytes,self._uniffi_clone_pointer(),) + _UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_method_transactionendorsingdata_get_signing_bytes,self._uniffi_clone_pointer(),) ) @@ -3466,13 +3466,13 @@ def build_add_validator_transaction(client: "LedgerClient",_from: "str",validato _UniffiConverterString.check_lower(validator_address) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_add_validator_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_add_validator_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(_from), _UniffiConverterString.lower(validator_address)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -3489,14 +3489,14 @@ def build_assign_role_transaction(client: "LedgerClient",_from: "str",role: "int _UniffiConverterString.check_lower(account) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_assign_role_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_assign_role_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(_from), _UniffiConverterUInt8.lower(role), _UniffiConverterString.lower(account)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -3511,13 +3511,13 @@ def build_create_credential_definition_endorsing_data(client: "LedgerClient",id: _UniffiConverterString.check_lower(credential_definition) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_credential_definition_endorsing_data( + _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_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -3536,15 +3536,15 @@ def build_create_credential_definition_signed_transaction(client: "LedgerClient" _UniffiConverterTypeSignatureData.check_lower(signature) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_credential_definition_signed_transaction( + _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_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -3561,14 +3561,14 @@ def build_create_credential_definition_transaction(client: "LedgerClient",_from: _UniffiConverterString.check_lower(credential_definition) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_credential_definition_transaction( + _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_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -3583,13 +3583,13 @@ def build_create_schema_endorsing_data(client: "LedgerClient",id: "str",schema: _UniffiConverterString.check_lower(schema) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_schema_endorsing_data( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_create_schema_endorsing_data( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(id), _UniffiConverterString.lower(schema)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -3608,15 +3608,15 @@ def build_create_schema_signed_transaction(client: "LedgerClient",_from: "str",i _UniffiConverterTypeSignatureData.check_lower(signature) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_schema_signed_transaction( + _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_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -3633,14 +3633,14 @@ def build_create_schema_transaction(client: "LedgerClient",_from: "str",id: "str _UniffiConverterString.check_lower(schema) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_create_schema_transaction( + _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_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -3659,15 +3659,15 @@ def build_did_add_delegate_endorsing_data(client: "LedgerClient",did: "str",dele _UniffiConverterUInt64.check_lower(validity) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_add_delegate_endorsing_data( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_add_delegate_endorsing_data( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(did), _UniffiConverterString.lower(delegate_type), _UniffiConverterString.lower(delegate), _UniffiConverterUInt64.lower(validity)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -3690,7 +3690,7 @@ def build_did_add_delegate_signed_transaction(client: "LedgerClient",_from: "str _UniffiConverterTypeSignatureData.check_lower(signature) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_add_delegate_signed_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_add_delegate_signed_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(_from), _UniffiConverterString.lower(did), @@ -3698,9 +3698,9 @@ def build_did_add_delegate_signed_transaction(client: "LedgerClient",_from: "str _UniffiConverterString.lower(delegate), _UniffiConverterUInt64.lower(validity), _UniffiConverterTypeSignatureData.lower(signature)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -3721,16 +3721,16 @@ def build_did_add_delegate_transaction(client: "LedgerClient",_from: "str",did: _UniffiConverterUInt64.check_lower(validity) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_add_delegate_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_add_delegate_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(_from), _UniffiConverterString.lower(did), _UniffiConverterString.lower(delegate_type), _UniffiConverterString.lower(delegate), _UniffiConverterUInt64.lower(validity)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -3745,13 +3745,13 @@ def build_did_change_owner_endorsing_data(client: "LedgerClient",did: "str",new_ _UniffiConverterString.check_lower(new_owner) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_change_owner_endorsing_data( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_change_owner_endorsing_data( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(did), _UniffiConverterString.lower(new_owner)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -3770,15 +3770,15 @@ def build_did_change_owner_signed_transaction(client: "LedgerClient",_from: "str _UniffiConverterTypeSignatureData.check_lower(signature) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_change_owner_signed_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_change_owner_signed_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(_from), _UniffiConverterString.lower(did), _UniffiConverterString.lower(new_owner), _UniffiConverterTypeSignatureData.lower(signature)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -3795,14 +3795,14 @@ def build_did_change_owner_transaction(client: "LedgerClient",_from: "str",did: _UniffiConverterString.check_lower(new_owner) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_change_owner_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_change_owner_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(_from), _UniffiConverterString.lower(did), _UniffiConverterString.lower(new_owner)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -3817,13 +3817,13 @@ def build_did_revoke_attribute_endorsing_data(client: "LedgerClient",did: "str", _UniffiConverterString.check_lower(attribute) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_revoke_attribute_endorsing_data( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_revoke_attribute_endorsing_data( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(did), _UniffiConverterString.lower(attribute)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -3842,15 +3842,15 @@ def build_did_revoke_attribute_signed_transaction(client: "LedgerClient",_from: _UniffiConverterTypeSignatureData.check_lower(signature) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_revoke_attribute_signed_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_revoke_attribute_signed_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(_from), _UniffiConverterString.lower(did), _UniffiConverterString.lower(attribute), _UniffiConverterTypeSignatureData.lower(signature)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -3867,14 +3867,14 @@ def build_did_revoke_attribute_transaction(client: "LedgerClient",_from: "str",d _UniffiConverterString.check_lower(attribute) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_revoke_attribute_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_revoke_attribute_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(_from), _UniffiConverterString.lower(did), _UniffiConverterString.lower(attribute)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -3891,14 +3891,14 @@ def build_did_revoke_delegate_endorsing_data(client: "LedgerClient",did: "str",d _UniffiConverterString.check_lower(delegate) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_revoke_delegate_endorsing_data( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_revoke_delegate_endorsing_data( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(did), _UniffiConverterString.lower(delegate_type), _UniffiConverterString.lower(delegate)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -3919,16 +3919,16 @@ def build_did_revoke_delegate_signed_transaction(client: "LedgerClient",_from: " _UniffiConverterTypeSignatureData.check_lower(signature) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_revoke_delegate_signed_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_revoke_delegate_signed_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(_from), _UniffiConverterString.lower(did), _UniffiConverterString.lower(delegate_type), _UniffiConverterString.lower(delegate), _UniffiConverterTypeSignatureData.lower(signature)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -3947,15 +3947,15 @@ def build_did_revoke_delegate_transaction(client: "LedgerClient",_from: "str",di _UniffiConverterString.check_lower(delegate) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_revoke_delegate_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_revoke_delegate_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(_from), _UniffiConverterString.lower(did), _UniffiConverterString.lower(delegate_type), _UniffiConverterString.lower(delegate)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -3972,14 +3972,14 @@ def build_did_set_attribute_endorsing_data(client: "LedgerClient",did: "str",att _UniffiConverterUInt64.check_lower(validity) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_set_attribute_endorsing_data( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_set_attribute_endorsing_data( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(did), _UniffiConverterString.lower(attribute), _UniffiConverterUInt64.lower(validity)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -4000,16 +4000,16 @@ def build_did_set_attribute_signed_transaction(client: "LedgerClient",_from: "st _UniffiConverterTypeSignatureData.check_lower(signature) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_set_attribute_signed_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_set_attribute_signed_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(_from), _UniffiConverterString.lower(did), _UniffiConverterString.lower(attribute), _UniffiConverterUInt64.lower(validity), _UniffiConverterTypeSignatureData.lower(signature)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -4028,15 +4028,15 @@ def build_did_set_attribute_transaction(client: "LedgerClient",_from: "str",did: _UniffiConverterUInt64.check_lower(validity) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_did_set_attribute_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_did_set_attribute_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(_from), _UniffiConverterString.lower(did), _UniffiConverterString.lower(attribute), _UniffiConverterUInt64.lower(validity)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -4049,12 +4049,12 @@ def build_get_credential_definition_created_transaction(client: "LedgerClient",i _UniffiConverterString.check_lower(id) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_credential_definition_created_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_credential_definition_created_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(id)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -4071,14 +4071,14 @@ def build_get_credential_definition_query(client: "LedgerClient",id: "str",from_ _UniffiConverterOptionalUInt64.check_lower(to_block) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_credential_definition_query( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_credential_definition_query( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(id), _UniffiConverterOptionalUInt64.lower(from_block), _UniffiConverterOptionalUInt64.lower(to_block)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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, # Error FFI converter @@ -4091,12 +4091,12 @@ def build_get_did_changed_transaction(client: "LedgerClient",did: "str"): _UniffiConverterString.check_lower(did) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_did_changed_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_did_changed_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(did)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -4113,14 +4113,14 @@ def build_get_did_events_query(client: "LedgerClient",did: "str",from_block: "ty _UniffiConverterOptionalUInt64.check_lower(to_block) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_did_events_query( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_did_events_query( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(did), _UniffiConverterOptionalUInt64.lower(from_block), _UniffiConverterOptionalUInt64.lower(to_block)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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, # Error FFI converter @@ -4133,12 +4133,12 @@ def build_get_did_owner_transaction(client: "LedgerClient",did: "str"): _UniffiConverterString.check_lower(did) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_did_owner_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_did_owner_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(did)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -4151,12 +4151,12 @@ def build_get_identity_nonce_transaction(client: "LedgerClient",identity: "str") _UniffiConverterString.check_lower(identity) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_identity_nonce_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_identity_nonce_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(identity)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -4169,12 +4169,12 @@ def build_get_role_transaction(client: "LedgerClient",account: "str"): _UniffiConverterString.check_lower(account) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_role_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_role_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(account)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -4187,12 +4187,12 @@ def build_get_schema_created_transaction(client: "LedgerClient",id: "str"): _UniffiConverterString.check_lower(id) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_schema_created_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_schema_created_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(id)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -4209,14 +4209,14 @@ def build_get_schema_query(client: "LedgerClient",id: "str",from_block: "typing. _UniffiConverterOptionalUInt64.check_lower(to_block) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_schema_query( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_schema_query( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(id), _UniffiConverterOptionalUInt64.lower(from_block), _UniffiConverterOptionalUInt64.lower(to_block)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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, # Error FFI converter @@ -4227,11 +4227,11 @@ def build_get_validators_transaction(client: "LedgerClient"): _UniffiConverterTypeLedgerClient.check_lower(client) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_get_validators_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_get_validators_transaction( _UniffiConverterTypeLedgerClient.lower(client)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -4246,13 +4246,13 @@ def build_has_role_transaction(client: "LedgerClient",role: "int",account: "str" _UniffiConverterString.check_lower(account) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_has_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_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -4267,13 +4267,13 @@ def build_remove_validator_transaction(client: "LedgerClient",_from: "str",valid _UniffiConverterString.check_lower(validator_address) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_remove_validator_transaction( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_build_remove_validator_transaction( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(_from), _UniffiConverterString.lower(validator_address)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -4290,14 +4290,14 @@ def build_revoke_role_transaction(client: "LedgerClient",_from: "str",role: "int _UniffiConverterString.check_lower(account) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_build_revoke_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_indy2_vdr_uniffi_rust_future_poll_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_pointer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_pointer, + _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 @@ -4309,7 +4309,7 @@ def parse_credential_definition_created_event(client: "LedgerClient",log: "Event _UniffiConverterTypeEventLog.check_lower(log) - return _UniffiConverterString.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_credential_definition_created_event, + 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))) @@ -4319,7 +4319,7 @@ def parse_credential_definition_created_result(client: "LedgerClient",bytes: "by _UniffiConverterBytes.check_lower(bytes) - return _UniffiConverterUInt64.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_credential_definition_created_result, + return _UniffiConverterUInt64.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_credential_definition_created_result, _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterBytes.lower(bytes))) @@ -4329,7 +4329,7 @@ def parse_did_attribute_changed_event_response(client: "LedgerClient",log: "Even _UniffiConverterTypeEventLog.check_lower(log) - return _UniffiConverterTypeDidAttributeChanged.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_did_attribute_changed_event_response, + return _UniffiConverterTypeDidAttributeChanged.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_attribute_changed_event_response, _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterTypeEventLog.lower(log))) @@ -4339,7 +4339,7 @@ def parse_did_changed_result(client: "LedgerClient",bytes: "bytes") -> "int": _UniffiConverterBytes.check_lower(bytes) - return _UniffiConverterUInt64.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_did_changed_result, + return _UniffiConverterUInt64.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_changed_result, _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterBytes.lower(bytes))) @@ -4349,7 +4349,7 @@ def parse_did_delegate_changed_event_response(client: "LedgerClient",log: "Event _UniffiConverterTypeEventLog.check_lower(log) - return _UniffiConverterTypeDidDelegateChanged.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_did_delegate_changed_event_response, + return _UniffiConverterTypeDidDelegateChanged.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_delegate_changed_event_response, _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterTypeEventLog.lower(log))) @@ -4359,7 +4359,7 @@ def parse_did_event_response(client: "LedgerClient",log: "EventLog") -> "DidEven _UniffiConverterTypeEventLog.check_lower(log) - return _UniffiConverterTypeDidEvents.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_did_event_response, + return _UniffiConverterTypeDidEvents.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_event_response, _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterTypeEventLog.lower(log))) @@ -4369,7 +4369,7 @@ def parse_did_owner_changed_event_response(client: "LedgerClient",log: "EventLog _UniffiConverterTypeEventLog.check_lower(log) - return _UniffiConverterTypeDidOwnerChanged.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_did_owner_changed_event_response, + return _UniffiConverterTypeDidOwnerChanged.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_owner_changed_event_response, _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterTypeEventLog.lower(log))) @@ -4379,7 +4379,7 @@ def parse_did_owner_result(client: "LedgerClient",bytes: "bytes") -> "str": _UniffiConverterBytes.check_lower(bytes) - return _UniffiConverterString.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_did_owner_result, + return _UniffiConverterString.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_did_owner_result, _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterBytes.lower(bytes))) @@ -4389,7 +4389,7 @@ def parse_get_role_result(client: "LedgerClient",bytes: "bytes") -> "int": _UniffiConverterBytes.check_lower(bytes) - return _UniffiConverterUInt8.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_get_role_result, + return _UniffiConverterUInt8.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_get_role_result, _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterBytes.lower(bytes))) @@ -4399,7 +4399,7 @@ def parse_get_validators_result(client: "LedgerClient",bytes: "bytes") -> "str": _UniffiConverterBytes.check_lower(bytes) - return _UniffiConverterString.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_get_validators_result, + return _UniffiConverterString.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_get_validators_result, _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterBytes.lower(bytes))) @@ -4409,7 +4409,7 @@ def parse_has_role_result(client: "LedgerClient",bytes: "bytes") -> "bool": _UniffiConverterBytes.check_lower(bytes) - return _UniffiConverterBool.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_has_role_result, + return _UniffiConverterBool.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_has_role_result, _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterBytes.lower(bytes))) @@ -4419,7 +4419,7 @@ def parse_schema_created_event(client: "LedgerClient",log: "EventLog") -> "str": _UniffiConverterTypeEventLog.check_lower(log) - return _UniffiConverterString.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_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_schema_created_event, _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterTypeEventLog.lower(log))) @@ -4429,7 +4429,7 @@ def parse_schema_created_result(client: "LedgerClient",bytes: "bytes") -> "int": _UniffiConverterBytes.check_lower(bytes) - return _UniffiConverterUInt64.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_parse_schema_created_result, + return _UniffiConverterUInt64.lift(_rust_call_with_error(_UniffiConverterTypeVdrError,_UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_parse_schema_created_result, _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterBytes.lower(bytes))) @@ -4440,12 +4440,12 @@ def resolve_credential_definition(client: "LedgerClient",id: "str"): _UniffiConverterString.check_lower(id) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_resolve_credential_definition( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_resolve_credential_definition( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(id)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_rust_buffer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_rust_buffer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_rust_buffer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_rust_buffer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_rust_buffer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_rust_buffer, # lift function _UniffiConverterString.lift, # Error FFI converter @@ -4460,13 +4460,13 @@ def resolve_did(client: "LedgerClient",did: "str",options: "typing.Optional[DidR _UniffiConverterOptionalTypeDidResolutionOptions.check_lower(options) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_resolve_did( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_resolve_did( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(did), _UniffiConverterOptionalTypeDidResolutionOptions.lower(options)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_rust_buffer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_rust_buffer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_rust_buffer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_rust_buffer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_rust_buffer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_rust_buffer, # lift function _UniffiConverterString.lift, # Error FFI converter @@ -4479,12 +4479,12 @@ def resolve_schema(client: "LedgerClient",id: "str"): _UniffiConverterString.check_lower(id) return _uniffi_rust_call_async( - _UniffiLib.uniffi_indy2_vdr_uniffi_fn_func_resolve_schema( + _UniffiLib.uniffi_indy_besu_vdr_uniffi_fn_func_resolve_schema( _UniffiConverterTypeLedgerClient.lower(client), _UniffiConverterString.lower(id)), - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_poll_rust_buffer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_complete_rust_buffer, - _UniffiLib.ffi_indy2_vdr_uniffi_rust_future_free_rust_buffer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_poll_rust_buffer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_complete_rust_buffer, + _UniffiLib.ffi_indy_besu_vdr_uniffi_rust_future_free_rust_buffer, # lift function _UniffiConverterString.lift, # Error FFI converter diff --git a/vdr/wrappers/python/indy2_vdr/version.py b/vdr/wrappers/python/indy_besu_vdr/version.py similarity index 100% rename from vdr/wrappers/python/indy2_vdr/version.py rename to vdr/wrappers/python/indy_besu_vdr/version.py diff --git a/vdr/wrappers/python/setup.py b/vdr/wrappers/python/setup.py index a883aa60..c763f317 100644 --- a/vdr/wrappers/python/setup.py +++ b/vdr/wrappers/python/setup.py @@ -4,7 +4,7 @@ import runpy from setuptools import find_packages, setup -PACKAGE_NAME = "indy2_vdr" +PACKAGE_NAME = "indy_besu_vdr" version_meta = runpy.run_path("./{}/version.py".format(PACKAGE_NAME)) VERSION = version_meta["__version__"] @@ -23,9 +23,9 @@ include_package_data=True, package_data={ "": [ - "indy2_vdr_uniffi.dll", - "libindy2_vdr_uniffi.dylib", - "libindy2_vdr_uniffi.so", + "indy_besu_vdr_uniffi.dll", + "libindy_besu_vdr_uniffi.dylib", + "libindy_besu_vdr_uniffi.so", ] }, python_requires=">=3.6.3", From 9bb3ad110f284e9671ceca288d99138f27d6e468 Mon Sep 17 00:00:00 2001 From: "artem.ivanov" Date: Tue, 30 Jan 2024 17:52:42 +0300 Subject: [PATCH 5/5] Corrected DID Document building Signed-off-by: artem.ivanov --- vdr/src/contracts/did/types/did_doc.rs | 7 +++++++ vdr/src/contracts/did/types/did_doc_builder.rs | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/vdr/src/contracts/did/types/did_doc.rs b/vdr/src/contracts/did/types/did_doc.rs index 5c36b446..e4e1722f 100644 --- a/vdr/src/contracts/did/types/did_doc.rs +++ b/vdr/src/contracts/did/types/did_doc.rs @@ -108,6 +108,7 @@ pub enum VerificationKeyType { JsonWebKey2020, EcdsaSecp256k1VerificationKey2019, EcdsaSecp256k1VerificationKey2020, + EcdsaSecp256k1RecoveryMethod2020, } impl ToString for VerificationKeyType { @@ -130,6 +131,9 @@ impl ToString for VerificationKeyType { | VerificationKeyType::EcdsaSecp256k1VerificationKey2020 => { "EcdsaSecp256k1VerificationKey2019".to_string() } + VerificationKeyType::EcdsaSecp256k1RecoveryMethod2020 => { + "EcdsaSecp256k1RecoveryMethod2020".to_string() + } } } } @@ -144,6 +148,9 @@ impl TryFrom<&str> for VerificationKeyType { "Ed25519VerificationKey2020" => Ok(VerificationKeyType::Ed25519VerificationKey2020), "X25519KeyAgreementKey2020" => Ok(VerificationKeyType::X25519KeyAgreementKey2020), "JsonWebKey2020" => Ok(VerificationKeyType::JsonWebKey2020), + "EcdsaSecp256k1RecoveryMethod2020" => { + Ok(VerificationKeyType::EcdsaSecp256k1RecoveryMethod2020) + } "EcdsaSecp256k1VerificationKey2019" => { Ok(VerificationKeyType::EcdsaSecp256k1VerificationKey2020) } diff --git a/vdr/src/contracts/did/types/did_doc_builder.rs b/vdr/src/contracts/did/types/did_doc_builder.rs index 0e1251b5..4cfc2086 100644 --- a/vdr/src/contracts/did/types/did_doc_builder.rs +++ b/vdr/src/contracts/did/types/did_doc_builder.rs @@ -78,7 +78,7 @@ impl DidDocumentBuilder { ) -> DidDocumentBuilder { let id = id.map(String::from).unwrap_or_else(|| { format!( - "{}:delegate-{}", + "{}+delegate-{}", self.id.as_ref(), self.verification_method.len() ) @@ -186,7 +186,7 @@ impl DidDocumentBuilder { ) -> DidDocumentBuilder { let id = id .map(String::from) - .unwrap_or_else(|| format!("#service-{}", self.service.len() + 1)); + .unwrap_or_else(|| format!("#{}#service-{}", self.id.as_ref(), self.service.len() + 1)); let service = Service { id, type_: type_.to_string(),

    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