test(fc): produce block enforces MAX_ATTESTATIONS_DATA limit (#565)#613
Merged
tcoratger merged 2 commits intoleanEthereum:mainfrom Apr 15, 2026
Merged
Conversation
7a4983c to
989b9f3
Compare
70932e9 to
60cc434
Compare
…ereum#565) Adds a fork choice filler that verifies the block builder caps distinct AttestationData entries at MAX_ATTESTATIONS_DATA when more are available. All values (chain length, tick times, expected count) are derived from protocol constants so the test adapts automatically if they change. Also cleans up API server test teardown to use aclose() consistently, removing redundant stop() + sleep() calls across all test classes. Co-Authored-By: Ayush Rangrej <rangrejayush4@gmail.com> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
60cc434 to
08fd174
Compare
Contributor
Author
|
@tcoratger Fix for the CI error, removes expected_attestations and block_attestations= from the StoreChecks. The validator-based matching in _validate_block_attestations can't disambiguate entries with identical participants. I had this error before but it might have come back when you squashed all the commits. |
tcoratger
approved these changes
Apr 15, 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.
🗒️ Description
This PR adds a fork choice filler test that verifies the block builder caps the number of distinct attestation data entries at
MAX_ATTESTATIONS_DATA = 16when more than 16 are available in the store.What the test does
Builds a chain of 17 blocks (slots 1–17), each labeled so they can be referenced as attestation targets. This gives 17 blocks with distinct roots.
Ticks to 70s (slot 17, interval 2 — the aggregate interval) while the gossip pool is empty. This fires the
aggregate()step as a no-op, which is important: if we gossip attestations before this interval fires,aggregate()will drop them from the new pool (it only keeps proofs it creates itself, not pre-existing ones).Gossips 17 aggregated attestations, each targeting a different block (blocks 1–17). All share the same attestation slot (18), validators
{0, 1, 2}, and source (the genesis justified checkpoint). Because each attestation has a different target checkpoint, they are 17 distinctAttestationDataentries in the store.Ticks to 72s (slot 18 start). This passes through slot 17, interval 4 — the acceptance interval — which calls
accept_new_attestations()and moves all 17 gossip payloads from the "new" pool to the "known" pool. The block builder reads from the known pool.Produces a block at slot 18 and asserts
block_attestation_count=16. The block builder iterates through the 17 entries sorted bytarget.slot. After processing 16 entries (blocks 1–16), the count reachesMAX_ATTESTATIONS_DATA, and the builder breaks — excluding the entry targeting block 17.Why the timing matters
The gossip aggregated attestations are stored in the "new" pool. There are two pool-related events in the interval system per slot:
aggregate()fires. This replaces the new pool with only freshly created proofs. A pre-existing lone proof in the new pool (like our gossip attestation) gets dropped because there is nothing to combine it with.accept_new_attestations()fires. This migrates everything in the new pool to the known pool.To avoid the drop at interval 2, the attestations must arrive after that interval fires. To get them into the known pool before the block is built, the tick to slot 18 must pass through interval 4 first. This is the same pattern used in the existing
test_produce_block_includes_pending_attestationstest.What this correctly tests
The spec requires that a block can include at most 16 distinct
AttestationDataentries. This test:This catches any regression where the limit is removed, raised, or the break condition in the builder loop is broken.
🔗 Related Issues or PRs
Closes #565
✅ Checklist
toxchecks to avoid unnecessary CI fails:uvx tox