Expand description

A static size tracker for the election snapshot data.


The goal of the size tracker is to provide a static, no-allocation byte tracker to be used by the election data provider when preparing the results of [ElectionDataProvider::electing_voters]. The StaticTracker implementation uses [codec::Encode::size_hint] to estimate the SCALE encoded size of the snapshot voters struct as it is being constructed without requiring extra stack allocations.

The StaticTracker::try_register_voter is called to update the static tracker internal state, if It will return an error if the resulting SCALE encoded size (in bytes) is larger than the provided DataProviderBounds.


use pallet_staking::election_size_tracker::*;

// instantiates a new tracker.
let mut size_tracker = StaticTracker::<Staking>::default();

let voter_bounds = ElectionBoundsBuilder::default().voter_size(1_00.into()).build().voters;

let mut sorted_voters = T::VoterList.iter();
let mut selected_voters = vec![];

// fit as many voters in the vec as the bounds permit.
for v in sorted_voters {
    let voter = (v, weight_of(&v), targets_of(&v));
    if size_tracker.try_register_voter(&voter, &voter_bounds).is_err() {
        // voter bounds size exhausted

// The SCALE encoded size in bytes of `selected_voters` is guaranteed to be below
// `voter_bounds`.
    selected_voters.encoded_size() <=
    SizeTracker::<Staking>::final_byte_size_of(size_tracker.num_voters, size_tracker.size)

Implementation Details

The current implementation of the static tracker is tightly coupled with the staking pallet implementation, namely the representation of a voter ([VoterOf]). The SCALE encoded byte size is calculated using [Encode::size_hint] of each type in the voter tuple. Each voter’s byte size is the sum of:

  • 1 * [Encode::size_hint] of the AccountId type;
  • 1 * [Encode::size_hint] of the VoteWeight type;
  • num_votes * [Encode::size_hint] of the AccountId type.


  • Keeps track of the SCALE encoded byte length of the snapshot’s voters or targets.