diff --git a/Cargo.lock b/Cargo.lock index 6b082ab8c3aafdbdad92ea086e67e4a17c3bfb0d..62bfb7f2eb603a413c376f094c5e68a37ce1a956 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1403,6 +1403,7 @@ dependencies = [ "jsonrpc-core", "log", "maplit", + "pallet-certification", "pallet-grandpa", "pallet-transaction-payment-rpc", "pallet-transaction-payment-rpc-runtime-api", diff --git a/node/Cargo.toml b/node/Cargo.toml index 199ad31b104e2452bd5d3b493f528e8faf48f04e..1df3d4884aafe6de654216664a5a8cf2a91b6533 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -31,6 +31,7 @@ common-runtime = { path = '../runtime/common' } g1-runtime = { path = '../runtime/g1' } gdev-runtime = { path = '../runtime/gdev' } gtest-runtime = { path = '../runtime/gtest' } +pallet-certification = { path = '../pallets/certification' } # crates.io dependencies async-io = "1.3" diff --git a/node/src/chain_spec.rs b/node/src/chain_spec.rs index b43a097208f1a23730fd426eb15a271f93f8907e..e160f97c782cdd140814c9b6d3ac0bafc1bdcf22 100644 --- a/node/src/chain_spec.rs +++ b/node/src/chain_spec.rs @@ -22,7 +22,7 @@ use common_runtime::IdtyIndex; use common_runtime::{entities::IdtyName, AccountId, Signature}; use sp_core::{Pair, Public}; use sp_runtime::traits::{IdentifyAccount, Verify}; -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::BTreeMap; pub type AccountPublic = <Signature as Verify>::Signer; @@ -49,13 +49,22 @@ where AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account() } -fn clique_wot(initial_identities_len: usize) -> BTreeMap<IdtyIndex, BTreeSet<IdtyIndex>> { +fn clique_wot( + initial_identities_len: usize, + cert_validity_period: common_runtime::BlockNumber, +) -> BTreeMap<IdtyIndex, BTreeMap<IdtyIndex, common_runtime::BlockNumber>> { let mut certs_by_issuer = BTreeMap::new(); for i in 1..=initial_identities_len { certs_by_issuer.insert( i as IdtyIndex, (1..=initial_identities_len) - .filter_map(|j| if i != j { Some(j as IdtyIndex) } else { None }) + .filter_map(|j| { + if i != j { + Some((j as IdtyIndex, cert_validity_period)) + } else { + None + } + }) .collect(), ); } diff --git a/node/src/chain_spec/gdev.rs b/node/src/chain_spec/gdev.rs index e8f19d2761f70d06fb3dd3ea7e8037a0249abacf..33f4294bd59046874f77185ac939c88b744f0702 100644 --- a/node/src/chain_spec/gdev.rs +++ b/node/src/chain_spec/gdev.rs @@ -133,7 +133,10 @@ fn devnet_genesis( .collect(), }, strong_cert: StrongCertConfig { - certs_by_issuer: clique_wot(initial_identities.len()), + certs_by_issuer: clique_wot( + initial_identities.len(), + gdev_runtime::parameters::ValidityPeriod::get(), + ), phantom: std::marker::PhantomData, }, ud_accounts_storage: UdAccountsStorageConfig { diff --git a/node/src/chain_spec/gtest.rs b/node/src/chain_spec/gtest.rs index 95c58d6bb22f7066266a786d331365fa6c3c790e..f509baa06e2aa90c5e93d63fc0f89bca92ba7665 100644 --- a/node/src/chain_spec/gtest.rs +++ b/node/src/chain_spec/gtest.rs @@ -187,7 +187,10 @@ fn devnet_genesis( .collect(), }, strong_cert: StrongCertConfig { - certs_by_issuer: clique_wot(initial_identities.len()), + certs_by_issuer: clique_wot( + initial_identities.len(), + gtest_runtime::parameters::ValidityPeriod::get(), + ), phantom: std::marker::PhantomData, }, ud_accounts_storage: UdAccountsStorageConfig { @@ -249,7 +252,10 @@ fn testnet_genesis( .collect(), }, strong_cert: StrongCertConfig { - certs_by_issuer: clique_wot(initial_identities.len()), + certs_by_issuer: clique_wot( + initial_identities.len(), + gdev_runtime::parameters::ValidityPeriod::get(), + ), phantom: std::marker::PhantomData, }, ud_accounts_storage: UdAccountsStorageConfig { diff --git a/pallets/certification/src/lib.rs b/pallets/certification/src/lib.rs index 85abc2f3b99e97d3caad459903b59f945760fae8..e3488589856867d71f45da02d27c11c72c583282 100644 --- a/pallets/certification/src/lib.rs +++ b/pallets/certification/src/lib.rs @@ -39,7 +39,7 @@ pub mod pallet { use super::*; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; - use sp_std::collections::{btree_map::BTreeMap, btree_set::BTreeSet}; + use sp_std::collections::btree_map::BTreeMap; /// The current storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); @@ -87,7 +87,7 @@ pub mod pallet { #[pallet::genesis_config] pub struct GenesisConfig<T: Config<I>, I: 'static = ()> { - pub certs_by_issuer: BTreeMap<T::IdtyIndex, BTreeSet<T::IdtyIndex>>, + pub certs_by_issuer: BTreeMap<T::IdtyIndex, BTreeMap<T::IdtyIndex, T::BlockNumber>>, pub phantom: PhantomData<I>, } @@ -109,7 +109,7 @@ pub mod pallet { let mut certs_by_receiver = BTreeMap::<T::IdtyIndex, Vec<T::IdtyIndex>>::new(); for (issuer, receivers) in &self.certs_by_issuer { assert!( - !receivers.contains(issuer), + !receivers.contains_key(issuer), "Identity cannot certify it-self." ); assert!( @@ -122,11 +122,11 @@ pub mod pallet { *issuer, IdtyCertMeta { issued_count: receivers.len() as u8, - next_issuable_on: T::CertPeriod::get(), + next_issuable_on: sp_runtime::traits::Zero::zero(), received_count: 0, }, ); - for receiver in receivers { + for receiver in receivers.keys() { certs_by_receiver .entry(*receiver) .or_default() @@ -142,26 +142,47 @@ pub mod pallet { issuers.sort(); <StorageCertsByReceiver<T, I>>::insert(receiver, issuers); } - // Write StorageIdtyCertMeta - for (issuer, cert_meta) in cert_meta_by_issuer { - <StorageIdtyCertMeta<T, I>>::insert(issuer, cert_meta); - } - // Write StorageCertsByIssuer && StorageCertsRemovableOn - let mut all_couples = Vec::new(); + // Write StorageCertsByIssuer + let mut certs_removable_on = + BTreeMap::<T::BlockNumber, Vec<(T::IdtyIndex, T::IdtyIndex)>>::new(); for (issuer, receivers) in &self.certs_by_issuer { - for receiver in receivers { - all_couples.push((*issuer, *receiver)); + for (receiver, removable_on) in receivers { + certs_removable_on + .entry(*removable_on) + .or_default() + .push((*issuer, *receiver)); + + use sp_runtime::traits::Saturating as _; + let issuer_next_issuable_on = removable_on + .saturating_add(T::CertPeriod::get()) + .saturating_sub(T::ValidityPeriod::get()); + if let Some(cert_meta) = cert_meta_by_issuer.get_mut(issuer) { + if cert_meta.next_issuable_on < issuer_next_issuable_on { + cert_meta.next_issuable_on = issuer_next_issuable_on; + } + } + let renewable_on = removable_on.saturating_sub( + T::ValidityPeriod::get().saturating_sub(T::CertRenewablePeriod::get()), + ); + <StorageCertsByIssuer<T, I>>::insert( issuer, receiver, CertValue { - renewable_on: T::CertRenewablePeriod::get(), - removable_on: T::ValidityPeriod::get(), + renewable_on, + removable_on: *removable_on, }, ); } } - <StorageCertsRemovableOn<T, I>>::insert(T::ValidityPeriod::get(), all_couples); + // Write StorageIdtyCertMeta + for (issuer, cert_meta) in cert_meta_by_issuer { + <StorageIdtyCertMeta<T, I>>::insert(issuer, cert_meta); + } + // Write storage StorageCertsRemovableOn + for (removable_on, certs) in certs_removable_on { + <StorageCertsRemovableOn<T, I>>::insert(removable_on, certs); + } } } diff --git a/pallets/certification/src/tests.rs b/pallets/certification/src/tests.rs index 72017eebbca868ebadac330d6a5f5976bd8f8a06..c044907491ccd2c6803d488803425a1ffaca0ca6 100644 --- a/pallets/certification/src/tests.rs +++ b/pallets/certification/src/tests.rs @@ -14,11 +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/>. +use crate::mock::Event as RuntimeEvent; use crate::mock::*; -use crate::Error; +use crate::{Error, Event}; use frame_support::assert_ok; //use frame_system::{EventRecord, Phase}; -use maplit::{btreemap, btreeset}; +use maplit::btreemap; use sp_std::collections::btree_map::BTreeMap; #[test] @@ -35,10 +36,84 @@ fn test_must_receive_cert_before_can_issue() { }); } +#[test] +fn test_genesis_build() { + new_test_ext(DefaultCertificationConfig { + certs_by_issuer: btreemap![ + 0 => btreemap![ + 1 => 10, + 2 => 5, + ], + 1 => btreemap![ + 0 => 7, + 2 => 4, + ], + 2 => btreemap![ + 0 => 9, + 1 => 3, + ], + ], + phantom: core::marker::PhantomData, + }) + .execute_with(|| { + run_to_block(1); + // Verify state of idty 0 + assert_eq!( + DefaultCertification::idty_cert_meta(0), + Some(crate::IdtyCertMeta { + issued_count: 2, + next_issuable_on: 2, + received_count: 2, + }) + ); + // Verify state of idty 1 + assert_eq!( + DefaultCertification::idty_cert_meta(1), + Some(crate::IdtyCertMeta { + issued_count: 2, + next_issuable_on: 0, + received_count: 2, + }) + ); + // Verify state of idty 2 + assert_eq!( + DefaultCertification::idty_cert_meta(2), + Some(crate::IdtyCertMeta { + issued_count: 2, + next_issuable_on: 1, + received_count: 2, + }) + ); + // Cert 2->1 must be removable at block #3 + assert_eq!( + DefaultCertification::certs_removable_on(3), + Some(vec![(2, 1)]), + ); + // Cert 2->0 cannot be renewed before #5 + assert_eq!( + DefaultCertification::add_cert(Origin::root(), 2, 0), + Err(Error::<Test, _>::NotRespectRenewablePeriod.into()) + ); + + run_to_block(3); + // Cert 2->1 must have expired + assert_eq!( + System::events()[0].event, + RuntimeEvent::DefaultCertification(Event::RemovedCert { + issuer: 2, + issuer_issued_count: 1, + receiver: 1, + receiver_received_count: 1, + expiration: true, + },) + ); + }); +} + #[test] fn test_cert_period() { new_test_ext(DefaultCertificationConfig { - certs_by_issuer: btreemap![0 => btreeset![1]], + certs_by_issuer: btreemap![0 => btreemap![1 => 10]], phantom: core::marker::PhantomData, }) .execute_with(|| { @@ -61,7 +136,7 @@ fn test_cert_period() { #[test] fn test_renewable_period() { new_test_ext(DefaultCertificationConfig { - certs_by_issuer: btreemap![0 => btreeset![1]], + certs_by_issuer: btreemap![0 => btreemap![1 => 10]], phantom: core::marker::PhantomData, }) .execute_with(|| { diff --git a/runtime/g1/src/lib.rs b/runtime/g1/src/lib.rs index ae5cdce9adbdcaab40fafa6f1ae00f7b97a9ed88..822b91855b8afbe5077a02860c8f209bc7dde992 100644 --- a/runtime/g1/src/lib.rs +++ b/runtime/g1/src/lib.rs @@ -22,7 +22,7 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -mod parameters; +pub mod parameters; pub use self::parameters::*; pub use common_runtime::{ diff --git a/runtime/gdev/src/lib.rs b/runtime/gdev/src/lib.rs index e1cefe2068383165ca2108dd0c24c6d133ab5b4d..badbc7991bc3e390aac401688312578e5d98f152 100644 --- a/runtime/gdev/src/lib.rs +++ b/runtime/gdev/src/lib.rs @@ -22,7 +22,7 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -mod parameters; +pub mod parameters; pub use self::parameters::*; pub use common_runtime::{ diff --git a/runtime/gtest/src/lib.rs b/runtime/gtest/src/lib.rs index b7b3900403a90c3e68fd4684c66633e93f7f4172..d1d02aa77e2221b518d12ecfc07ecb3dfa34ce37 100644 --- a/runtime/gtest/src/lib.rs +++ b/runtime/gtest/src/lib.rs @@ -22,7 +22,7 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -mod parameters; +pub mod parameters; pub use self::parameters::*; pub use common_runtime::{