Skip to content

[Conway] Property : voteDelegs range lies in VDelegs of registered DReps (#1233) - #1290

Open
williamdemeo wants to merge 4 commits into
masterfrom
1233-conway-votedelegs-range-is-contained-in-vdelegs
Open

[Conway] Property : voteDelegs range lies in VDelegs of registered DReps (#1233)#1290
williamdemeo wants to merge 4 commits into
masterfrom
1233-conway-votedelegs-range-is-contained-in-vdelegs

Conversation

@williamdemeo

@williamdemeo williamdemeo commented Aug 6, 2026

Copy link
Copy Markdown
Member

Every value of voteDelegs is a VDeleg of a registered DRep, vDelegAbstain, or vDelegNoConfidence, and CERTS preserves that.

CERTS-voteDelegsVDeleg : LedgerInvariant _⊢_⇀⦇_,CERTS⦈_ voteDelegsVDeleg

The original statement was corrected. It said

range (VoteDelegsOf d) ⊆ mapˢ vDelegCredential (dom (VoteDelegsOf d))

which is well typed (mapˢ vDelegCredential lifts the domain into ℙ VDeleg) but false, for two independent reasons: vDelegAbstain and vDelegNoConfidence are legal voteDelegs values and neither is vDelegCredential c for any c; and the range wraps DRep credentials, while regdrep never adds a key to voteDelegs, so a delegatee need not lie in dom voteDelegs.

It is now an invariant rather than a postcondition, because master removed POST-CERT in the meantime. That rule used to corestrict voteDelegs to the active VDelegs at the end of every batch, which made the containment unconditional on the output of CERTS. With the final sweep gone, an input state may already violate it and no CERTS step would repair it, so the property is stated and proved as preservation instead.

The containment is now maintained incrementally by the two rules that could break it: DELEG-delegate may install only a VDeleg that is already active for the current delegatees, and GOVCERT-deregdrep, the one rule that shrinks the registered DReps, deletes every delegation to the credential it deregisters in the same step. The proof establishes invariance for DELEG, GOVCERT, CERT and PRE-CERT, then lifts the CERT lemma along RTC-preserves-inv.

Four small lemmas go to Axiom.Set.Map.Extra: coex-∈⁻, and dom-∪ˡ-⊇ʳ with its corollaries dom-insert-⊇ and dom-mapValueRestricted-⊇.

Closes #1233

@williamdemeo
williamdemeo marked this pull request as draft August 6, 2026 13:16
@williamdemeo williamdemeo changed the title Certs property #1233: voteDelegs range lies in VDelegs of registered DReps WIP -- [Conway] Certs property : voteDelegs range lies in VDelegs of registered DReps (#1233) Aug 6, 2026
@williamdemeo williamdemeo changed the title WIP -- [Conway] Certs property : voteDelegs range lies in VDelegs of registered DReps (#1233) WIP -- [Conway] Property : voteDelegs range lies in VDelegs of registered DReps (#1233) Aug 6, 2026
@williamdemeo
williamdemeo requested a balanced review from Copilot August 6, 2026 19:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR upgrades the “vote delegation targets are valid” statement from an informal claim to a formally proved theorem, ensuring post-CERTS states only contain vote delegations to registered DReps (or the two special constants).

Changes:

  • Replaces an informal claim with a theorem statement in the Conway spec properties overview.
  • Adds a full formalization and proof that CERTS steps leave only “active” VDeleg values in voteDelegs.
  • Introduces a supporting set-theory lemma about corestriction range containment and records the change in the changelog.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
src/Ledger/Conway/Specification/Properties.lagda.md Updates the high-level spec statement from “Claim” to “Theorem” with a refined description.
src/Ledger/Conway/Specification/Certs/Properties/VoteDelegsVDeleg.lagda.md Defines activeVDelegs, restates the property over CertState, and adds a proof for the CERTS step.
src-lib-exts/abstract-set-theory/Axiom/Set/Map/Extra.agda Adds lemma cores-range-⊆ used by the new proof.
CHANGELOG.md Documents the newly stated/proved voteDelegs property.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +165 to +167
Let `s`{.AgdaBound}, `s'`{.AgdaBound} be `CertStates`{.AgdaRecord} and
`certs`{.AgdaBound} a list of `DCerts`{.AgdaDatatype} such that `s`{.AgdaBound}
`⇀⦇`{.AgdaDatatype} `certs`{.AgdaBound} `,CERTS⦈`{.AgdaDatatype} `s'`{.AgdaBound}.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Keeping these, because the pluralization is a repo-wide prose convention rather than something local to this entry. It occurs 19 times under src/, including the two neighbouring bullets in this same file and the modules this bullet links to (Certs/Properties/PoV.lagda.md L61-62, Certs/Properties/PoVLemmas.lagda.md L50 and L215-218). Aligning only this entry would make it the odd one out.

You are right on the underlying point, though: CertStates and DCerts are not identifiers, so tagging them {.AgdaRecord} / {.AgdaDatatype} applies Agda-identifier styling to non-identifiers. That is pre-existing and repo-wide, so it belongs in its own pass over the prose rather than here.

---

## Claim: <span class="AgdaField">voteDelegs</span> field values are <span class="AgdaDatatype">VDelegs</span> constructed from their keys {#clm:VDelegsInRegDReps}
## Theorem: <span class="AgdaField">voteDelegs</span> values point at registered <span class="AgdaFunction">DReps</span> {#clm:VDelegsInRegDReps}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Deliberately keeping the anchor:

  1. It is referenced from build-tools/static/mkdocs/includes/links.md and is a published-docs URL fragment, so renaming breaks existing external links to #clm:VDelegsInRegDReps.
  2. There is already in-repo precedent for a proved theorem retaining a clm: anchor: src/Ledger/Conway/Specification/Gov/Properties/LastVoteApplied.lagda.md L6 is ## Theorem: ... {#clm:LastVoteApplied}.
  3. Preserving this anchor was an explicit requirement for this change.

Your point stands that the clm: / thm: prefixes are no longer a reliable classification signal. With two files now in this state, the fix is one pass over every anchor plus links.md (and ideally redirects for the published fragments), not a one-off rename here.

Comment on lines +713 to +715
cores-range-⊆ : ∀ {A B : Type} ⦃ _ : DecEq B ⦄ (m : A ⇀ B) {X : ℙ B} → range (m ∣^ X) ⊆ X
cores-range-⊆ _ b∈range with Equivalence.from ∈-map b∈range
... | _ , refl , ab∈cores = proj₁ (Equivalence.from ∈-filter ab∈cores)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Two separate points here; the first rests on a misreading.

cores-range-⊆ is not inside the module _ {A B : Type} ... block that opens at L64. It starts at column 0, which closes that block, so the ∀ {A B : Type} is required rather than redundant. It also must stay: that module's parameters include ⦃ CommutativeMonoid _ _ B ⦄ and ⦃ IsCommutativeSemigroup _◇_ ⦄, and a corestriction lemma has no business carrying a commutative-monoid constraint. The form used matches the adjacent top-level lemmas (lookupᵐ?-insert, ∈-insert-≢, lookupᵐ?-insert-≢), which are all ∀ {A B : Type} ⦃ _ : DecEq _ ⦄.

The naming nit is fair, and is fixed in 9dd24fb: cores-range-⊆ _ b∈range is now cores-range-⊆ m b∈range. m stays unused in the body (the proof only inspects the membership proof), but naming it saves the reader a trip to the signature to recover the argument order.

@williamdemeo
williamdemeo force-pushed the 1233-conway-votedelegs-range-is-contained-in-vdelegs branch from 9dd24fb to fcc8747 Compare August 10, 2026 20:16
@williamdemeo williamdemeo added era: conway property Ledger property (tracked in the catalog) labels Aug 13, 2026
@williamdemeo
williamdemeo force-pushed the 1233-conway-votedelegs-range-is-contained-in-vdelegs branch from fcc8747 to 222f36c Compare September 2, 2026 02:22
@williamdemeo

Copy link
Copy Markdown
Member Author

Rebased onto master (8f3bb1173) and reworked, because master removed POST-CERT while this sat open.

That rule was load-bearing here. It corestricted voteDelegs to the active VDelegs at the end of every batch, so the containment held unconditionally of the output of CERTS and the proof was a one-liner off CERT-post. With the final sweep gone, an input state may already violate the containment and no CERTS step repairs it, so the property is now stated and proved as preservation:

CERTS-voteDelegsVDeleg : LedgerInvariant _⊢_⇀⦇_,CERTS⦈_ voteDelegsVDeleg

This is the honest correction rather than a simplification: the statement is the more useful one (a real invariant), but the proof grew, since the containment is now maintained incrementally by DELEG-delegate and GOVCERT-deregdrep instead of being re-established wholesale at the end.

Two notes for anyone re-reading the earlier review threads:

  • cores-range-⊆, the subject of the third Copilot comment and my reply, is gone. Nothing corestricts any more, so it would have been dead code. The complement form coex-∈⁻ replaced it, and the naming point from that thread carries over to it and to the three new domain lemmas.
  • The correction to the original issue statement is unaffected by any of this, and both reasons it was false still hold.

Verified with agda on each edited module and a full nix build before pushing.

@williamdemeo
williamdemeo force-pushed the 1233-conway-votedelegs-range-is-contained-in-vdelegs branch 2 times, most recently from 690f9ef to 385048f Compare September 2, 2026 03:02
@williamdemeo williamdemeo changed the title WIP -- [Conway] Property : voteDelegs range lies in VDelegs of registered DReps (#1233) [Conway] Property : voteDelegs range lies in VDelegs of registered DReps (#1233) Sep 2, 2026
@williamdemeo
williamdemeo marked this pull request as ready for review September 2, 2026 03:03
@williamdemeo
williamdemeo force-pushed the 1233-conway-votedelegs-range-is-contained-in-vdelegs branch 2 times, most recently from e293798 to b45abca Compare September 8, 2026 19:11
…DReps

The property in Certs.Properties.VoteDelegsVDeleg was false as stated.  It
claimed the range of voteDelegs is contained in the VDelegs built from the
*domain* of voteDelegs, but the domain holds delegator stake credentials while
the range holds VDelegs wrapping DRep credentials (or vDelegAbstain /
vDelegNoConfidence).  The module anchor {#clm:VDelegsInRegDReps} records the
intended claim: vote delegations point at registered DReps.

Restate it as a property of the CERTS rule and prove it:

    Gamma |- s ->(certs ,CERTS) s'  ->  range (VoteDelegsOf s') subset-of activeVDelegs s'

where

    activeVDelegs s = mapS vDelegCredential (dom (DRepsOf s))
                       union fromList (vDelegNoConfidence :: vDelegAbstain :: [])

is the set POST-CERT corestricts to.  Nothing is assumed about the initial
state: POST-CERT ends every CERTS batch with voteDelegs |^ activeVDelegs, so
the property holds unconditionally of the output state.

The proof inverts the CERTS step, inducts over the CERT trace, and closes the
run-[] case with a new lemma cores-range-subset (range (m |^ X) subset-of X)
added to Axiom.Set.Map.Extra; agda-sets carries nothing about _|^_ beyond
cores-subset.  Its map argument is explicit because _|^_ goes through
subset-map, which mentions the map only under proj1, so it is not recoverable
by unification.

Also promote the prose entry in Conway/Specification/Properties.lagda.md from
Claim to Theorem and restate it, and add a CHANGELOG entry.

AI-assisted development: Claude Opus 5 (Anthropic)
Address a review nit: the clause head now mirrors the type signature.  `m` is
unused in the body (the proof only inspects the membership proof), but naming it
saves the reader a trip to the signature to recover the argument order.

AI-assisted development: Claude Opus 5 (Anthropic)
Master removed the POST-CERT rule; delegated voting stake is now dropped by
GOVCERT at the moment a DRep is deregistered.  POST-CERT used to corestrict
voteDelegs to the active VDelegs at the end of every batch, which is what made
the property an unconditional postcondition of CERTS and its proof a one-liner.
That sweep is gone, so an arbitrary input state may already violate the
containment and nothing in a CERTS step would repair it.

Restate the property as a genuine CERTS invariant and prove it:

    CERTS-voteDelegsVDeleg : LedgerInvariant _|-_->(_,CERTS)_ voteDelegsVDeleg

The containment is now maintained incrementally by the two rules that could
break it.  DELEG-delegate may install only a VDeleg that is already active for
the current delegatees, and GOVCERT-deregdrep, the one rule that shrinks the
registered DReps, deletes every delegation to the credential it deregisters in
the same step.  The remaining rules either leave both fields alone or only grow
the DRep domain, for which activeVDelegs is monotone.

The proof establishes invariance for DELEG, GOVCERT, CERT and PRE-CERT, then
lifts the CERT lemma along RTC-preserves-inv.  In Axiom.Set.Map.Extra, drop
cores-range-|_ (nothing corestricts any more) and add what the new proof needs:
coex-|-in, for reading a pair back out of a complement corestriction, and
dom-cup-l-supset-r with its corollaries dom-insert-supset and
dom-mapValueRestricted-supset, for the two left-biased unions that refresh and
extend the DReps.  Each takes the map whose keys are preserved explicitly, since
it sits under proj1 and unification cannot recover it.

Also restate the prose entry in Conway/Specification/Properties.lagda.md and
restore the changelog line dropped in an earlier rebase.

AI-assisted development: Claude Opus 5 (Anthropic)
@williamdemeo
williamdemeo force-pushed the 1233-conway-votedelegs-range-is-contained-in-vdelegs branch from 8e8d680 to ffe741d Compare September 8, 2026 20:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

era: conway property Ledger property (tracked in the catalog)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Conway] voteDelegs range is contained in VDelegs built from its domain

2 participants