Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added smart contract to store mapping between legacy and new DID/Schema/CredDef identifiers #22

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 48 additions & 24 deletions docs/design/legacy-identifiers-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,68 +4,92 @@ The idea is using of a basic mapping between legacy DIDs identifiers and ethereu
`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:
* Create a new `LegacyMappingRegistry` smart contract which will be holding mapping of legacy identifiers to ethereum accounts/new ids:
```
contract LegacyIdMappingRegistry {
// did:sov:<indentifier> -> ethr account address
mapping(string => address) public didMappings;
contract LegacyMappingRegistry {
// Mapping storing indy/sov DID identifiers to the corresponding account address
mapping(bytes16 legacyIdentifier => address account) public didMapping;

// legacy formated ids of schemas and cred defs -> new id
mapping(string => string) public clMappings;
// Mapping storing indy/sov formatted identifiers of schema/credential-definition to the corresponding new form
mapping(string legacyId => string newId) public resourceMapping;

function createDidMapping(string legacyDid, bytes32 key, bytes32 ed25518Signature) {
function createDidMapping(
address identity,
string calldata identifier,
bytes32 ed25519Key,
bytes calldata ed25519Signature
)
// check signature
// check legacyDid is derived from key
didMappings[legacyDid] = msg.sender;
didMapping[identifier] = msg.sender;
}

function endorseDidMapping(address identity, string legacyDid, bytes32 key, bytes32 ed25518Signature, bytes32 ecdsaSignature) {
function createDidMappingSigned(
address identity,
uint8 sigV,
bytes32 sigR,
bytes32 sigS,
string calldata identifier,
bytes32 ed25519Key,
bytes calldata ed25518Signature
)
// check signatures
didMappings[legacyDid] = identity;
didMapping[identifier] = identity;
}

// resolve mapping done through `didMappings(string)` function available after contract compilation
// resolve mapping done through `didMapping(bytes16 identifier)` function available after contract compilation

function createClMapping(string legacyId, string id, bytes32 key, bytes32 signature) {
function createResourceMapping(
address identity,
string calldata legacyIssuerIdentifier,
string calldata legacyIdentifier,
string calldata newIdentifier
)
// 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;
resourceMapping[legacyIdentifier] = newIdentifier;
}

function endorseClMapping(address identity, string legacyId, string id, bytes32 key, bytes32 ed25518Signature, bytes32 ecdsaSignature) {
function createResourceMappingSigned(
address identity,
uint8 sigV,
bytes32 sigR,
bytes32 sigS,
string calldata legacyIssuerIdentifier,
string calldata legacyIdentifier,
string calldata newIdentifier
)
// 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;
resourceMapping[legacyIdentifier] = newIdentifier;
}

// resolve mapping done through `clMappings(string)` function available after contract compilation
// resolve mapping done through `resourceMapping(string legacyIdentifier)` 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:
executing `LegacyMappingRegistry.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:
* Signature must be done over `legacyDid` bytes
* add mapping between legacy schema/credDef id's and new ones executing `LegacyMappingRegistry.createResourceMapping()` method he must pass:
* Legacy DID
* 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
using `LegacyMappingRegistry.didMapping(legacyIdentifier)`, 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
using `LegacyMappingRegistry.resourceMapping(legacyIdentifier)`, and next resolve Schema/Credential Definition as it described in the
corresponding specification.
39 changes: 4 additions & 35 deletions examples/migration/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/migration/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ async-trait = "0.1.73"
indy-credx = "1.1.1"
bs58 = "0.5.0"
futures = "0.1.23"
indy-data-types = "0.6.1"
indy-data-types = "0.7.1"
indy-besu-vdr = { path = "../../vdr", features = ["migration", "basic_signer"] }
indy-vdr = { git = "https://github.com/hyperledger/indy-vdr.git" }
serde = "1.0.188"
Expand Down
8 changes: 6 additions & 2 deletions examples/migration/besu-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"nodeAddress": "http://127.0.0.1:8545",
"contracts": {
"didRegistry": {
"address": "0x0000000000000000000000000000000000018888",
"address": "0x0000000000000000000000000000000000003333",
"path": "../../smart_contracts/artifacts/contracts/did/EthereumExtDidRegistry.sol/EthereumExtDidRegistry.json"
},
"schemaRegistry": {
Expand All @@ -17,6 +17,10 @@
"roleControl": {
"address": "0x0000000000000000000000000000000000006666",
"path": "../../smart_contracts/artifacts/contracts/auth/RoleControl.sol/RoleControl.json"
},
"legacyMappingRegistry": {
"address": "0x0000000000000000000000000000000000019999",
"path": "../../smart_contracts/artifacts/contracts/migration/LegacyMappingRegistry.sol/LegacyMappingRegistry.json"
}
}
}
}
50 changes: 49 additions & 1 deletion examples/migration/src/issuer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
ledger::{BesuLedger, IndyLedger, Ledgers},
wallet::{BesuWallet, IndyWallet},
};
use indy_besu_vdr::{Address, DidDocAttribute, DID};
use indy_besu_vdr::{Address, DidDocAttribute, ResourceIdentifier, DID};
use indy_credx::types::{
AttributeNames, AttributeValues, Credential, CredentialDefinition, CredentialDefinitionConfig,
CredentialDefinitionId, CredentialDefinitionPrivate, CredentialKeyCorrectnessProof,
Expand Down Expand Up @@ -190,6 +190,18 @@ impl Issuer {
.publish_did_attribute(&self.account, &self.besu_did, attribute, &self.besu_wallet)
.await
}
pub async fn publish_did_mapping_to_besu(&self) {
self.besu_ledger
.publish_did_mapping(
&self.account,
&self.besu_did,
&self.indy_did,
&self.edkey,
&vec![1, 2, 3, 4, 5, 6, 7, 8, 9],
&self.besu_wallet,
)
.await
}

pub async fn publish_schema_to_besu(
&self,
Expand All @@ -200,6 +212,24 @@ impl Issuer {
.await
}

pub async fn publish_schema_id_mapping_to_besu(
&self,
legacy_did: &str,
legacy_schema_id: &SchemaId,
new_schema_id: &indy_besu_vdr::SchemaId,
) {
self.besu_ledger
.publish_resource_mapping(
&self.account,
&indy_besu_vdr::DID::from(self.besu_did.as_str()),
&indy_data_types::did::DidValue(legacy_did.to_string()),
&ResourceIdentifier::from(legacy_schema_id.0.as_str()),
&ResourceIdentifier::from(new_schema_id.as_ref()),
&self.besu_wallet,
)
.await
}

pub async fn publish_cred_def_to_besu(
&self,
cred_def: &indy_besu_vdr::CredentialDefinition,
Expand All @@ -209,6 +239,24 @@ impl Issuer {
.await
}

pub async fn publish_cred_def_id_mapping_to_besu(
&self,
legacy_did: &str,
legacy_cred_def_id: &CredentialDefinitionId,
new_cred_def_id: &indy_besu_vdr::CredentialDefinitionId,
) {
self.besu_ledger
.publish_resource_mapping(
&self.account,
&indy_besu_vdr::DID::from(self.besu_did.as_str()),
&indy_data_types::did::DidValue(legacy_did.to_string()),
&ResourceIdentifier::from(legacy_cred_def_id.0.as_str()),
&ResourceIdentifier::from(new_cred_def_id.as_ref()),
&self.besu_wallet,
)
.await
}

pub fn use_indy_ledger(&mut self) {
self.used_ledger = Ledgers::Indy
}
Expand Down
Loading
Loading