Gov property #414: state that GA deposits are eventually refunded#1217
Gov property #414: state that GA deposits are eventually refunded#1217williamdemeo wants to merge 15 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new Conway governance property statement (no proof yet) asserting that held governance action (GA) deposits are eventually refunded, and wires it into the spec’s property aggregation/index and changelog.
Changes:
- Introduces
Ledger.Conway.Specification.Chain.Properties.EventuallyRefundedwith definitions forgaDepositInPot,CHAINStar, and the property statementGADepositsEventuallyRefunded(proof TODO). - Registers the new property module in the
Chain.Propertiesaggregator and lists the claim in the properties index. - Documents the new stated claim in
CHANGELOG.md.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/Ledger/Conway/Specification/Chain/Properties/EventuallyRefunded.lagda.md | New property statement module + supporting definitions (proof stub). |
| src/Ledger/Conway/Specification/Chain/Properties.lagda.md | Exposes the new property module via the properties aggregator. |
| src/Ledger/Conway/Specification/Properties.lagda.md | Adds the claim to the properties index. |
| CHANGELOG.md | Notes the addition of the stated (unproved) claim. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Machine-checked this branch with Agda 2.8.0 (via the project's Nix flake): Pushed two small refinements:
Statement only; proof to follow. Part of #414. Generated by Claude Code |
46683f0 to
88b7157
Compare
a161a6b to
e3e7ecd
Compare
Add the statement stub for issue #414 as a CHAIN-level claim in a new module Ledger.Conway.Specification.Chain.Properties.EventuallyRefunded: - gaDepositInPot: a governance-action deposit is still held in a chain state - CHAINStar: reflexive-transitive closure of CHAIN over a list of blocks - GADepositsEventuallyRefunded: every held GA deposit is eventually removed from the deposit pot once the chain progresses past its expiry epoch The proof is left as future work ("coming soon"). Wire the module into the Chain.Properties aggregator, list the claim in the properties index, and note it in the changelog.
Add the statement stub for issue #414 as a CHAIN-level claim in a new module Ledger.Conway.Specification.Chain.Properties.EventuallyRefunded: - gaDepositInPot: a governance-action deposit is still held in a chain state - CHAINStar: reflexive-transitive closure of CHAIN over a list of blocks - GADepositsEventuallyRefunded: every held GA deposit is eventually removed from the deposit pot once the chain progresses past its expiry epoch The proof is left as future work ("coming soon"). Wire the module into the Chain.Properties aggregator, list the claim in the properties index, and note it in the changelog.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
The EventuallyRefunded statement stub typechecks under Agda 2.8.0 as-is (no proof yet). Two refinements: - Use the `*Proof*. (coming soon)` pending marker (was `(TODO)`), matching the convention the property-tracking scanner keys on, so the claim is read as `stated` (proof pending) rather than being mistaken for proved. - Fix the roadmap entry in the Conway properties index: add the `[CHAIN-EventuallyRefunded]` / `[Chain.Properties.EventuallyRefunded]` link definitions and render the claim as a list item, matching siblings. Part of #414 (statement only; proof to follow). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RP1jARAhD3898yZhVnPHZ4
The naive statement is false for arbitrary ChainStates: an "orphan" GovActionDeposit entry (present in the deposit map but absent from GovState) would never be removed by any EPOCH transition. Adding govDepsMatch—a known CHAIN invariant—ensures every such deposit has a matching GovActionState with an expiresIn epoch. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Revise GADepositsEventuallyRefunded with four preconditions: 1. govDepsMatch — deposits match governance state 2. GovState membership — identifies the action's expiresIn 3. LastEpochOf cs ≤ expiresIn gaSt — action not yet expired 4. FreshId gaid bs — no transaction reuses the GovActionID (NEW) FreshId is needed because the formal spec's abstract TxId type does not enforce freshness; in practice TxId is a hash so collisions cannot happen. Also prove supporting lemmas: - ≤e<sucᵉ⇒⊥: discharges the CHAINStar base case - gdm-dep⇒dpMap / gdm-¬dpMap⇒¬dep: bridge between govDepsMatch and deposit-pot membership Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…Y lemmas
The EPOCH transition uses a two-epoch pipeline: at epoch
sucᵉ (expiresIn), RATIFIES marks the expired action for removal
(adding it to fut'.removed); at the FOLLOWING epoch,
GovernanceUpdate actually filters it out of the governance state.
The previous witness sucᵉ (expiresIn) was one epoch too early.
Changes:
- Update cutoff to sucᵉ (sucᵉ (expiresIn gaSt)) in statement and prose
- Add ≤e<sucᵉsucᵉ⇒⊥ corollary for the base case
- Prove four RATIFY/RATIFIES lemmas:
* ratify-expired⇒in-removed: single step, expired → in removed
* ratify-removed-mono: single step preserves removed membership
* ratifies-removed-mono: RTC preserves removed membership
* ratifies-expired∈⇒in-removed: expired action in processed list
ends up in removed (main lemma)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Changes to EventuallyRefunded: - Add SucIsLeast as a 5th precondition (e < e' → sucᵉ e ≤ e', needed for the inductive step, not yet an EpochStructure axiom) - Fix witness epoch to sucᵉ (sucᵉ (expiresIn gaSt)) to account for the two-epoch RATIFY/GovernanceUpdate pipeline - Add ≤e<sucᵉsucᵉ⇒⊥ corollary for the base case - Prove govUpdate-removes: actions in fut.removed are filtered out of GovernanceUpdate.govSt' - Prove RATIFY/RATIFIES lemmas: * ratify-expired⇒in-removed (single step) * ratify/ratifies-removed-mono (removed only grows) * ratifies-expired∈⇒in-removed (expired in list → in removed) Also write /tmp/new-issue-add-axiom.md proposing the addition of <⇒sucᵉ≤ to EpochStructure. Proof of the full theorem is in progress; remaining sub-lemmas (LEDGERS preserves/doesn't add GovState entries with fresh TxId) require further set-theoretic infrastructure. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Prove that GovActionDeposit gaid stays absent from the deposits map through all deposit-modifying operations, given FreshId: - GA∉dom-certDep: cert deposits never add GA keys - updCertDeps-GA-absent: updateCertDeposits preserves GA absence (by induction on certs; each case uses ∪⁺/∪ˡ/∣_ᶜ helpers) - GovActionDeposit-inj: constructor is injective - updPropDeps-GA-absent: updateProposalDeposits with fresh TxId preserves GA absence - updateDeposits-GA-absent: combined lemma for updateDeposits These lemmas establish the "stays gone" invariant: once a GA deposit is removed by EPOCH, it cannot be re-added by LEDGER steps when FreshId holds. All domain-specific sub-lemmas for GADepositsEventuallyRefunded are now proved. Epoch order: ≤e<sucᵉ⇒⊥, ≤e<sucᵉsucᵉ⇒⊥ govDepsMatch bridges: gdm-dep⇒dpMap, gdm-¬dpMap⇒¬dep RATIFY/RATIFIES: ratify-expired⇒in-removed, ratify-removed-mono, ratifies-removed-mono, ratifies-expired∈⇒in-removed GovernanceUpdate: govUpdate-removes Deposit-absence preservation: GA∉dom-certDep, updCertDeps-GA-absent, GovActionDeposit-inj, updPropDeps-GA-absent, updateDeposits-GA-absent, ∉-dom-∪⁺ᵈ, ∉-dom-∪ˡᵈ, ∉-dom-resᶜᵈ The proof section now contains a detailed roadmap for the remaining assembly: connecting these lemmas through the nested CHAIN/TICK/NEWEPOCH/BBODY/LEDGERS derivation structure. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Prove the "stays gone" chain of lemmas: once GovActionDeposit gaid is absent from the deposits, it stays absent through any chain extension (given FreshId). New lemmas: - EPOCH-GA-absent: EPOCH preserves deposit absence (deposits only shrink via GovernanceUpdate ∣_ᶜ and POOLREAP ∣_ᶜ) - LEDGER-GA-absent: single LEDGER step preserves absence (via updateDeposits-GA-absent for Scripts-Yes, identity for Scripts-No) - LEDGERS-GA-absent: lift to LEDGERS (RTC of LEDGER) - CHAIN-GA-absent: single CHAIN step, case-splitting on NEWEPOCH-New / Not-New / No-Reward-Update - CHAINStar-GA-absent: lift to full CHAINStar — the main "stays gone" invariant Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The proof of gaDepositsEventuallyRefunded is complete under --safe. Update the prose to accurately describe the proved theorem: - Fix precondition count (5 → 6) to include CHAINStar-Invariant - Add description of CHAINStar-Invariant and InvariantAt - Replace "deferred to a follow-up" with accurate proof description - Add summary table of all six preconditions and their status - Rename <⇒sucᵉ≤ reference to SucIsLeast in prose Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Swap primes: GADepositsEventuallyRefunded is now the clean theorem statement (pattern-matches REFUNDED to extract gaid); GADepositsEventuallyRefunded' is the flat workhorse proof - Add gaDepositsEventuallyRefunded as the main theorem, which unpacks the REFUNDED derivation and delegates to the workhorse - Fix gaid scoping in GADepositsEventuallyRefunded (option A: pattern-match on REFUNDED constructor to bind gaid) - Update prose to refer to gaDepositsEventuallyRefunded Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
53f5072 to
be80c3f
Compare
|
|
||
| ## Conway spec | ||
|
|
||
| - State the claim that governance action deposits are eventually refunded (statement only; see #414) |
| blocks. | ||
|
|
||
| ```agda | ||
| -- The deposits of `cs` still holds the deposit for governance action `gaid`. |
| + The membership witness | ||
| `(gaid , gaSt) ∈ fromList (GovStateOf cs)`{.Agda} | ||
| identifies the `GovActionState`{.AgdaRecord} whose `expiresIn`{.AgdaField} field | ||
| determines the deadline. |
Description
Closes #414.
States and proves the governance property in #414 ("GA deposits are eventually refunded"). The proof is machine-checked under
--safewith Agda 2.8.0.New module
Ledger.Conway.Specification.Chain.Properties.EventuallyRefunded:gaDepositInPot cs gaid— the deposit pot of aChainStatestill holds theGovActionDepositforgaid.CHAINStar— reflexive-transitive closure ofCHAINalong a list of blocks.FreshId gaid bs— no transaction inbshasTxIdequal toproj₁ gaid.SucIsLeast— successor is least:e < e' → sucᵉ e ≤ e'.InvariantAt/CHAINStar-Invariant— IH conditions at intermediate states._⊢_⇀⦇_,REFUNDED⦈_— bundles all premises into a single STS-style relation.GADepositsEventuallyRefunded— the theorem type: given aREFUNDEDderivation,¬ gaDepositInPot cs' gaid.gaDepositsEventuallyRefunded— the proof.Also wires the module into the
Chain.Propertiesaggregator, lists the claim in the properties index (Ledger.Conway.Specification.Properties), and adds aCHANGELOGentry.Theorem
The
REFUNDEDrelation bundles the premises in STS style. The theoremgaDepositsEventuallyRefundedstates: given aREFUNDEDderivation, the deposit is no longer in the pot.The
REFUNDEDpremises are:govDepsMatchCHAINinvariantGovStatemembershipLastEpochOf cs ≤ expiresIn gaStFreshIdTxIdis a hash)SucIsLeastEpochStructureaxiom (see #1263)CHAINStar-InvariantWitness epoch:
sucᵉ (sucᵉ (expiresIn gaSt))— two epochs due to the RATIFY/GovernanceUpdate pipeline (RATIFY marks for removal atsucᵉ (expiresIn); GovernanceUpdate filters at the following epoch).Preconditions 4–6 are "engineering debt": they hold for all reachable states but their formal derivation from the existing abstract interface requires infrastructure not yet present in the specification.
Proof structure
The theorem
gaDepositsEventuallyRefundedunpacks theREFUNDEDderivation and delegates to the workhorsegaDepositsEventuallyRefunded', which proceeds by induction onCHAINStar:≤e<sucᵉsucᵉ⇒⊥).CHAINStar-Invariantat the intermediate state is eitherinj₁(deposit already absent →CHAINStar-GA-absentpropagates) orinj₂(IH preconditions hold → recurse).Key sub-lemmas proved
ratifies-expired∈⇒in-removed— RATIFIES puts expired actions inremovedgovUpdate-removes— GovernanceUpdate filters condemned actions fromgovSt'EPOCH-GA-absent— EPOCH preserves GA-deposit absence (deposits only shrink via∣_ᶜ)LEDGER-GA-absent/LEDGERS-GA-absent— LEDGER preserves GA-deposit absence (viaupdateDeposits-GA-absent)CHAIN-GA-absent/CHAINStar-GA-absent— the "stays gone" invariantupdateDeposits-GA-absent— combined cert + proposal deposit absence preservationgdm-dep⇒dpMap/gdm-¬dpMap⇒¬dep— govDepsMatch bridgesKey discoveries
sucᵉ(expiresIn), GovernanceUpdate removes atsucᵉ(sucᵉ(expiresIn))govDepsMatchalone insufficient — orphan deposits, expired-but-present actionsFreshIdneeded — abstractTxIdhas no freshness guaranteeSucIsLeastneeded — not derivable from existing EpochStructure axiomsChecklist
CHANGELOG.md