Skip to content

Commit 5e41b66

Browse files
committed
Update Certs PoV proofs for direct-deposit application in POST-CERT (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.
1 parent 4e3d554 commit 5e41b66

5 files changed

Lines changed: 133 additions & 34 deletions

File tree

src/Ledger/Dijkstra/Specification/Account.lagda.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ DirectDeposits : Type
3333
DirectDeposits = Credential ⇀ Coin
3434
```
3535

36+
<!--
37+
```agda
38+
record HasDirectDeposits {a} (A : Type a) : Type a where
39+
field DirectDepositsOf : A → DirectDeposits
40+
open HasDirectDeposits ⦃...⦄ public
41+
```
42+
-->
43+
3644
## Balance Intervals {#sec:balance-intervals}
3745

3846
[CIP 159][] allows a transaction to assert that an account's balance falls within a

src/Ledger/Dijkstra/Specification/Certs.lagda.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ instance
181181
HasWithdrawals-CertEnv : HasWithdrawals CertEnv
182182
HasWithdrawals-CertEnv .WithdrawalsOf = CertEnv.wdrls
183183
184+
HasDirectDeposits-CertEnv : HasDirectDeposits CertEnv
185+
HasDirectDeposits-CertEnv .DirectDepositsOf = CertEnv.directDeposits
186+
184187
HasVoteDelegs-DState : HasVoteDelegs DState
185188
HasVoteDelegs-DState .VoteDelegsOf = DState.voteDelegs
186189

src/Ledger/Dijkstra/Specification/Certs/Properties/PoV.lagda.md

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@ module Ledger.Dijkstra.Specification.Certs.Properties.PoV
1616
1717
open import Ledger.Prelude
1818
19+
open import Ledger.Dijkstra.Specification.Account gs
1920
open import Ledger.Dijkstra.Specification.Certs gs
2021
open import Ledger.Dijkstra.Specification.Certs.Properties.PoVLemmas gs
2122
open import Ledger.Dijkstra.Specification.Gov.Actions gs hiding (yes; no)
2223
open import Ledger.Prelude
2324
open import Data.List.Relation.Unary.Unique.Propositional using (Unique)
24-
open import Data.Nat.Properties using (+-0-monoid)
25+
open import Data.Nat.Properties using (+-0-monoid; +-comm; +-assoc)
2526
2627
open CertState
2728
open RewardAddress
@@ -39,22 +40,59 @@ module Certs-PoV
3940
( sum-map-proj₂≡getCoin : ∀ (m : Withdrawals) → sum (map proj₂ (setToList (m ˢ))) ≡ getCoin m )
4041
4142
( setToList-Unique : ∀ (m : Withdrawals) → Unique (map (stake ∘ proj₁) (setToList (m ˢ))) )
43+
44+
-- New CIP-159 assumption (forwarded to Certs-Pov-lemmas): see PoVLemmas.
45+
( indexedSumᵛ'-∪⁺ : ∀ (m m' : Rewards) → getCoin (m ∪⁺ m') ≡ getCoin m + getCoin m' )
46+
4247
where
43-
open Certs-Pov-lemmas ∪ˡ-res-lookup-preserve sum-map-proj₂≡getCoin setToList-Unique
48+
open Certs-Pov-lemmas ∪ˡ-res-lookup-preserve sum-map-proj₂≡getCoin setToList-Unique
49+
indexedSumᵛ'-∪⁺
4450
```
4551
-->
4652

4753
## Theorem: The `CERTS` rule preserves value {#thm:CERTS-PoV}
4854

55+
In Dijkstra, the `CERTS`{.AgdaDatatype} rule processes withdrawals (via
56+
`PRE-CERT`{.AgdaDatatype}) and direct deposits (via `POST-CERT`{.AgdaDatatype})
57+
in addition to the certificate steps. Withdrawals reduce the rewards balance;
58+
direct deposits increase it; the preservation-of-value equation is a symmetric
59+
"consumed equals produced" statement:
60+
61+
`getCoin s₁ + getCoin (CertEnv.directDeposits Γ) ≡ getCoin sₙ + getCoin (WithdrawalsOf Γ)`.
62+
63+
Equivalently, the *increase* in rewards balance from `s₁`{.AgdaBound} to
64+
`sₙ`{.AgdaBound} equals `directDeposits − withdrawals`.
65+
4966
```agda
50-
CERTS-pov : {Γ : CertEnv} {s₁ sₙ : CertState}
51-
→ ∀[ a ∈ dom (WithdrawalsOf Γ) ] NetworkIdOf a ≡ NetworkId
52-
→ Γ ⊢ s₁ ⇀⦇ l ,CERTS⦈ sₙ
53-
→ getCoin s₁ ≡ getCoin sₙ + getCoin (WithdrawalsOf Γ)
67+
CERTS-pov : {Γ : CertEnv} {s₁ sₙ : CertState}
68+
→ ∀[ a ∈ dom (WithdrawalsOf Γ) ] NetworkIdOf a ≡ NetworkId
69+
→ Γ ⊢ s₁ ⇀⦇ l ,CERTS⦈ sₙ
70+
→ getCoin s₁ + getCoin (DirectDepositsOf Γ) ≡ getCoin sₙ + getCoin (WithdrawalsOf Γ)
5471
```
5572

73+
The proof composes `PRE-CERT-pov`{.AgdaFunction} (which gives
74+
`getCoin s₁ ≡ getCoin s' + getCoin (WithdrawalsOf Γ)`) with `sts-pov`{.AgdaFunction}
75+
(which gives `getCoin s' + getCoin (DirectDepositsOf Γ) ≡ getCoin sₙ`),
76+
plus an arithmetic shuffle to interleave the two accounting terms.
77+
78+
<!--
5679
```agda
57-
CERTS-pov {Γ = Γ} validNetId (run (pre-cert , certs)) =
58-
trans (PRE-CERT-pov validNetId pre-cert)
59-
(cong (_+ getCoin (WithdrawalsOf Γ)) (sts-pov certs))
80+
CERTS-pov {Γ = Γ} {s₁} {sₙ} validNetId (run {s' = s'} (pre-cert , certs)) =
81+
begin
82+
getCoin s₁ + cdd ≡⟨ cong (_+ cdd) (PRE-CERT-pov validNetId pre-cert) ⟩
83+
getCoin s' + cwd + cdd ≡⟨ swap-right _ (cwd) (cdd) ⟩
84+
getCoin s' + cdd + cwd ≡⟨ cong (_+ cwd) (sts-pov certs) ⟩
85+
getCoin sₙ + cwd ∎
86+
where
87+
open ≡-Reasoning
88+
cdd cwd : Coin
89+
cdd = getCoin (DirectDepositsOf Γ)
90+
cwd = getCoin (WithdrawalsOf Γ)
91+
92+
swap-right : ∀ a b c → (a + b) + c ≡ (a + c) + b
93+
swap-right a b c =
94+
trans (+-assoc a b c)
95+
(trans (cong (a +_) (+-comm b c))
96+
(sym (+-assoc a c b)))
6097
```
98+
-->

src/Ledger/Dijkstra/Specification/Certs/Properties/PoVLemmas.lagda.md

Lines changed: 75 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,17 @@ source_path: src/Ledger/Dijkstra/Specification/Certs/Properties/PoVLemmas.lagda.
88

99
## Key Differences from Conway
1010

11-
+ **`PRE-CERT`**: Conway uses `constMap wdrlCreds 0 ∪ˡ rewards` (zeroing).
11+
+ **`PRE-CERT`**. Conway uses `constMap wdrlCreds 0 ∪ˡ rewards` (zeroing).
1212
Dijkstra (CIP-159) uses `applyWithdrawals wdrls rewards` (subtraction).
1313
The PoV equation still holds; the proof structure differs.
14-
+ **`CERT` / `DELEG`**: Same value-relevant structure as Conway.
15-
+ **No `CERT-vdel`**: Dijkstra has `CERT-deleg`, `CERT-pool`, `CERT-gov` only.
14+
+ **`POST-CERT`**. Conway only filters `voteDelegs` and preserves `getCoin`.
15+
Dijkstra (CIP-159) additionally applies `rewards ∪⁺ directDeposits`, increasing
16+
the value by `getCoin (DirectDepositsOf Γ)`. The PoV equation
17+
therefore changes: `POST-CERT-pov` and `sts-pov` now relate the pre- and
18+
post-state by the direct-deposit total, and `CERTS-pov` becomes a symmetric
19+
"consumed ≡ produced" equation balancing withdrawals against direct deposits.
20+
+ **`CERT` / `DELEG`**. Same value-relevant structure as Conway.
21+
+ **No `CERT-vdel`**. Dijkstra has `CERT-deleg`, `CERT-pool`, `CERT-gov` only.
1622

1723
<!--
1824
```agda
@@ -23,6 +29,7 @@ open import Ledger.Dijkstra.Specification.Gov.Base using (GovStructure)
2329
module Ledger.Dijkstra.Specification.Certs.Properties.PoVLemmas
2430
(gs : GovStructure) (open GovStructure gs) where
2531
32+
open import Ledger.Dijkstra.Specification.Account gs
2633
open import Ledger.Dijkstra.Specification.Certs gs
2734
open import Ledger.Dijkstra.Specification.Certs.Properties.ApplyWithdrawalsPoV gs
2835
open import Ledger.Dijkstra.Specification.Gov.Actions gs hiding (yes; no)
@@ -56,6 +63,8 @@ CERT-pov : {Γ : CertEnv} {s s' : CertState}
5663
→ Γ ⊢ s ⇀⦇ dCert ,CERT⦈ s' → getCoin s ≡ getCoin s'
5764
```
5865

66+
(The `CERT` rule is unchanged in Dijkstra, so this lemma matches the Conway version.)
67+
5968
<!--
6069
```agda
6170
CERT-pov (CERT-deleg (DELEG-delegate {rwds = rwds} _)) = sym (∪ˡsingleton0≡ rwds)
@@ -88,26 +97,20 @@ CERT-pov (CERT-gov _) = refl
8897
```
8998
-->
9099

91-
## POST-CERT-pov and sts-pov
92-
93-
```agda
94-
POST-CERT-pov : {Γ : CertEnv} {s s' : CertState}
95-
→ Γ ⊢ s ⇀⦇ _ ,POST-CERT⦈ s' → getCoin s ≡ getCoin s'
100+
## CIP-159 PoV lemmas (parameterized)
96101

97-
POST-CERT-pov CERT-post = refl
98-
99-
sts-pov : {Γ : CertEnv} {s₁ sₙ : CertState} {sigs : List DCert}
100-
→ RunTraceAndThen _⊢_⇀⦇_,CERT⦈_ _⊢_⇀⦇_,POST-CERT⦈_ Γ s₁ sigs sₙ
101-
→ getCoin s₁ ≡ getCoin sₙ
102-
sts-pov (run-[] x) = POST-CERT-pov x
103-
sts-pov (run-∷ x xs) = trans (CERT-pov x) (sts-pov xs)
104-
```
102+
The `POST-CERT-pov`, `sts-pov`, and `PRE-CERT-pov` proofs all live inside the
103+
parameterized `Certs-Pov-lemmas`{.AgdaModule} sub-module.
105104

106-
## PRE-CERT-pov (CIP-159: partial withdrawals)
107-
108-
The key new assumption `applyWithdrawals-pov` states that applying withdrawals
109-
decreases `rewardsBalance` by exactly the total withdrawn amount. This replaces
110-
Conway's `constMap`/`res-decomp`/`sumConstZero` chain.
105+
+ `PRE-CERT-pov`{.AgdaFunction} relies on `applyWithdrawals-pov`{.AgdaFunction}
106+
from `Certs.Properties.ApplyWithdrawalsPoV`{.AgdaModule}, which itself takes
107+
three module parameters bridging gaps in the `agda-sets` API.
108+
+ `POST-CERT-pov`{.AgdaFunction} relies on a fourth parameter
109+
`indexedSumᵛ'-∪⁺`{.AgdaFunction} stating that `getCoin` distributes over
110+
`∪⁺`{.AgdaFunction} (union with addition). This is the natural analogue of
111+
the existing Conway `indexedSumᵛ'-∪`{.AgdaFunction} lemma for `∪ˡ`{.AgdaFunction}
112+
on disjoint domains, but for `∪⁺`{.AgdaFunction} the equation holds
113+
*unconditionally* — values at shared keys are added rather than dropped.
111114

112115
<!--
113116
```agda
@@ -124,11 +127,62 @@ module Certs-Pov-lemmas
124127
( sum-map-proj₂≡getCoin : ∀ (m : Withdrawals) → sum (map proj₂ (setToList (m ˢ))) ≡ getCoin m )
125128
126129
( setToList-Unique : ∀ (m : Withdrawals) → Unique (map (stake ∘ proj₁) (setToList (m ˢ))) )
130+
131+
-- New CIP-159 assumption: getCoin distributes over ∪⁺.
132+
-- `∪⁺` adds values of shared keys, so `getCoin (m ∪⁺ m') ≡ getCoin m + getCoin m'`
133+
-- holds unconditionally. TODO: Prove this in Ledger.Prelude or agda-sets.
134+
( indexedSumᵛ'-∪⁺ : ∀ (m m' : Rewards) → getCoin (m ∪⁺ m') ≡ getCoin m + getCoin m' )
127135
where
128136
open ApplyWithdrawals-PoV ∪ˡ-res-lookup-preserve sum-map-proj₂≡getCoin setToList-Unique
129137
```
130138
-->
131139

140+
### POST-CERT-pov (CIP-159: direct deposits)
141+
142+
The `POST-CERT`{.AgdaDatatype} rule applies direct deposits via `rewards ∪⁺ dd`,
143+
*increasing* the rewards balance by `getCoin dd`. The PoV equation therefore
144+
becomes "pre-balance plus direct deposits equals post-balance":
145+
146+
```agda
147+
POST-CERT-pov : {Γ : CertEnv} {s s' : CertState}
148+
→ Γ ⊢ s ⇀⦇ _ ,POST-CERT⦈ s'
149+
→ getCoin s + getCoin (DirectDepositsOf Γ) ≡ getCoin s'
150+
```
151+
152+
<!--
153+
```agda
154+
POST-CERT-pov (CERT-post {dd = dd} {rewards = rewards} _) =
155+
sym (indexedSumᵛ'-∪⁺ rewards dd)
156+
```
157+
-->
158+
159+
### sts-pov
160+
161+
A trace of `CERT`{.AgdaDatatype} steps followed by `POST-CERT`{.AgdaDatatype}
162+
increases the rewards balance by exactly the direct-deposit total: each
163+
`CERT`{.AgdaDatatype} step preserves value (by `CERT-pov`{.AgdaFunction}), and the
164+
final `POST-CERT`{.AgdaDatatype} step adds `getCoin (DirectDepositsOf Γ)`.
165+
166+
```agda
167+
sts-pov : {Γ : CertEnv} {s₁ sₙ : CertState} {sigs : List DCert}
168+
→ RunTraceAndThen _⊢_⇀⦇_,CERT⦈_ _⊢_⇀⦇_,POST-CERT⦈_ Γ s₁ sigs sₙ
169+
→ getCoin s₁ + getCoin (DirectDepositsOf Γ) ≡ getCoin sₙ
170+
```
171+
172+
<!--
173+
```agda
174+
sts-pov (run-[] x) = POST-CERT-pov x
175+
sts-pov {Γ = Γ} (run-∷ x xs) =
176+
trans (cong (_+ getCoin (DirectDepositsOf Γ)) (CERT-pov x)) (sts-pov xs)
177+
```
178+
-->
179+
180+
### PRE-CERT-pov (CIP-159: partial withdrawals)
181+
182+
The key new assumption `applyWithdrawals-pov` states that applying withdrawals
183+
decreases `rewardsBalance` by exactly the total withdrawn amount. This replaces
184+
Conway's `constMap`/`res-decomp`/`sumConstZero` chain.
185+
132186
```agda
133187
PRE-CERT-pov : {Γ : CertEnv} {s s' : CertState}
134188
→ ∀[ a ∈ dom (WithdrawalsOf Γ) ] NetworkIdOf a ≡ NetworkId

src/Ledger/Dijkstra/Specification/Transaction.lagda.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -412,10 +412,6 @@ could be either of them.
412412
field CurrentTreasuryOf : A → Maybe Coin
413413
open HasCurrentTreasury ⦃...⦄ public
414414
415-
record HasDirectDeposits {a} (A : Type a) : Type a where
416-
field DirectDepositsOf : A → DirectDeposits
417-
open HasDirectDeposits ⦃...⦄ public
418-
419415
record HasBalanceIntervals {a} (A : Type a) : Type a where
420416
field BalanceIntervalsOf : A → AccountBalanceIntervals
421417
open HasBalanceIntervals ⦃...⦄ public

0 commit comments

Comments
 (0)