test(fc): add attestation target walkback bound filler#614
Merged
tcoratger merged 2 commits intoleanEthereum:mainfrom Apr 15, 2026
Merged
Conversation
Adds test_attestation_target_walkback_bounded_by_lookback to verify that get_attestation_target caps the walk from head at JUSTIFICATION_LOOKBACK_SLOTS, preventing target collapse to safe_target when the head runs far ahead. Head and target are derived symbolically from JUSTIFICATION_LOOKBACK_SLOTS and Slot.is_justifiable_after, so the test stays valid if either the constant or the justifiability rules change.
… targeting, not genesis collapse Without the walkback bound the target stays near head (too aggressive), it does not collapse to genesis. The docstring previously described the opposite failure mode. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.
Summary
Adds
test_attestation_target_walkback_bounded_by_lookbacktotests/consensus/devnet/fc/test_attestation_target_selection.py, verifying thatStore.get_attestation_targetcaps its walk from head atJUSTIFICATION_LOOKBACK_SLOTSand does not collapse the target back tosafe_targetwhen the head runs farahead.
Motivation
The existing target-selection fillers exercise
get_attestation_targetend-to-end but none isolate the bounded-walk property in a "head far ahead of safe_target"configuration. Without explicit coverage, a regression that removed or weakened the lookback bound (e.g. letting the walk run all the way back to
safe_target) wouldnot be caught — the justification frontier would silently collapse.
What the test does
safe_targetprovably stays at genesis.StoreChecks(attestation_target_slot=...)that the target sits exactlyJUSTIFICATION_LOOKBACK_SLOTSslots behind head, notat
safe_target.Note on the issue's literal example (head=10, target=7)
The issue's example numbers (
head=10→attestation_target_slot=Slot(7)) do not hold against the current implementation. After the bounded walk,get_attestation_targetcontinues backward until the result is justifiable (store.py:1240-1243). At head=10 withsafe_target=0,head - LOOKBACK = 7anddelta = 7is not ≤5, not a perfect square, and not pronic — so the algorithm walks further back to slot 6 (pronic). The existingtest_attestation_target_justifiable_constraintalready verifies this at line 423.The new test bumps head to 12 — the smallest "long chain" head where
head - LOOKBACK = 9is justifiable from genesis (perfect square) — so the bounded-walkproperty can be asserted cleanly without the secondary justifiability walk masking the result.
Why it is symbolic, not hardcoded
Both
headandtarget_slotare derived fromJUSTIFICATION_LOOKBACK_SLOTSandSlot.is_justifiable_aftervia a short inline loop, mirroring the convention fromtests/consensus/devnet/fc/test_block_attestation_limits.py:15,35. If either the constant or the justifiability rules change, the loop recomputes a valid head andthe test continues to express the same property — no edits required.
closes #560