referrerpolicy=no-referrer-when-downgrade

Crate pallet_election_provider_multi_block

Source
Expand description

§Multi-phase, multi-block, election provider pallet.

This pallet is sometimes abbreviated as EPMB, and pallet_election_provider_multi_phase as EPM.

§Overall idea

pallet_election_provider_multi_phase provides the basic ability for NPoS solutions to be computed offchain (essentially anywhere) and submitted back to the chain as signed or unsigned transaction, with sensible configurations and fail-safe mechanisms to ensure system safety. Nonetheless, it has a limited capacity in terms of number of voters it can process in a single block.

This pallet takes EPM system, keeps most of its ideas and core premises, and extends it to support paginated, multi-block operations. The final goal of this pallet is to scale linearly with the number of blocks allocated to the elections. Moreover, the amount of work that it does in one block should be bounded and measurable, making it suitable for a parachain. In principle, with large enough blocks (in a dedicated parachain), the number of voters included in the NPoS system can grow significantly (yet, obviously not indefinitely).

Note that this pallet does not consider how the recipient is processing the results. To ensure scalability, the recipient of this pallet’s data (i.e. pallet-staking) must also be capable of pagination and multi-block processing.

§Companion pallets

This pallet will only function in a sensible way if it is peered with its companion pallets.

These pallets are in fact hierarchical. This particular one is the top level one. It contains the shared information that all child pallets use. All child pallets depend on the top level pallet ONLY, but not the other way around. For those cases, traits are used.

As in, notice that crate::verifier::Config relies on crate::Config, but for the reverse, we rely on crate::verifier::Verifier trait, which is indeed part of crate::Config. This is merely an implementation opinion.

§Pallet Ordering:

TODO: @kiaenigma: this needs clarification and a enforcement. Signed pallet should come first. Fixing this should yield removing verifier_done from the phase transition.

The ordering of these pallets in a runtime should be:

  • parent
  • verifier
  • signed
  • unsigned

This is critical for the phase transition to work.

This should be manually checked, there is not automated way to test it.

§Pagination

Most of the external APIs of this pallet are paginated. All pagination follow a pattern where if N pages exist, the first paginated call is function(N-1) and the last one is function(0). For example, with 3 pages, the elect of [ElectionProvider] is expected to be called as elect(2) -> elect(1) -> elect(0). In essence, calling a paginated function with index 0 is always a signal of termination, meaning that no further calls will follow.

The snapshot creation for voters (Nominators in staking), submission of signed pages, validation of signed solutions and exporting of pages are all paginated. Note that this pallet is yet to support paginated target (Validators in staking) snapshotting.

§Terminology Note: msp and lsp

Stand for most significant page (n-1) and least significant page (0).

See [ElectionProvider::msp] and [ElectionProvider::lsp], and their usage.

§Phases

The operations in this pallet are divided intor rounds, a u32 number stored in Round. This value helps this pallet organize itself, and leaves the door open for lazy deletion of any stale data. A round, under the happy path, starts by receiving the call to [ElectionProvider::start], and is terminated by receiving a call to [ElectionProvider::elect] with value 0.

The timeline of pallet is overall as follows:

 <  Off  >
0 ------------ 12 13 14 15 ----------- 20 ---------25 ------- 30
	           |       |              |            |          |
	     Snapshot      Signed   SignedValidation  Unsigned   Elect
  • Duration of Snapshot is determined by Config::Pages + 1.
    • Whereby in the first page we take the “Targets” snapshot, and in the subsequent pages we take the voter snapshot.
    • For example, with Pages = 4:
      • Snapshot(4) -> Targets(all)
      • Snapshot(3) -> Voters(3)
      • Snapshot(2) -> Voters(2)
      • Snapshot(1) -> Voters(1)
      • Snapshot(0) -> Voters(0)
  • Duration of Signed, SignedValidation and Unsigned are determined by Config::SignedPhase, Config::SignedValidationPhase and Config::UnsignedPhase respectively.
  • Config::Pages calls to elect are expected, but all in all the pallet will close a round once elect(0) is called.

