[Dijkstra] (DEPRECATED) CIP-159-11a: Prove Certs preservation of value (#1185)#1188
Closed
williamdemeo wants to merge 8 commits into
Closed
[Dijkstra] (DEPRECATED) CIP-159-11a: Prove Certs preservation of value (#1185)#1188williamdemeo wants to merge 8 commits into
williamdemeo wants to merge 8 commits into
Conversation
3 tasks
e4f46a7 to
4e3d554
Compare
4 tasks
c4f6a1b to
a2963c6
Compare
a2963c6 to
f635bd6
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds the Dijkstra-era CERTS preservation-of-value (PoV) proof stack (including the new fold-based applyWithdrawals PoV lemma needed for CIP-159 partial withdrawals), and refactors/shared some generic getCoin/set-theory lemmas into Ledger.Prelude so Conway/Dijkstra PoV code can reuse them.
Changes:
- Introduces new Dijkstra
Certs.PropertiesPoV modules (ApplyWithdrawalsPoV,PoVLemmas,PoV) and wires them into the subtree aggregator. - Extends
Ledger.Preludewith reusablegetCoin/indexedSumlemmas (singleton/union/congruence,sumConstZero,setToList-∈). - Moves/centralizes
HasDirectDeposits(removed fromTransaction, now defined alongside account types) and updates related instances/usages; minor Conway PoV cleanups to rely on Prelude lemmas.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Ledger/Prelude.lagda.md | Adds reusable getCoin/indexedSum helper lemmas (singleton/union/congruence, sumConstZero, setToList-∈). |
| src/Ledger/Dijkstra/Specification/Transaction.lagda.md | Removes the local HasDirectDeposits record (keeps instances), relying on the Account-level definition. |
| src/Ledger/Dijkstra/Specification/Certs/Properties/PoVLemmas.lagda.md | New Dijkstra CERTS PoV lemma module (parameterized, CIP-159-aware). |
| src/Ledger/Dijkstra/Specification/Certs/Properties/PoV.lagda.md | New Dijkstra top-level CERTS-pov theorem (accounts for withdrawals and direct deposits). |
| src/Ledger/Dijkstra/Specification/Certs/Properties/ApplyWithdrawalsPoV.lagda.md | New fold-induction infrastructure for applyWithdrawals-pov (parameterized by a few deferred lemmas). |
| src/Ledger/Dijkstra/Specification/Certs/Properties.lagda.md | Imports/exports the new PoV modules in the Certs properties subtree. |
| src/Ledger/Dijkstra/Specification/Certs.lagda.md | Refactors applyWithdrawals by lifting applyOne; adds HasDirectDeposits instance for CertEnv; uses type aliases Retiring/CCHotKeys. |
| src/Ledger/Dijkstra/Specification/Account.lagda.md | Introduces HasDirectDeposits alongside DirectDeposits (so it can be shared/re-exported). |
| src/Ledger/Conway/Specification/Utxo/Properties/GenMinSpend.lagda.md | Switches to Prelude’s getCoin-singleton lemma (removes local duplicate). |
| src/Ledger/Conway/Specification/Ledger/Properties/PoV.lagda.md | Simplifies parameters by relying on Certs-PoV with fewer assumptions. |
| src/Ledger/Conway/Specification/Certs/Properties/PoVLemmas.lagda.md | Removes duplicated helper lemmas/import tweaks; relies on Prelude-provided helpers. |
| src/Ledger/Conway/Specification/Certs/Properties/PoV.lagda.md | Simplifies Certs-PoV module parameters to match the updated lemma structure. |
| src/Ledger/Conway/Conformance/Properties.lagda.md | Drops an unused/removed indexedSum-∪⁺-hom parameter from a local module. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+55
to
+71
| In Dijkstra, the `CERTS`{.AgdaDatatype} rule processes withdrawals (via | ||
| `PRE-CERT`{.AgdaDatatype}) and direct deposits (via `POST-CERT`{.AgdaDatatype}) | ||
| in addition to the certificate steps. Withdrawals reduce the rewards balance; | ||
| direct deposits increase it; the preservation-of-value equation is a symmetric | ||
| "consumed equals produced" statement: | ||
|
|
||
| `getCoin s₁ + getCoin (CertEnv.directDeposits Γ) ≡ getCoin sₙ + getCoin (WithdrawalsOf Γ)`. | ||
|
|
||
| Equivalently, the *increase* in rewards balance from `s₁`{.AgdaBound} to | ||
| `sₙ`{.AgdaBound} equals `directDeposits − withdrawals`. | ||
|
|
||
| ```agda | ||
| CERTS-pov : {Γ : CertEnv} {s₁ sₙ : CertState} | ||
| → ∀[ a ∈ dom (WithdrawalsOf Γ) ] NetworkIdOf a ≡ NetworkId | ||
| → Γ ⊢ s₁ ⇀⦇ l ,CERTS⦈ sₙ | ||
| → getCoin s₁ + getCoin (DirectDepositsOf Γ) ≡ getCoin sₙ + getCoin (WithdrawalsOf Γ) | ||
| ``` |
013fa3e to
9f21a34
Compare
b99a69f to
1db822b
Compare
Comment on lines
+134
to
+135
| res-decomp m m' = ∪-cong (≡ᵉ.refl {x = m ˢ}) (≡ᵉ.sym (filterᵐ-idem {m = m'})) | ||
| where module ≡ᵉ = IsEquivalence (≡ᵉ-isEquivalence {A × Coin}) |
…CIP-159)
After direct-deposit application moved from LEDGER-V/SUBLEDGER-V into the
POST-CERT rule, the Certs preservation-of-value proofs needed to account for
the `getCoin (DirectDepositsOf Γ)` increase that POST-CERT now produces via
`rewards ∪⁺ directDeposits`.
Statement changes:
- POST-CERT-pov: getCoin s ≡ getCoin s'
→ getCoin s + getCoin (DirectDepositsOf Γ) ≡ getCoin s'
- sts-pov: gains a `+ getCoin (DirectDepositsOf Γ)` term on the LHS
- CERTS-pov: becomes the symmetric "consumed = produced" form
getCoin s₁ + getCoin (DirectDepositsOf Γ)
≡ getCoin sₙ + getCoin (WithdrawalsOf Γ)
Structural changes:
- POST-CERT-pov and sts-pov move into the parameterized `Certs-Pov-lemmas`
sub-module (alongside PRE-CERT-pov), since they now require a fourth
module parameter:
indexedSumᵛ'-∪⁺ : ∀ (m m' : Rewards) → getCoin (m ∪⁺ m') ≡ getCoin m + getCoin m'
This is the natural ∪⁺ analogue of the existing `indexedSumᵛ'-∪` lemma for
`∪ˡ` on disjoint domains, but unconditional because `∪⁺` adds (rather than
drops) values at shared keys. TODO: upstream to agda-sets.
- `Certs-PoV` (in PoV.lagda.md) gains the same parameter and forwards it.
CERT-pov and PRE-CERT-pov are unchanged: the CERT and PRE-CERT rules did
not change in this refactor.
Closes part of #1185.
Following the merge of CIP-159 PR #1197 (DirectDeposits keyed by RewardAddress; applyDirectDeposits and applyWithdrawals refactored through a shared applyToRewards fold) and the agda-sets cleanup PR #1196 (Conway Equivalence.Map utilities moved into Ledger.Prelude), this commit updates the Dijkstra CERTS preservation-of-value proofs to compile against the new APIs. Main changes: + Rename `ApplyWithdrawals-PoV` sub-module to `ApplyToRewards-PoV`, since it now houses lemmas for both withdrawals and direct deposits. + Add `getCoin-∪ˡ-overwrite` bridge lemma: `getCoin (❴ c , v ❵ ∪ˡ acc) ≡ v + getCoin (acc ∣ ❴ c ❵ ᶜ)`. Encapsulates the listing-vs-replacement reconciliation between the new `❴ k , v ❵ ∪ˡ acc` form (used by `applyToRewards`) and the equivalent complement-restricted form used by the existing decomposition reasoning. + Factor `split-by-lookup` as a top-level lemma decomposing `getCoin acc` along a known lookup result. Used by both `applyOne-pov` (subtraction) and the new `applyOne-pov-add` (addition). + Add the additive parallel: `applyOne-pov-add`, `foldl-applyOne-pov-add`, and `applyDirectDeposits-pov`. Mirrors the existing withdrawal chain, sharing `getCoin-∪ˡ-overwrite` and `split-by-lookup`. + Strengthen the `setToList-Unique` module parameter with a `NetworkId` premise on the map's domain (the assumption no longer conflates withdrawals-specifically with general `RewardAddress ⇀ Coin` maps). + Replace the `∪ˡ-res-lookup-preserve` module parameter (which carried a no-longer-needed complement restriction on the right operand) with `∪ˡ-lookup-preserve`, stated against the new `❴ c , v ❵ ∪ˡ m` form. + Add a small top-level helper `∈-dom⇒¬lookup-nothing` to discharge the defensive `nothing` case of `foldl-applyOne-pov-add`. + Update `POST-CERT-pov` to use the new `applyDirectDeposits-pov`; the proof is `sym (applyDirectDeposits-pov ...)`. The CERT-post step's own `mapˢ stake (dom dd) ⊆ dom rewards` premise is extracted from the pattern rather than threaded as a separate parameter, since the pre-CERT* state's `dom rewards` is not preserved across `CERT` trace steps (in particular by `DELEG-dereg`). + Update `sts-pov` and `CERTS-pov` signatures accordingly: add the `DirectDeposits`-`NetworkId` premise, drop the membership-of-deposits premise. The proofs now typecheck on top of master.
1db822b to
2a6a3dd
Compare
This was referenced May 20, 2026
Member
Author
|
superseded by PR #1210 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
DEPRECATED. This PR was based on CERT-Post and CERT-Pre setup. It is superseded by #1210 which is based on the
ENTITIESapproach.Description
Closes #1185.
This PR adds the preservation-of-value (PoV) proofs for the Dijkstra
Certsrules. The ConwayCERTS-povprovesgetCoin s₁ ≡ getCoin sₙ + getCoin (WithdrawalsOf Γ)assuming full withdrawals; CIP-159 introduces partial withdrawals (#1116), so the equation still holds —getCoin (WithdrawalsOf Γ)is the actual amount withdrawn — but the underlyingPRE-CERTrule changes fromconstMap-based zeroing to fold-based subtraction, requiring a newapplyWithdrawals-povlemma.This PR is the first of three replacing the original PR #1169, which has been split along module-tree boundaries. It contains only the
Certs/Propertiessub-tree.Modules
Certs.Properties.ApplyWithdrawalsPoVapplyWithdrawals-pov(top-level) plusapplyOne-pov/foldl-applyOne-povbuilding blocksCerts.Properties.PoVLemmasCERT-pov,POST-CERT-pov,sts-pov,PRE-CERT-povCerts.Properties.PoVCERTS-povtop-level theoremDesign notes
PRE-CERT-povusesapplyWithdrawals-povinstead of Conway'sconstMapchainConway's
PRE-CERTzeros out withdrawn credentials viaconstMap wdrlCreds 0 ∪ˡ rewards, and the PoV proof decomposes the rewards map into restricted/complement parts, showing the zeroing removes exactlygetCoin wdrls.Dijkstra's
PRE-CERTusesapplyWithdrawals wdrls rewards(CIP-159 partial withdrawals), which subtracts each withdrawal amount. The PoV equationgetCoin s ≡ getCoin s' + getCoin wdrlsstill holds, but the proof requires a new lemma —applyWithdrawals-pov— based on fold induction rather than map decomposition.applyWithdrawals-povis structured as three layersapplyOne-pov). Decomposes the accumulator into complement + restriction, shows the per-step decrease equalsamtusingm∸n+n≡m.foldl-applyOne-pov). Induction oversetToList (wdrls ˢ), maintaining an invariant that remaining entries have registered credentials with bounded balances. Relies onUnique(fromstakeinjectivity, which follows from the per-batchNetworkIdconstraint).applyWithdrawals-pov). Instantiates the fold with the withdrawal map's list representation.CERT-pov,POST-CERT-pov,sts-povare essentially unchanged from ConwayThe Dijkstra
DELEG-delegateandDELEG-deregconstructors have the same value-relevant structure (adding/removing zero-balance entries), andPOST-CERTstill only filtersvoteDelegs.CERT-povis missing theCERT-vdelcase because Dijkstra has onlyCERT-deleg,CERT-pool,CERT-gov.Outstanding proof obligations
Three lemmas are stated as module parameters with detailed proof sketches in comments. Each is provable from the existing
agda-sets/Withdrawalsmachinery; they are kept as parameters here to keep this PR focused on the new fold-induction infrastructure.∪ˡ-res-lookup-preserve— for anyc' ≠ c, lookup in❴ c , v ❵ ∪ˡ (m ∣ ❴ c ❵ ᶜ)agrees with lookup inm. Painful to thread throughagda-sets⁇instance resolution.sum-map-proj₂≡getCoin—getCoinrepresentation of a withdrawal map's coin sum.setToList-Unique—Uniqueonmap (stake ∘ proj₁) (setToList (wdrls ˢ)). Follows fromstakeinjectivity, which holds because the per-batchNetworkIdconstraint forces all withdrawals to share the samenet.These will be discharged in a follow-up; the relevant tracking has been added to issue #1185.
Checklist
CHANGELOG.md