Crate pallet_elections_phragmen
source ·Expand description
Phragmén Election Module.
An election module based on sequential phragmen.
Term and Round
The election happens in rounds: every N
blocks, all previous members are retired and a new
set is elected (which may or may not have an intersection with the previous set). Each round
lasts for some number of blocks defined by Config::TermDuration
. The words term and
round can be used interchangeably in this context.
Config::TermDuration
might change during a round. This can shorten or extend the length of
the round. The next election round’s block number is never stored but rather always checked on
the fly. Based on the current block number and Config::TermDuration
, the condition
BlockNumber % TermDuration == 0
being satisfied will always trigger a new election round.
Bonds and Deposits
Both voting and being a candidate requires deposits to be taken, in exchange for the data that needs to be kept on-chain. The terms bond and deposit can be used interchangeably in this context.
Bonds will be unreserved only upon adhering to the protocol laws. Failing to do so will cause in the bond to slashed.
Voting
Voters can vote for a limited number of the candidates by providing a list of account ids,
bounded by MAXIMUM_VOTE
. Invalid votes (voting for non-candidates) and duplicate votes are
ignored during election. Yet, a voter might vote for a future candidate. Voters reserve a bond
as they vote. Each vote defines a value
. This amount is locked from the account of the voter
and indicates the weight of the vote. Voters can update their votes at any time by calling
vote()
again. This can update the vote targets (which might update the deposit) or update the
vote’s stake (Voter::stake
). After a round, votes are kept and might still be valid for
further rounds. A voter is responsible for calling remove_voter
once they are done to have
their bond back and remove the lock.
See Call::vote
, Call::remove_voter
.
Defunct Voter
A voter is defunct once all of the candidates that they have voted for are not a valid candidate
(as seen further below, members and runners-up are also always candidates). Defunct voters can
be removed via a root call (Call::clean_defunct_voters
). Upon being removed, their bond is
returned. This is an administrative operation and can be called only by the root origin in the
case of state bloat.
Candidacy and Members
Candidates also reserve a bond as they submit candidacy. A candidate can end up in one of the below situations:
- Members: A winner is kept as a member. They must still have a bond in reserve and they
are automatically counted as a candidate for the next election. The number of desired
members is set by
Config::DesiredMembers
. - Runner-up: Runners-up are the best candidates immediately after the winners. The number
of runners up to keep is set by
Config::DesiredRunnersUp
. Runners-up are used, in the same order as they are elected, as replacements when a candidate is kicked byCall::remove_member
, or when an active member renounces their candidacy. Runners are automatically counted as a candidate for the next election. - Loser: Any of the candidate who are not member/runner-up are left as losers. A loser might be an outgoing member or runner-up, meaning that they are an active member who failed to keep their spot. An outgoing candidate/member/runner-up will always lose their bond.
Renouncing candidacy.
All candidates, elected or not, can renounce their candidacy. A call to
Call::renounce_candidacy
will always cause the candidacy bond to be refunded.
Note that with the members being the default candidates for the next round and votes persisting
in storage, the election system is entirely stable given no further input. This means that if
the system has a particular set of candidates C
and voters V
that lead to a set of members
M
being elected, as long as V
and C
don’t remove their candidacy and votes, M
will keep
being re-elected at the end of each round.
Module Information
Re-exports
pub use weights::WeightInfo;
pub use pallet::*;