mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 14:01:02 +00:00
bounding staking: BoundedElectionProvider trait (#12362)
* add a bounded election provider trait * extract common trait election provider base * fmt * only bound the outer support vector * fix tests * docs * fix rust docs * fmt * fix rustdocs * docs * improve docs * small doc change
This commit is contained in:
@@ -231,7 +231,8 @@
|
|||||||
|
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
use frame_election_provider_support::{
|
use frame_election_provider_support::{
|
||||||
ElectionDataProvider, ElectionProvider, InstantElectionProvider, NposSolution,
|
ElectionDataProvider, ElectionProvider, ElectionProviderBase, InstantElectionProvider,
|
||||||
|
NposSolution,
|
||||||
};
|
};
|
||||||
use frame_support::{
|
use frame_support::{
|
||||||
dispatch::DispatchClass,
|
dispatch::DispatchClass,
|
||||||
@@ -289,7 +290,7 @@ pub type SolutionTargetIndexOf<T> = <SolutionOf<T> as NposSolution>::TargetIndex
|
|||||||
pub type SolutionAccuracyOf<T> =
|
pub type SolutionAccuracyOf<T> =
|
||||||
<SolutionOf<<T as crate::Config>::MinerConfig> as NposSolution>::Accuracy;
|
<SolutionOf<<T as crate::Config>::MinerConfig> as NposSolution>::Accuracy;
|
||||||
/// The fallback election type.
|
/// The fallback election type.
|
||||||
pub type FallbackErrorOf<T> = <<T as crate::Config>::Fallback as ElectionProvider>::Error;
|
pub type FallbackErrorOf<T> = <<T as crate::Config>::Fallback as ElectionProviderBase>::Error;
|
||||||
|
|
||||||
/// Configuration for the benchmarks of the pallet.
|
/// Configuration for the benchmarks of the pallet.
|
||||||
pub trait BenchmarkingConfig {
|
pub trait BenchmarkingConfig {
|
||||||
@@ -312,7 +313,7 @@ pub trait BenchmarkingConfig {
|
|||||||
/// A fallback implementation that transitions the pallet to the emergency phase.
|
/// A fallback implementation that transitions the pallet to the emergency phase.
|
||||||
pub struct NoFallback<T>(sp_std::marker::PhantomData<T>);
|
pub struct NoFallback<T>(sp_std::marker::PhantomData<T>);
|
||||||
|
|
||||||
impl<T: Config> ElectionProvider for NoFallback<T> {
|
impl<T: Config> ElectionProviderBase for NoFallback<T> {
|
||||||
type AccountId = T::AccountId;
|
type AccountId = T::AccountId;
|
||||||
type BlockNumber = T::BlockNumber;
|
type BlockNumber = T::BlockNumber;
|
||||||
type DataProvider = T::DataProvider;
|
type DataProvider = T::DataProvider;
|
||||||
@@ -321,7 +322,9 @@ impl<T: Config> ElectionProvider for NoFallback<T> {
|
|||||||
fn ongoing() -> bool {
|
fn ongoing() -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Config> ElectionProvider for NoFallback<T> {
|
||||||
fn elect() -> Result<Supports<T::AccountId>, Self::Error> {
|
fn elect() -> Result<Supports<T::AccountId>, Self::Error> {
|
||||||
// Do nothing, this will enable the emergency phase.
|
// Do nothing, this will enable the emergency phase.
|
||||||
Err("NoFallback.")
|
Err("NoFallback.")
|
||||||
@@ -1563,7 +1566,7 @@ impl<T: Config> Pallet<T> {
|
|||||||
<QueuedSolution<T>>::take()
|
<QueuedSolution<T>>::take()
|
||||||
.ok_or(ElectionError::<T>::NothingQueued)
|
.ok_or(ElectionError::<T>::NothingQueued)
|
||||||
.or_else(|_| {
|
.or_else(|_| {
|
||||||
T::Fallback::elect()
|
<T::Fallback as ElectionProvider>::elect()
|
||||||
.map(|supports| ReadySolution {
|
.map(|supports| ReadySolution {
|
||||||
supports,
|
supports,
|
||||||
score: Default::default(),
|
score: Default::default(),
|
||||||
@@ -1598,7 +1601,7 @@ impl<T: Config> Pallet<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Config> ElectionProvider for Pallet<T> {
|
impl<T: Config> ElectionProviderBase for Pallet<T> {
|
||||||
type AccountId = T::AccountId;
|
type AccountId = T::AccountId;
|
||||||
type BlockNumber = T::BlockNumber;
|
type BlockNumber = T::BlockNumber;
|
||||||
type Error = ElectionError<T>;
|
type Error = ElectionError<T>;
|
||||||
@@ -1610,7 +1613,9 @@ impl<T: Config> ElectionProvider for Pallet<T> {
|
|||||||
_ => true,
|
_ => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Config> ElectionProvider for Pallet<T> {
|
||||||
fn elect() -> Result<Supports<T::AccountId>, Self::Error> {
|
fn elect() -> Result<Supports<T::AccountId>, Self::Error> {
|
||||||
match Self::do_elect() {
|
match Self::do_elect() {
|
||||||
Ok(supports) => {
|
Ok(supports) => {
|
||||||
@@ -1627,7 +1632,6 @@ impl<T: Config> ElectionProvider for Pallet<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// convert a DispatchError to a custom InvalidTransaction with the inner code being the error
|
/// convert a DispatchError to a custom InvalidTransaction with the inner code being the error
|
||||||
/// number.
|
/// number.
|
||||||
pub fn dispatch_error_to_invalid(error: DispatchError) -> InvalidTransaction {
|
pub fn dispatch_error_to_invalid(error: DispatchError) -> InvalidTransaction {
|
||||||
|
|||||||
@@ -297,7 +297,7 @@ impl onchain::Config for OnChainSeqPhragmen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct MockFallback;
|
pub struct MockFallback;
|
||||||
impl ElectionProvider for MockFallback {
|
impl ElectionProviderBase for MockFallback {
|
||||||
type AccountId = AccountId;
|
type AccountId = AccountId;
|
||||||
type BlockNumber = u64;
|
type BlockNumber = u64;
|
||||||
type Error = &'static str;
|
type Error = &'static str;
|
||||||
@@ -306,7 +306,8 @@ impl ElectionProvider for MockFallback {
|
|||||||
fn ongoing() -> bool {
|
fn ongoing() -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
impl ElectionProvider for MockFallback {
|
||||||
fn elect() -> Result<Supports<AccountId>, Self::Error> {
|
fn elect() -> Result<Supports<AccountId>, Self::Error> {
|
||||||
Self::elect_with_bounds(Bounded::max_value(), Bounded::max_value())
|
Self::elect_with_bounds(Bounded::max_value(), Bounded::max_value())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,11 @@
|
|||||||
//! This crate provides two traits that could interact to enable extensible election functionality
|
//! This crate provides two traits that could interact to enable extensible election functionality
|
||||||
//! within FRAME pallets.
|
//! within FRAME pallets.
|
||||||
//!
|
//!
|
||||||
//! Something that will provide the functionality of election will implement [`ElectionProvider`],
|
//! Something that will provide the functionality of election will implement
|
||||||
//! whilst needing an associated [`ElectionProvider::DataProvider`], which needs to be fulfilled by
|
//! [`ElectionProvider`] and its parent-trait [`ElectionProviderBase`], whilst needing an
|
||||||
//! an entity implementing [`ElectionDataProvider`]. Most often, *the data provider is* the receiver
|
//! associated [`ElectionProviderBase::DataProvider`], which needs to be
|
||||||
//! of the election, resulting in a diagram as below:
|
//! fulfilled by an entity implementing [`ElectionDataProvider`]. Most often, *the data provider is*
|
||||||
|
//! the receiver of the election, resulting in a diagram as below:
|
||||||
//!
|
//!
|
||||||
//! ```ignore
|
//! ```ignore
|
||||||
//! ElectionDataProvider
|
//! ElectionDataProvider
|
||||||
@@ -131,12 +132,16 @@
|
|||||||
//! type DataProvider: ElectionDataProvider<AccountId=AccountId, BlockNumber = BlockNumber>;
|
//! type DataProvider: ElectionDataProvider<AccountId=AccountId, BlockNumber = BlockNumber>;
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! impl<T: Config> ElectionProvider for GenericElectionProvider<T> {
|
//! impl<T: Config> ElectionProviderBase for GenericElectionProvider<T> {
|
||||||
//! type AccountId = AccountId;
|
//! type AccountId = AccountId;
|
||||||
//! type BlockNumber = BlockNumber;
|
//! type BlockNumber = BlockNumber;
|
||||||
//! type Error = &'static str;
|
//! type Error = &'static str;
|
||||||
//! type DataProvider = T::DataProvider;
|
//! type DataProvider = T::DataProvider;
|
||||||
//! fn ongoing() -> bool { false }
|
//! fn ongoing() -> bool { false }
|
||||||
|
//!
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! impl<T: Config> ElectionProvider for GenericElectionProvider<T> {
|
||||||
//! fn elect() -> Result<Supports<AccountId>, Self::Error> {
|
//! fn elect() -> Result<Supports<AccountId>, Self::Error> {
|
||||||
//! Self::DataProvider::electable_targets(None)
|
//! Self::DataProvider::electable_targets(None)
|
||||||
//! .map_err(|_| "failed to elect")
|
//! .map_err(|_| "failed to elect")
|
||||||
@@ -177,8 +182,8 @@ pub use frame_support::{traits::Get, weights::Weight, BoundedVec, RuntimeDebug};
|
|||||||
/// Re-export some type as they are used in the interface.
|
/// Re-export some type as they are used in the interface.
|
||||||
pub use sp_arithmetic::PerThing;
|
pub use sp_arithmetic::PerThing;
|
||||||
pub use sp_npos_elections::{
|
pub use sp_npos_elections::{
|
||||||
Assignment, BalancingConfig, ElectionResult, Error, ExtendedBalance, IdentifierT, PerThing128,
|
Assignment, BalancingConfig, BoundedSupports, ElectionResult, Error, ExtendedBalance,
|
||||||
Support, Supports, VoteWeight,
|
IdentifierT, PerThing128, Support, Supports, VoteWeight,
|
||||||
};
|
};
|
||||||
pub use traits::NposSolution;
|
pub use traits::NposSolution;
|
||||||
|
|
||||||
@@ -349,12 +354,12 @@ pub trait ElectionDataProvider {
|
|||||||
fn clear() {}
|
fn clear() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Something that can compute the result of an election and pass it back to the caller.
|
/// Base trait for [`ElectionProvider`] and [`BoundedElectionProvider`]. It is
|
||||||
|
/// meant to be used only with an extension trait that adds an election
|
||||||
|
/// functionality.
|
||||||
///
|
///
|
||||||
/// This trait only provides an interface to _request_ an election, i.e.
|
/// Data can be bounded or unbounded and is fetched from [`Self::DataProvider`].
|
||||||
/// [`ElectionProvider::elect`]. That data required for the election need to be passed to the
|
pub trait ElectionProviderBase {
|
||||||
/// implemented of this trait through [`ElectionProvider::DataProvider`].
|
|
||||||
pub trait ElectionProvider {
|
|
||||||
/// The account identifier type.
|
/// The account identifier type.
|
||||||
type AccountId;
|
type AccountId;
|
||||||
|
|
||||||
@@ -372,24 +377,39 @@ pub trait ElectionProvider {
|
|||||||
|
|
||||||
/// Indicate if this election provider is currently ongoing an asynchronous election or not.
|
/// Indicate if this election provider is currently ongoing an asynchronous election or not.
|
||||||
fn ongoing() -> bool;
|
fn ongoing() -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
/// Elect a new set of winners, without specifying any bounds on the amount of data fetched from
|
/// Elect a new set of winners, bounded by `MaxWinners`.
|
||||||
/// [`Self::DataProvider`]. An implementation could nonetheless impose its own custom limits.
|
///
|
||||||
///
|
/// Returns a result in bounded, target major format, namely as
|
||||||
/// The result is returned in a target major format, namely as *vector of supports*.
|
/// *BoundedVec<(AccountId, Vec<Support>), MaxWinners>*.
|
||||||
///
|
pub trait BoundedElectionProvider: ElectionProviderBase {
|
||||||
/// This should be implemented as a self-weighing function. The implementor should register its
|
/// The upper bound on election winners.
|
||||||
/// appropriate weight at the end of execution with the system pallet directly.
|
type MaxWinners: Get<u32>;
|
||||||
|
/// Performs the election. 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<BoundedSupports<Self::AccountId, Self::MaxWinners>, Self::Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Same a [`BoundedElectionProvider`], but no bounds are imposed on the number
|
||||||
|
/// of winners.
|
||||||
|
///
|
||||||
|
/// The result is returned in a target major format, namely as
|
||||||
|
///*Vec<(AccountId, Vec<Support>)>*.
|
||||||
|
pub trait ElectionProvider: ElectionProviderBase {
|
||||||
|
/// Performs the election. This should be implemented as a self-weighing
|
||||||
|
/// function, similar to [`BoundedElectionProvider::elect()`].
|
||||||
fn elect() -> Result<Supports<Self::AccountId>, Self::Error>;
|
fn elect() -> Result<Supports<Self::AccountId>, Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A sub-trait of the [`ElectionProvider`] for cases where we need to be sure an election needs to
|
/// A sub-trait of the [`ElectionProvider`] for cases where we need to be sure
|
||||||
/// happen instantly, not asynchronously.
|
/// an election needs to happen instantly, not asynchronously.
|
||||||
///
|
///
|
||||||
/// The same `DataProvider` is assumed to be used.
|
/// The same `DataProvider` is assumed to be used.
|
||||||
///
|
///
|
||||||
/// Consequently, allows for control over the amount of data that is being fetched from the
|
/// Consequently, allows for control over the amount of data that is being
|
||||||
/// [`ElectionProvider::DataProvider`].
|
/// fetched from the [`ElectionProviderBase::DataProvider`].
|
||||||
pub trait InstantElectionProvider: ElectionProvider {
|
pub trait InstantElectionProvider: ElectionProvider {
|
||||||
/// Elect a new set of winners, but unlike [`ElectionProvider::elect`] which cannot enforce
|
/// Elect a new set of winners, but unlike [`ElectionProvider::elect`] which cannot enforce
|
||||||
/// bounds, this trait method can enforce bounds on the amount of data provided by the
|
/// bounds, this trait method can enforce bounds on the amount of data provided by the
|
||||||
@@ -410,7 +430,7 @@ pub trait InstantElectionProvider: ElectionProvider {
|
|||||||
pub struct NoElection<X>(sp_std::marker::PhantomData<X>);
|
pub struct NoElection<X>(sp_std::marker::PhantomData<X>);
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl<AccountId, BlockNumber, DataProvider> ElectionProvider
|
impl<AccountId, BlockNumber, DataProvider> ElectionProviderBase
|
||||||
for NoElection<(AccountId, BlockNumber, DataProvider)>
|
for NoElection<(AccountId, BlockNumber, DataProvider)>
|
||||||
where
|
where
|
||||||
DataProvider: ElectionDataProvider<AccountId = AccountId, BlockNumber = BlockNumber>,
|
DataProvider: ElectionDataProvider<AccountId = AccountId, BlockNumber = BlockNumber>,
|
||||||
@@ -420,15 +440,22 @@ where
|
|||||||
type Error = &'static str;
|
type Error = &'static str;
|
||||||
type DataProvider = DataProvider;
|
type DataProvider = DataProvider;
|
||||||
|
|
||||||
fn elect() -> Result<Supports<AccountId>, Self::Error> {
|
|
||||||
Err("<NoElection as ElectionProvider> cannot do anything.")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ongoing() -> bool {
|
fn ongoing() -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl<AccountId, BlockNumber, DataProvider> ElectionProvider
|
||||||
|
for NoElection<(AccountId, BlockNumber, DataProvider)>
|
||||||
|
where
|
||||||
|
DataProvider: ElectionDataProvider<AccountId = AccountId, BlockNumber = BlockNumber>,
|
||||||
|
{
|
||||||
|
fn elect() -> Result<Supports<AccountId>, Self::Error> {
|
||||||
|
Err("<NoElection as ElectionProvider> cannot do anything.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A utility trait for something to implement `ElectionDataProvider` in a sensible way.
|
/// A utility trait for something to implement `ElectionDataProvider` in a sensible way.
|
||||||
///
|
///
|
||||||
/// This is generic over `AccountId` and it can represent a validator, a nominator, or any other
|
/// This is generic over `AccountId` and it can represent a validator, a nominator, or any other
|
||||||
|
|||||||
@@ -20,7 +20,8 @@
|
|||||||
//! careful when using it onchain.
|
//! careful when using it onchain.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Debug, ElectionDataProvider, ElectionProvider, InstantElectionProvider, NposSolver, WeightInfo,
|
Debug, ElectionDataProvider, ElectionProvider, ElectionProviderBase, InstantElectionProvider,
|
||||||
|
NposSolver, WeightInfo,
|
||||||
};
|
};
|
||||||
use frame_support::{dispatch::DispatchClass, traits::Get};
|
use frame_support::{dispatch::DispatchClass, traits::Get};
|
||||||
use sp_npos_elections::*;
|
use sp_npos_elections::*;
|
||||||
@@ -133,15 +134,6 @@ fn elect_with<T: Config>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Config> ElectionProvider for UnboundedExecution<T> {
|
impl<T: Config> ElectionProvider for UnboundedExecution<T> {
|
||||||
type AccountId = <T::System as frame_system::Config>::AccountId;
|
|
||||||
type BlockNumber = <T::System as frame_system::Config>::BlockNumber;
|
|
||||||
type Error = Error;
|
|
||||||
type DataProvider = T::DataProvider;
|
|
||||||
|
|
||||||
fn ongoing() -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
fn elect() -> Result<Supports<Self::AccountId>, Self::Error> {
|
fn elect() -> Result<Supports<Self::AccountId>, Self::Error> {
|
||||||
// This should not be called if not in `std` mode (and therefore neither in genesis nor in
|
// This should not be called if not in `std` mode (and therefore neither in genesis nor in
|
||||||
// testing)
|
// testing)
|
||||||
@@ -156,6 +148,17 @@ impl<T: Config> ElectionProvider for UnboundedExecution<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Config> ElectionProviderBase for UnboundedExecution<T> {
|
||||||
|
type AccountId = <T::System as frame_system::Config>::AccountId;
|
||||||
|
type BlockNumber = <T::System as frame_system::Config>::BlockNumber;
|
||||||
|
type Error = Error;
|
||||||
|
type DataProvider = T::DataProvider;
|
||||||
|
|
||||||
|
fn ongoing() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: Config> InstantElectionProvider for UnboundedExecution<T> {
|
impl<T: Config> InstantElectionProvider for UnboundedExecution<T> {
|
||||||
fn elect_with_bounds(
|
fn elect_with_bounds(
|
||||||
max_voters: usize,
|
max_voters: usize,
|
||||||
@@ -165,7 +168,7 @@ impl<T: Config> InstantElectionProvider for UnboundedExecution<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: BoundedConfig> ElectionProvider for BoundedExecution<T> {
|
impl<T: BoundedConfig> ElectionProviderBase for BoundedExecution<T> {
|
||||||
type AccountId = <T::System as frame_system::Config>::AccountId;
|
type AccountId = <T::System as frame_system::Config>::AccountId;
|
||||||
type BlockNumber = <T::System as frame_system::Config>::BlockNumber;
|
type BlockNumber = <T::System as frame_system::Config>::BlockNumber;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
@@ -174,7 +177,9 @@ impl<T: BoundedConfig> ElectionProvider for BoundedExecution<T> {
|
|||||||
fn ongoing() -> bool {
|
fn ongoing() -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: BoundedConfig> ElectionProvider for BoundedExecution<T> {
|
||||||
fn elect() -> Result<Supports<Self::AccountId>, Self::Error> {
|
fn elect() -> Result<Supports<Self::AccountId>, Self::Error> {
|
||||||
elect_with::<T>(Some(T::VotersBound::get() as usize), Some(T::TargetsBound::get() as usize))
|
elect_with::<T>(Some(T::VotersBound::get() as usize), Some(T::TargetsBound::get() as usize))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ macro_rules! log {
|
|||||||
pub mod pallet {
|
pub mod pallet {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
use frame_election_provider_support::ElectionProvider;
|
use frame_election_provider_support::ElectionProviderBase;
|
||||||
use frame_support::{
|
use frame_support::{
|
||||||
pallet_prelude::*,
|
pallet_prelude::*,
|
||||||
traits::{Defensive, ReservableCurrency},
|
traits::{Defensive, ReservableCurrency},
|
||||||
@@ -330,7 +330,8 @@ pub mod pallet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if <T as pallet_staking::Config>::ElectionProvider::ongoing() {
|
if <<T as pallet_staking::Config>::ElectionProvider as ElectionProviderBase>::ongoing()
|
||||||
|
{
|
||||||
// NOTE: we assume `ongoing` does not consume any weight.
|
// NOTE: we assume `ongoing` does not consume any weight.
|
||||||
// there is an ongoing election -- we better not do anything. Imagine someone is not
|
// there is an ongoing election -- we better not do anything. Imagine someone is not
|
||||||
// exposed anywhere in the last era, and the snapshot for the election is already
|
// exposed anywhere in the last era, and the snapshot for the election is already
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ parameter_types! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct MockElection;
|
pub struct MockElection;
|
||||||
impl frame_election_provider_support::ElectionProvider for MockElection {
|
impl frame_election_provider_support::ElectionProviderBase for MockElection {
|
||||||
type AccountId = AccountId;
|
type AccountId = AccountId;
|
||||||
type BlockNumber = BlockNumber;
|
type BlockNumber = BlockNumber;
|
||||||
type DataProvider = Staking;
|
type DataProvider = Staking;
|
||||||
@@ -113,7 +113,9 @@ impl frame_election_provider_support::ElectionProvider for MockElection {
|
|||||||
fn ongoing() -> bool {
|
fn ongoing() -> bool {
|
||||||
Ongoing::get()
|
Ongoing::get()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl frame_election_provider_support::ElectionProvider for MockElection {
|
||||||
fn elect() -> Result<frame_election_provider_support::Supports<AccountId>, Self::Error> {
|
fn elect() -> Result<frame_election_provider_support::Supports<AccountId>, Self::Error> {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,17 +74,16 @@
|
|||||||
|
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
|
use codec::{Decode, Encode, MaxEncodedLen};
|
||||||
use scale_info::TypeInfo;
|
use scale_info::TypeInfo;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use sp_arithmetic::{traits::Zero, Normalizable, PerThing, Rational128, ThresholdOrd};
|
use sp_arithmetic::{traits::Zero, Normalizable, PerThing, Rational128, ThresholdOrd};
|
||||||
use sp_core::RuntimeDebug;
|
use sp_core::{bounded::BoundedVec, RuntimeDebug};
|
||||||
use sp_std::{
|
use sp_std::{
|
||||||
cell::RefCell, cmp::Ordering, collections::btree_map::BTreeMap, prelude::*, rc::Rc, vec,
|
cell::RefCell, cmp::Ordering, collections::btree_map::BTreeMap, prelude::*, rc::Rc, vec,
|
||||||
};
|
};
|
||||||
|
|
||||||
use codec::{Decode, Encode, MaxEncodedLen};
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod mock;
|
mod mock;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -451,6 +450,11 @@ impl<AccountId> Default for Support<AccountId> {
|
|||||||
/// The main advantage of this is that it is encodable.
|
/// The main advantage of this is that it is encodable.
|
||||||
pub type Supports<A> = Vec<(A, Support<A>)>;
|
pub type Supports<A> = Vec<(A, Support<A>)>;
|
||||||
|
|
||||||
|
/// Same as `Supports` bounded by `MaxWinners`.
|
||||||
|
///
|
||||||
|
/// To note, the inner `Support` is still unbounded.
|
||||||
|
pub type BoundedSupports<A, MaxWinners> = BoundedVec<(A, Support<A>), MaxWinners>;
|
||||||
|
|
||||||
/// Linkage from a winner to their [`Support`].
|
/// Linkage from a winner to their [`Support`].
|
||||||
///
|
///
|
||||||
/// This is more helpful than a normal [`Supports`] as it allows faster error checking.
|
/// This is more helpful than a normal [`Supports`] as it allows faster error checking.
|
||||||
|
|||||||
Reference in New Issue
Block a user