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

MESH-2091/add-parent-child-map #1568

Merged
merged 2 commits into from
Dec 5, 2023
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
9 changes: 6 additions & 3 deletions pallets/identity/src/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.

use crate::{
types, AccountKeyRefCount, Config, DidKeys, DidRecords, Error, IsDidFrozen, KeyRecords, Module,
MultiPurposeNonce, OffChainAuthorizationNonce, ParentDid, PermissionedCallOriginData, RawEvent,
RpcDidRecords,
types, AccountKeyRefCount, ChildDid, Config, DidKeys, DidRecords, Error, IsDidFrozen,
KeyRecords, Module, MultiPurposeNonce, OffChainAuthorizationNonce, ParentDid,
PermissionedCallOriginData, RawEvent, RpcDidRecords,
};
use codec::{Decode, Encode as _};
use core::mem;
Expand Down Expand Up @@ -472,6 +472,7 @@ impl<T: Config> Module<T> {
Self::deposit_event(RawEvent::DidCreated(child_did, key.clone(), vec![]));
// Link new identity to parent identity.
ParentDid::insert(child_did, parent_did);
ChildDid::insert(parent_did, child_did, true);

Self::deposit_event(RawEvent::ChildDidCreated(parent_did, child_did, key));
Ok(())
Expand Down Expand Up @@ -542,6 +543,7 @@ impl<T: Config> Module<T> {

// Link new identity to parent identity.
ParentDid::insert(child_did, parent_did);
ChildDid::insert(parent_did, child_did, true);

Self::deposit_event(RawEvent::ChildDidCreated(parent_did, child_did, key));
}
Expand All @@ -566,6 +568,7 @@ impl<T: Config> Module<T> {

// Unlink child identity from parent identity.
ParentDid::remove(child_did);
ChildDid::remove(parent_did, child_did);

Self::deposit_event(RawEvent::ChildDidUnlinked(
caller_did, parent_did, child_did,
Expand Down
161 changes: 15 additions & 146 deletions pallets/identity/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ use polymesh_primitives::{

pub type Event<T> = polymesh_common_utilities::traits::identity::Event<T>;

storage_migration_ver!(3);
storage_migration_ver!(4);

decl_storage! {
trait Store for Module<T: Config> as Identity {
Expand Down Expand Up @@ -170,7 +170,7 @@ decl_storage! {
pub CddAuthForPrimaryKeyRotation get(fn cdd_auth_for_primary_key_rotation): bool;

/// Storage version.
StorageVersion get(fn storage_version) build(|_| Version::new(3)): Version;
StorageVersion get(fn storage_version) build(|_| Version::new(4)): Version;

/// How many "strong" references to the account key.
///
Expand All @@ -185,6 +185,10 @@ decl_storage! {
/// Parent identity if the DID is a child Identity.
pub ParentDid get(fn parent_did):
map hasher(identity) IdentityId => Option<IdentityId>;

/// All child identities of a parent (i.e ParentDID, ChildDID, true)
pub ChildDid get(fn child_did):
double_map hasher(identity) IdentityId, hasher(identity) IdentityId => bool;
}
add_extra_genesis {
// Identities at genesis.
Expand Down Expand Up @@ -247,8 +251,8 @@ decl_module! {
fn deposit_event() = default;

fn on_runtime_upgrade() -> Weight {
storage_migrate_on!(StorageVersion, 3, {
migration::migrate_to_v3::<T>();
storage_migrate_on!(StorageVersion, 4, {
migration::migrate_to_v4::<T>();
});
Weight::zero()
}
Expand Down Expand Up @@ -768,151 +772,16 @@ pub mod migration {
use super::*;
use sp_runtime::runtime_logger::RuntimeLogger;

mod v2 {
use super::*;
use polymesh_primitives::{CountryCode, Moment};
use scale_info::TypeInfo;

type ScopeId = IdentityId;

#[derive(Encode, Decode, TypeInfo, Clone, PartialEq, Eq, Debug, Hash)]
pub enum ClaimV1 {
Accredited(Scope),
Affiliate(Scope),
BuyLockup(Scope),
SellLockup(Scope),
CustomerDueDiligence(CddId),
KnowYourCustomer(Scope),
Jurisdiction(CountryCode, Scope),
Exempted(Scope),
Blocked(Scope),
InvestorUniqueness(Scope, ScopeId, CddId),
NoData,
InvestorUniquenessV2(CddId),
Custom(CustomClaimTypeId, Option<Scope>),
}

impl ClaimV1 {
pub fn try_into(self) -> Option<Claim> {
match self {
Self::Accredited(scope) => Some(Claim::Accredited(scope)),
Self::Affiliate(scope) => Some(Claim::Affiliate(scope)),
Self::BuyLockup(scope) => Some(Claim::BuyLockup(scope)),
Self::SellLockup(scope) => Some(Claim::SellLockup(scope)),
Self::CustomerDueDiligence(cdd) => Some(Claim::CustomerDueDiligence(cdd)),
Self::KnowYourCustomer(scope) => Some(Claim::KnowYourCustomer(scope)),
Self::Jurisdiction(cc, scope) => Some(Claim::Jurisdiction(cc, scope)),
Self::Exempted(scope) => Some(Claim::Exempted(scope)),
Self::Blocked(scope) => Some(Claim::Blocked(scope)),
Self::Custom(type_id, scope) => Some(Claim::Custom(type_id, scope)),
_ => None,
}
}
}

#[derive(Encode, Decode, TypeInfo, Clone, PartialEq, Eq)]
pub struct IdentityClaimV1 {
pub claim_issuer: IdentityId,
pub issuance_date: Moment,
pub last_update_date: Moment,
pub expiry: Option<Moment>,
pub claim: ClaimV1,
}

impl IdentityClaimV1 {
pub fn try_into(self) -> Option<IdentityClaim> {
let claim = self.claim.try_into()?;
Some(IdentityClaim {
claim_issuer: self.claim_issuer,
issuance_date: self.issuance_date,
last_update_date: self.last_update_date,
expiry: self.expiry,
claim,
})
}
}

#[derive(Encode, Decode, TypeInfo)]
#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord, Hash)]
pub enum ClaimTypeV1 {
Accredited,
Affiliate,
BuyLockup,
SellLockup,
CustomerDueDiligence,
KnowYourCustomer,
Jurisdiction,
Exempted,
Blocked,
InvestorUniqueness,
NoType,
InvestorUniquenessV2,
Custom(CustomClaimTypeId),
}

#[derive(Encode, Decode, TypeInfo, Clone, PartialEq, Eq, Debug, PartialOrd, Ord)]
pub struct Claim1stKeyV1 {
pub target: IdentityId,
pub claim_type: ClaimTypeV1,
}

decl_storage! {
trait Store for Module<T: Config> as Identity {
pub Claims: double_map hasher(twox_64_concat) Claim1stKeyV1, hasher(blake2_128_concat) Claim2ndKey => Option<IdentityClaim>;
}
}

decl_module! {
pub struct Module<T: Config> for enum Call where origin: T::RuntimeOrigin { }
}
}

pub fn migrate_to_v3<T: Config>() {
pub fn migrate_to_v4<T: Config>() {
RuntimeLogger::init();
log::info!(" >>> Migrating Identity.Claims.");
migrate_claims::<T>();
log::info!(" >>> All Claims have been migrated.");
log::info!(" >>> Initializing ChildDid storage");
initialize_child_did::<T>();
log::info!(" >>> ChildDid has been initialized");
}

fn migrate_claims<T: Config>() {
let mut same = 0;
let mut converted = 0;
let mut removed = 0;
let mut remap = Vec::new();
// Migrate all Claims
v2::Claims::translate::<v2::IdentityClaimV1, _>(|old_key1, key2, old_claim| {
if let Some(claim) = old_claim.try_into() {
let claim_type = claim.claim.claim_type();
let new_key1 = Claim1stKey {
target: old_key1.target,
claim_type,
};
// Need to move `ClaimType::Custom(_)` to new key1.
match claim_type {
ClaimType::Custom(_) => {
converted += 1;
remap.push((new_key1, key2, claim));
// Remove value from old key.
None
}
_ => {
// No convert/migration need.
same += 1;
Some(claim)
}
}
} else {
removed += 1;
None
}
});

// Re-add claims with changed `key1` values.
for (key1, key2, claim) in remap {
Claims::insert(key1, key2, claim);
fn initialize_child_did<T: Config>() {
for (child_did, parent_did) in ParentDid::iter() {
ChildDid::insert(parent_did, child_did, true);
}
log::info!(
"> Migrated Claims: converted={converted}, removed={removed}, unchanged={same}."
);
}
}
8 changes: 7 additions & 1 deletion pallets/runtime/tests/src/identity_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use frame_support::{
};
use pallet_asset::SecurityToken;
use pallet_balances as balances;
use pallet_identity::{CustomClaimIdSequence, CustomClaims, CustomClaimsInverse};
use pallet_identity::{ChildDid, CustomClaimIdSequence, CustomClaims, CustomClaimsInverse};
use polymesh_common_utilities::{
constants::currency::POLY,
traits::{
Expand Down Expand Up @@ -2111,6 +2111,8 @@ fn do_child_identity_test() {
// Ensure bob has a new identity.
assert!(valid_cdd(bob));
assert_ne!(bob.did, alice.did);
assert_eq!(ParentDid::get(bob.did), Some(alice.did));
assert_eq!(ChildDid::get(alice.did, bob.did), true);

// Attach secondary key to child identity.
let ferdie = User::new_with(bob.did, AccountKeyring::Ferdie);
Expand Down Expand Up @@ -2174,6 +2176,8 @@ fn do_child_identity_test() {

// Unlink child from parent again.
exec_ok!(Identity::unlink_child_identity(bob.origin(), bob_did));
assert_eq!(ParentDid::get(bob.did), None);
assert_eq!(ChildDid::get(alice.did, bob.did), false);

assert!(valid_cdd(bob));

Expand All @@ -2183,6 +2187,8 @@ fn do_child_identity_test() {
let ferdie_did = did_of(ferdie).expect("Ferdie's new identity");
let ferdie = User::new_with(ferdie_did, AccountKeyring::Ferdie);
assert!(valid_cdd(ferdie));
assert_eq!(ParentDid::get(ferdie.did), Some(bob.did));
assert_eq!(ChildDid::get(bob.did, ferdie.did), true);
}

#[test]
Expand Down