test(e2e): deflake epochs_mbps_redistribution#24182
Merged
PhilWindle merged 1 commit intoJun 18, 2026
Merged
Conversation
…design Assert a race-robust invariant — the checkpoint's last two block indices jointly hold the whole late-tx burst (> 2*S) — instead of requiring all late txs in a single block, which raced the proposer's per-block mempool snapshot.
PhilWindle
approved these changes
Jun 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
e2e_epochs/epochs_mbps_redistributionasserted that a burst of late txs all land in a single (last) block of a checkpoint. But the proposer snapshots the mempool once per block as soon asminTxsPerBlockare available, and the burst (sent viaPromise.all(send())) reaches the proposer over gossip one tx at a time — so the last block's snapshot routinely captured only a subset and the rest spilled into the next checkpoint, flaking the assertion. Empirically the one-before-last block grabs its full redistributed allotment, leaving the last block with fewer than its static share, so "all in the last block" was never a reliable invariant in the first place.Approach
Check the redistribution claim against a race-robust invariant rather than an exact block placement:
blockDurationMs8000 → 6000, slot unchanged at 36s) with a tightmaxTxsPerCheckpoint = 9, giving a static per-block capS = ceil(9 * 1.2 / 4) = 3under the 1.2 multiplier floor.x/7 - x) across the last two blocks as it propagates.> 2 * S = 6). Without redistribution each block is capped atS, so the two could hold at most 6 and the 7th spills into the next checkpoint. The count is by checkpoint-relative block index (not global block number) so a spilled tx can't masquerade as redistributed, and the checkpoint block count is asserted to be 4 so a build collapse fails diagnostically rather than misleadingly.This removes the dependence on which of the last two blocks wins the race. Verified robust by temporarily forcing the one-before-last block to both extremes (1 and 5 txs) — the joint count stays 7 in both cases.
Changes
epochs_mbps_redistributiontest (C=4, immediate burst dump, joint last-two-blocks assertion) and refresh its comments; update the second test's comments to reflect the shared C=4 timing (its logic and assertions are unchanged).Related: this investigation surfaced a separate production bug (A-1251) where
waitForMinTxsgates on a non-age-filtered pending count while the block-building iterator filters byminTxPoolAgeMs; that is tracked separately and not addressed here.This PR is an alternative to #24101