Recursive election provider as fallback (#9648)

* Recursive election provider as fallback

* minor fix

* Fix integrity tests

* Update frame/election-provider-multi-phase/src/lib.rs

Co-authored-by: Zeke Mostov <32168567+emostov@users.noreply.github.com>

* Fix everything

* fmt again

* Fix test

* Fix state machine warning

* Fix build

Co-authored-by: Zeke Mostov <32168567+emostov@users.noreply.github.com>
This commit is contained in:
Kian Paimani
2021-09-12 15:38:32 +01:00
committed by GitHub
parent c09d52ead7
commit 056fd9b8a8
12 changed files with 190 additions and 157 deletions
+2
View File
@@ -1925,6 +1925,8 @@ dependencies = [
"frame-system",
"parity-scale-codec",
"sp-arithmetic",
"sp-core",
"sp-io",
"sp-npos-elections",
"sp-runtime",
"sp-std",
+20 -11
View File
@@ -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<Self>,
>;
type GenesisElectionProvider = onchain::OnChainSequentialPhragmen<Self>;
type WeightInfo = pallet_staking::weights::SubstrateWeight<Runtime>;
}
@@ -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<Self>;
type Solver = frame_election_provider_support::SequentialPhragmen<
AccountId,
pallet_election_provider_multi_phase::SolutionAccuracyOf<Runtime>,
pallet_election_provider_multi_phase::SolutionAccuracyOf<Self>,
OffchainRandomBalancing,
>;
type WeightInfo = pallet_election_provider_multi_phase::weights::SubstrateWeight<Runtime>;
type WeightInfo = pallet_election_provider_multi_phase::weights::SubstrateWeight<Self>;
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::<Runtime>();
}
#[test]
fn perbill_as_onchain_accuracy() {
type OnChainAccuracy = <Runtime as onchain::Config>::Accuracy;
let maximum_chain_accuracy: Vec<UpperOf<OnChainAccuracy>> = (0..MAX_NOMINATIONS)
.map(|_| <UpperOf<OnChainAccuracy>>::from(OnChainAccuracy::one().deconstruct()))
.collect();
let _: UpperOf<OnChainAccuracy> =
maximum_chain_accuracy.iter().fold(0, |acc, x| acc.checked_add(*x).unwrap());
}
#[test]
fn call_size() {
assert!(
-2
View File
@@ -192,8 +192,6 @@ parameter_types! {
}
impl onchain::Config for Test {
type AccountId = <Self as frame_system::Config>::AccountId;
type BlockNumber = <Self as frame_system::Config>::BlockNumber;
type Accuracy = Perbill;
type DataProvider = Staking;
}
@@ -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
//! <https://github.com/paritytech/substrate/pull/7929> 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<T> = <SolutionOf<T> as NposSolution>::VoterIndex;
pub type SolutionTargetIndexOf<T> = <SolutionOf<T> as NposSolution>::TargetIndex;
/// The accuracy of the election, when submitted from offchain. Derived from [`SolutionOf`].
pub type SolutionAccuracyOf<T> = <SolutionOf<T> as NposSolution>::Accuracy;
/// The accuracy of the election, when computed on-chain. Equal to [`Config::OnChainAccuracy`].
pub type OnChainAccuracyOf<T> = <T as Config>::OnChainAccuracy;
/// Wrapper type that implements the configurations needed for the on-chain backup.
pub struct OnChainConfig<T: Config>(sp_std::marker::PhantomData<T>);
impl<T: Config> onchain::Config for OnChainConfig<T> {
type AccountId = T::AccountId;
type BlockNumber = T::BlockNumber;
type Accuracy = T::OnChainAccuracy;
type DataProvider = T::DataProvider;
}
/// The fallback election type.
pub type FallbackErrorOf<T> = <<T as crate::Config>::Fallback as ElectionProvider<
<T as frame_system::Config>::AccountId,
<T as frame_system::Config>::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<T>(sp_std::marker::PhantomData<T>);
impl<T: Config> ElectionProvider<T::AccountId, T::BlockNumber> for NoFallback<T> {
type DataProvider = T::DataProvider;
type Error = &'static str;
fn elect() -> Result<Supports<T::AccountId>, 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<Bn> {
@@ -384,19 +372,6 @@ impl<Bn: PartialEq + Eq> Phase<Bn> {
}
}
/// 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<T: Config> {
/// An error happened in the feasibility check sub-system.
Feasibility(FeasibilityError),
/// An error in the miner (offchain) sub-system.
Miner(unsigned::MinerError<T>),
/// 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<T>),
}
impl<T: Config> From<onchain::Error> for ElectionError<T> {
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<T>`.
#[cfg(test)]
impl<T: Config> PartialEq for ElectionError<T>
where
FallbackErrorOf<T>: 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<FallbackStrategy>;
type Fallback: ElectionProvider<
Self::AccountId,
Self::BlockNumber,
DataProvider = Self::DataProvider,
>;
/// OCW election solution miner algorithm implementation.
type Solver: NposSolver<AccountId = Self::AccountId>;
@@ -789,18 +778,6 @@ pub mod pallet {
// Based on the requirements of [`sp_npos_elections::Assignment::try_normalize`].
let max_vote: usize = <SolutionOf<T> as NposSolution>::LIMIT;
// 1. Maximum sum of [ChainAccuracy; 16] must fit into `UpperOf<ChainAccuracy>`..
let maximum_chain_accuracy: Vec<UpperOf<OnChainAccuracyOf<T>>> = (0..max_vote)
.map(|_| {
<UpperOf<OnChainAccuracyOf<T>>>::from(
<OnChainAccuracyOf<T>>::one().deconstruct(),
)
})
.collect();
let _: UpperOf<OnChainAccuracyOf<T>> = maximum_chain_accuracy
.iter()
.fold(Zero::zero(), |acc, x| acc.checked_add(x).unwrap());
// 2. Maximum sum of [SolutionAccuracy; 16] must fit into `UpperOf<OffchainAccuracy>`.
let maximum_chain_accuracy: Vec<UpperOf<SolutionAccuracyOf<T>>> = (0..max_vote)
.map(|_| {
@@ -1455,15 +1432,6 @@ impl<T: Config> Pallet<T> {
Self::kill_snapshot();
}
/// On-chain fallback of election.
fn onchain_fallback() -> Result<Supports<T::AccountId>, ElectionError<T>> {
<onchain::OnChainSequentialPhragmen<OnChainConfig<T>> as ElectionProvider<
T::AccountId,
T::BlockNumber,
>>::elect()
.map_err(Into::into)
}
fn do_elect() -> Result<Supports<T::AccountId>, ElectionError<T>> {
// We have to unconditionally try finalizing the signed phase here. There are only two
// possibilities:
@@ -1475,15 +1443,10 @@ impl<T: Config> Pallet<T> {
let _ = Self::finalize_signed_phase();
<QueuedSolution<T>>::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);
})
}
@@ -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<super::Event<Runtime>> {
}
/// 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<AccountId, u64> for MockFallback {
type Error = &'static str;
type DataProvider = StakingMock;
fn elect() -> Result<Supports<AccountId>, Self::Error> {
if OnChianFallback::get() {
onchain::OnChainSequentialPhragmen::<Runtime>::elect()
.map_err(|_| "OnChainSequentialPhragmen failed")
} else {
super::NoFallback::<Runtime>::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<AccountId>;
type Solution = TestNposSolution;
type Solver = SequentialPhragmen<AccountId, SolutionAccuracyOf<Runtime>, Balancing>;
@@ -474,13 +495,13 @@ impl ExtBuilder {
<SolutionImprovementThreshold>::set(p);
self
}
pub fn phases(self, signed: u64, unsigned: u64) -> Self {
pub fn phases(self, signed: BlockNumber, unsigned: BlockNumber) -> Self {
<SignedPhase>::set(signed);
<UnsignedPhase>::set(unsigned);
self
}
pub fn fallback(self, fallback: FallbackStrategy) -> Self {
<Fallback>::set(fallback);
pub fn onchain_fallback(self, onchain: bool) -> Self {
<OnChianFallback>::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))
}
@@ -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"]
@@ -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<T: Config>(PhantomData<T>);
/// 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<T: Config> ElectionProvider<T::AccountId, T::BlockNumber> for OnChainSequen
let staked = assignment_ratio_to_staked_normalized(assignments, &stake_of)?;
let weight = T::BlockWeights::get().max_block;
frame_system::Pallet::<T>::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<BlockNumber, sp_runtime::traits::BlakeTwo256>;
pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic<AccountId, (), (), ()>;
pub type Block = sp_runtime::generic::Block<Header, UncheckedExtrinsic>;
frame_support::construct_runtime!(
pub enum Runtime where
Block = Block,
NodeBlock = Block,
UncheckedExtrinsic = UncheckedExtrinsic
{
System: frame_system::{Pallet, Call, Event<T>},
}
);
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<Self::AccountId>;
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)] })
]
);
})
}
}
-2
View File
@@ -194,8 +194,6 @@ parameter_types! {
}
impl onchain::Config for Test {
type AccountId = <Self as frame_system::Config>::AccountId;
type BlockNumber = <Self as frame_system::Config>::BlockNumber;
type Accuracy = Perbill;
type DataProvider = Staking;
}
@@ -151,8 +151,6 @@ parameter_types! {
pub type Extrinsic = sp_runtime::testing::TestXt<Call, ()>;
impl onchain::Config for Test {
type AccountId = AccountId;
type BlockNumber = BlockNumber;
type Accuracy = Perbill;
type DataProvider = Staking;
}
@@ -159,8 +159,6 @@ where
}
impl onchain::Config for Test {
type AccountId = AccountId;
type BlockNumber = BlockNumber;
type Accuracy = sp_runtime::Perbill;
type DataProvider = Staking;
}
-2
View File
@@ -243,8 +243,6 @@ impl OnUnbalanced<NegativeImbalanceOf<Test>> for RewardRemainderMock {
}
impl onchain::Config for Test {
type AccountId = AccountId;
type BlockNumber = BlockNumber;
type Accuracy = Perbill;
type DataProvider = Staking;
}
@@ -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;