From a998d76e14e06ce35d70432ec8ae564bd89b9a2a Mon Sep 17 00:00:00 2001 From: librelois <c@elo.tf> Date: Fri, 14 Jan 2022 20:57:07 +0100 Subject: [PATCH] feat(certs): allow to config certs expire_on at genesis --- Cargo.lock | 1 + node/Cargo.toml | 1 + node/src/chain_spec.rs | 15 ++++-- node/src/chain_spec/gdev.rs | 5 +- node/src/chain_spec/gtest.rs | 10 +++- pallets/certification/src/lib.rs | 53 +++++++++++++------ pallets/certification/src/tests.rs | 83 ++++++++++++++++++++++++++++-- runtime/g1/src/lib.rs | 2 +- runtime/gdev/src/lib.rs | 2 +- runtime/gtest/src/lib.rs | 2 +- 10 files changed, 145 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6b082ab8c..62bfb7f2e 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 199ad31b1..1df3d4884 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 b43a09720..e160f97c7 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 e8f19d276..33f4294bd 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 95c58d6bb..f509baa06 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 85abc2f3b..e34885898 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 72017eebb..c04490749 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 ae5cdce9a..822b91855 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 e1cefe206..badbc7991 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 b7b390040..d1d02aa77 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::{ -- GitLab