apollo_staking: bound next-epoch resolution window by the epoch length#14689
apollo_staking: bound next-epoch resolution window by the epoch length#14689matanl-starkware wants to merge 1 commit into
Conversation
Heights were resolved to "current epoch + 1" for up to MIN_EPOCH_LENGTH blocks past the current epoch's end. When epochs are shorter than MIN_EPOCH_LENGTH, this attributed heights of later epochs to a stale epoch ID, so epoch-gated committee changes took effect at a different height on each node. Bound the window by min(MIN_EPOCH_LENGTH, epoch_length) so the resolved epoch is always exact; behavior is unchanged for epochs of at least MIN_EPOCH_LENGTH. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
PR SummaryMedium Risk Overview
Tests add Reviewed by Cursor Bugbot for commit d675c18. Bugbot is set up for automated code reviews on this repo. Configure here. |
Problem
EpochCache::try_resolve_epoch_idresolves heights up toMIN_EPOCH_LENGTH(150) blocks past the current epoch's end as "current epoch + 1". When epochs are shorter thanMIN_EPOCH_LENGTH(e.g.MockStakingContract's 30-block epochs), heights belonging to later epochs are attributed to a stale epoch ID for up to 150 heights, and the epoch cache re-syncs at a node-specific phase. As a result,override_committee.start_epochis evaluated against the stale label and a committee change takes effect at a different height on each node, diverging the round-robin proposer schedules ((height + round) % lenwith differentlen) for several minutes.Fix
Bound the next-epoch resolution window by
min(MIN_EPOCH_LENGTH, epoch_length):MIN_EPOCH_LENGTH: behavior unchanged.Testing
get_committee_short_epochs_override_activates_at_start_epoch: with 30-block epochs and the epoch cache synced two epochs before the override'sstart_epoch, the last pre-override height gets the default committee and the first override height gets the override committee. Fails without the fix (stale default committee served past the activation epoch).E2_H2is nowstart + MIN_EPOCH_LENGTH(first invalid height) andget_committee_for_next_epochalso asserts the last height within bounds resolves.🤖 Generated with Claude Code