Skip to content

feat(fc): prove FC-1 head selection is deterministic - #43

Merged
adust09 merged 1 commit into
mainfrom
feat/fc-1-update-head-deterministic
Jul 5, 2026
Merged

feat(fc): prove FC-1 head selection is deterministic#43
adust09 merged 1 commit into
mainfrom
feat/fc-1-update-head-deterministic

Conversation

@adust09

@adust09 adust09 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Opens the fork-choice domain (LeanSpec/Forks/Lstar/Store/), modeling upstream at main @ 57d4339 — i.e. after the #1179/#1181 fixes, so the model starts from the hardened spec: the vote tie-break is insertion-order independent and the store invariants are documented.

What is modeled

Store/Store.lean mirrors containers/store.py and the head-selection subset of fork_choice.py:

  • Store container (all fields; Python dicts as association lists)
  • _checkpoint_is_ancestorcheckpointIsAncestor
  • _extract_attestations_from_aggregated_payloadsextractAttestationsFromAggregatedPayloads — newest-first, equal-slot ties toward the larger canonical root (the #1181 determinism rule), via the HasHashTreeRoot typeclass (SSZ-7)
  • _accumulate_ancestor_weights / compute_block_weights
  • _compute_lmd_ghost_headcomputeLmdGhostHead (weight-then-lex-root child selection)
  • update_headupdateHead (upstream successor of the catalog's compute_head), including the finalized re-derivation climb

Modeling choices (documented in the module docstring): XMSS material opaque (Arklib side); unbounded while walks on blocks.length + 1 fuel — WellFormed.parentSlotLt is exactly what bounds them upstream too; Python asserts as total fallbacks.

FC-1

  • Store.update_head_deterministic — the catalog meta-property (rfl; totality by fuel-bounded construction)
  • Substantive well-definedness: Store.computeLmdGhostHead_in_store and Store.updateHead_head_in_store — the selected head is the justified anchor or a block the store knows (the membership FC-2 will build on)

Store.WellFormed

States the invariants extracted in leanEthereum/leanSpec#1176 (documented/enforced by #1179): dict-key uniqueness, blocks↔states alignment (M-4), parent-slot ordering (walk termination / FC-4 acyclicity source), justified anchor known, justified-descends-from-finalized (M-1). FC-2/FC-4 will consume these.

Supporting additions

  • Containers/Aggregation.lean (SingleMessageAggregate, proof bytes opaque), Containers/Interval.lean (Interval, fromSlot), INTERVALS_PER_SLOT in Config.lean
  • LawfulBEq Bytes32 instance for association-list membership reasoning

Catalog: FC-1 checked, progress table 17/13/1, FC intro cites Store.WellFormed. lake build passes with no sorry.

Open the fork-choice domain: LeanSpec/Forks/Lstar/Store/Store.lean
mirrors containers/store.py and the head-selection subset of
fork_choice.py at upstream main 57d4339 (post #1179/#1181, so the vote
tie-break is insertion-order independent and the store invariants are
documented upstream).

Model: Python dicts as association lists; XMSS material opaque;
unbounded while-walks on blocks.length fuel (WellFormed.parentSlotLt
is what bounds them upstream too); asserts as total fallbacks.

FC-1 is update_head_deterministic (upstream renamed compute_head to
update_head), with the substantive well-definedness proved as
computeLmdGhostHead_in_store and updateHead_head_in_store: the
selected head is the justified anchor or a stored block.

Store.WellFormed states the invariants extracted in
leanEthereum/leanSpec#1176 for the FC-2/FC-4 follow-ups.

Supporting additions: SingleMessageAggregate and Interval containers,
INTERVALS_PER_SLOT, and a LawfulBEq Bytes32 instance for
association-list membership reasoning.
@adust09
adust09 merged commit 91823d8 into main Jul 5, 2026
1 check passed
@adust09
adust09 deleted the feat/fc-1-update-head-deterministic branch July 5, 2026 14:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant