Expand description
Validator Collators pallet.
Stores the validator set announced by the chain that runs pallet-staking-async, typically
Asset Hub, and offers it as a session manager, so the relay-chain validators of the current era
collate on a system parachain.
§Overview
The announcing chain sends the active validator set of each era, tagged with the era index of
pallet-staking-async.
This pallet stores the latest set, received through set_validators from Config::SetOrigin
or from another pallet through Pallet::receive_validator_set. It rejects a set whose era
is not newer than the stored one, or that has more validators than Config::MaxValidators.
The pallet is a [pallet_session::SessionManager]. At every session rotation it returns the
stored validators that have registered local session keys, checked with
Config::ValidatorRegistration. The runtime combines this pallet with
pallet-collator-selection through [pallet_session::UnionSessionManager], so invulnerables
and candidates keep collating next to the validators.
MaxCollators optionally caps how many validators are returned. Governance can start with a
low cap and raise it in steps, or lower it again, to roll out validator collators gradually.
Under a cap the pallet draws the validators at random at the first forced rotation after a set
arrives or the cap changes, stores them in Collators and returns those with registered keys
until the next draw. The draw shuffles the whole set with a seed made of the genesis hash, the
era and the relay chain epoch randomness cached in EpochRandomness, then keeps the first
validators with registered keys up to the cap. Every validator with keys has the same chance to
be drawn in each era. A cap change draws again from the stored set, so the drawn validators
can change. Every draw takes its seed from the randomness cached at the time of the draw. The
seed includes the genesis hash, so each chain draws independently from the same set. A
validator that registers keys after the draw waits for the next set or for a cap change. Each
set, so each era, gets a new draw, which is enacted at the second forced rotation with no
notice, so a validator with keys must already run a synced collator node to collate when drawn.
The pallet implements [cumulus_pallet_parachain_system::OnSystemEvent]. The runtime must
include it in the OnSystemEvent of cumulus-pallet-parachain-system, alone or in a tuple
with other handlers, to keep EpochRandomness up to date from the relay chain state proof.
The runtime should also return the keys of Pallet::relay_keys_to_prove from
KeyToIncludeInRelayProof, so collators
include the randomness key in the proof.
The draw runs in the session rotation, before the block’s own proof is processed, so it uses
the value cached by the previous block.
A block whose proof lacks the trie nodes of the randomness key, or holds a value that does not
decode, is invalid. A proof that shows the key absent, as before the relay chain’s first epoch
change, caches the zero value a draw without randomness uses.
Without the OnSystemEvent wiring, every draw uses a zero randomness value and logs an error.
The stored set is the one staking elected for the era. The relay chain enacts only the elected validators with relay-chain session keys, and each system chain returns only those with keys registered there, so a returned collator is not necessarily an active relay-chain validator.
The pallet is also a [pallet_session::ShouldEndSession]. Pallet-session queues a new set at
one rotation and enacts it at the next. When a set arrives, or the cap changes while a set is
stored, the pallet forces two rotations in the following two blocks, so the change is in force
without waiting for the regular period. The regular rotations given by
Config::PeriodicSession continue as before.
The returned validators author blocks like any collator, so a pallet-collator-selection event
handler pays them from its pot and records them in LastAuthoredBlock.
A runtime must configure pallet-collator-selection’s KickThreshold to exceed a full Aura
round of the merged list, Config::MaxValidators plus the invulnerables and candidates, times
the blocks the chain produces per Aura slot. Otherwise bonded candidates are kicked as stale
between their slots. Config::MaxValidators rather than the cap is the bound, since the cap
can be raised or removed without a runtime upgrade.
§TODO
- Counting the blocks each validator authors and reporting era points to the chain where
pallet-staking-asyncruns, typically Asset Hub. - Dropping validators that author no blocks for a session, judged among the drawn validators under a cap.
- (Only if a need is established) Propagating relay-chain offences to the collator set.
- Under a cap, revisit the redraw period and notice once operators have run collators. A draw per era without notice is the first step, with operators expected to run a synced collator node all the time. Options: redraw every few eras or sessions, keep a drawn validator for several eras while it stays in the active set, and announce the drawn validators before they collate so they can sync a node. Open points: the time a node needs to sync, and refilling the place of a drawn validator that leaves the active set, which needs notice too.
Re-exports§
pub use pallet::*;