diff --git a/substrate/frame/bags-list/remote-tests/src/snapshot.rs b/substrate/frame/bags-list/remote-tests/src/snapshot.rs index f05c00cd9a..78f462e55b 100644 --- a/substrate/frame/bags-list/remote-tests/src/snapshot.rs +++ b/substrate/frame/bags-list/remote-tests/src/snapshot.rs @@ -55,11 +55,8 @@ pub async fn execute ::SortedListProvider::count(), ); - let voters = as ElectionDataProvider< - Runtime::AccountId, - Runtime::BlockNumber, - >>::voters(voter_limit) - .unwrap(); + let voters = + as ElectionDataProvider>::voters(voter_limit).unwrap(); let mut voters_nominator_only = voters .iter() diff --git a/substrate/frame/election-provider-multi-phase/src/benchmarking.rs b/substrate/frame/election-provider-multi-phase/src/benchmarking.rs index 1e0d3b1e93..04101f886c 100644 --- a/substrate/frame/election-provider-multi-phase/src/benchmarking.rs +++ b/substrate/frame/election-provider-multi-phase/src/benchmarking.rs @@ -289,7 +289,7 @@ frame_benchmarking::benchmarks! { assert!(>::get().is_some()); assert!(>::get().is_some()); }: { - assert_ok!( as ElectionProvider>::elect()); + assert_ok!( as ElectionProvider>::elect()); } verify { assert!(>::queued_solution().is_none()); assert!(>::get().is_none()); diff --git a/substrate/frame/election-provider-multi-phase/src/lib.rs b/substrate/frame/election-provider-multi-phase/src/lib.rs index 70668dbe9f..175de0eeb0 100644 --- a/substrate/frame/election-provider-multi-phase/src/lib.rs +++ b/substrate/frame/election-provider-multi-phase/src/lib.rs @@ -139,7 +139,7 @@ //! To generate an emergency solution, one must only provide one argument: [`Supports`]. This is //! essentially a collection of elected winners for the election, and voters who support them. The //! supports can be generated by any means. In the simplest case, it could be manual. For example, -//! in the case of massive network failure or misbehaviour, [`Config::ForceOrigin`] might decide to +//! in the case of massive network failure or misbehavior, [`Config::ForceOrigin`] might decide to //! select only a small number of emergency winners (which would greatly restrict the next validator //! set, if this pallet is used with `pallet-staking`). If the failure is for other technical //! reasons, then a simple and safe way to generate supports is using the staking-miner binary @@ -286,10 +286,7 @@ 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 fallback election type. -pub type FallbackErrorOf = <::Fallback as ElectionProvider< - ::AccountId, - ::BlockNumber, ->>::Error; +pub type FallbackErrorOf = <::Fallback as ElectionProvider>::Error; /// Configuration for the benchmarks of the pallet. pub trait BenchmarkingConfig { @@ -312,7 +309,9 @@ pub trait BenchmarkingConfig { /// A fallback implementation that transitions the pallet to the emergency phase. pub struct NoFallback(sp_std::marker::PhantomData); -impl ElectionProvider for NoFallback { +impl ElectionProvider for NoFallback { + type AccountId = T::AccountId; + type BlockNumber = T::BlockNumber; type DataProvider = T::DataProvider; type Error = &'static str; @@ -654,7 +653,10 @@ pub mod pallet { type MinerMaxLength: Get; /// Something that will provide the election data. - type DataProvider: ElectionDataProvider; + type DataProvider: ElectionDataProvider< + AccountId = Self::AccountId, + BlockNumber = Self::BlockNumber, + >; /// The solution type. type Solution: codec::Codec @@ -669,8 +671,8 @@ pub mod pallet { /// Configuration for the fallback type Fallback: ElectionProvider< - Self::AccountId, - Self::BlockNumber, + AccountId = Self::AccountId, + BlockNumber = Self::BlockNumber, DataProvider = Self::DataProvider, >; @@ -818,7 +820,7 @@ pub mod pallet { // NOTE that this pallet does not really need to enforce this in runtime. The // solution cannot represent any voters more than `LIMIT` anyhow. assert_eq!( - >::MAXIMUM_VOTES_PER_VOTER, + ::MAXIMUM_VOTES_PER_VOTER, as NposSolution>::LIMIT as u32, ); } @@ -1492,7 +1494,9 @@ impl Pallet { } } -impl ElectionProvider for Pallet { +impl ElectionProvider for Pallet { + type AccountId = T::AccountId; + type BlockNumber = T::BlockNumber; type Error = ElectionError; type DataProvider = T::DataProvider; diff --git a/substrate/frame/election-provider-multi-phase/src/mock.rs b/substrate/frame/election-provider-multi-phase/src/mock.rs index d686df2a72..4e494322b0 100644 --- a/substrate/frame/election-provider-multi-phase/src/mock.rs +++ b/substrate/frame/election-provider-multi-phase/src/mock.rs @@ -285,7 +285,9 @@ impl onchain::Config for Runtime { } pub struct MockFallback; -impl ElectionProvider for MockFallback { +impl ElectionProvider for MockFallback { + type AccountId = AccountId; + type BlockNumber = u64; type Error = &'static str; type DataProvider = StakingMock; @@ -438,7 +440,9 @@ pub type Extrinsic = sp_runtime::testing::TestXt; pub struct ExtBuilder {} pub struct StakingMock; -impl ElectionDataProvider for StakingMock { +impl ElectionDataProvider for StakingMock { + type AccountId = AccountId; + type BlockNumber = u64; const MAXIMUM_VOTES_PER_VOTER: u32 = ::LIMIT as u32; fn targets(maybe_max_len: Option) -> data_provider::Result> { let targets = Targets::get(); diff --git a/substrate/frame/election-provider-support/src/lib.rs b/substrate/frame/election-provider-support/src/lib.rs index ac3bfccbbd..a4fce64ff1 100644 --- a/substrate/frame/election-provider-support/src/lib.rs +++ b/substrate/frame/election-provider-support/src/lib.rs @@ -90,21 +90,24 @@ //! //! pub trait Config: Sized { //! type ElectionProvider: ElectionProvider< -//! AccountId, -//! BlockNumber, -//! DataProvider = Module, +//! AccountId = AccountId, +//! BlockNumber = BlockNumber, +//! DataProvider = Pallet, //! >; //! } //! -//! pub struct Module(std::marker::PhantomData); +//! pub struct Pallet(std::marker::PhantomData); //! -//! impl ElectionDataProvider for Module { +//! impl ElectionDataProvider for Pallet { +//! type AccountId = AccountId; +//! type BlockNumber = BlockNumber; //! const MAXIMUM_VOTES_PER_VOTER: u32 = 1; +//! //! fn desired_targets() -> data_provider::Result { //! Ok(1) //! } //! fn voters(maybe_max_len: Option) -//! -> data_provider::Result)>> +//! -> data_provider::Result)>> //! { //! Ok(Default::default()) //! } @@ -124,10 +127,12 @@ //! pub struct GenericElectionProvider(std::marker::PhantomData); //! //! pub trait Config { -//! type DataProvider: ElectionDataProvider; +//! type DataProvider: ElectionDataProvider; //! } //! -//! impl ElectionProvider for GenericElectionProvider { +//! impl ElectionProvider for GenericElectionProvider { +//! type AccountId = AccountId; +//! type BlockNumber = BlockNumber; //! type Error = &'static str; //! type DataProvider = T::DataProvider; //! @@ -146,7 +151,7 @@ //! //! struct Runtime; //! impl generic_election_provider::Config for Runtime { -//! type DataProvider = data_provider_mod::Module; +//! type DataProvider = data_provider_mod::Pallet; //! } //! //! impl data_provider_mod::Config for Runtime { @@ -178,7 +183,13 @@ pub mod data_provider { } /// Something that can provide the data to an [`ElectionProvider`]. -pub trait ElectionDataProvider { +pub trait ElectionDataProvider { + /// The account identifier type. + type AccountId; + + /// The block number type. + type BlockNumber; + /// Maximum number of votes per voter that this data provider is providing. const MAXIMUM_VOTES_PER_VOTER: u32; @@ -189,7 +200,7 @@ pub trait ElectionDataProvider { /// /// This should be implemented as a self-weighing function. The implementor should register its /// appropriate weight at the end of execution with the system pallet directly. - fn targets(maybe_max_len: Option) -> data_provider::Result>; + fn targets(maybe_max_len: Option) -> data_provider::Result>; /// All possible voters for the election. /// @@ -202,7 +213,7 @@ pub trait ElectionDataProvider { /// appropriate weight at the end of execution with the system pallet directly. fn voters( maybe_max_len: Option, - ) -> data_provider::Result)>>; + ) -> data_provider::Result)>>; /// The number of targets to elect. /// @@ -216,14 +227,14 @@ pub trait ElectionDataProvider { /// [`ElectionProvider::elect`]. /// /// This is only useful for stateful election providers. - fn next_election_prediction(now: BlockNumber) -> BlockNumber; + fn next_election_prediction(now: Self::BlockNumber) -> Self::BlockNumber; /// Utility function only to be used in benchmarking scenarios, to be implemented optionally, /// else a noop. #[cfg(any(feature = "runtime-benchmarks", test))] fn put_snapshot( - _voters: Vec<(AccountId, VoteWeight, Vec)>, - _targets: Vec, + _voters: Vec<(Self::AccountId, VoteWeight, Vec)>, + _targets: Vec, _target_stake: Option, ) { } @@ -233,22 +244,29 @@ pub trait ElectionDataProvider { /// /// Same as `put_snapshot`, but can add a single voter one by one. #[cfg(any(feature = "runtime-benchmarks", test))] - fn add_voter(_voter: AccountId, _weight: VoteWeight, _targets: Vec) {} + fn add_voter(_voter: Self::AccountId, _weight: VoteWeight, _targets: Vec) {} /// Utility function only to be used in benchmarking scenarios, to be implemented optionally, /// else a noop. /// /// Same as `put_snapshot`, but can add a single voter one by one. #[cfg(any(feature = "runtime-benchmarks", test))] - fn add_target(_target: AccountId) {} + fn add_target(_target: Self::AccountId) {} /// Clear all voters and targets. #[cfg(any(feature = "runtime-benchmarks", test))] fn clear() {} } +/// An election data provider that should only be used for testing. #[cfg(feature = "std")] -impl ElectionDataProvider for () { +pub struct TestDataProvider(sp_std::marker::PhantomData); + +#[cfg(feature = "std")] +impl ElectionDataProvider for TestDataProvider<(AccountId, BlockNumber)> { + type AccountId = AccountId; + type BlockNumber = BlockNumber; + const MAXIMUM_VOTES_PER_VOTER: u32 = 0; fn targets(_maybe_max_len: Option) -> data_provider::Result> { Ok(Default::default()) @@ -271,12 +289,21 @@ impl ElectionDataProvider for () /// This trait only provides an interface to _request_ an election, i.e. /// [`ElectionProvider::elect`]. That data required for the election need to be passed to the /// implemented of this trait through [`ElectionProvider::DataProvider`]. -pub trait ElectionProvider { +pub trait ElectionProvider { + /// The account identifier type. + type AccountId; + + /// The block number type. + type BlockNumber; + /// The error type that is returned by the provider. type Error: Debug; /// The data provider of the election. - type DataProvider: ElectionDataProvider; + type DataProvider: ElectionDataProvider< + AccountId = Self::AccountId, + BlockNumber = Self::BlockNumber, + >; /// Elect a new set of winners. /// @@ -284,16 +311,22 @@ pub trait ElectionProvider { /// /// This should be implemented as a self-weighing function. The implementor should register its /// appropriate weight at the end of execution with the system pallet directly. - fn elect() -> Result, Self::Error>; + fn elect() -> Result, Self::Error>; } +/// An election provider to be used only for testing. #[cfg(feature = "std")] -impl ElectionProvider for () { +pub struct NoElection(sp_std::marker::PhantomData); + +#[cfg(feature = "std")] +impl ElectionProvider for NoElection<(AccountId, BlockNumber)> { + type AccountId = AccountId; + type BlockNumber = BlockNumber; type Error = &'static str; - type DataProvider = (); + type DataProvider = TestDataProvider<(AccountId, BlockNumber)>; fn elect() -> Result, Self::Error> { - Err("<() as ElectionProvider> cannot do anything.") + Err(" cannot do anything.") } } diff --git a/substrate/frame/election-provider-support/src/onchain.rs b/substrate/frame/election-provider-support/src/onchain.rs index a2eb53edcf..ce15edd592 100644 --- a/substrate/frame/election-provider-support/src/onchain.rs +++ b/substrate/frame/election-provider-support/src/onchain.rs @@ -62,10 +62,15 @@ pub trait Config: frame_system::Config { /// The accuracy used to compute the election: type Accuracy: PerThing128; /// Something that provides the data for election. - type DataProvider: ElectionDataProvider; + type DataProvider: ElectionDataProvider< + AccountId = Self::AccountId, + BlockNumber = Self::BlockNumber, + >; } -impl ElectionProvider for OnChainSequentialPhragmen { +impl ElectionProvider for OnChainSequentialPhragmen { + type AccountId = T::AccountId; + type BlockNumber = T::BlockNumber; type Error = Error; type DataProvider = T::DataProvider; @@ -160,7 +165,9 @@ mod tests { use crate::data_provider; pub struct DataProvider; - impl ElectionDataProvider for DataProvider { + impl ElectionDataProvider for DataProvider { + type AccountId = AccountId; + type BlockNumber = BlockNumber; const MAXIMUM_VOTES_PER_VOTER: u32 = 2; fn voters( _: Option, diff --git a/substrate/frame/staking/src/pallet/impls.rs b/substrate/frame/staking/src/pallet/impls.rs index 6c11e94210..95af3d223e 100644 --- a/substrate/frame/staking/src/pallet/impls.rs +++ b/substrate/frame/staking/src/pallet/impls.rs @@ -844,7 +844,9 @@ impl Pallet { } } -impl ElectionDataProvider> for Pallet { +impl ElectionDataProvider for Pallet { + type AccountId = T::AccountId; + type BlockNumber = BlockNumberFor; const MAXIMUM_VOTES_PER_VOTER: u32 = T::MAX_NOMINATIONS; fn desired_targets() -> data_provider::Result { diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index 091df82e28..d03a6198c7 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -79,16 +79,16 @@ pub mod pallet { /// Something that provides the election functionality. type ElectionProvider: frame_election_provider_support::ElectionProvider< - Self::AccountId, - Self::BlockNumber, + AccountId = Self::AccountId, + BlockNumber = Self::BlockNumber, // we only accept an election provider that has staking as data provider. DataProvider = Pallet, >; /// Something that provides the election functionality at genesis. type GenesisElectionProvider: frame_election_provider_support::ElectionProvider< - Self::AccountId, - Self::BlockNumber, + AccountId = Self::AccountId, + BlockNumber = Self::BlockNumber, DataProvider = Pallet, >; diff --git a/substrate/frame/staking/src/tests.rs b/substrate/frame/staking/src/tests.rs index aa806d4a15..74d5de7bf4 100644 --- a/substrate/frame/staking/src/tests.rs +++ b/substrate/frame/staking/src/tests.rs @@ -4013,7 +4013,7 @@ mod election_data_provider { ExtBuilder::default().build_and_execute(|| { assert_eq!(Staking::nominators(101).unwrap().targets, vec![11, 21]); assert_eq!( - >::voters(None) + ::voters(None) .unwrap() .iter() .find(|x| x.0 == 101) @@ -4028,7 +4028,7 @@ mod election_data_provider { // 11 is gone. start_active_era(2); assert_eq!( - >::voters(None) + ::voters(None) .unwrap() .iter() .find(|x| x.0 == 101) @@ -4040,7 +4040,7 @@ mod election_data_provider { // resubmit and it is back assert_ok!(Staking::nominate(Origin::signed(100), vec![11, 21])); assert_eq!( - >::voters(None) + ::voters(None) .unwrap() .iter() .find(|x| x.0 == 101)