Skip to content

feat(val): prove VAL-3 each slot has exactly one proposer - #40

Merged
adust09 merged 3 commits into
mainfrom
feat/val-3-unique-proposer
Jul 3, 2026
Merged

feat(val): prove VAL-3 each slot has exactly one proposer#40
adust09 merged 3 commits into
mainfrom
feat/val-3-unique-proposer

Conversation

@adust09

@adust09 adust09 commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Discharges VAL-3 from docs/lean4-proof-propositions.md: each slot has exactly one proposer.

  • LeanSpec/Forks/Lstar/Containers/Identifiers.lean:
    • ValidatorIndex.isProposerFor — validator vid : Fin n is the scheduled proposer of slot iff vid.val = slot.toNat % n (the equality-with-proposer_for_slot check the validator service uses, e.g. in validator_duties.py).
    • unique_proposer (VAL-3) — existence (slot % n < n for a nonempty registry) plus uniqueness (Fin.ext). The catalog's ∃! is written in its expanded form ∃ vid, P vid ∧ ∀ vid', P vid' → vid' = vidExistsUnique lives in Mathlib, which this repo does not depend on (noted in the catalog annotation).
  • Catalog: VAL-3 checked off (VAL 2/3/0, total 16 proved — halfway through the catalog).

Stacked on #39 — merge order: #39 → this (retarget to main before merging #39).

Verification

  • lake build green with zero warnings; no sorry, no new axioms.

Remaining VAL propositions (VAL-2 dual keys, VAL-4 no double vote, VAL-5 XMSS preparation monotonicity) need the ValidatorService / KeyRegistry / XMSS-state models — a separate machinery step.

adust09 added 2 commits July 3, 2026 01:03
Extract ValidatorIndex.proposerForSlot mirroring proposer_for_slot in
upstream containers/identifiers.py and refactor processBlockHeader's
proposer check to consume it (semantics unchanged: the UInt64
construction never wraps since slot % n <= slot < 2^64, recorded as
proposerForSlot_toNat). Prove proposer_index_round_robin, the catalog
form of the round-robin selection. Axiom-free, no Mathlib.
Define isProposerFor (equality with the round-robin index, phrased on
Fin n so registry membership is carried by the type) and prove
unique_proposer: the proposer slot % n exists and any proposer equals
it. The catalog's exists-unique is written in expanded form since
ExistsUnique is Mathlib-only. Axiom-free.
@adust09
adust09 changed the base branch from feat/val-1-proposer-round-robin to main July 3, 2026 00:42
@adust09
adust09 merged commit cfab267 into main Jul 3, 2026
1 check passed
@adust09
adust09 deleted the feat/val-3-unique-proposer branch July 3, 2026 00:43
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