Skip to content

forkchoice: simplify store's latest_justified and latest_finalized updates - #194

Merged
unnawut merged 2 commits into
leanEthereum:mainfrom
unnawut:simpler-store-update
Nov 27, 2025
Merged

forkchoice: simplify store's latest_justified and latest_finalized updates#194
unnawut merged 2 commits into
leanEthereum:mainfrom
unnawut:simpler-store-update

Conversation

@unnawut

@unnawut unnawut commented Nov 26, 2025

Copy link
Copy Markdown
Collaborator

🗒️ Description

The fork choice store was relying on looping through the entire historical states to update itself to the latest_justified and latest_finalized checkpoints. This is an overkill and also problematic as the genesis state's latest_justified and latest_finalized block roots are set to 0x00... (the latter might also be an issue, I'll bring up as a separate PR)

Zeam is doing it more elegantly by simply just comparing the latest state's latest_justified and latest_finalized with the fork choice store, and update the store if the state contains higher checkpoints. So I propose bringing this optimization over.

This should not change the behavior of the fork choice so tests are unchanged.

🔗 Related Issues or PRs

✅ Checklist

  • Ran tox checks to avoid unnecessary CI fails:
    uvx tox
  • Considered adding appropriate tests for the changes.
  • Considered updating the online docs in the ./docs/ directory.

@tcoratger tcoratger left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much better this way.

@unnawut
unnawut merged commit a1ae091 into leanEthereum:main Nov 27, 2025
10 checks passed
@unnawut
unnawut deleted the simpler-store-update branch November 27, 2025 06:57
@unnawut unnawut added this to the pq-devnet-1 milestone Nov 28, 2025
@unnawut unnawut added the specs Scope: Changes to the specifications label Nov 28, 2025
GrapeBaBa added a commit to GrapeBaBa/leanSpec that referenced this pull request Jun 13, 2026
…ependent max

on_block advanced latest_finalized by an independent monotonic max over every
imported block's post-state, decoupled from latest_justified and the head. A
fork that finalizes a higher slot but then loses head selection left its
finalized checkpoint latched in the store, so latest_finalized could sit on a
dead branch that is not an ancestor of the head. Validators then derive
attestation targets against that phantom finalized while the canonical state
transition validates against its own lower finalized, so every advancing target
is rejected and finalization freezes.

Keep the store's finalized only when it lies on the head's chain (a genuinely
finalized checkpoint such as a checkpoint-sync anchor), advancing it to the head
state's finalized; otherwise replace it with the head chain's finalized. This
restores the consistency the forkchoice store had before leanEthereum#194 and matches the
3sf-mini reference, where the finalized checkpoint travels with the chosen state.

Add a regression test: a dead fork finalizes slot 4 then loses to a heavier fork
that justifies slot 7 but finalizes only slot 1; the store's finalized must track
the head (slot 1), not the dead fork (slot 4).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

specs Scope: Changes to the specifications

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants