forkchoice: seed anchor checkpoints from the anchor slot#677
Merged
tcoratger merged 1 commit intoleanEthereum:mainfrom Apr 23, 2026
Conversation
Store.from_anchor previously built the store's justified/finalized checkpoints by copying the slot from the anchor state's embedded latest_justified/latest_finalized (which can be strictly less than the anchor slot) while overriding only the root to the anchor block root. That produced a slot/root-inconsistent checkpoint: the slot pointed at pre-anchor history while the root identified the anchor block itself. Seed both checkpoints from the anchor itself: slot = anchor.slot, root = anchor_root. The anchor state's embedded checkpoints are intentionally ignored, matching the "store treats the anchor as the new genesis" framing already used at the checkpoint-sync entry point. Genesis initialization is unaffected: at genesis the anchor state's embedded checkpoints already sit at slot 0 = anchor.slot, so the new seeding produces identical values. Also updates the checkpoint-sync tests and a misleading inline comment that described the previous (pre-anchor-slot) behavior.
Contributor
Author
|
I believe the CI failure is unrelated |
tcoratger
approved these changes
Apr 22, 2026
march-fatcat
pushed a commit
to nleanEth/nlean
that referenced
this pull request
Apr 23, 2026
Ports leanEthereum/leanSpec#677 into nlean's checkpoint-sync anchor creation. CreateCheckpointHeadState used to build the justified and finalized checkpoints by copying the slot from the anchor state's embedded latest_justified / latest_finalized while overriding only the root to the anchor block root. The two fields went out of sync: the slot still pointed at pre-anchor history while the root identified the anchor block itself. Externally the inconsistency surfaced on leanpoint as "finalized slot > justified slot" once the checkpoint-synced node advanced past its anchor — leanpoint reads the state.slot field from /states/finalized and compared it with the justified checkpoint JSON. Seed both checkpoints from the anchor block directly, matching the beacon chain fork-choice spec the leanSpec PR references.
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
Store.from_anchorpreviously built the store's justified/finalized checkpoints by copying the slot from the anchor state's embeddedlatest_justified/latest_finalized(which can be strictly less than the anchor slot) while overriding only the root to the anchor block root. That produced a slot/root-inconsistent checkpoint: the slot pointed at pre-anchor history while the root identified the anchor block itself.This PR changes
Store.from_anchorto use the anchor block as the justified/finalized checkpoints of theStore, following the beacon chain specs.Also updates the checkpoint-sync tests and a misleading inline comment that described the previous (pre-anchor-slot) behavior.
🔗 Related Issues or PRs
✅ Checklist
toxchecks to avoid unnecessary CI fails:uvx tox