diff --git a/Cargo.lock b/Cargo.lock index bb8fad0549244..31de4625e56de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1925,6 +1925,8 @@ dependencies = [ "frame-system", "parity-scale-codec", "sp-arithmetic", + "sp-core", + "sp-io", "sp-npos-elections", "sp-runtime", "sp-std", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 7dc87c531ab57..d7257a9ea71b5 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -42,7 +42,6 @@ use frame_system::{ pub use node_primitives::{AccountId, Signature}; use node_primitives::{AccountIndex, Balance, BlockNumber, Hash, Index, Moment}; use pallet_contracts::weights::WeightInfo; -use pallet_election_provider_multi_phase::FallbackStrategy; use pallet_grandpa::{ fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, }; @@ -487,6 +486,11 @@ parameter_types! { } use frame_election_provider_support::onchain; +impl onchain::Config for Runtime { + type Accuracy = Perbill; + type DataProvider = Staking; +} + impl pallet_staking::Config for Runtime { const MAX_NOMINATIONS: u32 = MAX_NOMINATIONS; type Currency = Balances; @@ -510,9 +514,7 @@ impl pallet_staking::Config for Runtime { type NextNewSession = Session; type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; type ElectionProvider = ElectionProviderMultiPhase; - type GenesisElectionProvider = onchain::OnChainSequentialPhragmen< - pallet_election_provider_multi_phase::OnChainConfig, - >; + type GenesisElectionProvider = onchain::OnChainSequentialPhragmen; type WeightInfo = pallet_staking::weights::SubstrateWeight; } @@ -527,9 +529,6 @@ parameter_types! { pub const SignedDepositBase: Balance = 1 * DOLLARS; pub const SignedDepositByte: Balance = 1 * CENTS; - // fallback: no on-chain fallback. - pub const Fallback: FallbackStrategy = FallbackStrategy::Nothing; - pub SolutionImprovementThreshold: Perbill = Perbill::from_rational(1u32, 10_000); // miner configs @@ -615,15 +614,14 @@ impl pallet_election_provider_multi_phase::Config for Runtime { type SlashHandler = (); // burn slashes type RewardHandler = (); // nothing to do upon rewards type DataProvider = Staking; - type OnChainAccuracy = Perbill; type Solution = NposSolution16; - type Fallback = Fallback; + type Fallback = pallet_election_provider_multi_phase::NoFallback; type Solver = frame_election_provider_support::SequentialPhragmen< AccountId, - pallet_election_provider_multi_phase::SolutionAccuracyOf, + pallet_election_provider_multi_phase::SolutionAccuracyOf, OffchainRandomBalancing, >; - type WeightInfo = pallet_election_provider_multi_phase::weights::SubstrateWeight; + type WeightInfo = pallet_election_provider_multi_phase::weights::SubstrateWeight; type ForceOrigin = EnsureRootOrHalfCouncil; type BenchmarkingConfig = BenchmarkConfig; } @@ -1686,6 +1684,7 @@ impl_runtime_apis! { mod tests { use super::*; use frame_system::offchain::CreateSignedTransaction; + use sp_runtime::UpperOf; #[test] fn validate_transaction_submitter_bounds() { @@ -1698,6 +1697,16 @@ mod tests { is_submit_signed_transaction::(); } + #[test] + fn perbill_as_onchain_accuracy() { + type OnChainAccuracy = ::Accuracy; + let maximum_chain_accuracy: Vec> = (0..MAX_NOMINATIONS) + .map(|_| >::from(OnChainAccuracy::one().deconstruct())) + .collect(); + let _: UpperOf = + maximum_chain_accuracy.iter().fold(0, |acc, x| acc.checked_add(*x).unwrap()); + } + #[test] fn call_size() { assert!( diff --git a/frame/babe/src/mock.rs b/frame/babe/src/mock.rs index f4f1310e83566..bc0be32624cba 100644 --- a/frame/babe/src/mock.rs +++ b/frame/babe/src/mock.rs @@ -192,8 +192,6 @@ parameter_types! { } impl onchain::Config for Test { - type AccountId = ::AccountId; - type BlockNumber = ::BlockNumber; type Accuracy = Perbill; type DataProvider = Staking; } diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index 977a4d34e84a9..a3b6083914ca5 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -114,8 +114,8 @@ //! If we reach the end of both phases (i.e. call to [`ElectionProvider::elect`] happens) and no //! good solution is queued, then the fallback strategy [`pallet::Config::Fallback`] is used to //! determine what needs to be done. The on-chain election is slow, and contains no balancing or -//! reduction post-processing. See [`onchain::OnChainSequentialPhragmen`]. The -//! [`FallbackStrategy::Nothing`] just returns an error, and enables the [`Phase::Emergency`]. +//! reduction post-processing. [`NoFallback`] does nothing and enables [`Phase::Emergency`], which +//! is a more *fail-safe* approach. //! //! ### Emergency Phase //! @@ -146,13 +146,11 @@ //! //! ## Accuracy //! -//! The accuracy of the election is configured via two trait parameters. namely, -//! [`OnChainAccuracyOf`] dictates the accuracy used to compute the on-chain fallback election and -//! [`SolutionAccuracyOf`] is the accuracy that the submitted solutions must adhere to. +//! The accuracy of the election is configured via +//! [`SolutionAccuracyOf`] which is the accuracy that the submitted solutions must adhere to. //! -//! Note that both accuracies are of great importance. The offchain solution should be as small as -//! possible, reducing solutions size/weight. The on-chain solution can use more space for accuracy, -//! but should still be fast to prevent massively large blocks in case of a fallback. +//! Note that the accuracy is of great importance. The offchain solution should be as small as +//! possible, reducing solutions size/weight. //! //! ## Error types //! @@ -201,26 +199,9 @@ //! [`DesiredTargets`], no more, no less. Over time, we can change this to a [min, max] where any //! solution within this range is acceptable, where bigger solutions are prioritized. //! -//! **Recursive Fallback**: Currently, the fallback is a separate enum. A different and fancier way -//! of doing this would be to have the fallback be another -//! [`frame_election_provider_support::ElectionProvider`]. In this case, this pallet can even have -//! the on-chain election provider as fallback, or special _noop_ fallback that simply returns an -//! error, thus replicating [`FallbackStrategy::Nothing`]. In this case, we won't need the -//! additional config OnChainAccuracy either. -//! //! **Score based on (byte) size**: We should always prioritize small solutions over bigger ones, if //! there is a tie. Even more harsh should be to enforce the bound of the `reduce` algorithm. //! -//! **Make the number of nominators configurable from the runtime**. Remove `sp_npos_elections` -//! dependency from staking and the solution type. It should be generated at runtime, there -//! it should be encoded how many votes each nominators have. Essentially translate -//! to this pallet. -//! -//! **More accurate weight for error cases**: Both `ElectionDataProvider` and `ElectionProvider` -//! assume no weight is consumed in their functions, when operations fail with `Err`. This can -//! clearly be improved, but not a priority as we generally expect snapshot creation to fail only -//! due to extreme circumstances. -//! //! **Take into account the encode/decode weight in benchmarks.** Currently, we only take into //! account the weight of encode/decode in the `submit_unsigned` given its priority. Nonetheless, //! all operations on the solution and the snapshot are worthy of taking this into account. @@ -228,7 +209,7 @@ #![cfg_attr(not(feature = "std"), no_std)] use codec::{Decode, Encode}; -use frame_election_provider_support::{onchain, ElectionDataProvider, ElectionProvider}; +use frame_election_provider_support::{ElectionDataProvider, ElectionProvider}; use frame_support::{ dispatch::DispatchResultWithPostInfo, ensure, @@ -241,8 +222,8 @@ use sp_arithmetic::{ UpperOf, }; use sp_npos_elections::{ - assignment_ratio_to_staked_normalized, ElectionScore, EvaluateSupport, NposSolution, - PerThing128, Supports, VoteWeight, + assignment_ratio_to_staked_normalized, ElectionScore, EvaluateSupport, NposSolution, Supports, + VoteWeight, }; use sp_runtime::{ traits::Bounded, @@ -282,17 +263,11 @@ pub type SolutionVoterIndexOf = as NposSolution>::VoterIndex; pub type SolutionTargetIndexOf = as NposSolution>::TargetIndex; /// The accuracy of the election, when submitted from offchain. Derived from [`SolutionOf`]. pub type SolutionAccuracyOf = as NposSolution>::Accuracy; -/// The accuracy of the election, when computed on-chain. Equal to [`Config::OnChainAccuracy`]. -pub type OnChainAccuracyOf = ::OnChainAccuracy; - -/// Wrapper type that implements the configurations needed for the on-chain backup. -pub struct OnChainConfig(sp_std::marker::PhantomData); -impl onchain::Config for OnChainConfig { - type AccountId = T::AccountId; - type BlockNumber = T::BlockNumber; - type Accuracy = T::OnChainAccuracy; - type DataProvider = T::DataProvider; -} +/// The fallback election type. +pub type FallbackErrorOf = <::Fallback as ElectionProvider< + ::AccountId, + ::BlockNumber, +>>::Error; /// Configuration for the benchmarks of the pallet. pub trait BenchmarkingConfig { @@ -322,6 +297,19 @@ impl BenchmarkingConfig for () { const MAXIMUM_TARGETS: u32 = 2_000; } +/// A fallback implementation that transitions the pallet to the emergency phase. +pub struct NoFallback(sp_std::marker::PhantomData); + +impl ElectionProvider for NoFallback { + type DataProvider = T::DataProvider; + type Error = &'static str; + + fn elect() -> Result, Self::Error> { + // Do nothing, this will enable the emergency phase. + Err("NoFallback.") + } +} + /// Current phase of the pallet. #[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, Debug)] pub enum Phase { @@ -384,19 +372,6 @@ impl Phase { } } -/// A configuration for the pallet to indicate what should happen in the case of a fallback i.e. -/// reaching a call to `elect` with no good solution. -#[cfg_attr(test, derive(Clone))] -pub enum FallbackStrategy { - /// Run a on-chain sequential phragmen. - /// - /// This might burn the chain for a few minutes due to a stall, but is generally a safe - /// approach to maintain a sensible validator set. - OnChain, - /// Nothing. Return an error. - Nothing, -} - /// The type of `Computation` that provided this election data. #[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, Debug)] pub enum ElectionCompute { @@ -406,6 +381,8 @@ pub enum ElectionCompute { Signed, /// Election was computed with an unsigned submission. Unsigned, + /// Election was computed using the fallback + Fallback, /// Election was computed with emergency status. Emergency, } @@ -485,24 +462,35 @@ pub struct SolutionOrSnapshotSize { /// Internal errors of the pallet. /// /// Note that this is different from [`pallet::Error`]. -#[derive(frame_support::DebugNoBound, frame_support::PartialEqNoBound)] +#[derive(frame_support::DebugNoBound)] #[cfg_attr(feature = "runtime-benchmarks", derive(strum_macros::IntoStaticStr))] pub enum ElectionError { /// An error happened in the feasibility check sub-system. Feasibility(FeasibilityError), /// An error in the miner (offchain) sub-system. Miner(unsigned::MinerError), - /// An error in the on-chain fallback. - OnChainFallback(onchain::Error), /// An error happened in the data provider. DataProvider(&'static str), - /// No fallback is configured. This is a special case. - NoFallbackConfigured, + /// An error nested in the fallback. + Fallback(FallbackErrorOf), } -impl From for ElectionError { - fn from(e: onchain::Error) -> Self { - ElectionError::OnChainFallback(e) +// NOTE: we have to do this manually because of the additional where clause needed on +// `FallbackErrorOf`. +#[cfg(test)] +impl PartialEq for ElectionError +where + FallbackErrorOf: PartialEq, +{ + fn eq(&self, other: &Self) -> bool { + use ElectionError::*; + match (self, other) { + (&Feasibility(ref x), &Feasibility(ref y)) if x == y => true, + (&Miner(ref x), &Miner(ref y)) if x == y => true, + (&DataProvider(ref x), &DataProvider(ref y)) if x == y => true, + (&Fallback(ref x), &Fallback(ref y)) if x == y => true, + _ => false, + } } } @@ -657,11 +645,12 @@ pub mod pallet { + Ord + NposSolution; - /// Accuracy used for fallback on-chain election. - type OnChainAccuracy: PerThing128; - /// Configuration for the fallback - type Fallback: Get; + type Fallback: ElectionProvider< + Self::AccountId, + Self::BlockNumber, + DataProvider = Self::DataProvider, + >; /// OCW election solution miner algorithm implementation. type Solver: NposSolver; @@ -789,18 +778,6 @@ pub mod pallet { // Based on the requirements of [`sp_npos_elections::Assignment::try_normalize`]. let max_vote: usize = as NposSolution>::LIMIT; - // 1. Maximum sum of [ChainAccuracy; 16] must fit into `UpperOf`.. - let maximum_chain_accuracy: Vec>> = (0..max_vote) - .map(|_| { - >>::from( - >::one().deconstruct(), - ) - }) - .collect(); - let _: UpperOf> = maximum_chain_accuracy - .iter() - .fold(Zero::zero(), |acc, x| acc.checked_add(x).unwrap()); - // 2. Maximum sum of [SolutionAccuracy; 16] must fit into `UpperOf`. let maximum_chain_accuracy: Vec>> = (0..max_vote) .map(|_| { @@ -1455,15 +1432,6 @@ impl Pallet { Self::kill_snapshot(); } - /// On-chain fallback of election. - fn onchain_fallback() -> Result, ElectionError> { - > as ElectionProvider< - T::AccountId, - T::BlockNumber, - >>::elect() - .map_err(Into::into) - } - fn do_elect() -> Result, ElectionError> { // We have to unconditionally try finalizing the signed phase here. There are only two // possibilities: @@ -1475,15 +1443,10 @@ impl Pallet { let _ = Self::finalize_signed_phase(); >::take() .map_or_else( - || match T::Fallback::get() { - FallbackStrategy::OnChain => Self::onchain_fallback() - .map(|s| { - // onchain election incurs maximum block weight - Self::register_weight(T::BlockWeights::get().max_block); - (s, ElectionCompute::OnChain) - }) - .map_err(Into::into), - FallbackStrategy::Nothing => Err(ElectionError::NoFallbackConfigured), + || { + T::Fallback::elect() + .map_err(|fe| ElectionError::Fallback(fe)) + .map(|supports| (supports, ElectionCompute::Fallback)) }, |ReadySolution { supports, compute, .. }| Ok((supports, compute)), ) @@ -1889,7 +1852,7 @@ mod tests { multi_phase_events(), vec![ Event::SignedPhaseStarted(1), - Event::ElectionFinalized(Some(ElectionCompute::OnChain)) + Event::ElectionFinalized(Some(ElectionCompute::Fallback)) ], ); // All storage items must be cleared. @@ -1941,14 +1904,12 @@ mod tests { #[test] fn fallback_strategy_works() { - ExtBuilder::default().fallback(FallbackStrategy::OnChain).build_and_execute(|| { - roll_to(15); - assert_eq!(MultiPhase::current_phase(), Phase::Signed); - + ExtBuilder::default().onchain_fallback(true).build_and_execute(|| { roll_to(25); assert_eq!(MultiPhase::current_phase(), Phase::Unsigned((true, 25))); - // Zilch solutions thus far. + // Zilch solutions thus far, but we get a result. + assert!(MultiPhase::queued_solution().is_none()); let supports = MultiPhase::elect().unwrap(); assert_eq!( @@ -1960,15 +1921,15 @@ mod tests { ) }); - ExtBuilder::default().fallback(FallbackStrategy::Nothing).build_and_execute(|| { - roll_to(15); - assert_eq!(MultiPhase::current_phase(), Phase::Signed); - + ExtBuilder::default().onchain_fallback(false).build_and_execute(|| { roll_to(25); assert_eq!(MultiPhase::current_phase(), Phase::Unsigned((true, 25))); // Zilch solutions thus far. - assert_eq!(MultiPhase::elect().unwrap_err(), ElectionError::NoFallbackConfigured); + assert!(MultiPhase::queued_solution().is_none()); + assert_eq!(MultiPhase::elect().unwrap_err(), ElectionError::Fallback("NoFallback.")); + // phase is now emergency. + assert_eq!(MultiPhase::current_phase(), Phase::Emergency); }) } diff --git a/frame/election-provider-multi-phase/src/mock.rs b/frame/election-provider-multi-phase/src/mock.rs index a7e68491c272a..28a15291e6520 100644 --- a/frame/election-provider-multi-phase/src/mock.rs +++ b/frame/election-provider-multi-phase/src/mock.rs @@ -17,7 +17,9 @@ use super::*; use crate as multi_phase; -use frame_election_provider_support::{data_provider, ElectionDataProvider, SequentialPhragmen}; +use frame_election_provider_support::{ + data_provider, onchain, ElectionDataProvider, SequentialPhragmen, +}; pub use frame_support::{assert_noop, assert_ok}; use frame_support::{parameter_types, traits::Hooks, weights::Weight}; use multi_phase::unsigned::{IndexAssignmentOf, Voter}; @@ -57,7 +59,7 @@ frame_support::construct_runtime!( pub(crate) type Balance = u64; pub(crate) type AccountId = u64; -pub(crate) type BlockNumber = u32; +pub(crate) type BlockNumber = u64; pub(crate) type VoterIndex = u32; pub(crate) type TargetIndex = u16; @@ -76,7 +78,7 @@ pub(crate) fn multi_phase_events() -> Vec> { } /// To from `now` to block `n`. -pub fn roll_to(n: u64) { +pub fn roll_to(n: BlockNumber) { let now = System::block_number(); for i in now + 1..=n { System::set_block_number(i); @@ -84,7 +86,7 @@ pub fn roll_to(n: u64) { } } -pub fn roll_to_with_ocw(n: u64) { +pub fn roll_to_with_ocw(n: BlockNumber) { let now = System::block_number(); for i in now + 1..=n { System::set_block_number(i); @@ -197,7 +199,7 @@ impl frame_system::Config for Runtime { type BaseCallFilter = frame_support::traits::Everything; type Origin = Origin; type Index = u64; - type BlockNumber = u64; + type BlockNumber = BlockNumber; type Call = Call; type Hash = H256; type Hashing = BlakeTwo256; @@ -251,10 +253,9 @@ parameter_types! { (40, 40, vec![40]), ]; - pub static Fallback: FallbackStrategy = FallbackStrategy::OnChain; pub static DesiredTargets: u32 = 2; - pub static SignedPhase: u64 = 10; - pub static UnsignedPhase: u64 = 5; + pub static SignedPhase: BlockNumber = 10; + pub static UnsignedPhase: BlockNumber = 5; pub static SignedMaxSubmissions: u32 = 5; pub static SignedDepositBase: Balance = 5; pub static SignedDepositByte: Balance = 0; @@ -269,6 +270,27 @@ parameter_types! { pub static MockWeightInfo: bool = false; pub static EpochLength: u64 = 30; + pub static OnChianFallback: bool = true; +} + +impl onchain::Config for Runtime { + type Accuracy = sp_runtime::Perbill; + type DataProvider = StakingMock; +} + +pub struct MockFallback; +impl ElectionProvider for MockFallback { + type Error = &'static str; + type DataProvider = StakingMock; + + fn elect() -> Result, Self::Error> { + if OnChianFallback::get() { + onchain::OnChainSequentialPhragmen::::elect() + .map_err(|_| "OnChainSequentialPhragmen failed") + } else { + super::NoFallback::::elect() + } + } } // Hopefully this won't be too much of a hassle to maintain. @@ -376,8 +398,7 @@ impl crate::Config for Runtime { type DataProvider = StakingMock; type WeightInfo = DualMockWeightInfo; type BenchmarkingConfig = (); - type OnChainAccuracy = Perbill; - type Fallback = Fallback; + type Fallback = MockFallback; type ForceOrigin = frame_system::EnsureRoot; type Solution = TestNposSolution; type Solver = SequentialPhragmen, Balancing>; @@ -474,13 +495,13 @@ impl ExtBuilder { ::set(p); self } - pub fn phases(self, signed: u64, unsigned: u64) -> Self { + pub fn phases(self, signed: BlockNumber, unsigned: BlockNumber) -> Self { ::set(signed); ::set(unsigned); self } - pub fn fallback(self, fallback: FallbackStrategy) -> Self { - ::set(fallback); + pub fn onchain_fallback(self, onchain: bool) -> Self { + ::set(onchain); self } pub fn miner_weight(self, weight: Weight) -> Self { @@ -555,6 +576,6 @@ impl ExtBuilder { } } -pub(crate) fn balances(who: &u64) -> (u64, u64) { +pub(crate) fn balances(who: &AccountId) -> (Balance, Balance) { (Balances::free_balance(who), Balances::reserved_balance(who)) } diff --git a/frame/election-provider-support/Cargo.toml b/frame/election-provider-support/Cargo.toml index c0d332315b020..d713b98fcefa1 100644 --- a/frame/election-provider-support/Cargo.toml +++ b/frame/election-provider-support/Cargo.toml @@ -23,6 +23,8 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys [dev-dependencies] sp-npos-elections = { version = "4.0.0-dev", path = "../../primitives/npos-elections" } sp-runtime = { version = "4.0.0-dev", path = "../../primitives/runtime" } +sp-core = { version = "4.0.0-dev", path = "../../primitives/core" } +sp-io = { version = "4.0.0-dev", path = "../../primitives/io" } [features] default = ["std"] diff --git a/frame/election-provider-support/src/onchain.rs b/frame/election-provider-support/src/onchain.rs index 8e548408ef1a3..fb1ccfdfe2566 100644 --- a/frame/election-provider-support/src/onchain.rs +++ b/frame/election-provider-support/src/onchain.rs @@ -18,6 +18,7 @@ //! An implementation of [`ElectionProvider`] that does an on-chain sequential phragmen. use crate::{ElectionDataProvider, ElectionProvider}; +use frame_support::{traits::Get, weights::DispatchClass}; use sp_npos_elections::*; use sp_std::{collections::btree_map::BTreeMap, marker::PhantomData, prelude::*}; @@ -53,11 +54,11 @@ pub struct OnChainSequentialPhragmen(PhantomData); /// Configuration trait of [`OnChainSequentialPhragmen`]. /// /// Note that this is similar to a pallet traits, but [`OnChainSequentialPhragmen`] is not a pallet. -pub trait Config { - /// The account identifier type. - type AccountId: IdentifierT; - /// The block number type. - type BlockNumber; +/// +/// WARNING: the user of this pallet must ensure that the `Accuracy` type will work nicely with the +/// normalization operation done inside `seq_phragmen`. See +/// [`sp_npos_elections::assignment::try_normalize`] for more info. +pub trait Config: frame_system::Config { /// The accuracy used to compute the election: type Accuracy: PerThing128; /// Something that provides the data for election. @@ -87,6 +88,12 @@ impl ElectionProvider for OnChainSequen let staked = assignment_ratio_to_staked_normalized(assignments, &stake_of)?; + let weight = T::BlockWeights::get().max_block; + frame_system::Pallet::::register_extra_weight_unchecked( + weight, + DispatchClass::Mandatory, + ); + Ok(to_supports(&staked)) } } @@ -98,11 +105,49 @@ mod tests { use sp_runtime::Perbill; type AccountId = u64; - type BlockNumber = u32; - struct Runtime; - impl Config for Runtime { - type AccountId = AccountId; + type BlockNumber = u64; + + pub type Header = sp_runtime::generic::Header; + pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic; + pub type Block = sp_runtime::generic::Block; + + frame_support::construct_runtime!( + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: frame_system::{Pallet, Call, Event}, + } + ); + + impl frame_system::Config for Runtime { + type SS58Prefix = (); + type BaseCallFilter = frame_support::traits::Everything; + type Origin = Origin; + type Index = AccountId; type BlockNumber = BlockNumber; + type Call = Call; + type Hash = sp_core::H256; + type Hashing = sp_runtime::traits::BlakeTwo256; + type AccountId = AccountId; + type Lookup = sp_runtime::traits::IdentityLookup; + type Header = sp_runtime::testing::Header; + type Event = (); + type BlockHashCount = (); + type DbWeight = (); + type BlockLength = (); + type BlockWeights = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type OnSetCode = (); + } + + impl Config for Runtime { type Accuracy = Perbill; type DataProvider = mock_data_provider::DataProvider; } @@ -138,12 +183,14 @@ mod tests { #[test] fn onchain_seq_phragmen_works() { - assert_eq!( - OnChainPhragmen::elect().unwrap(), - vec![ - (10, Support { total: 25, voters: vec![(1, 10), (3, 15)] }), - (30, Support { total: 35, voters: vec![(2, 20), (3, 15)] }) - ] - ); + sp_io::TestExternalities::new_empty().execute_with(|| { + assert_eq!( + OnChainPhragmen::elect().unwrap(), + vec![ + (10, Support { total: 25, voters: vec![(1, 10), (3, 15)] }), + (30, Support { total: 35, voters: vec![(2, 20), (3, 15)] }) + ] + ); + }) } } diff --git a/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs index b8d6f699f890c..26dda514516a3 100644 --- a/frame/grandpa/src/mock.rs +++ b/frame/grandpa/src/mock.rs @@ -194,8 +194,6 @@ parameter_types! { } impl onchain::Config for Test { - type AccountId = ::AccountId; - type BlockNumber = ::BlockNumber; type Accuracy = Perbill; type DataProvider = Staking; } diff --git a/frame/offences/benchmarking/src/mock.rs b/frame/offences/benchmarking/src/mock.rs index 431877c3a8f9d..c4fd88def0e33 100644 --- a/frame/offences/benchmarking/src/mock.rs +++ b/frame/offences/benchmarking/src/mock.rs @@ -151,8 +151,6 @@ parameter_types! { pub type Extrinsic = sp_runtime::testing::TestXt; impl onchain::Config for Test { - type AccountId = AccountId; - type BlockNumber = BlockNumber; type Accuracy = Perbill; type DataProvider = Staking; } diff --git a/frame/session/benchmarking/src/mock.rs b/frame/session/benchmarking/src/mock.rs index 9de4a0320d15d..c685db2bb2524 100644 --- a/frame/session/benchmarking/src/mock.rs +++ b/frame/session/benchmarking/src/mock.rs @@ -159,8 +159,6 @@ where } impl onchain::Config for Test { - type AccountId = AccountId; - type BlockNumber = BlockNumber; type Accuracy = sp_runtime::Perbill; type DataProvider = Staking; } diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 82eca58e5355e..0357fa05cb1dd 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -243,8 +243,6 @@ impl OnUnbalanced> for RewardRemainderMock { } impl onchain::Config for Test { - type AccountId = AccountId; - type BlockNumber = BlockNumber; type Accuracy = Perbill; type DataProvider = Staking; } diff --git a/primitives/state-machine/src/lib.rs b/primitives/state-machine/src/lib.rs index e5ba9e1acb84b..05d2c6d20ccee 100644 --- a/primitives/state-machine/src/lib.rs +++ b/primitives/state-machine/src/lib.rs @@ -1579,7 +1579,8 @@ mod tests { let mut seed = [0; 16]; for i in 0..50u32 { let mut child_infos = Vec::new(); - seed[0..4].copy_from_slice(&i.to_be_bytes()[..]); + let seed_partial = &mut seed[0..4]; + seed_partial.copy_from_slice(&i.to_be_bytes()[..]); let mut rand = SmallRng::from_seed(seed); let nb_child_trie = rand.next_u32() as usize % 25;