From 373fe27566818085940fafeefbf211772547ab95 Mon Sep 17 00:00:00 2001 From: cgeek <cem.moreau@gmail.com> Date: Thu, 22 Jun 2023 13:01:30 +0200 Subject: [PATCH] wip: compilation ok --- end2end-tests/tests/common/distance.rs | 2 +- pallets/distance/src/lib.rs | 207 +++++++++++-------- pallets/distance/src/mock.rs | 272 +++++++++++++++++++++++++ pallets/distance/src/tests.rs | 30 +++ pallets/distance/src/types.rs | 9 +- 5 files changed, 430 insertions(+), 90 deletions(-) create mode 100644 pallets/distance/src/mock.rs create mode 100644 pallets/distance/src/tests.rs diff --git a/end2end-tests/tests/common/distance.rs b/end2end-tests/tests/common/distance.rs index 6c792700d..ecf58a070 100644 --- a/end2end-tests/tests/common/distance.rs +++ b/end2end-tests/tests/common/distance.rs @@ -29,7 +29,7 @@ pub async fn request_evaluation(client: &Client, from: AccountKeyring, to: u32) client .tx() .create_signed( - &gdev::tx().distance().evaluate_distance(to), + &gdev::tx().distance().evaluate_distance(), &from, BaseExtrinsicParamsBuilder::new(), ) diff --git a/pallets/distance/src/lib.rs b/pallets/distance/src/lib.rs index 09c38cbb2..ff7816604 100644 --- a/pallets/distance/src/lib.rs +++ b/pallets/distance/src/lib.rs @@ -20,6 +20,12 @@ mod median; mod traits; mod types; +#[cfg(test)] +mod tests; + +#[cfg(test)] +mod mock; + use median::*; pub use pallet::*; pub use traits::*; @@ -32,7 +38,7 @@ use sp_distance::{InherentError, INHERENT_IDENTIFIER}; use sp_inherents::{InherentData, InherentIdentifier}; use sp_std::convert::TryInto; -type IdtyIndex = u32; +type IdtyIndex = u64; #[frame_support::pallet] pub mod pallet { @@ -40,6 +46,7 @@ pub mod pallet { use frame_support::{pallet_prelude::*, traits::ReservableCurrency, BoundedBTreeSet}; use frame_system::pallet_prelude::*; use sp_runtime::Perbill; + use std::collections::BTreeMap; /// The current storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); @@ -53,10 +60,13 @@ pub mod pallet { pub trait Config<I: 'static = ()>: frame_system::Config + pallet_authorship::Config - + pallet_certification::Config<I, IdtyIndex = IdtyIndex> + // + pallet_certification::Config<I, IdtyIndex = IdtyIndex> + pallet_identity::Config<IdtyIndex = IdtyIndex> - + pallet_session::Config + // + pallet_session::Config { + /// Because this pallet emits events, it depends on the runtime's definition of an event. + type RuntimeEvent: From<Event<Self, I>> + + IsType<<Self as frame_system::Config>::RuntimeEvent>; type Currency: ReservableCurrency<Self::AccountId>; /// Amount reserved during evaluation #[pallet::constant] @@ -81,7 +91,7 @@ pub mod pallet { _, EvaluationPool< <T as frame_system::Config>::AccountId, - <T as pallet_certification::Config<I>>::IdtyIndex, + // <T as pallet_certification::Config<I>>::IdtyIndex, <T as Config<I>>::MaxEvaluationsPerSession, <T as Config<I>>::MaxEvaluatorsPerSession, >, @@ -93,7 +103,7 @@ pub mod pallet { _, EvaluationPool< <T as frame_system::Config>::AccountId, - <T as pallet_certification::Config<I>>::IdtyIndex, + // <T as pallet_certification::Config<I>>::IdtyIndex, <T as Config<I>>::MaxEvaluationsPerSession, <T as Config<I>>::MaxEvaluatorsPerSession, >, @@ -105,7 +115,7 @@ pub mod pallet { _, EvaluationPool< <T as frame_system::Config>::AccountId, - <T as pallet_certification::Config<I>>::IdtyIndex, + // <T as pallet_certification::Config<I>>::IdtyIndex, <T as Config<I>>::MaxEvaluationsPerSession, <T as Config<I>>::MaxEvaluatorsPerSession, >, @@ -119,13 +129,8 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn distance_ok_identities)] - pub type IdentitiesDistanceStatus<T: Config<I>, I: 'static = ()> = StorageMap< - _, - Twox64Concat, - <T as pallet_certification::Config<I>>::IdtyIndex, - DistanceStatus, - OptionQuery, - >; + pub type IdentitiesDistanceStatus<T: Config<I>, I: 'static = ()> = + StorageMap<_, Twox64Concat, u64, DistanceStatus, OptionQuery>; /// Did evaluation get updated in this block? #[pallet::storage] @@ -137,6 +142,13 @@ pub mod pallet { // storage_id + 2 => receives new identities // (this avoids problems for session_index < 3) + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event<T: Config<I>, I: 'static = ()> { + /// TODO: define + EvalutionSuccess, + } + // ERRORS // #[pallet::error] @@ -171,6 +183,24 @@ pub mod pallet { } } + #[pallet::genesis_config] + #[allow(clippy::type_complexity)] + pub struct GenesisConfig<T: Config<I>, I: 'static = ()>(PhantomData<(T, I)>); + + #[cfg(feature = "std")] + impl<T: Config<I>, I: 'static> Default for GenesisConfig<T, I> { + fn default() -> Self { + Self { + 0: Default::default(), + } + } + } + + #[pallet::genesis_build] + impl<T: Config<I>, I: 'static> GenesisBuild<T, I> for GenesisConfig<T, I> { + fn build(&self) {} + } + // CALLS // #[pallet::call] @@ -203,37 +233,38 @@ pub mod pallet { !DidUpdate::<T, I>::exists(), Error::<T, I>::ManyEvaluationsInBlock, ); - - Pallet::<T, I>::mutate_current_pool( - pallet_session::CurrentIndex::<T>::get().wrapping_add(1), - |result_pool| { - ensure!( - computation_result.distances.len() == result_pool.0.len(), - Error::<T, I>::WrongResultLength - ); - - let author = - pallet_authorship::Pallet::<T>::author().ok_or(Error::<T, I>::NoAuthor)?; - - if result_pool - .1 - .try_insert(author) - .map_err(|_| Error::<T, I>::TooManyEvaluators)? - { - for (distance_value, (_identity, median_acc)) in computation_result - .distances - .into_iter() - .zip(result_pool.0.iter_mut()) - { - median_acc.push(distance_value); - } - - Ok(()) - } else { - Err(Error::<T, I>::ManyEvaluationsByAuthor.into()) - } - }, - ) + Ok(()) + + // Pallet::<T, I>::mutate_current_pool( + // pallet_session::CurrentIndex::<T>::get().wrapping_add(1), + // |result_pool| { + // ensure!( + // computation_result.distances.len() == result_pool.0.len(), + // Error::<T, I>::WrongResultLength + // ); + // + // let author = + // pallet_authorship::Pallet::<T>::author().ok_or(Error::<T, I>::NoAuthor)?; + // + // if result_pool + // .1 + // .try_insert(author) + // .map_err(|_| Error::<T, I>::TooManyEvaluators)? + // { + // for (distance_value, (_identity, median_acc)) in computation_result + // .distances + // .into_iter() + // .zip(result_pool.0.iter_mut()) + // { + // median_acc.push(distance_value); + // } + // + // Ok(()) + // } else { + // Err(Error::<T, I>::ManyEvaluationsByAuthor.into()) + // } + // }, + // ) } } @@ -242,27 +273,29 @@ pub mod pallet { impl<T: Config<I>, I: 'static> Pallet<T, I> { pub fn do_evaluate_distance( who: T::AccountId, - idty_index: <T as pallet_certification::Config<I>>::IdtyIndex, + idty_index: u64, + // idty_index: <T as pallet_certification::Config<I>>::IdtyIndex, ) -> Result<(), DispatchError> { - Pallet::<T, I>::mutate_current_pool( - pallet_session::CurrentIndex::<T>::get(), - |current_pool| { - ensure!( - current_pool.0.len() - < (<T as Config<I>>::MaxEvaluationsPerSession::get() as usize), - Error::<T, I>::QueueFull - ); - - T::Currency::reserve(&who, <T as Config<I>>::EvaluationPrice::get())?; - - current_pool - .0 - .try_push((idty_index, median::MedianAcc::new())) - .map_err(|_| Error::<T, I>::QueueFull)?; - - Ok(()) - }, - ) + // Pallet::<T, I>::mutate_current_pool( + // pallet_session::CurrentIndex::<T>::get(), + // |current_pool| { + // ensure!( + // current_pool.0.len() + // < (<T as Config<I>>::MaxEvaluationsPerSession::get() as usize), + // Error::<T, I>::QueueFull + // ); + // + // T::Currency::reserve(&who, <T as Config<I>>::EvaluationPrice::get())?; + // + // current_pool + // .0 + // .try_push((idty_index, median::MedianAcc::new())) + // .map_err(|_| Error::<T, I>::QueueFull)?; + // + // Ok(()) + // }, + // ) + Ok(()) } } @@ -270,27 +303,27 @@ pub mod pallet { impl<T: Config<I>, I: 'static> Pallet<T, I> { /// Mutate the evaluation pool containing the results to be applied on this session. - fn mutate_current_pool< - R, - F: FnOnce( - &mut EvaluationPool< - <T as frame_system::Config>::AccountId, - <T as pallet_certification::Config<I>>::IdtyIndex, - <T as Config<I>>::MaxEvaluationsPerSession, - <T as Config<I>>::MaxEvaluatorsPerSession, - >, - ) -> R, - >( - index: SessionIndex, - f: F, - ) -> R { - match index % 3 { - 0 => EvaluationPool2::<T, I>::mutate(f), - 1 => EvaluationPool0::<T, I>::mutate(f), - 2 => EvaluationPool1::<T, I>::mutate(f), - _ => panic!("index % 3 < 3"), - } - } + // fn mutate_current_pool< + // R, + // F: FnOnce( + // &mut EvaluationPool< + // <T as frame_system::Config>::AccountId, + // <T as pallet_certification::Config<I>>::IdtyIndex, + // <T as Config<I>>::MaxEvaluationsPerSession, + // <T as Config<I>>::MaxEvaluatorsPerSession, + // >, + // ) -> R, + // >( + // index: SessionIndex, + // f: F, + // ) -> R { + // match index % 3 { + // 0 => EvaluationPool2::<T, I>::mutate(f), + // 1 => EvaluationPool0::<T, I>::mutate(f), + // 2 => EvaluationPool1::<T, I>::mutate(f), + // _ => panic!("index % 3 < 3"), + // } + // } /// Take the evaluation pool containing the results to be applied on this session. #[allow(clippy::type_complexity)] @@ -298,7 +331,7 @@ pub mod pallet { index: SessionIndex, ) -> EvaluationPool< <T as frame_system::Config>::AccountId, - <T as pallet_certification::Config<I>>::IdtyIndex, + // <T as pallet_certification::Config<I>>::IdtyIndex, <T as Config<I>>::MaxEvaluationsPerSession, <T as Config<I>>::MaxEvaluatorsPerSession, > { @@ -320,7 +353,7 @@ pub mod pallet { #[allow(clippy::type_complexity)] let current_pool: EvaluationPool< <T as frame_system::Config>::AccountId, - <T as pallet_certification::Config<I>>::IdtyIndex, + // <T as pallet_certification::Config<I>>::IdtyIndex, <T as Config<I>>::MaxEvaluationsPerSession, <T as Config<I>>::MaxEvaluatorsPerSession, > = Pallet::<T, I>::take_current_pool(index); diff --git a/pallets/distance/src/mock.rs b/pallets/distance/src/mock.rs new file mode 100644 index 000000000..a6c3209d7 --- /dev/null +++ b/pallets/distance/src/mock.rs @@ -0,0 +1,272 @@ +// Copyright 2021 Axiom-Team +// +// This file is part of Duniter-v2S. +// +// Duniter-v2S is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, version 3 of the License. +// +// Duniter-v2S is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. + +use crate::{self as pallet_distance}; +use frame_support::{ + parameter_types, sp_io, + traits::{Everything, OnFinalize, OnInitialize}, +}; +use frame_system as system; +use pallet_session::{ShouldEndSession, TestSessionHandler}; +use sp_core::{ConstU32, H256}; +use sp_runtime::testing::UintAuthorityId; +use sp_runtime::traits::{ConvertInto, IdentifyAccount, IsMember, Verify}; +use sp_runtime::{ + impl_opaque_keys, + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, + BuildStorage, MultiSignature, +}; + +// type AccountId = u64; +type BlockNumber = u64; +type Block = frame_system::mocking::MockBlock<Test>; +pub type IdtyIndex = u64; +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>; +pub type Signature = MultiSignature; +pub type AccountPublic = <Signature as Verify>::Signer; +pub type AccountId = <AccountPublic as IdentifyAccount>::AccountId; + +// type AccountId = u64; +// type Block = frame_system::mocking::MockBlock<Test>; +// type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>; + +// Configure a mock runtime to test the pallet. +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event<T>}, + // Session: pallet_session::{Pallet, Call, Storage, Config<T>, Event}, + Authorship: pallet_authorship::{Pallet, Call, Storage}, + Distance: pallet_distance::{Pallet, Call, Config<T>, Storage, Event<T>}, + Identity: pallet_identity::{Pallet, Call, Config<T>, Storage, Event<T>}, + // Cert: pallet_certification::{Pallet, Call, Config<T>, Storage, Event<T>}, + // AuthorityMembers: pallet_authority_members::{Pallet, Call, Storage, Config<T>, Event<T>}, + } +); + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const SS58Prefix: u8 = 42; +} + +impl system::Config for Test { + type BaseCallFilter = Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Index = u64; + type BlockNumber = BlockNumber; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup<Self::AccountId>; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = SS58Prefix; + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +pub struct EnsureRoot; +impl frame_support::traits::EnsureOrigin<(RuntimeOrigin, IdtyIndex, IdtyIndex)> for EnsureRoot { + type Success = (); + + fn try_origin( + o: (RuntimeOrigin, IdtyIndex, IdtyIndex), + ) -> Result<Self::Success, (RuntimeOrigin, IdtyIndex, IdtyIndex)> { + match o.0.clone().into() { + Ok(system::RawOrigin::Root) => Ok(()), + _ => Err(o), + } + } +} + +impl pallet_distance::Config for Test { + type RuntimeEvent = RuntimeEvent; + type Currency = (); + type EvaluationPrice = (); + type MaxEvaluationsPerSession = (); + type MaxEvaluatorsPerSession = (); + type MinAccessibleReferees = (); + type ResultExpiration = (); +} + +impl_opaque_keys! { + pub struct MockSessionKeys { + pub dummy: UintAuthorityId, + } +} + +impl From<UintAuthorityId> for MockSessionKeys { + fn from(dummy: UintAuthorityId) -> Self { + Self { dummy } + } +} + +const SESSION_LENGTH: u64 = 5; +pub struct TestShouldEndSession; +impl ShouldEndSession<u64> for TestShouldEndSession { + fn should_end_session(now: u64) -> bool { + now % SESSION_LENGTH == 0 + } +} + +// impl pallet_session::Config for Test { +// type RuntimeEvent = RuntimeEvent; +// type ValidatorId = u64; +// type ValidatorIdOf = ConvertInto; +// type ShouldEndSession = TestShouldEndSession; +// type NextSessionRotation = (); +// type SessionManager = AuthorityMembers; +// type SessionHandler = TestSessionHandler; +// type Keys = MockSessionKeys; +// type WeightInfo = (); +// } + +parameter_types! { + pub const ChangeOwnerKeyPeriod: u64 = 10; + pub const ConfirmPeriod: u64 = 2; + pub const IdtyCreationPeriod: u64 = 3; + pub const MaxInactivityPeriod: u64 = 5; + pub const ValidationPeriod: u64 = 2; +} + +pub struct IdtyNameValidatorTestImpl; +impl pallet_identity::traits::IdtyNameValidator for IdtyNameValidatorTestImpl { + fn validate(idty_name: &pallet_identity::IdtyName) -> bool { + idty_name.0.len() < 16 + } +} + +impl pallet_identity::Config for Test { + type ChangeOwnerKeyPeriod = ChangeOwnerKeyPeriod; + type ConfirmPeriod = ConfirmPeriod; + type CheckIdtyCallAllowed = (); + type IdtyCreationPeriod = IdtyCreationPeriod; + type IdtyData = (); + type IdtyNameValidator = IdtyNameValidatorTestImpl; + type IdtyIndex = u64; + type NewOwnerKeySigner = AccountPublic; + type NewOwnerKeySignature = Signature; + type OnIdtyChange = (); + type RemoveIdentityConsumers = (); + type RevocationSigner = AccountPublic; + type RevocationSignature = Signature; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); +} + +// parameter_types! { +// pub const MaxByIssuer: u32 = 4; +// pub const MinReceivedCertToBeAbleToIssueCert: u32 = 2; +// pub const CertPeriod: u64 = 2; +// pub const ValidityPeriod: u64 = 10; +// } +// +// impl pallet_certification::Config for Test { +// type CertPeriod = CertPeriod; +// type IdtyIndex = IdtyIndex; +// type OwnerKeyOf = sp_runtime::traits::ConvertInto; +// type CheckCertAllowed = (); +// type MaxByIssuer = MaxByIssuer; +// type MinReceivedCertToBeAbleToIssueCert = MinReceivedCertToBeAbleToIssueCert; +// type OnNewcert = (); +// type OnRemovedCert = (); +// type RuntimeEvent = RuntimeEvent; +// type WeightInfo = (); +// type ValidityPeriod = ValidityPeriod; +// } + +impl pallet_authorship::Config for Test { + type FindAuthor = (); + type UncleGenerations = (); + type FilterUncle = (); + type EventHandler = (); +} + +pub struct TestIsSmithMember; +impl IsMember<u64> for TestIsSmithMember { + fn is_member(member_id: &u64) -> bool { + member_id % 3 == 0 + } +} + +// impl pallet_authority_members::Config for Test { +// type KeysWrapper = MockSessionKeys; +// type IsMember = TestIsSmithMember; +// type MaxAuthorities = ConstU32<4>; +// type MaxKeysLife = ConstU32<5>; +// type MaxOfflineSessions = ConstU32<2>; +// type MemberId = u64; +// type MemberIdOf = ConvertInto; +// type OnNewSession = (); +// type OnRemovedMember = (); +// type RemoveMemberOrigin = system::EnsureRoot<u64>; +// type RuntimeEvent = RuntimeEvent; +// type WeightInfo = (); +// } + +pub struct FullIdentificationOfImpl; +impl sp_runtime::traits::Convert<AccountId, Option<()>> for FullIdentificationOfImpl { + fn convert(_: AccountId) -> Option<()> { + Some(()) + } +} +// impl pallet_session::historical::Config for Test { +// type FullIdentification = (); +// type FullIdentificationOf = FullIdentificationOfImpl; +// } + +// Build genesis storage according to the mock runtime. +pub fn new_test_ext() -> sp_io::TestExternalities { + GenesisConfig { + system: SystemConfig::default(), + // authority_members: pallet_authority_members::GenesisConfig::default(), + // cert: pallet_certification::GenesisConfig::default(), + distance: pallet_distance::GenesisConfig::default(), + identity: pallet_identity::GenesisConfig::default(), + // session: pallet_session::GenesisConfig::default(), + } + .build_storage() + .unwrap() + .into() +} + +pub fn run_to_block(n: u64) { + while System::block_number() < n { + Distance::on_finalize(System::block_number()); + // TODO: autres pallet? + System::on_finalize(System::block_number()); + System::reset_events(); + System::set_block_number(System::block_number() + 1); + System::on_initialize(System::block_number()); + Distance::on_initialize(System::block_number()); + // TODO: autres pallet? + } +} diff --git a/pallets/distance/src/tests.rs b/pallets/distance/src/tests.rs new file mode 100644 index 000000000..5f1410151 --- /dev/null +++ b/pallets/distance/src/tests.rs @@ -0,0 +1,30 @@ +// Copyright 2021 Axiom-Team +// +// This file is part of Duniter-v2S. +// +// Duniter-v2S is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, version 3 of the License. +// +// Duniter-v2S is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. + +use crate::mock::*; +use frame_support::{assert_noop, assert_ok}; +use sp_std::collections::btree_map::BTreeMap; + +#[test] +fn test_must_receive_cert_before_can_issue() { + new_test_ext().execute_with(|| { + assert_eq!(true, true); + // assert_eq!( + // Distance::add_cert(RuntimeOrigin::signed(0), 0, 1), + // Err(Error::<Test, _>::NotEnoughCertReceived.into()) + // ); + }); +} diff --git a/pallets/distance/src/types.rs b/pallets/distance/src/types.rs index ab629ec48..74338d349 100644 --- a/pallets/distance/src/types.rs +++ b/pallets/distance/src/types.rs @@ -30,8 +30,13 @@ pub enum DistanceStatus { Valid, } -pub type EvaluationPool<AccountId, IdtyIndex, MaxEvaluationsPerSession, MaxEvaluatorsPerSession> = ( - BoundedVec<(IdtyIndex, MedianAcc<Perbill, MaxEvaluatorsPerSession>), MaxEvaluationsPerSession>, +pub type EvaluationPool< + AccountId, + // IdtyIndex, + MaxEvaluationsPerSession, + MaxEvaluatorsPerSession, +> = ( + BoundedVec<(u64, MedianAcc<Perbill, MaxEvaluatorsPerSession>), MaxEvaluationsPerSession>, BoundedBTreeSet<AccountId, MaxEvaluatorsPerSession>, ); -- GitLab