Skip to content

fix: update added_validators and removed_validators on stake-bound force-removals#168

Open
matthias-wright wants to merge 3 commits into
audit-may-2026from
m/update-removed-validators
Open

fix: update added_validators and removed_validators on stake-bound force-removals#168
matthias-wright wants to merge 3 commits into
audit-may-2026from
m/update-removed-validators

Conversation

@matthias-wright
Copy link
Copy Markdown
Collaborator

@matthias-wright matthias-wright commented May 12, 2026

The finalized header for an epoch will be created on the penultimate block of an epoch. This is because the finalized header has to be included in the last block of an epoch, so that the aggregated signature from the finalization certificate can be used to attest to the finalized header.
Therefore, all the fields that will be included in the finalized header (including removed_validators) have to be calculated after processing the penultimate block of an epoch.

Protocol parameter updates are processed on the last block of an epoch. If MinimumStake is increased, validators whose stake is below the new minimum stake will be removed.
However, when the validators are removed on the last block of an epoch, they won't be included in the removed_validators field of the finalized header.
Similarly, validators that are scheduled to join in a future epoch won't be removed from the added_validators map.

When a joining validator wants to verify a checkpoint, they calculate the validator set for each epoch based on the validator deltas included in the finalized headers. Stake-bound force-removals would be missing from this delta, and pending validators whose participation was aborted before joining will be included wrongfully.

Changes:

  • On the penultimate block of an epoch, it is checked if a protocol parameter change for the maximum or minimum stake is currently pending. If yes, the list of active validators whose stake is below the new minimum stake is calculated and added to removed_validators. The list of joining validators whose stake is below the new minimum stake is calculated and removed from added_validators. The actual handling of the protocol parameter updates is still done at the last block of an epoch to ensure that the protocol parameter updates are only effective for the new epoch.
  • If a protocol parameter request for MinimumStake arrives with the last block of an epoch, some validators could be removed, but the changes wouldn't be recorded in removed_validators. Therefore, protocol param requests arriving with the last block of an epoch will be buffered until the next epoch.
  • An e2e test test_removed_validators_at_epoch_boundary_stake_bound is added to verify that the finalized header's removed_validators field will include validators that were forcefully removed due to insufficient stake.
  • An e2e test test_joining_validator_activation_cancelled_on_stake_bound_force_removal is added to verify that if a joining validator is kicked before becoming active, they won't be included in the finalized header's added_validators field.

@matthias-wright matthias-wright changed the title fix: update removed_validators with stake-bound force-removals fix: update added_validators and removed_validators on stake-bound force-removals May 13, 2026
@sebastian-osec
Copy link
Copy Markdown

LGTM. This PR stages stake-bound force removals into removed_validators and cancels below-minimum joining validator activations before they can appear in finalized header deltas, so checkpoint/header reconstruction stays aligned with live validator state.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants