Expand description
Primitive traits for providing election functionality.
This crate provides two traits that could interact to enable extensible election functionality within FRAME pallets.
Something that will provide the functionality of election will implement ElectionProvider
,
whilst needing an associated ElectionProvider::DataProvider
, which needs to be fulfilled by
an entity implementing ElectionDataProvider
. Most often, the data provider is the receiver
of the election, resulting in a diagram as below:
ElectionDataProvider
<------------------------------------------+
| |
v |
+-----+----+ +------+---+
| | | |
pallet-do-election | | | | pallet-needs-election
| | | |
| | | |
+-----+----+ +------+---+
| ^
| |
+------------------------------------------+
ElectionProvider
It could also be possible that a third party pallet (C), provides the data of election to an election provider (B), which then passes the election result to another pallet (A).
Election Types
Typically, two types of elections exist:
- Stateless: Election data is provided, and the election result is immediately ready.
- Stateful: Election data is is queried ahead of time, and the election result might be ready some number of blocks in the future.
To accommodate both type of elections in one trait, the traits lean toward stateful
election, as it is more general than the stateless. This is why ElectionProvider::elect
has no parameters. All value and type parameter must be provided by the ElectionDataProvider
trait, even if the election happens immediately.
Election Data
The data associated with an election, essentially what the ElectionDataProvider
must convey
is as follows:
- A list of voters, with their stake.
- A list of targets (i.e. candidates).
- A number of desired targets to be elected (i.e. winners)
In addition to that, the ElectionDataProvider
must also hint ElectionProvider
at when
the next election might happen (ElectionDataProvider::next_election_prediction
). A stateless
election provider would probably ignore this. A stateful election provider can use this to
prepare the election result in advance.
Nonetheless, an ElectionProvider
shan’t rely on this and should preferably provide some
means of fallback election as well, in case the elect
was called immaturely early.
Example
type AccountId = u64;
type Balance = u64;
type BlockNumber = u32;
mod data_provider_mod {
use super::*;
pub trait Config: Sized {
type ElectionProvider: ElectionProvider<
AccountId = AccountId,
BlockNumber = BlockNumber,
DataProvider = Pallet<Self>,
>;
}
pub struct Pallet<T: Config>(std::marker::PhantomData<T>);
impl<T: Config> ElectionDataProvider for Pallet<T> {
type AccountId = AccountId;
type BlockNumber = BlockNumber;
type MaxVotesPerVoter = ConstU32<1>;
fn desired_targets() -> data_provider::Result<u32> {
Ok(1)
}
fn electing_voters(maybe_max_len: Option<usize>)
-> data_provider::Result<Vec<VoterOf<Self>>>
{
Ok(Default::default())
}
fn electable_targets(maybe_max_len: Option<usize>) -> data_provider::Result<Vec<AccountId>> {
Ok(vec![10, 20, 30])
}
fn next_election_prediction(now: BlockNumber) -> BlockNumber {
0
}
}
}
mod generic_election_provider {
use super::*;
pub struct GenericElectionProvider<T: Config>(std::marker::PhantomData<T>);
pub trait Config {
type DataProvider: ElectionDataProvider<AccountId=AccountId, BlockNumber = BlockNumber>;
}
impl<T: Config> ElectionProvider for GenericElectionProvider<T> {
type AccountId = AccountId;
type BlockNumber = BlockNumber;
type Error = &'static str;
type DataProvider = T::DataProvider;
fn elect() -> Result<Supports<AccountId>, Self::Error> {
Self::DataProvider::electable_targets(None)
.map_err(|_| "failed to elect")
.map(|t| vec![(t[0], Support::default())])
}
}
}
mod runtime {
use super::generic_election_provider;
use super::data_provider_mod;
use super::AccountId;
struct Runtime;
impl generic_election_provider::Config for Runtime {
type DataProvider = data_provider_mod::Pallet<Runtime>;
}
impl data_provider_mod::Config for Runtime {
type ElectionProvider = generic_election_provider::GenericElectionProvider<Runtime>;
}
}
Re-exports
pub use traits::NposSolution;
pub use weights::WeightInfo;
Modules
ElectionProvider
that uses an NposSolver
to do the election. As the
name suggests, this is meant to be used onchain. Given how heavy the calculations are, please be
careful when using it onchain.Macros
sp_npos_elections::Assignment<_>
.Structs
IndexAssignment
type is an intermediate between the assignments list
(&[Assignment<T>]
) and SolutionOf<T>
.sp_npos_elections::phragmms()
that implements NposSolver
. See the
documentation of sp_npos_elections::phragmms()
for more info.sp_npos_elections::seq_phragmen
that implements NposSolver
. See the
documentation of sp_npos_elections::seq_phragmen
for more info.Enums
frame-election-provider-solution-type
.Traits
ElectionProvider
.ElectionProvider
for cases where we need to be sure an election needs to
happen instantly, not asynchronously.X
, as parts per
X
.Score
of an account. Similar to ElectionProvider
and
ElectionDataProvider
, this should typically be implementing by whoever is supposed to use
SortedListProvider
.ElectionDataProvider
in a sensible way.Type Definitions
IndexAssignment
made from NposSolution
.ExtendedBalance
for computation.Voter
, but parameterized by an ElectionDataProvider
.