Given this, it is rather important for the user of this pallet to ensure it always terminates election via elect before requesting a new one.

§Feasible Solution (correct solution)

All submissions must undergo a feasibility check. Signed solutions are checked one by one at the end of the signed phase, and the unsigned solutions are checked on the spot. A feasible solution is as follows:

  1. all of the used indices must be correct.
  2. present exactly correct number of winners.
  3. any assignment is checked to match with PagedVoterSnapshot.
  4. the claimed score is valid, based on the fixed point arithmetic accuracy.

More about this in verifier, who is responsible for doing all of the above.

§Fallback and Emergency

If at any page, [ElectionProvider::elect] fails, a call with the same page-index is dispatched to Config::Fallback. Config::Fallback is itself (yet) another implementation of [ElectionProvider], and can decide to do anything, but a few reasonable options are provided here:

  1. Do nothing: Continue
  2. Force us into the emergency phase: crate::InitiateEmergencyPhase. This initiates Phase::Emergency, which will halt almost all operations of this pallet, and it can only be recovered by AdminOperation, dispatched via Call::manage.
  3. compute an onchain from the give page of snapshot.

Note that configuring the fallback to be onchain computation is not recommended, unless for test-nets for a number of reasons:

  1. The solution score of fallback is never checked to match the “minimum” score. That being said, the computation happens onchain so we can trust it.
  2. The onchain fallback runs on the same number of voters and targets that reside on a single page of a snapshot, which will very likely be too much for actual onchain computation. Yet, we don’t have another choice as we cannot request another smaller snapshot from the data provider mid-election without more bookkeeping on the staking side.

If onchain solution is to be seriously considered, an improvement to this pallet should re-request a smaller set of voters from T::DataProvider in a stateless manner.

§Signed Phase

Signed phase is when an offchain miner, aka, polkadot-staking-miner should operate upon. See signed for more information.

§Unsigned Phase

Unsigned phase is a built-in fallback in which validators may submit a single page election, taking into account only the [ElectionProvider::msp] (most significant page). See crate::unsigned for more information.

Re-exports§

pub use weights::traits::pallet_election_provider_multi_block::WeightInfo;
pub use pallet::*;
pub use types::*;

Modules§

benchmarking
helpers
Some helper functions/macros for this crate.
pallet
The pallet module in each FRAME pallet hosts the most important items needed to construct this pallet.
signed
The signed pallet The signed phase of the multi-block election system.
types
Common types of the pallet Common types and traits of the EPMB pallet group.
unsigned
The unsigned pallet
verifier
The verifier pallet
weights
The weight module WeightInfo for the election provider multi-block pallet group.

Macros§

log
Emit a log specific to this pallet, setting the target to crate::LOG_PREFIX
miner_log
Emit a log from within the offchain miner.
sublog
Emit a log within a submodule of the pallet

Structs§

CleanRound
An implementation of OnRoundRotation that immediately deletes all the data in all the pallets, once the round is over.
Continue
A fallback implementation that silently continues into the next page.
GetDone
A Get impl for Phase::Done
GetSigned
A Get impl for Phase::Signed(T::SignedPhase::get())
IfSolutionQueuedElse
A easy means to configure Config::AreWeDone.
InitiateEmergencyPhase
A fallback implementation that transitions the pallet to the emergency phase.

Enums§

AdminOperation
Different operations that the Config::AdminOrigin can perform on the pallet.
ElectionError
Internal errors of the pallet. This is used in the implementation of [ElectionProvider].

Constants§

LOG_PREFIX
The common logging prefix of all pallets in this crate.

Traits§

OnRoundRotation
Trait to notify other sub-systems that a round has ended.

Type Aliases§

ProceedRegardlessOf
A shorthand for IfSolutionQueuedElse that proceeds regardless of the solution being queued.
RevertToSignedIfNotQueuedOf
A shorthand for IfSolutionQueuedElse that proceeds to Phase::Done if the solution is queued. Otherwise, it proceeds to Phase::Signed.