Skip to content

[Dijkstra] CIP-159-11c: Prove LEDGER preservation of value (#1187)#1190

Draft
williamdemeo wants to merge 9 commits into
1186-dijkstra-utxo-and-utxow-povfrom
1187-dijkstra-ledger-pov
Draft

[Dijkstra] CIP-159-11c: Prove LEDGER preservation of value (#1187)#1190
williamdemeo wants to merge 9 commits into
1186-dijkstra-utxo-and-utxow-povfrom
1187-dijkstra-ledger-pov

Conversation

@williamdemeo
Copy link
Copy Markdown
Member

Description

Closes #1187.

This PR proves the top-level LEDGER-pov theorem for the Dijkstra era, building on the Certs and Utxo/Utxow PoV machinery from PRs #<new-A> and #<new-B>. It is the third of three replacing the original PR #1169.

It targets the branch of PR #<new-B> so that CI sees the full PoV chain in order; once #<new-B> merges, this PR will be retargeted to master.


Module

Module Purpose Status
Ledger.Properties.PoV HasCoin instances and LEDGER-pov Proved (modulo module parameters)

Design notes

Why the proof reasons about LEDGER-V as a single step

The Dijkstra LEDGER-pov proof does not decompose into independent SUBLEDGERS-pov and UTXOW-pov pieces, because (i) individual SUBUTXO rules have no balance equation — only the batch-level consumedBatch ≡ producedBatch (in UTXO) constrains the total — and (ii) sub-transactions may individually transfer value between UTxO and CertState (via sub-withdrawals, sub-deposits, sub-direct-deposits) without local balancing. Instead, the proof reasons about the entire LEDGER-V step at once.

applyDirectDeposits cancellation is the main new challenge

In LEDGER-V, certStateFinal = certStateWithDDeps tx certState₂ = record certState₂ { dState = applyDirectDeposits (DirectDepositsOf tx) (DStateOf certState₂) }. Direct deposit value appears in producedBatch (UTxO side) and in certStateFinal (CertState side), so it cancels in the total. The proof is an equational chain combining SUBLEDGERS-certs-pov, top-level CERTS-pov, the batch-UTxO-accounting step, and the applyDirectDeposits-rewardsBalance identity. Per-transaction direct deposit application (PR #1161) makes this slightly cleaner than batch-wide application would have been, because each transaction's direct-deposit total appears next to its own producedTx term in producedBatch, mirrored by its own certStateWithDDeps step.

Helpers proved here

  • SUBLEDGERS-certs-pov — induction over the SUBLEDGERS reflexive-transitive closure, composing per-sub-transaction CERTS-pov invocations.
  • SUBLEDGERS-utxo-coin — parallel induction tracking getCoin (UTxOStateOf _) through the SUBLEDGERS chain via the per-step SUBUTXOW coin equation.
  • LEDGER-pov — both LEDGER-V and LEDGER-I cases.

The LEDGER-I case is straightforward: certState and govSt are unchanged, SUBLEDGERS is a no-op, and only the UTXOW step affects getCoin, which it preserves via utxow-pov-invalid (from PR #<new-B>).


Outstanding proof obligations

The following are stated as module parameters of Ledger.Properties.PoV, with detailed proof sketches in comments. Each will be discharged in a follow-up; the dependencies are now in place.

CIP-159–specific or Dijkstra-specific:

  • applyDirectDeposits-rewardsBalance — should follow from ∪⁺ properties.
  • subutxow-step-coin — per-step SUBUTXOW coin equation. Requires a batch-wide "spend inputs preserved" invariant and freshness of each sub-tx's TxId relative to the running UTxO.
  • utxo₁-tx-spend-eq and fresh-top-tx-id — batch-wide invariants on the post-SUBLEDGERS UTxO state. Both follow from batch-wide input disjointness and TxId freshness, which the outer UTXO rule establishes at the batch level but does not expose per-step.

Era-independent (can be discharged in a small standalone follow-up):

  • posNeg-deposits — deposit-change posPart/negPart identity. Provable from the definition of calculateDepositsChange and the standard y + posPart (x − y) ≡ x + negPart (x − y) lemma.
  • DD-split — aggregation identity for allDirectDeposits. Provable once we confirm allDirectDeposits sums top-level and sub-level direct deposits disjointly.
  • sum-map-+ — standard list algebra.

The shared parameters (balance-∪, split-balance, outs-disjoint, noMintTx, noMintSubTx, ∪ˡ-res-lookup-preserve, sum-map-proj₂≡getCoin, setToList-Unique) are the same ones already taken as parameters in PRs #<new-A> and #<new-B>; they are threaded through here.

The invariant properties from §§3–6 of the parent issue #1123 (phantom asset, non-negative balance, direct-deposit registration, balance-interval satisfaction) are mostly straightforward consequences of UTXO-Premises conjuncts and are deferred to a follow-up.


Checklist

  • Commit sequence broadly makes sense and commits have useful messages
  • Any semantic changes to the specifications are documented in CHANGELOG.md
  • Code is formatted according to CONTRIBUTING.md
  • Self-reviewed the diff

@williamdemeo williamdemeo self-assigned this May 7, 2026
@williamdemeo williamdemeo linked an issue May 7, 2026 that may be closed by this pull request
5 tasks
@williamdemeo williamdemeo changed the base branch from master to 1186-dijkstra-utxo-and-utxow-pov May 7, 2026 20:28
@williamdemeo williamdemeo force-pushed the 1186-dijkstra-utxo-and-utxow-pov branch from ca99121 to aec8700 Compare May 7, 2026 20:34
@williamdemeo williamdemeo force-pushed the 1187-dijkstra-ledger-pov branch from cf1eeab to 24e189f Compare May 7, 2026 20:34
…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.
@williamdemeo williamdemeo force-pushed the 1186-dijkstra-utxo-and-utxow-pov branch from aec8700 to 8638126 Compare May 8, 2026 00:24
@williamdemeo williamdemeo force-pushed the 1187-dijkstra-ledger-pov branch from 24e189f to c20ef17 Compare May 8, 2026 00:25
@williamdemeo williamdemeo force-pushed the 1186-dijkstra-utxo-and-utxow-pov branch from 89df52c to f34dd7b Compare May 8, 2026 22:24
@williamdemeo williamdemeo force-pushed the 1186-dijkstra-utxo-and-utxow-pov branch from f34dd7b to ed32fcc Compare May 8, 2026 22:32
@williamdemeo williamdemeo force-pushed the 1187-dijkstra-ledger-pov branch from c20ef17 to 1a6f0e5 Compare May 8, 2026 22:33
After moving direct-deposit application from LEDGER-V into POST-CERT,
CERTS-pov now produces a symmetric "consumed = produced" equation:

  getCoin s₁ + getCoin (DirectDepositsOf Γ)
  ≡ getCoin sₙ + getCoin (WithdrawalsOf Γ)

Thread the direct-deposit term through the LEDGER-pov proof:

* SUBLEDGERS-certs-pov gains "+ sum (map ddwl stxs)" on the LHS,
  where ddwl = getCoin ∘ DirectDepositsOf is the per-sub-tx
  direct-deposit total (analogous to wdrwl).

* combined-certs gains "+ allDirectDeps" on the LHS, composing the
  per-sub CERTS-pov chain with the top-level call.

* The main LEDGER-V chain wraps the result in +-cancelʳ-≡ to
  discharge the asymmetric "+ allDirectDeps" combined-certs introduces.

Removed:

* The certStateFinal local definition (LEDGER-V no longer applies
  applyDirectDeposits).
* step-ii and the applyDirectDeposits-rewardsBalance module parameter
  (subsumed by indexedSumᵛ'-∪⁺ inside POST-CERT-pov).
* The DD-split module parameter (subsumed by per-tx CERTS-pov chain).
* Stale "Key Lemma" subsection and stale commented-out lines in bat'.
* Unused imports +-identityʳ and +-0-monoid.
* Redundant local aliases in bat's where-block.

Documentation: rewrote "Key Differences from Conway" point 2 and the
LEDGER-V Proof Outline to reflect the new architecture; clarified the
LEDGER-I outline.
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.

[Dijkstra] LEDGER PoV

1 participant