---
# System prepended metadata

title: MB Snapshot creation
tags: [staking, parachains]

---

## MB Snapshot creation

The multi-block election creation is performed over `Pages` blocks. At each block, the EPM calls `DataProvider::electing_voters(page)` to fetch a page of voters (with nominations and stake). Note that the electable targets snapshot can be constructed as a single page.

The goal of the snapshot is for the on-chain and off-chain election processes (build solution, check solution, etc) work on top of a common state, regardless of any changes that may happen in the staker ledgers during the election round.

While the snapshot is being constructed, the nominator's ledger state may change. For this discussion, only the bags list position of the voters is relevant. If a nominator increases/decreases its stake and rebags its position while the snapshot is being created, the following may happen:

1. the voter will be in multiple pages since rebagging puts it back in a bag that will be iterated over in subsequent pages.  
    - not great as it may impact negatively the election score but both solving the solution and checking it is not impacted.
    - in the worst case scenario, up to `T::Pages - 1` voter in the snapshot are a noop.
2. a voter that would be expected to be part of a later X page during the process of page Y will end up not being part of any of the pages since its been rebagged between processing page Y and X.
    - not a problem, other voter with higher stake will take its place in the snapshot.
 3. the voter being rebagged is the last iterated through in a page (i.e the current iterator cursor)
     - this can be very problematic. This would move the cursor up or down the bags list, which will impact the snapshot, e.g.:
         - if cursor is rebagged to last bag, the next voters are stake-wise weak (worst case scenario means that `T::Pages - 1` are empty).
         - if cursor is rebagged upwards, there may be too many repeated voters in the subsequent page in the snapshot (in the worst case scenario, all pages will have the same set of voters).

In addition, the fact that a staker's account ID is the cursor of the multi-block snapshot creation, the staker may even not change its stake to end up in the 3. situation. The problem may happen as well if there's a rebag (considering that when the staker became the cursor, it was out of place in the bagslist).

The point 3 is potentially catastrophic and could result on a snapshot with a "usable" stake lower than bonded in the system.

---

If the cursor is the position in the snapshot (rather than the last account ID processed), the impacts of rebagging voters between snapshot blocks is probably within sensible bounds (fewer, if any, duplicate voters in the snapshot).

The cursor could be a tuple of `{accountId, last_bag_id}`
- if in the next iteration, `bag_of(accountId) != last_bag_id`, restart from beginning of `last_bag_id`
- otherwise, keep iterating from `accountId`

This approach requires new functionality in the `SortedListProvider`.

➡️ Another simpler option would be to not allow `VoterList::rebag` while the snapshot is being created.