diff --git a/Cargo.lock b/Cargo.lock index 9c56b56a52e47e3850f5ebd6cb2589c25c2db092..4cb2d89c8e0e7be6768fb1b9bb8f77ba2b7d0cf0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -855,6 +855,7 @@ dependencies = [ "frame-system", "pallet-certification", "pallet-identity", + "pallet-membership", "pallet-session", "pallet-ud-accounts-storage", "parity-scale-codec", @@ -1461,6 +1462,7 @@ dependencies = [ "sp-finality-grandpa", "sp-inherents", "sp-keyring", + "sp-membership", "sp-offchain", "sp-runtime", "sp-session", @@ -2120,6 +2122,7 @@ dependencies = [ "pallet-grandpa", "pallet-identity", "pallet-im-online", + "pallet-membership", "pallet-multisig", "pallet-offences", "pallet-scheduler", @@ -2174,6 +2177,7 @@ dependencies = [ "pallet-certification", "pallet-grandpa", "pallet-identity", + "pallet-membership", "pallet-multisig", "pallet-scheduler", "pallet-sudo", @@ -2363,6 +2367,7 @@ dependencies = [ "pallet-grandpa", "pallet-identity", "pallet-im-online", + "pallet-membership", "pallet-multisig", "pallet-offences", "pallet-scheduler", @@ -4549,6 +4554,7 @@ dependencies = [ "serde", "sp-core", "sp-io", + "sp-membership", "sp-runtime", "sp-std", ] @@ -4585,6 +4591,7 @@ dependencies = [ "serde", "sp-core", "sp-io", + "sp-membership", "sp-runtime", "sp-std", ] @@ -7392,6 +7399,17 @@ dependencies = [ "zstd", ] +[[package]] +name = "sp-membership" +version = "3.0.0" +dependencies = [ + "frame-support", + "parity-scale-codec", + "scale-info", + "serde", + "sp-std", +] + [[package]] name = "sp-offchain" version = "4.0.0-dev" diff --git a/Cargo.toml b/Cargo.toml index 2e4c71d5e414d89f9a366e0aac03a57b6b76557a..f5f8a0a024c97a655e41a8b1a12d3fe42ae137cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ members = [ 'pallets/membership', 'pallets/ud-accounts-storage', 'pallets/universal-dividend', + 'primitives/membership', ] # The list of dependencies below (which can be both direct and indirect dependencies) are crates diff --git a/node/Cargo.toml b/node/Cargo.toml index 313c494a377790d669cefef3ba5ed3bfb5b79891..45e9a5e2446c6c7bf1d0ae03fb136150dc64b8dd 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -43,6 +43,7 @@ g1-runtime = { path = '../runtime/g1', optional = true } gdev-runtime = { path = '../runtime/gdev', optional = true } gtest-runtime = { path = '../runtime/gtest', optional = true } pallet-certification = { path = '../pallets/certification' } +sp-membership = { path = '../primitives/membership' } # crates.io dependencies async-io = "1.3" diff --git a/node/src/chain_spec/gdev.rs b/node/src/chain_spec/gdev.rs index aeb45dfd21511480a43a8765387d01e7703c2f5c..133dddd494a7aa97b0e2b13224941c3a6fccbc84 100644 --- a/node/src/chain_spec/gdev.rs +++ b/node/src/chain_spec/gdev.rs @@ -18,13 +18,14 @@ use super::*; use common_runtime::entities::IdtyName; use gdev_runtime::{ AccountId, BalancesConfig, GenesisConfig, GrandpaConfig, IdentityConfig, IdtyRight, IdtyValue, - StrongCertConfig, SudoConfig, SystemConfig, UdAccountsStorageConfig, UniversalDividendConfig, - WASM_BINARY, + MembershipConfig, StrongCertConfig, SudoConfig, SystemConfig, UdAccountsStorageConfig, + UniversalDividendConfig, WASM_BINARY, }; use maplit::btreemap; use sc_service::ChainType; use sp_core::sr25519; use sp_finality_grandpa::AuthorityId as GrandpaId; +use sp_membership::MembershipData; use std::collections::BTreeMap; pub type ChainSpec = sc_service::GenericChainSpec<GenesisConfig>; @@ -112,12 +113,10 @@ fn devnet_genesis( .iter() .map(|(name, account)| IdtyValue { data: Default::default(), - expire_on: gdev_runtime::MaxInactivityPeriod::get(), owner_key: account.clone(), name: name.clone(), next_creatable_identity_on: Default::default(), removable_on: 0, - renewable_on: gdev_runtime::StrongCertRenewablePeriod::get(), rights: vec![ (IdtyRight::CreateIdty, None), (IdtyRight::StrongCert, None), @@ -127,6 +126,19 @@ fn devnet_genesis( }) .collect(), }, + membership: MembershipConfig { + memberships: (1..=initial_identities.len()) + .map(|i| { + ( + i as u32, + MembershipData { + expire_on: gdev_runtime::MembershipPeriod::get(), + renewable_on: gdev_runtime::RenewablePeriod::get(), + }, + ) + }) + .collect(), + }, strong_cert: StrongCertConfig { certs_by_issuer: clique_wot( initial_identities.len(), diff --git a/node/src/chain_spec/gtest.rs b/node/src/chain_spec/gtest.rs index 15fae450ae495dbfec5449c3fd05d76699a11e6a..36e228cdb3f3f1c7df59b7c2f15beb5e22d4528a 100644 --- a/node/src/chain_spec/gtest.rs +++ b/node/src/chain_spec/gtest.rs @@ -19,8 +19,8 @@ use common_runtime::constants::*; use common_runtime::entities::IdtyName; use gtest_runtime::{ opaque::SessionKeys, AccountId, BabeConfig, BalancesConfig, GenesisConfig, IdentityConfig, - IdtyRight, IdtyValue, ImOnlineId, SessionConfig, StrongCertConfig, SudoConfig, SystemConfig, - UdAccountsStorageConfig, UniversalDividendConfig, WASM_BINARY, + IdtyRight, IdtyValue, ImOnlineId, MembershipConfig, SessionConfig, StrongCertConfig, + SudoConfig, SystemConfig, UdAccountsStorageConfig, UniversalDividendConfig, WASM_BINARY, }; use maplit::btreemap; use sc_service::ChainType; @@ -28,6 +28,7 @@ use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_consensus_babe::AuthorityId as BabeId; use sp_core::sr25519; use sp_finality_grandpa::AuthorityId as GrandpaId; +use sp_membership::MembershipData; use std::collections::BTreeMap; pub type AuthorityKeys = ( @@ -99,18 +100,29 @@ fn devnet_genesis( identities: initial_identities .iter() .map(|(name, account)| IdtyValue { + data: Default::default(), name: name.clone(), - expire_on: gtest_runtime::MaxInactivityPeriod::get(), owner_key: account.clone(), removable_on: 0, - renewable_on: gtest_runtime::StrongCertRenewablePeriod::get(), rights: vec![ (IdtyRight::CreateIdty, None), (IdtyRight::StrongCert, None), (IdtyRight::Ud, None), ], status: gtest_runtime::IdtyStatus::Validated, - data: Default::default(), + }) + .collect(), + }, + membership: MembershipConfig { + memberships: (1..=initial_identities.len()) + .map(|i| { + ( + i as u32, + MembershipData { + expire_on: gtest_runtime::MembershipPeriod::get(), + renewable_on: gtest_runtime::RenewablePeriod::get(), + }, + ) }) .collect(), }, @@ -292,18 +304,29 @@ fn testnet_genesis( identities: initial_identities .iter() .map(|(name, account)| IdtyValue { + data: Default::default(), name: name.clone(), - expire_on: gtest_runtime::MaxInactivityPeriod::get(), owner_key: account.clone(), removable_on: 0, - renewable_on: gtest_runtime::StrongCertRenewablePeriod::get(), rights: vec![ (IdtyRight::CreateIdty, None), (IdtyRight::StrongCert, None), (IdtyRight::Ud, None), ], status: gtest_runtime::IdtyStatus::Validated, - data: Default::default(), + }) + .collect(), + }, + membership: MembershipConfig { + memberships: (1..=initial_identities.len()) + .map(|i| { + ( + i as u32, + MembershipData { + expire_on: gtest_runtime::MembershipPeriod::get(), + renewable_on: gtest_runtime::RenewablePeriod::get(), + }, + ) }) .collect(), }, diff --git a/pallets/identity/Cargo.toml b/pallets/identity/Cargo.toml index 0fbcb113af30a5822a592fc16b3a46e203f4b077..d7b804275173c23321b94b0084a87e9b5305039e 100644 --- a/pallets/identity/Cargo.toml +++ b/pallets/identity/Cargo.toml @@ -19,12 +19,14 @@ std = [ 'frame-benchmarking/std', 'serde', 'sp-core/std', + 'sp-membership/std', 'sp-runtime/std', 'sp-std/std', ] try-runtime = ['frame-support/try-runtime'] [dependencies] +sp-membership = { path = "../../primitives/membership", default-features = false } # substrate scale-info = { version = "1.0", default-features = false, features = ["derive"] } @@ -81,6 +83,5 @@ version = '1.0.119' ### DEV ### [dev-dependencies.sp-io] -default-features = false git = 'https://github.com/librelois/substrate.git' branch = 'duniter-monthly-2022-01' diff --git a/pallets/identity/src/lib.rs b/pallets/identity/src/lib.rs index c7da9310720a2be4862a0d94ff3c1726e2be6dea..7ce3a9c33088874ac26d335682040ac7bc84bf20 100644 --- a/pallets/identity/src/lib.rs +++ b/pallets/identity/src/lib.rs @@ -35,6 +35,7 @@ pub use types::*; use crate::traits::*; use codec::Codec; use frame_support::dispatch::Weight; +use frame_system::RawOrigin; use sp_runtime::traits::{AtLeast32BitUnsigned, One, Saturating, Zero}; use sp_std::fmt::Debug; use sp_std::prelude::*; @@ -43,10 +44,20 @@ use sp_std::prelude::*; pub mod pallet { use super::*; use frame_support::pallet_prelude::*; + use frame_support::traits::StorageVersion; use frame_system::pallet_prelude::*; - use scale_info::TypeInfo; + use sp_membership::traits::MembershipAction as _; + + /// The current storage version. + const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + #[pallet::storage_version(STORAGE_VERSION)] + pub struct Pallet<T>(_); + + // CONFIG // - /// Configure the pallet by specifying the parameters and types on which it depends. #[pallet::config] pub trait Config: frame_system::Config { #[pallet::constant] @@ -87,83 +98,13 @@ pub mod pallet { /// On right key change type OnRightKeyChange: OnRightKeyChange<Self>; #[pallet::constant] - /// Maximum period of inactivity, after this period, the identity is permanently deleted - type MaxInactivityPeriod: Get<Self::BlockNumber>; - #[pallet::constant] /// Maximum period with no rights, after this period, the identity is permanently deleted type MaxNoRightPeriod: Get<Self::BlockNumber>; - /// Duration after which an identity is renewable - type RenewablePeriod: Get<Self::BlockNumber>; - #[pallet::constant] - /// Period after which a non-validated identity is deleted - type ValidationPeriod: Get<Self::BlockNumber>; - } - - // STORAGE // - - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet<T>(_); - - // A value placed in storage that represents the current version of the Balances storage. - // This value is used by the `on_runtime_upgrade` logic to determine whether we run - // storage migration logic. This should match directly with the semantic versions of the Rust crate. - #[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)] - pub enum Releases { - V1_0_0, + /// + type Membership: sp_membership::traits::MembershipAction<Self::IdtyIndex, Self::Origin>; } - impl Default for Releases { - fn default() -> Self { - Releases::V1_0_0 - } - } - - /// Storage version of the pallet. - #[pallet::storage] - pub(super) type StorageVersion<T: Config> = StorageValue<_, Releases, ValueQuery>; - - /// Identities - #[pallet::storage] - #[pallet::getter(fn identity)] - pub type Identities<T: Config> = StorageMap< - _, - Blake2_128Concat, - T::IdtyIndex, - IdtyValue<T::AccountId, T::BlockNumber, T::IdtyData, T::IdtyRight>, - OptionQuery, - >; - - /// IdentitiesByDid - #[pallet::storage] - #[pallet::getter(fn identity_by_did)] - pub type IdentitiesByDid<T: Config> = - StorageMap<_, Blake2_128Concat, IdtyName, T::IdtyIndex, ValueQuery>; - #[pallet::storage] - pub(super) type NextIdtyIndex<T: Config> = StorageValue<_, T::IdtyIndex, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn identities_count)] - pub(super) type IdentitiesCount<T: Config> = StorageValue<_, u64, ValueQuery>; - - /// Identities by expiration block - #[pallet::storage] - #[pallet::getter(fn expire_on)] - pub type IdentitiesExpireOn<T: Config> = - StorageMap<_, Blake2_128Concat, T::BlockNumber, Vec<T::IdtyIndex>, ValueQuery>; - - /// Identities by removed block - #[pallet::storage] - #[pallet::getter(fn removable_on)] - pub type IdentitiesRemovableOn<T: Config> = StorageMap< - _, - Blake2_128Concat, - T::BlockNumber, - Vec<(T::IdtyIndex, IdtyStatus)>, - ValueQuery, - >; - - // GENESIS // + // GENESIS STUFFĂ‚ // #[pallet::genesis_config] pub struct GenesisConfig<T: Config> { pub identities: Vec<IdtyValue<T::AccountId, T::BlockNumber, T::IdtyData, T::IdtyRight>>, @@ -205,7 +146,6 @@ pub mod pallet { let mut identities = self.identities.clone(); identities.sort_by(|idty_val_1, idty_val_2| idty_val_1.name.cmp(&idty_val_2.name)); - <StorageVersion<T>>::put(Releases::V1_0_0); <IdentitiesCount<T>>::put(self.identities.len() as u64); for idty_value in &identities { let idty_index = Pallet::<T>::get_next_idty_index(); @@ -220,13 +160,50 @@ pub mod pallet { } } + // STORAGE // + + /// Identities + #[pallet::storage] + #[pallet::getter(fn identity)] + pub type Identities<T: Config> = StorageMap< + _, + Blake2_128Concat, + T::IdtyIndex, + IdtyValue<T::AccountId, T::BlockNumber, T::IdtyData, T::IdtyRight>, + OptionQuery, + >; + + /// IdentitiesByDid + #[pallet::storage] + #[pallet::getter(fn identity_by_did)] + pub type IdentitiesByDid<T: Config> = + StorageMap<_, Blake2_128Concat, IdtyName, T::IdtyIndex, ValueQuery>; + + #[pallet::storage] + pub(super) type NextIdtyIndex<T: Config> = StorageValue<_, T::IdtyIndex, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn identities_count)] + pub(super) type IdentitiesCount<T: Config> = StorageValue<_, u64, ValueQuery>; + + /// Identities by removed block + #[pallet::storage] + #[pallet::getter(fn removable_on)] + pub type IdentitiesRemovableOn<T: Config> = StorageMap< + _, + Blake2_128Concat, + T::BlockNumber, + Vec<(T::IdtyIndex, IdtyStatus)>, + ValueQuery, + >; + // HOOKS // #[pallet::hooks] impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> { fn on_initialize(n: T::BlockNumber) -> Weight { if n > T::BlockNumber::zero() { - Self::expire_identities(n) + Self::prune_identities(n) + Self::prune_identities(n) } else { 0 } @@ -282,46 +259,67 @@ pub mod pallet { idty_name: IdtyName, owner_key: T::AccountId, ) -> DispatchResultWithPostInfo { + // Verification phase // + let who = ensure_signed(origin)?; + let creator_idty_val = Identities::<T>::try_get(&creator).map_err(|_| Error::<T>::CreatorNotExist)?; + let expected_account = if let Ok(index) = creator_idty_val + .rights + .binary_search_by(|(right_, _)| right_.cmp(&T::IdtyRight::create_idty_right())) + { + creator_idty_val.rights[index] + .1 + .clone() + .unwrap_or(creator_idty_val.owner_key) + } else { + return Err(Error::<T>::CreatorNotHaveRightToCreateIdty.into()); + }; + + if who != expected_account { + return Err(Error::<T>::RequireToBeOwner.into()); + } + let block_number = frame_system::pallet::Pallet::<T>::block_number(); - if creator_idty_val.next_creatable_identity_on - > block_number + T::IdtyCreationPeriod::get() - { + if creator_idty_val.next_creatable_identity_on > block_number { return Err(Error::<T>::NotRespectIdtyCreationPeriod.into()); } - T::EnsureIdtyCallAllowed::can_create_identity( - origin, - creator, - creator_idty_val, - &idty_name, - &owner_key, - )?; + if !T::EnsureIdtyCallAllowed::can_create_identity(creator) { + return Err(Error::<T>::CreatorNotAllowedToCreateIdty.into()); + } if !T::IdtyNameValidator::validate(&idty_name) { return Err(Error::<T>::IdtyNameInvalid.into()); } - let idty_data = - T::IdtyDataProvider::provide_identity_data(creator, &idty_name, &owner_key); if <IdentitiesByDid<T>>::contains_key(&idty_name) { return Err(Error::<T>::IdtyNameAlreadyExist.into()); } + // Apply phase // + + <Identities<T>>::mutate_exists(creator, |idty_val_opt| { + if let Some(ref mut idty_val) = idty_val_opt { + idty_val.next_creatable_identity_on = + block_number + T::IdtyCreationPeriod::get(); + } + }); + + let idty_data = + T::IdtyDataProvider::provide_identity_data(creator, &idty_name, &owner_key); + let removable_on = block_number + T::ConfirmPeriod::get(); let idty_index = Self::get_next_idty_index(); <Identities<T>>::insert( idty_index, IdtyValue { - expire_on: T::BlockNumber::zero(), name: idty_name.clone(), next_creatable_identity_on: T::BlockNumber::zero(), owner_key: owner_key.clone(), removable_on, - renewable_on: T::BlockNumber::zero(), rights: Vec::with_capacity(0), status: IdtyStatus::Created, data: idty_data, @@ -347,22 +345,11 @@ pub mod pallet { if idty_value.status != IdtyStatus::Created { return Err(Error::<T>::IdtyAlreadyConfirmed.into()); } + T::Membership::request_membership_(RawOrigin::Signed(who).into(), idty_index)?; - let block_number = frame_system::pallet::Pallet::<T>::block_number(); - let expire_on = block_number + T::MaxInactivityPeriod::get(); - let removable_on = block_number + T::ValidationPeriod::get(); - let renewable_on = block_number + T::RenewablePeriod::get(); - idty_value.expire_on = expire_on; - idty_value.removable_on = removable_on; - idty_value.renewable_on = renewable_on; idty_value.status = IdtyStatus::ConfirmedByOwner; <Identities<T>>::insert(idty_index, idty_value); - IdentitiesExpireOn::<T>::append(expire_on, idty_index); - IdentitiesRemovableOn::<T>::append( - removable_on, - (idty_index, IdtyStatus::ConfirmedByOwner), - ); Self::deposit_event(Event::IdtyConfirmed(idty_name)); T::OnIdtyChange::on_idty_change(idty_index, IdtyEvent::Confirmed); Ok(().into()) @@ -388,19 +375,15 @@ pub mod pallet { Err(Error::<T>::IdtyNotValidated.into()) } IdtyStatus::Validated | IdtyStatus::Expired => { - let block_number = frame_system::pallet::Pallet::<T>::block_number(); - if idty_value.renewable_on > block_number { - return Err(Error::<T>::IdtyNotYetRenewable.into()); - } - let expire_on = block_number + T::MaxInactivityPeriod::get(); - let renewable_on = block_number + T::RenewablePeriod::get(); - idty_value.expire_on = expire_on; - idty_value.renewable_on = renewable_on; + let _post_info = T::Membership::renew_membership_( + RawOrigin::Signed(who).into(), + idty_index, + )?; + let old_status = idty_value.status; idty_value.status = IdtyStatus::Validated; <Identities<T>>::insert(idty_index, idty_value); - IdentitiesExpireOn::<T>::append(expire_on, idty_index); Self::deposit_event(Event::IdtyRenewed(idty_name)); if old_status == IdtyStatus::Expired { T::OnIdtyChange::on_idty_change(idty_index, IdtyEvent::Validated); @@ -420,12 +403,14 @@ pub mod pallet { origin: OriginFor<T>, idty_index: T::IdtyIndex, ) -> DispatchResultWithPostInfo { - T::IdtyValidationOrigin::ensure_origin(origin)?; + T::IdtyValidationOrigin::ensure_origin(origin.clone())?; if let Ok(mut idty_value) = <Identities<T>>::try_get(idty_index) { match idty_value.status { IdtyStatus::Created => Err(Error::<T>::IdtyNotConfirmedByOwner.into()), IdtyStatus::ConfirmedByOwner => { + let _post_info = T::Membership::claim_membership_(origin, idty_index)?; + let block_number = frame_system::pallet::Pallet::<T>::block_number(); let removable_on = block_number + T::MaxNoRightPeriod::get(); idty_value.removable_on = removable_on; @@ -647,6 +632,10 @@ pub mod pallet { pub enum Error<T> { /// Creator not exist CreatorNotExist, + /// Creator not allowed to create identities + CreatorNotAllowedToCreateIdty, + /// Creator not have right to create identities + CreatorNotHaveRightToCreateIdty, /// Identity already confirmed IdtyAlreadyConfirmed, /// Identity already validated @@ -697,6 +686,33 @@ pub mod pallet { panic!("storage corrupted") } } + pub(super) fn do_expire_identity(idty_index: T::IdtyIndex) -> Weight { + let mut total_weight: Weight = 0; + + let block_number = frame_system::pallet::Pallet::<T>::block_number(); + let removable_on = block_number + T::MaxNoRightPeriod::get(); + <Identities<T>>::mutate_exists(idty_index, |idty_val_opt| { + if let Some(ref mut idty_val) = idty_val_opt { + idty_val.removable_on = removable_on; + idty_val.rights = Vec::with_capacity(0); + } + }); + <IdentitiesRemovableOn<T>>::append(removable_on, (idty_index, IdtyStatus::Expired)); + total_weight += T::OnIdtyChange::on_idty_change(idty_index, IdtyEvent::Expired); + + total_weight + } + pub(super) fn do_remove_identity(idty_index: T::IdtyIndex) -> Weight { + let mut total_weight: Weight = 0; + + if let Some(idty_val) = <Identities<T>>::take(idty_index) { + <IdentitiesByDid<T>>::remove(idty_val.name); + } + Self::dec_identities_counter(); + total_weight += T::OnIdtyChange::on_idty_change(idty_index, IdtyEvent::Removed); + + total_weight + } fn get_next_idty_index() -> T::IdtyIndex { if let Ok(next_index) = <NextIdtyIndex<T>>::try_get() { <NextIdtyIndex<T>>::put(next_index.saturating_add(T::IdtyIndex::one())); @@ -713,24 +729,17 @@ pub mod pallet { <IdentitiesCount<T>>::put(1); } } - fn expire_identities(block_number: T::BlockNumber) -> Weight { + fn prune_identities(block_number: T::BlockNumber) -> Weight { let mut total_weight: Weight = 0; use frame_support::storage::generator::StorageMap as _; - if let Some(identities_index) = IdentitiesExpireOn::<T>::from_query_to_optional_value( - IdentitiesExpireOn::<T>::take(block_number), + if let Some(identities) = IdentitiesRemovableOn::<T>::from_query_to_optional_value( + IdentitiesRemovableOn::<T>::take(block_number), ) { - for idty_index in identities_index { + for (idty_index, idty_status) in identities { if let Ok(idty_val) = <Identities<T>>::try_get(idty_index) { - if idty_val.expire_on == block_number { - <Identities<T>>::mutate_exists(idty_index, |idty_val_opt| { - if let Some(ref mut idty_val) = idty_val_opt { - idty_val.rights = Vec::with_capacity(0); - idty_val.status = IdtyStatus::Expired; - } - }); - total_weight += - T::OnIdtyChange::on_idty_change(idty_index, IdtyEvent::Expired); + if idty_val.removable_on == block_number && idty_val.status == idty_status { + total_weight += Self::do_remove_identity(idty_index) } } } @@ -738,28 +747,47 @@ pub mod pallet { total_weight } - fn prune_identities(block_number: T::BlockNumber) -> Weight { - let mut total_weight: Weight = 0; + } +} - use frame_support::storage::generator::StorageMap as _; - if let Some(identities) = IdentitiesRemovableOn::<T>::from_query_to_optional_value( - IdentitiesRemovableOn::<T>::take(block_number), - ) { - for (idty_index, idty_status) in identities { - if let Ok(idty_val) = <Identities<T>>::try_get(idty_index) { - if idty_val.removable_on == block_number && idty_val.status == idty_status { - let name = idty_val.name; - <Identities<T>>::remove(idty_index); - <IdentitiesByDid<T>>::remove(name); - Self::dec_identities_counter(); - total_weight += - T::OnIdtyChange::on_idty_change(idty_index, IdtyEvent::Removed); - } +impl<T: Config> sp_membership::traits::IsOriginAllowedToUseIdty<T::Origin, T::IdtyIndex> + for Pallet<T> +{ + fn is_origin_allowed_to_use_idty( + origin: &T::Origin, + idty_index: &T::IdtyIndex, + ) -> sp_membership::OriginPermission { + match origin.clone().into() { + Ok(RawOrigin::Root) => sp_membership::OriginPermission::Root, + Ok(RawOrigin::Signed(account_id)) => { + if let Some(idty_val) = Pallet::<T>::identity(idty_index) { + if account_id == idty_val.owner_key { + sp_membership::OriginPermission::Allowed + } else { + sp_membership::OriginPermission::Forbidden } + } else { + sp_membership::OriginPermission::Forbidden } } + _ => sp_membership::OriginPermission::Forbidden, + } + } +} - total_weight +impl<T: Config> sp_membership::traits::OnEvent<T::IdtyIndex> for Pallet<T> { + fn on_event(membership_event: sp_membership::Event<T::IdtyIndex>) -> Weight { + match membership_event { + sp_membership::Event::<T::IdtyIndex>::MembershipAcquired(_) => 0, + sp_membership::Event::<T::IdtyIndex>::MembershipExpired(idty_index) => { + Pallet::<T>::do_expire_identity(idty_index) + } + sp_membership::Event::<T::IdtyIndex>::MembershipRenewed(_) => 0, + sp_membership::Event::<T::IdtyIndex>::MembershipRequested(_) => 0, + sp_membership::Event::<T::IdtyIndex>::MembershipRevoked(_) => 0, + sp_membership::Event::<T::IdtyIndex>::PendingMembershipExpired(idty_index) => { + Pallet::<T>::do_remove_identity(idty_index) + } } } } diff --git a/pallets/identity/src/mock.rs b/pallets/identity/src/mock.rs index d7b9ed028e0aae8c63bbf5b4af49e9eee143deb1..51e77fff10eb56665f9fe620b5aef0fef2a9b7f4 100644 --- a/pallets/identity/src/mock.rs +++ b/pallets/identity/src/mock.rs @@ -124,7 +124,7 @@ parameter_types! { pub struct IdtyNameValidatorTestImpl; impl pallet_identity::traits::IdtyNameValidator for IdtyNameValidatorTestImpl { fn validate(idty_name: &pallet_identity::IdtyName) -> bool { - idty_name.0.len() == 1 + idty_name.0.len() < 16 } } @@ -143,10 +143,8 @@ impl pallet_identity::Config for Test { type IdtyRight = IdtyRight; type OnIdtyChange = (); type OnRightKeyChange = (); - type MaxInactivityPeriod = MaxInactivityPeriod; type MaxNoRightPeriod = MaxNoRightPeriod; - type RenewablePeriod = RenewablePeriod; - type ValidationPeriod = ValidationPeriod; + type Membership = (); } // Build genesis storage according to the mock runtime. @@ -164,6 +162,7 @@ pub fn run_to_block(n: u64) { while System::block_number() < n { Identity::on_finalize(System::block_number()); System::on_finalize(System::block_number()); + System::reset_events(); System::set_block_number(System::block_number() + 1); System::on_initialize(System::block_number()); Identity::on_initialize(System::block_number()); diff --git a/pallets/identity/src/tests.rs b/pallets/identity/src/tests.rs index 7b976305e0a9cfab16ea3501bdff334833ffd4a5..264b324c27088c4e643ef6aea9ceb9fe1aaaa374 100644 --- a/pallets/identity/src/tests.rs +++ b/pallets/identity/src/tests.rs @@ -16,45 +16,181 @@ use crate::mock::IdtyRight as Right; use crate::mock::*; -use crate::{Error, IdtyName}; +use crate::{Error, IdtyName, IdtyValue}; use frame_support::assert_err; use frame_support::assert_ok; use frame_system::{EventRecord, Phase}; +type IdtyVal = IdtyValue<u64, u64, (), Right>; + +fn alice() -> IdtyVal { + IdtyVal { + data: (), + owner_key: 1, + name: IdtyName::from("Alice"), + next_creatable_identity_on: 0, + removable_on: 0, + rights: vec![(Right::Right1, None)], + status: crate::IdtyStatus::Validated, + } +} +fn bob() -> IdtyVal { + IdtyVal { + data: (), + owner_key: 2, + name: IdtyName::from("Bob"), + next_creatable_identity_on: 0, + removable_on: 0, + rights: vec![(Right::Right2, Some(20))], + status: crate::IdtyStatus::Validated, + } +} + #[test] fn test_no_identity() { - let identities = Vec::with_capacity(0); - new_test_ext(IdentityConfig { identities }).execute_with(|| { + new_test_ext(IdentityConfig { + identities: Vec::with_capacity(0), + }) + .execute_with(|| { assert_eq!(Identity::identities_count(), 0); }); } +#[test] +fn test_creator_not_exist() { + new_test_ext(IdentityConfig { + identities: Vec::with_capacity(0), + }) + .execute_with(|| { + assert_eq!( + Identity::create_identity(Origin::signed(1), 1, IdtyName::from("bob"), 2), + Err(Error::<Test>::CreatorNotExist.into()) + ); + }); +} + +#[test] +fn test_creator_not_have_right_to_create_identity() { + new_test_ext(IdentityConfig { + identities: vec![bob()], + }) + .execute_with(|| { + // We need to initialize at least one block before any call + run_to_block(1); + + // Bob not have right to create identities + assert_eq!( + Identity::create_identity(Origin::signed(2), 1, IdtyName::from("Charlie"), 3), + Err(Error::<Test>::CreatorNotHaveRightToCreateIdty.into()) + ); + }) +} + +#[test] +fn test_creator_not_owner() { + new_test_ext(IdentityConfig { + identities: vec![alice()], + }) + .execute_with(|| { + // We need to initialize at least one block before any call + run_to_block(1); + + // Someone try to create an identity pretending to be Alice + assert_eq!( + Identity::create_identity(Origin::signed(2), 1, IdtyName::from("Charlie"), 3), + Err(Error::<Test>::RequireToBeOwner.into()) + ); + }) +} + +#[test] +fn test_create_identity_ok() { + new_test_ext(IdentityConfig { + identities: vec![alice()], + }) + .execute_with(|| { + // We need to initialize at least one block before any call + run_to_block(1); + + // Alice should be able te create an identity + assert_ok!(Identity::create_identity( + Origin::signed(1), + 1, + IdtyName::from("bob"), + 2 + )); + let events = System::events(); + assert_eq!(events.len(), 1); + assert_eq!( + events[0], + EventRecord { + phase: Phase::Initialization, + event: Event::Identity(crate::Event::IdtyCreated(IdtyName::from("bob"), 2)), + topics: vec![], + } + ); + }); +} + +#[test] +fn test_idty_creation_period() { + new_test_ext(IdentityConfig { + identities: vec![alice()], + }) + .execute_with(|| { + // We need to initialize at least one block before any call + run_to_block(1); + + // Alice should be able te create an identity + assert_ok!(Identity::create_identity( + Origin::signed(1), + 1, + IdtyName::from("bob"), + 2 + )); + let events = System::events(); + assert_eq!(events.len(), 1); + assert_eq!( + events[0], + EventRecord { + phase: Phase::Initialization, + event: Event::Identity(crate::Event::IdtyCreated(IdtyName::from("bob"), 2)), + topics: vec![], + } + ); + assert_eq!(Identity::identity(1).unwrap().next_creatable_identity_on, 4); + + // Alice cannot create a new identity before block #4 + run_to_block(2); + assert_eq!( + Identity::create_identity(Origin::signed(1), 1, IdtyName::from("Charlie"), 3), + Err(Error::<Test>::NotRespectIdtyCreationPeriod.into()) + ); + + // Alice should be able te create a second identity after block #4 + run_to_block(4); + assert_ok!(Identity::create_identity( + Origin::signed(1), + 1, + IdtyName::from("Charlie"), + 3 + )); + let events = System::events(); + assert_eq!(events.len(), 1); + assert_eq!( + events[0], + EventRecord { + phase: Phase::Initialization, + event: Event::Identity(crate::Event::IdtyCreated(IdtyName::from("Charlie"), 3)), + topics: vec![], + } + ); + }); +} + #[test] fn test_two_identities() { - let identities = vec![ - crate::IdtyValue { - data: (), - expire_on: 5, - owner_key: 1, - name: IdtyName(vec![0]), - next_creatable_identity_on: 0, - removable_on: 0, - renewable_on: 3, - rights: vec![(Right::Right2, Some(10))], - status: crate::IdtyStatus::Validated, - }, - crate::IdtyValue { - data: (), - expire_on: 5, - owner_key: 2, - name: IdtyName(vec![1]), - next_creatable_identity_on: 0, - removable_on: 0, - renewable_on: 3, - rights: vec![(Right::Right1, Some(20))], - status: crate::IdtyStatus::Validated, - }, - ]; + let identities = vec![alice(), bob()]; new_test_ext(IdentityConfig { identities }).execute_with(|| { // Should have two identities @@ -63,9 +199,15 @@ fn test_two_identities() { // We need to initialize at least one block before any call run_to_block(1); - // Add right Right1 for IdtyName(vec![0]) + // Add right Right1 for Alice + // Should fail because Alice already have this right + assert_err!( + Identity::add_right(Origin::root(), 1, Right::Right1), + Error::<Test>::RightAlreadyAdded + ); + // Add right Right2 for alice // Should succes and trigger the correct event - assert_ok!(Identity::add_right(Origin::root(), 1, Right::Right1)); + assert_ok!(Identity::add_right(Origin::root(), 1, Right::Right2)); let events = System::events(); assert_eq!(events.len(), 1); assert_eq!( @@ -73,39 +215,33 @@ fn test_two_identities() { EventRecord { phase: Phase::Initialization, event: Event::Identity(crate::Event::IdtyAcquireRight( - IdtyName(vec![0]), - Right::Right1 + IdtyName::from("Alice"), + Right::Right2 )), topics: vec![], } ); - // Add right Right2 for IdtyName(vec![0]) - // Should fail because IdtyName(vec![0]) already have this right - assert_err!( - Identity::add_right(Origin::root(), 1, Right::Right2), - Error::<Test>::RightAlreadyAdded - ); run_to_block(3); - // Delete right Right1 for IdtyName(vec![1]) + // Delete right Right2 for Bob // Should succes and trigger the correct event - assert_ok!(Identity::del_right(Origin::root(), 2, Right::Right1)); + assert_ok!(Identity::del_right(Origin::root(), 2, Right::Right2)); let events = System::events(); - assert_eq!(events.len(), 2); + assert_eq!(events.len(), 1); assert_eq!( - events[1], + events[0], EventRecord { phase: Phase::Initialization, event: Event::Identity(crate::Event::IdtyLostRight( - IdtyName(vec![1]), - Right::Right1 + IdtyName::from("Bob"), + Right::Right2 )), topics: vec![], } ); - // The IdtyName(vec![1]) identity has no more rights, the inactivity period must start to run + // The Bob identity has no more rights, the inactivity period must start to run let idty2 = Identity::identity(2).expect("idty not found"); assert!(idty2.rights.is_empty()); assert_eq!(idty2.removable_on, 7); diff --git a/pallets/identity/src/traits.rs b/pallets/identity/src/traits.rs index caa9c2446b811c733bdd037c832e5b298f0b6e6d..d5b1e19b7b7383061c14f10669972ca5c92ef244 100644 --- a/pallets/identity/src/traits.rs +++ b/pallets/identity/src/traits.rs @@ -15,33 +15,17 @@ // along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>. use crate::*; -use frame_support::{dispatch::DispatchError, pallet_prelude::*}; -use frame_system::pallet_prelude::*; +use frame_support::pallet_prelude::*; use sp_runtime::traits::MaybeSerializeDeserialize; use sp_std::fmt::Debug; pub trait EnsureIdtyCallAllowed<T: Config> { - fn can_create_identity( - origin: T::Origin, - creator: T::IdtyIndex, - creator_idty: IdtyValue<T::AccountId, T::BlockNumber, T::IdtyData, T::IdtyRight>, - idty_name: &IdtyName, - idty_owner_key: &T::AccountId, - ) -> Result<(), DispatchError>; + fn can_create_identity(creator: T::IdtyIndex) -> bool; } impl<T: Config> EnsureIdtyCallAllowed<T> for () { - fn can_create_identity( - origin: T::Origin, - _creator: T::IdtyIndex, - _creator_idty: IdtyValue<T::AccountId, T::BlockNumber, T::IdtyData, T::IdtyRight>, - _idty_name: &IdtyName, - _idty_owner_key: &T::AccountId, - ) -> Result<(), DispatchError> { - match ensure_root(origin) { - Ok(()) => Ok(()), - Err(_) => Err(DispatchError::BadOrigin), - } + fn can_create_identity(_creator: T::IdtyIndex) -> bool { + true } } diff --git a/pallets/identity/src/types.rs b/pallets/identity/src/types.rs index dcca75ea962926705929c001bd7d0abf353a363f..b4231157bae636c39221a8d7f7bd10c305c83912 100644 --- a/pallets/identity/src/types.rs +++ b/pallets/identity/src/types.rs @@ -80,12 +80,10 @@ pub struct IdtyValue< IdtyRight: Decode + Encode + TypeInfo, > { pub data: IdtyData, - pub expire_on: BlockNumber, pub owner_key: AccountId, pub name: IdtyName, pub next_creatable_identity_on: BlockNumber, pub removable_on: BlockNumber, - pub renewable_on: BlockNumber, pub rights: Vec<(IdtyRight, Option<AccountId>)>, pub status: IdtyStatus, } diff --git a/pallets/membership/Cargo.toml b/pallets/membership/Cargo.toml index 1b49766c4b4babe7a1b9776937a7b4f7228f1705..acdec3a966d9f66f580530b71683122e492bfd45 100644 --- a/pallets/membership/Cargo.toml +++ b/pallets/membership/Cargo.toml @@ -19,12 +19,14 @@ std = [ 'frame-benchmarking/std', 'serde', 'sp-core/std', + 'sp-membership/std', 'sp-runtime/std', 'sp-std/std', ] try-runtime = ['frame-support/try-runtime'] [dependencies] +sp-membership = { path = "../../primitives/membership", default-features = false } # substrate scale-info = { version = "1.0", default-features = false, features = ["derive"] } diff --git a/pallets/membership/src/lib.rs b/pallets/membership/src/lib.rs index 951ad411c340fc5c0c5dd47e8563bc24ba8d7dbf..dd93b656e2555bd25dff794d838b72cbd6500eb1 100644 --- a/pallets/membership/src/lib.rs +++ b/pallets/membership/src/lib.rs @@ -17,9 +17,6 @@ #![cfg_attr(not(feature = "std"), no_std)] #![allow(clippy::type_complexity)] -pub mod traits; -pub mod types; - #[cfg(test)] mod mock; @@ -31,10 +28,10 @@ mod benchmarking;*/ pub use pallet::*; -use crate::traits::*; -use crate::types::{MembershipData, OriginPermission}; use frame_support::dispatch::Weight; use frame_support::pallet_prelude::DispatchResultWithPostInfo; +use sp_membership::traits::*; +use sp_membership::{MembershipData, OriginPermission}; use sp_runtime::traits::Zero; use sp_std::prelude::*; #[cfg(feature = "std")] @@ -183,15 +180,17 @@ pub mod pallet { pub enum Error<T, I = ()> { /// Identity not allowed to claim membership IdtyNotAllowedToClaimMembership, - /// Identity not allowed to renew membership - IdtyNotAllowedToRenewMembership, /// Identity not allowed to request membership IdtyNotAllowedToRequestMembership, - /// Origin not allowed to use this identity + /// Identity not allowed to renew membership + IdtyNotAllowedToRenewMembership, + /// Membership already acquired + MembershipAlreadyAcquired, /// Membership not yet renewable MembershipNotYetRenewable, /// Membership not found MembershipNotFound, + /// Origin not allowed to use this identity OriginNotAllowedToUseIdty, /// Membership request not found MembershipRequestNotFound, @@ -239,6 +238,9 @@ pub mod pallet { if !allowed { return Err(Error::<T, I>::IdtyNotAllowedToRequestMembership.into()); } + if Membership::<T, I>::contains_key(&idty_id) { + return Err(Error::<T, I>::MembershipAlreadyAcquired.into()); + } if RevokedMembership::<T, I>::contains_key(&idty_id) { return Err(Error::<T, I>::MembershipRevokedRecently.into()); } @@ -249,7 +251,7 @@ pub mod pallet { PendingMembership::<T, I>::insert(idty_id, ()); PendingMembershipsExpireOn::<T, I>::append(expire_on, idty_id); Self::deposit_event(Event::MembershipRequested(idty_id)); - T::OnEvent::on_event(crate::types::Event::MembershipRequested(idty_id)); + T::OnEvent::on_event(sp_membership::Event::MembershipRequested(idty_id)); Ok(().into()) } @@ -346,13 +348,13 @@ pub mod pallet { PendingMembership::<T, I>::remove(&idty_id); total_weight += Self::do_renew_membership_inner(idty_id); Self::deposit_event(Event::MembershipAcquired(idty_id)); - T::OnEvent::on_event(crate::types::Event::MembershipAcquired(idty_id)); + T::OnEvent::on_event(sp_membership::Event::MembershipAcquired(idty_id)); total_weight } pub(super) fn do_renew_membership(idty_id: T::IdtyId) -> Weight { let total_weight = Self::do_renew_membership_inner(idty_id); Self::deposit_event(Event::MembershipRenewed(idty_id)); - T::OnEvent::on_event(crate::types::Event::MembershipRenewed(idty_id)); + T::OnEvent::on_event(sp_membership::Event::MembershipRenewed(idty_id)); total_weight } fn do_renew_membership_inner(idty_id: T::IdtyId) -> Weight { @@ -371,14 +373,17 @@ pub mod pallet { 0 } pub(super) fn do_revoke_membership(idty_id: T::IdtyId) -> Weight { - let block_number = frame_system::pallet::Pallet::<T>::block_number(); - let pruned_on = block_number + T::RevocationPeriod::get(); - Self::remove_membership(&idty_id); - RevokedMembership::<T, I>::insert(idty_id, ()); - RevokedMembershipsPrunedOn::<T, I>::append(pruned_on, idty_id); + if T::RevocationPeriod::get() > Zero::zero() { + let block_number = frame_system::pallet::Pallet::<T>::block_number(); + let pruned_on = block_number + T::RevocationPeriod::get(); + + RevokedMembership::<T, I>::insert(idty_id, ()); + RevokedMembershipsPrunedOn::<T, I>::append(pruned_on, idty_id); + } Self::deposit_event(Event::MembershipRevoked(idty_id)); - T::OnEvent::on_event(crate::types::Event::MembershipRevoked(idty_id)); + T::OnEvent::on_event(sp_membership::Event::MembershipRevoked(idty_id)); + 0 } fn expire_memberships(block_number: T::BlockNumber) -> Weight { @@ -394,7 +399,7 @@ pub mod pallet { Self::remove_membership(&idty_id); Self::deposit_event(Event::MembershipExpired(idty_id)); total_weight += T::OnEvent::on_event( - crate::types::Event::MembershipExpired(idty_id), + sp_membership::Event::MembershipExpired(idty_id), ); } } @@ -416,7 +421,7 @@ pub mod pallet { PendingMembership::<T, I>::remove(&idty_id); Self::deposit_event(Event::PendingMembershipExpired(idty_id)); total_weight += T::OnEvent::on_event( - crate::types::Event::PendingMembershipExpired(idty_id), + sp_membership::Event::PendingMembershipExpired(idty_id), ); } } diff --git a/pallets/membership/src/mock.rs b/pallets/membership/src/mock.rs index 237d93a2794154501e2c06ab7d2aa9afe6d87703..3a9869bf0189d1d587b428b510181cbd043b8385 100644 --- a/pallets/membership/src/mock.rs +++ b/pallets/membership/src/mock.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU Affero General Public License // along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>. -use crate::traits::IsOriginAllowedToUseIdty; -use crate::types::OriginPermission; use crate::{self as pallet_membership}; use frame_support::{ parameter_types, @@ -23,6 +21,8 @@ use frame_support::{ }; use frame_system as system; use sp_core::H256; +use sp_membership::traits::IsOriginAllowedToUseIdty; +use sp_membership::OriginPermission; use sp_runtime::{ testing::Header, traits::{BlakeTwo256, IdentityLookup}, diff --git a/pallets/membership/src/tests.rs b/pallets/membership/src/tests.rs index f98e49909f25194f0fc3af5a6dee85eb21c086cb..0ac4522803238f4fc324c557ff2dad90e5a5f3a2 100644 --- a/pallets/membership/src/tests.rs +++ b/pallets/membership/src/tests.rs @@ -16,11 +16,11 @@ use crate::mock::Event as RuntimeEvent; use crate::mock::*; -use crate::traits::{IsInPendingMemberships, IsMember}; -use crate::types::MembershipData; use crate::{Error, Event}; use frame_support::assert_ok; use maplit::btreemap; +use sp_membership::traits::{IsInPendingMemberships, IsMember}; +use sp_membership::MembershipData; fn default_gen_conf() -> DefaultMembershipConfig { DefaultMembershipConfig { diff --git a/primitives/membership/Cargo.toml b/primitives/membership/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..29bb6472df273c18669c41966745a521b9561f56 --- /dev/null +++ b/primitives/membership/Cargo.toml @@ -0,0 +1,51 @@ +[package] +authors = ['librelois <c@elo.tf>'] +description = 'primitives for pallet membership.' +edition = '2018' +homepage = 'https://substrate.dev' +license = 'AGPL-3.0' +name = 'sp-membership' +readme = 'README.md' +repository = 'https://git.duniter.org/nodes/rust/duniter-v2s' +version = '3.0.0' + +[features] +default = ['std'] +std = [ + 'codec/std', + 'frame-support/std', + 'serde', + 'sp-std/std', +] +try-runtime = ['frame-support/try-runtime'] + +[dependencies] + +# substrate +scale-info = { version = "1.0", default-features = false, features = ["derive"] } + +[dependencies.codec] +default-features = false +features = ['derive'] +package = 'parity-scale-codec' +version = '2.3.1' + +[dependencies.frame-support] +default-features = false +git = 'https://github.com/librelois/substrate.git' +branch = 'duniter-monthly-2022-01' + +[dependencies.serde] +version = "1.0.101" +optional = true +features = ["derive"] + +[dependencies.sp-std] +default-features = false +git = 'https://github.com/librelois/substrate.git' +branch = 'duniter-monthly-2022-01' + +### DOC ### + +[package.metadata.docs.rs] +targets = ['x86_64-unknown-linux-gnu'] diff --git a/pallets/membership/src/types.rs b/primitives/membership/src/lib.rs similarity index 91% rename from pallets/membership/src/types.rs rename to primitives/membership/src/lib.rs index 5eac495064d28f0bfd3c7bacd9f169d3dfef0590..bae4cf2d8459ace2113225a6f6bff77a8aebb798 100644 --- a/pallets/membership/src/types.rs +++ b/primitives/membership/src/lib.rs @@ -14,7 +14,12 @@ // You should have received a copy of the GNU Affero General Public License // along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>. -//! Various basic types for use in the membership pallet. +//! Defines types and traits for users of pallet membership. + +#![cfg_attr(not(feature = "std"), no_std)] +#![allow(clippy::type_complexity)] + +pub mod traits; use codec::{Decode, Encode}; use frame_support::RuntimeDebug; @@ -24,22 +29,16 @@ use serde::{Deserialize, Serialize}; pub enum Event<IdtyId> { /// A membership has acquired - /// [idty_id] MembershipAcquired(IdtyId), /// A membership has expired - /// [idty_id] MembershipExpired(IdtyId), /// A membership has renewed - /// [idty_id] MembershipRenewed(IdtyId), /// An identity requested membership - /// [idty_id] MembershipRequested(IdtyId), /// A membership has revoked - /// [idty_id] MembershipRevoked(IdtyId), /// A pending membership request has expired - /// [idty_id] PendingMembershipExpired(IdtyId), } diff --git a/pallets/membership/src/traits.rs b/primitives/membership/src/traits.rs similarity index 80% rename from pallets/membership/src/traits.rs rename to primitives/membership/src/traits.rs index c0360b20157f2e9120a49a35d135349749269d7d..580eaa82e35fe0a356eacd0ad1cad54a0ab78a02 100644 --- a/pallets/membership/src/traits.rs +++ b/primitives/membership/src/traits.rs @@ -14,9 +14,8 @@ // You should have received a copy of the GNU Affero General Public License // along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>. -use crate::types::OriginPermission; use crate::*; -use frame_support::pallet_prelude::DispatchResultWithPostInfo; +use frame_support::pallet_prelude::{DispatchResultWithPostInfo, TypeInfo, Weight}; pub trait IsIdtyAllowedToClaimMembership<IdtyId> { fn is_idty_allowed_to_claim_membership(idty_id: &IdtyId) -> bool; @@ -73,11 +72,11 @@ impl<IdtyId> IsMember<IdtyId> for () { } pub trait OnEvent<IdtyId> { - fn on_event(event: crate::types::Event<IdtyId>) -> Weight; + fn on_event(event: crate::Event<IdtyId>) -> Weight; } impl<IdtyId> OnEvent<IdtyId> for () { - fn on_event(_: crate::types::Event<IdtyId>) -> Weight { + fn on_event(_: crate::Event<IdtyId>) -> Weight { 0 } } @@ -92,6 +91,30 @@ pub trait MembershipAction<IdtyId, Origin> { fn force_revoke_membership(idty_id: IdtyId) -> Weight; } +impl<IdtyId, Origin> MembershipAction<IdtyId, Origin> for () { + fn request_membership_(_: Origin, _: IdtyId) -> DispatchResultWithPostInfo { + Ok(().into()) + } + fn claim_membership_(_: Origin, _: IdtyId) -> DispatchResultWithPostInfo { + Ok(().into()) + } + fn renew_membership_(_: Origin, _: IdtyId) -> DispatchResultWithPostInfo { + Ok(().into()) + } + fn revoke_membership_(_: Origin, _: IdtyId) -> DispatchResultWithPostInfo { + Ok(().into()) + } + fn force_claim_membership(_: IdtyId) -> Weight { + 0 + } + fn force_renew_membership(_: IdtyId) -> Weight { + 0 + } + fn force_revoke_membership(_: IdtyId) -> Weight { + 0 + } +} + pub trait MembershipExternalStorage<BlockNumber: Decode + Encode + TypeInfo, IdtyId>: IsMember<IdtyId> { @@ -100,8 +123,6 @@ pub trait MembershipExternalStorage<BlockNumber: Decode + Encode + TypeInfo, Idt fn remove(idty_id: &IdtyId); } -use codec::{Decode, Encode}; -use frame_support::pallet_prelude::TypeInfo; static INVALID_CONF_MSG: &str = "invalid pallet configuration: if `MembershipExternalStorage` = (), you must set `ExternalizeMembershipStorage` to `false`."; impl<BlockNumber: Decode + Encode + TypeInfo, IdtyId> MembershipExternalStorage<BlockNumber, IdtyId> diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index 998747927a1ce6570868db344e3d7beac1d04c13..c1ba7a8676754fe6dac3cd2da4ce2ee738f12335 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -12,6 +12,7 @@ runtime-benchmarks = [ 'frame-system/runtime-benchmarks', 'pallet-certification/runtime-benchmarks', 'pallet-identity/runtime-benchmarks', + 'pallet-membership/runtime-benchmarks', 'pallet-ud-accounts-storage/runtime-benchmarks', 'sp-runtime/runtime-benchmarks', ] @@ -21,6 +22,7 @@ std = [ 'frame-system/std', 'pallet-certification/std', 'pallet-identity/std', + 'pallet-membership/std', 'pallet-ud-accounts-storage/std', 'serde', 'sp-arithmetic/std', @@ -32,6 +34,7 @@ std = [ [dependencies] pallet-certification = { path = '../../pallets/certification', default-features = false } pallet-identity = { path = '../../pallets/identity', default-features = false } +pallet-membership = { path = '../../pallets/membership', default-features = false } pallet-ud-accounts-storage = { path = '../../pallets/ud-accounts-storage', default-features = false } smallvec = "1.6.1" diff --git a/runtime/common/src/authorizations.rs b/runtime/common/src/authorizations.rs index 1c2ef413e85715ab5ed204c81a5219206ed246a8..d5be8c5a9eea64bec9ffe5ff7bea43ea8acc1233 100644 --- a/runtime/common/src/authorizations.rs +++ b/runtime/common/src/authorizations.rs @@ -14,9 +14,8 @@ // You should have received a copy of the GNU Affero General Public License // along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>. -use crate::entities::{IdtyData, IdtyRight}; +use crate::entities::IdtyRight; use crate::{BlockNumber, IdtyIndex}; -use frame_support::pallet_prelude::DispatchError; use frame_support::traits::EnsureOrigin; use pallet_certification::traits::IsIdtyAllowedToCreateCert; use pallet_identity::IdtyStatus; @@ -26,57 +25,13 @@ pub struct EnsureIdtyCallAllowedImpl<Runtime, IsIdtyAllowedToCreateCertImpl>( ); impl< Runtime: frame_system::Config<BlockNumber = BlockNumber> - + pallet_identity::Config< - IdtyData = IdtyData, - IdtyIndex = IdtyIndex, - IdtyRight = IdtyRight, - >, + + pallet_identity::Config<IdtyIndex = IdtyIndex>, IsIdtyAllowedToCreateCertImpl: IsIdtyAllowedToCreateCert<IdtyIndex>, > pallet_identity::traits::EnsureIdtyCallAllowed<Runtime> for EnsureIdtyCallAllowedImpl<Runtime, IsIdtyAllowedToCreateCertImpl> { - fn can_create_identity( - origin: Runtime::Origin, - creator: IdtyIndex, - creator_idty: pallet_identity::IdtyValue< - Runtime::AccountId, - BlockNumber, - IdtyData, - IdtyRight, - >, - _idty_name: &pallet_identity::IdtyName, - _idty_owner_key: &Runtime::AccountId, - ) -> Result<(), DispatchError> { - match origin.into() { - Ok(frame_system::RawOrigin::Root) => Ok(()), - Ok(frame_system::RawOrigin::Signed(signer)) => { - if let Some(authorized_key) = creator_idty.get_right_key(IdtyRight::CreateIdty) { - if signer != authorized_key { - frame_support::runtime_print!("signer != authorized_key"); - Err(DispatchError::Other("signer != authorized_key")) - } else if !IsIdtyAllowedToCreateCertImpl::is_idty_allowed_to_create_cert( - creator, - ) { - frame_support::runtime_print!("not allowed to create cert"); - Err(DispatchError::Other("not allowed to create cert")) - } else if creator_idty.data.can_create_on - > frame_system::Pallet::<Runtime>::block_number() - { - frame_support::runtime_print!("Not respect IdtyCreatePeriod"); - Err(DispatchError::Other("Not respect IdtyCreatePeriod")) - } else { - Ok(()) - } - } else { - frame_support::runtime_print!("Idty not have right CreateIdty"); - Err(DispatchError::Other("Idty not have right CreateIdty")) - } - } - _ => { - frame_support::runtime_print!("Origin neither root or signed"); - Err(DispatchError::Other("Origin neither root or signed")) - } - } + fn can_create_identity(creator: IdtyIndex) -> bool { + IsIdtyAllowedToCreateCertImpl::is_idty_allowed_to_create_cert(creator) } } diff --git a/runtime/common/src/entities.rs b/runtime/common/src/entities.rs index a61f165199b97188b150cebb32238398df484adc..0943cd78f6703da376afa3e6cb23f3fcf5181501 100644 --- a/runtime/common/src/entities.rs +++ b/runtime/common/src/entities.rs @@ -16,7 +16,6 @@ pub use pallet_identity::IdtyName; -use crate::BlockNumber; use frame_support::pallet_prelude::*; use scale_info::TypeInfo; #[cfg(feature = "std")] @@ -48,12 +47,6 @@ impl pallet_identity::traits::IdtyRight for IdtyRight { } } -#[cfg_attr(feature = "std", derive(Deserialize, Serialize))] -#[derive(Encode, Decode, Default, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)] -pub struct IdtyData { - pub can_create_on: BlockNumber, -} - #[cfg_attr(feature = "std", derive(Deserialize, Serialize))] #[derive( Encode, Decode, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, TypeInfo, diff --git a/runtime/common/src/pallets_config.rs b/runtime/common/src/pallets_config.rs index 3bb3e44fd4f473ca89e482368483732d0859d0fb..7113df7e006c9b73a6848e2ae8cb93efc235c686 100644 --- a/runtime/common/src/pallets_config.rs +++ b/runtime/common/src/pallets_config.rs @@ -191,20 +191,34 @@ macro_rules! pallets_config { type DelRightOrigin = EnsureRoot<Self::AccountId>; type EnsureIdtyCallAllowed = EnsureIdtyCallAllowedImpl<Runtime, StrongCert>; type IdtyCreationPeriod = IdtyCreationPeriod; - type IdtyDataProvider = IdtyDataProvider<Runtime, IDTY_CREATE_PERIOD>; - type IdtyData = IdtyData; + type IdtyDataProvider = (); + type IdtyData = (); type IdtyNameValidator = IdtyNameValidatorImpl; type IdtyIndex = IdtyIndex; type IdtyValidationOrigin = EnsureRoot<Self::AccountId>; type IdtyRight = IdtyRight; type OnIdtyChange = OnIdtyChangeHandler<Runtime>; type OnRightKeyChange = OnRightKeyChangeHandler<Runtime>; - type MaxInactivityPeriod = MaxInactivityPeriod; type MaxNoRightPeriod = MaxNoRightPeriod; - type RenewablePeriod = IdtyRenewablePeriod; - type ValidationPeriod = ValidationPeriod; + type Membership = Membership; } + impl pallet_membership::Config<frame_support::instances::Instance1> for Runtime { + type IsIdtyAllowedToClaimMembership = (); + type IsIdtyAllowedToRenewMembership = (); + type IsIdtyAllowedToRequestMembership = (); + type IsOriginAllowedToUseIdty = Identity; + type Event = Event; + type ExternalizeMembershipStorage = frame_support::traits::ConstBool<false>; + type IdtyId = IdtyIndex; + type OnEvent = Identity; + type MembershipExternalStorage = (); + type MembershipPeriod = MembershipPeriod; + type PendingMembershipPeriod = PendingMembershipPeriod; + type RenewablePeriod = RenewablePeriod; + type RevocationPeriod = frame_support::traits::ConstU32<0>; + } + impl pallet_certification::Config<frame_support::instances::Instance1> for Runtime { type AddCertOrigin = AddStrongCertOrigin<Runtime>; type CertPeriod = CertPeriod; diff --git a/runtime/common/src/providers.rs b/runtime/common/src/providers.rs index a48d9782e4d7af6349c952d6810ce093eb4791ea..1f49810e9455fefa28402692790c9259812d7f49 100644 --- a/runtime/common/src/providers.rs +++ b/runtime/common/src/providers.rs @@ -14,35 +14,10 @@ // You should have received a copy of the GNU Affero General Public License // along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>. -use crate::entities::IdtyData; -use crate::{AccountId, BlockNumber, IdtyIndex}; +use crate::AccountId; use frame_support::traits::Get; use sp_std::vec::Vec; -pub struct IdtyDataProvider<Runtime, const IDTY_CREATE_PERIOD: BlockNumber>( - core::marker::PhantomData<Runtime>, -); -impl<Runtime, const IDTY_CREATE_PERIOD: BlockNumber> - pallet_identity::traits::ProvideIdtyData<Runtime> - for IdtyDataProvider<Runtime, IDTY_CREATE_PERIOD> -where - Runtime: frame_system::Config<AccountId = AccountId, BlockNumber = BlockNumber> - + pallet_identity::Config<IdtyData = IdtyData, IdtyIndex = IdtyIndex>, -{ - fn provide_identity_data( - creator: IdtyIndex, - _idty_name: &pallet_identity::IdtyName, - _idty_owner_key: &AccountId, - ) -> IdtyData { - let block_number = frame_system::Pallet::<Runtime>::block_number(); - let creator_idty_data = IdtyData { - can_create_on: block_number + IDTY_CREATE_PERIOD, - }; - pallet_identity::Pallet::<Runtime>::set_idty_data(creator, creator_idty_data); - Default::default() - } -} - pub struct UdAccountsProvider<Runtime>(core::marker::PhantomData<Runtime>); impl<Runtime: pallet_ud_accounts_storage::Config> Get<u64> for UdAccountsProvider<Runtime> { fn get() -> u64 { diff --git a/runtime/g1/Cargo.toml b/runtime/g1/Cargo.toml index 6046607d31e72ac7cbffde8a15cea9e3a2a5825a..53fe0a7647f8fa129bf36310a21f8fdc303e1aec 100644 --- a/runtime/g1/Cargo.toml +++ b/runtime/g1/Cargo.toml @@ -39,6 +39,7 @@ std = [ 'pallet-grandpa/std', 'pallet-identity/std', 'pallet-im-online/std', + 'pallet-membership/std', 'pallet-multisig/std', 'pallet-session/std', 'pallet-sudo/std', @@ -67,6 +68,7 @@ std = [ [dependencies] pallet-certification = { path = '../../pallets/certification', default-features = false } pallet-identity = { path = '../../pallets/identity', default-features = false } +pallet-membership = { path = '../../pallets/membership', default-features = false } pallet-ud-accounts-storage = { path = '../../pallets/ud-accounts-storage', default-features = false } pallet-universal-dividend = { path = '../../pallets/universal-dividend', default-features = false } common-runtime = { path = "../common", default-features = false } diff --git a/runtime/g1/src/lib.rs b/runtime/g1/src/lib.rs index 5a1a9024cbe2a345276030e8b330f09814f74a19..6d5d6ec90c2addd7a304ea7d8e48766dfad223bd 100644 --- a/runtime/g1/src/lib.rs +++ b/runtime/g1/src/lib.rs @@ -27,7 +27,7 @@ pub mod parameters; pub use self::parameters::*; pub use common_runtime::{ constants::*, - entities::{IdtyData, IdtyRight, ValidatorFullIdentification}, + entities::{IdtyRight, ValidatorFullIdentification}, AccountId, Address, Balance, BlockNumber, FullIdentificationOfImpl, Hash, Header, IdtyIndex, IdtyNameValidatorImpl, Index, Signature, }; @@ -48,7 +48,6 @@ use common_runtime::{ OnIdtyChangeHandler, OnNewStrongCertHandler, OnRemovedStrongCertHandler, OnRightKeyChangeHandler, }, - providers::IdtyDataProvider, SessionManagerImpl, }; use frame_system::EnsureRoot; @@ -189,7 +188,8 @@ construct_runtime!( // Web Of Trust Identity: pallet_identity::{Pallet, Call, Config<T>, Storage, Event<T>} = 50, - StrongCert: pallet_certification::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>} = 51, + Membership: pallet_membership::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>} = 51, + StrongCert: pallet_certification::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>} = 52, // Multisig dispatch. Multisig: pallet_multisig::{Pallet, Call, Storage, Event<T>} = 60, diff --git a/runtime/g1/src/parameters.rs b/runtime/g1/src/parameters.rs index 2a1eea4d603c738bf5a414fe8847b43737bfe8de..5e334ce48cf1c1f04afbde88e25d7dba2dc6c7d3 100644 --- a/runtime/g1/src/parameters.rs +++ b/runtime/g1/src/parameters.rs @@ -94,16 +94,21 @@ parameter_types! { // Identity pub const IDTY_CREATE_PERIOD: BlockNumber = 100; -frame_support::parameter_types! { +parameter_types! { pub const ConfirmPeriod: BlockNumber = 14 * DAYS; pub const FirstIssuableOn: BlockNumber = 30* DAYS; pub const IdtyCreationPeriod: BlockNumber = MONTHS; - pub const IdtyRenewablePeriod: BlockNumber = 6 * MONTHS; - pub const MaxInactivityPeriod: BlockNumber = YEARS; pub const MaxNoRightPeriod: BlockNumber = YEARS; pub const ValidationPeriod: BlockNumber = YEARS; } +// Membership +parameter_types! { + pub const MembershipPeriod: BlockNumber = YEARS; + pub const PendingMembershipPeriod: BlockNumber = 2 * MONTHS; + pub const RenewablePeriod: BlockNumber = 2 * MONTHS; +} + // Certification pub const MIN_STRONG_CERT_FOR_UD: u32 = 5; pub const MIN_STRONG_CERT_FOR_STRONG_CERT: u32 = 5; diff --git a/runtime/gdev/Cargo.toml b/runtime/gdev/Cargo.toml index d8d6ce509e25a1364669b0fde09cb261251b51b3..0578b60d7dd22b8195ab74da1ed56bc50b00efde 100644 --- a/runtime/gdev/Cargo.toml +++ b/runtime/gdev/Cargo.toml @@ -37,6 +37,7 @@ std = [ 'pallet-balances/std', 'pallet-certification/std', 'pallet-identity/std', + 'pallet-membership/std', 'pallet-grandpa/std', 'pallet-multisig/std', 'pallet-sudo/std', @@ -63,6 +64,7 @@ std = [ [dependencies] pallet-certification = { path = '../../pallets/certification', default-features = false } pallet-identity = { path = '../../pallets/identity', default-features = false } +pallet-membership = { path = '../../pallets/membership', default-features = false } pallet-ud-accounts-storage = { path = '../../pallets/ud-accounts-storage', default-features = false } pallet-universal-dividend = { path = '../../pallets/universal-dividend', default-features = false } common-runtime = { path = "../common", default-features = false } diff --git a/runtime/gdev/src/lib.rs b/runtime/gdev/src/lib.rs index e450fb271b12ebb628fa6622b5932ecfbd820318..a804a418796abe6e9b56663a9738a471b90253af 100644 --- a/runtime/gdev/src/lib.rs +++ b/runtime/gdev/src/lib.rs @@ -26,10 +26,8 @@ pub mod parameters; pub use self::parameters::*; pub use common_runtime::{ - constants::*, - entities::{IdtyData, IdtyRight}, - AccountId, Address, Balance, BlockNumber, Hash, Header, IdtyIndex, IdtyNameValidatorImpl, - Index, Signature, + constants::*, entities::IdtyRight, AccountId, Address, Balance, BlockNumber, Hash, Header, + IdtyIndex, IdtyNameValidatorImpl, Index, Signature, }; pub use pallet_balances::Call as BalancesCall; pub use pallet_identity::{IdtyStatus, IdtyValue}; @@ -45,7 +43,6 @@ use common_runtime::{ OnIdtyChangeHandler, OnNewStrongCertHandler, OnRemovedStrongCertHandler, OnRightKeyChangeHandler, }, - providers::IdtyDataProvider, }; use frame_system::EnsureRoot; use pallet_grandpa::fg_primitives; @@ -172,7 +169,8 @@ construct_runtime!( // Web Of Trust Identity: pallet_identity::{Pallet, Call, Config<T>, Storage, Event<T>} = 50, - StrongCert: pallet_certification::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>} = 51, + Membership: pallet_membership::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>} = 51, + StrongCert: pallet_certification::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>} = 52, // Multisig dispatch. Multisig: pallet_multisig::{Pallet, Call, Storage, Event<T>} = 60, diff --git a/runtime/gdev/src/parameters.rs b/runtime/gdev/src/parameters.rs index e51875d38cb65d46c4c061f85db72302d8e89080..b6a1697f9c24855547805acb35a0b1ad3bf5607e 100644 --- a/runtime/gdev/src/parameters.rs +++ b/runtime/gdev/src/parameters.rs @@ -52,10 +52,14 @@ frame_support::parameter_types! { pub const ConfirmPeriod: BlockNumber = 40; pub const FirstIssuableOn: BlockNumber = 20; pub const IdtyCreationPeriod: BlockNumber = 50; - pub const IdtyRenewablePeriod: BlockNumber = 50; - pub const MaxInactivityPeriod: BlockNumber = 1_000; pub const MaxNoRightPeriod: BlockNumber = 1_000; - pub const ValidationPeriod: BlockNumber = 500; +} + +// Membership +parameter_types! { + pub const MembershipPeriod: BlockNumber = 1_000; + pub const PendingMembershipPeriod: BlockNumber = 500; + pub const RenewablePeriod: BlockNumber = 50; } // Certification diff --git a/runtime/gtest/Cargo.toml b/runtime/gtest/Cargo.toml index 707a56c0a790663c15b15782ca358b3ebb584b23..3109fb572b38e0ff790ab75ca222143679c22977 100644 --- a/runtime/gtest/Cargo.toml +++ b/runtime/gtest/Cargo.toml @@ -38,6 +38,7 @@ std = [ 'pallet-certification/std', 'pallet-grandpa/std', 'pallet-identity/std', + 'pallet-membership/std', 'pallet-im-online/std', 'pallet-multisig/std', 'pallet-session/std', @@ -67,6 +68,7 @@ std = [ [dependencies] pallet-certification = { path = '../../pallets/certification', default-features = false } pallet-identity = { path = '../../pallets/identity', default-features = false } +pallet-membership = { path = '../../pallets/membership', default-features = false } pallet-ud-accounts-storage = { path = '../../pallets/ud-accounts-storage', default-features = false } pallet-universal-dividend = { path = '../../pallets/universal-dividend', default-features = false } common-runtime = { path = "../common", default-features = false } diff --git a/runtime/gtest/src/lib.rs b/runtime/gtest/src/lib.rs index d3b0d711e3382f068b82a0ab582200423ca07556..e838a8127906b0e189a46e92c84600a6e2d0dace 100644 --- a/runtime/gtest/src/lib.rs +++ b/runtime/gtest/src/lib.rs @@ -27,7 +27,7 @@ pub mod parameters; pub use self::parameters::*; pub use common_runtime::{ constants::*, - entities::{IdtyData, IdtyRight, ValidatorFullIdentification}, + entities::{IdtyRight, ValidatorFullIdentification}, AccountId, Address, Balance, BlockNumber, FullIdentificationOfImpl, Hash, Header, IdtyIndex, IdtyNameValidatorImpl, Index, Signature, }; @@ -48,7 +48,6 @@ use common_runtime::{ OnIdtyChangeHandler, OnNewStrongCertHandler, OnRemovedStrongCertHandler, OnRightKeyChangeHandler, }, - providers::IdtyDataProvider, SessionManagerImpl, }; use frame_system::EnsureRoot; @@ -189,7 +188,8 @@ construct_runtime!( // Web Of Trust Identity: pallet_identity::{Pallet, Call, Config<T>, Storage, Event<T>} = 50, - StrongCert: pallet_certification::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>} = 51, + Membership: pallet_membership::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>} = 51, + StrongCert: pallet_certification::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>} = 52, // Multisig dispatch. Multisig: pallet_multisig::{Pallet, Call, Storage, Event<T>} = 60, diff --git a/runtime/gtest/src/parameters.rs b/runtime/gtest/src/parameters.rs index 44f287dfde8ef904b62b7c55c8f459b18eb9f7b3..ed4ca96bd7472e4511d8bb33f5350d7758377f65 100644 --- a/runtime/gtest/src/parameters.rs +++ b/runtime/gtest/src/parameters.rs @@ -97,10 +97,14 @@ frame_support::parameter_types! { pub const ConfirmPeriod: BlockNumber = 8 * HOURS; pub const FirstIssuableOn: BlockNumber = DAYS; pub const IdtyCreationPeriod: BlockNumber = DAYS; - pub const IdtyRenewablePeriod: BlockNumber = 12 * DAYS; - pub const MaxInactivityPeriod: BlockNumber = 73 * DAYS; pub const MaxNoRightPeriod: BlockNumber = 73 * DAYS; - pub const ValidationPeriod: BlockNumber = 73 * DAYS; +} + +// Membership +parameter_types! { + pub const MembershipPeriod: BlockNumber = 73 * DAYS; + pub const PendingMembershipPeriod: BlockNumber = 12 * DAYS; + pub const RenewablePeriod: BlockNumber = 12 * DAYS; } // Certification