Skip to content

Commit e04bad7

Browse files
committed
CIP-159-11: applyWithdrawals-pov and new library lemmas (#1123)
Add the applyWithdrawals preservation-of-value proof machinery and prove several lemmas that were previously assumed as module parameters in Conway. New proofs in Ledger.Prelude (previously Conway module parameters): - indexedSumᵛ'-∪: getCoin distributes over disjoint ∪ˡ - sumConstZero: getCoin (constMap X 0) ≡ 0 - getCoin-cong: indexedSum' proj₂ respects set equality - res-decomp: (m ∪ˡ m') ≡ᵉ (m ∪ˡ (m' ∣ dom m ᶜ)) - getCoin-singleton, ≡ᵉ-getCoin, ∪ˡsingleton∈dom, ∪ˡsingleton∉dom, ∪ˡsingleton0≡: singleton map getCoin lemmas - indexedSumL-proj₂-zero: sum of zero-valued entries is zero - setToList-∈: opaque bridge from list membership to set membership New module Certs.Properties.ApplyWithdrawalsPoV: - applyOne-pov: single withdrawal step decreases getCoin by amt - foldl-applyOne-pov: fold induction with Unique invariant - applyWithdrawals-pov: top-level lemma for PRE-CERT-pov - ∪ˡ-res-dom-preserve: ∪ˡ with complement restriction preserves domain membership for other credentials Remaining assumptions (deferred to agda-sets library): - ∪ˡ-res-lookup-preserve: lookupᵐ? stability under ∪ˡ for other keys - sum-map-proj₂≡getCoin: relates list-level sum to indexedSumᵛ' - setToList-Unique: credential uniqueness of withdrawal list - ≡ᵉ-getCoinˢ: getCoin invariance under injective key renaming
1 parent c619dbf commit e04bad7

10 files changed

Lines changed: 295 additions & 285 deletions

File tree

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

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,11 @@ instance
4747
_ = +-0-monoid
4848
4949
module Certs-PoV
50-
-- TODO: prove some or all of the following assumptions, used in roof of `CERTBASE-pov`.
51-
( res-decomp' : {A : Type} ⦃ _ : DecEq A ⦄ (m m' : A ⇀ Coin)
52-
→ (m ∪ˡ m')ˢ ≡ᵉ (m ∪ˡ (m' ∣ dom (m ˢ) ᶜ))ˢ )
53-
( getCoin-cong' : {A : Type} ⦃ _ : DecEq A ⦄ (s : A ⇀ Coin) (s' : ℙ (A × Coin)) → s ˢ ≡ᵉ s'
54-
→ indexedSum' proj₂ (s ˢ) ≡ indexedSum' proj₂ s' )
55-
( ≡ᵉ-getCoinˢ' : {A A' : Type} ⦃ _ : DecEq A ⦄ ⦃ _ : DecEq A' ⦄ (s : ℙ (A × Coin)) {f : A → A'}
56-
→ InjectiveOn (dom s) f → getCoin (mapˢ (map₁ f) s) ≡ getCoin s )
50+
-- TODO: prove the following assumption, used in roof of `CERTBASE-pov`.
51+
( ≡ᵉ-getCoinˢ' : {A A' : Type} ⦃ _ : DecEq A ⦄ ⦃ _ : DecEq A' ⦄ (s : ℙ (A × Coin)) {f : A → A'}
52+
→ InjectiveOn (dom s) f → getCoin (mapˢ (map₁ f) s) ≡ getCoin s )
5753
where
58-
open Certs-Pov-lemmas res-decomp' getCoin-cong' ≡ᵉ-getCoinˢ'
54+
open Certs-Pov-lemmas ≡ᵉ-getCoinˢ'
5955
```
6056
-->
6157

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

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ open import Axiom.Set.Properties th
2323
open import Algebra using (CommutativeMonoid)
2424
open import Data.Maybe.Properties
2525
open import Data.Nat.Properties using (+-0-monoid; +-0-commutativeMonoid; +-identityʳ; +-identityˡ)
26-
open import Relation.Binary using (IsEquivalence)
26+
import Relation.Binary as Eq using (IsEquivalence)
2727
open import Relation.Nullary.Decidable
2828
open import Tactic.ReduceDec
2929
@@ -77,7 +77,7 @@ CERT-pov {s = ⟦ _ , stᵖ , stᵍ ⟧ᶜˢ}{⟦ _ , stᵖ' , stᵍ' ⟧ᶜˢ}
7777
getCoin ⟦ ⟦ vDelegs ∣ ❴ c ❵ ᶜ , sDelegs ∣ ❴ c ❵ ᶜ , rwds ∣ ❴ c ❵ ᶜ ⟧ , stᵖ' , stᵍ' ⟧
7878
7979
where
80-
module ≡ᵉ = IsEquivalence (≡ᵉ-isEquivalence {Credential × Coin})
80+
module ≡ᵉ = Eq.IsEquivalence (≡ᵉ-isEquivalence {Credential × Coin})
8181
rwds-∪ˡ-decomp = (rwds ∣ ❴ c ❵ ᶜ) ∪ˡ (rwds ∣ ❴ c ❵ )
8282
8383
rwds-∪ˡ-∪ : rwds-∪ˡ-decomp ˢ ≡ᵉ (rwds ∣ ❴ c ❵ ᶜ)ˢ ∪ (rwds ∣ ❴ c ❵)ˢ
@@ -100,13 +100,9 @@ injOn _ h {record { stake = stakex }} {record { stake = stakey }} x∈ y∈ refl
100100
cong (λ u → record { net = u ; stake = stakex }) (trans (h x∈) (sym (h y∈)))
101101
102102
module Certs-Pov-lemmas
103-
-- TODO: prove some or all of the following assumptions, used in roof of `CERTBASE-pov`.
104-
( res-decomp : {A : Type} ⦃ _ : DecEq A ⦄ (m m' : A ⇀ Coin)
105-
→ (m ∪ˡ m')ˢ ≡ᵉ (m ∪ˡ (m' ∣ dom (m ˢ) ᶜ))ˢ )
106-
( getCoin-cong : {A : Type} ⦃ _ : DecEq A ⦄ (s : A ⇀ Coin) (s' : ℙ (A × Coin)) → s ˢ ≡ᵉ s'
107-
→ indexedSum' proj₂ (s ˢ) ≡ indexedSum' proj₂ s' )
108-
( ≡ᵉ-getCoinˢ : {A A' : Type} ⦃ _ : DecEq A ⦄ ⦃ _ : DecEq A' ⦄ (s : ℙ (A × Coin)) {f : A → A'}
109-
→ InjectiveOn (dom s) f → getCoin (mapˢ (map₁ f) s) ≡ getCoin s )
103+
-- TODO: prove the following assumption, used in roof of `CERTBASE-pov`.
104+
( ≡ᵉ-getCoinˢ : {A A' : Type} ⦃ _ : DecEq A ⦄ ⦃ _ : DecEq A' ⦄ (s : ℙ (A × Coin)) {f : A → A'}
105+
→ InjectiveOn (dom s) f → getCoin (mapˢ (map₁ f) s) ≡ getCoin s )
110106
where
111107
```
112108
-->
@@ -145,7 +141,7 @@ value of the withdrawals in `Γ`{.AgdaBound}. In other terms,
145141
let
146142
open DState (dState cs )
147143
open DState (dState cs') renaming (rewards to rewards')
148-
module ≡ᵉ = IsEquivalence (≡ᵉ-isEquivalence {Credential × Coin})
144+
module ≡ᵉ = Eq.IsEquivalence (≡ᵉ-isEquivalence {Credential × Coin})
149145
wdrlsCC = mapˢ (map₁ RewardAddress.stake) (wdrls ˢ)
150146
zeroMap = constMap (mapˢ RewardAddress.stake (dom wdrls)) 0
151147
rwds-∪ˡ-decomp = (rewards ∣ dom wdrlsCC ᶜ) ∪ˡ (rewards ∣ dom wdrlsCC)

src/Ledger/Conway/Specification/Ledger/Properties/PoV.lagda.md

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,9 @@ instance
3838
3939
module _
4040
(tx : Tx) (let open Tx tx; open TxBody body)
41-
( res-decomp : {A : Type} ⦃ _ : DecEq A ⦄ (m m' : A ⇀ Coin)
42-
→ (m ∪ˡ m')ˢ ≡ᵉ (m ∪ˡ (m' ∣ dom (m ˢ) ᶜ))ˢ )
43-
( getCoin-cong : {A : Type} ⦃ _ : DecEq A ⦄ (s : A ⇀ Coin) (s' : ℙ (A × Coin)) → s ˢ ≡ᵉ s'
44-
→ indexedSum' proj₂ (s ˢ) ≡ indexedSum' proj₂ s' )
45-
( ≡ᵉ-getCoinˢ : {A A' : Type} ⦃ _ : DecEq A ⦄ ⦃ _ : DecEq A' ⦄ (s : ℙ (A × Coin)) {f : A → A'}
46-
→ InjectiveOn (dom s) f → getCoin (mapˢ (map₁ f) s) ≡ getCoin s )
41+
-- TODO: prove the following assumption, used in roof of `CERTBASE-pov`.
42+
( ≡ᵉ-getCoinˢ : {A A' : Type} ⦃ _ : DecEq A ⦄ ⦃ _ : DecEq A' ⦄ (s : ℙ (A × Coin)) {f : A → A'}
43+
→ InjectiveOn (dom s) f → getCoin (mapˢ (map₁ f) s) ≡ getCoin s )
4744
where
4845
4946
pattern UTXO-induction r = UTXO-inductive⋯ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ r _ _ _
@@ -81,8 +78,8 @@ then the coin values of `s`{.AgdaBound} and `s'`{.AgdaBound} are equal, that is,
8178
open LState s' renaming (utxoSt to utxoSt'; govSt to govSt'; certState to certState')
8279
open CertState certState'
8380
open ≡-Reasoning
84-
open Certs-PoV res-decomp getCoin-cong ≡ᵉ-getCoinˢ
85-
zeroMap = constMap (mapˢ RewardAddress.stake (dom txWithdrawals)) 0
81+
open Certs-PoV ≡ᵉ-getCoinˢ
82+
zeroMap = constMap (mapˢ RewardAddress.stake (dom txWithdrawals)) 0
8683
in
8784
begin
8885
getCoin utxoSt + getCoin certState

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

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -294,22 +294,23 @@ The `LEDGER`{.AgdaDatatype} rule will call `applyDirectDeposits`{.AgdaFunction}
294294
credit direct deposits to account balances as part of processing a transaction batch.
295295

296296
```agda
297+
-- For each withdrawal entry `(addr, amt)`, look up `stake addr` in the acc,
298+
-- compute `bal ∸ amt`, create a singleton map with the new balance, and
299+
-- merge it with the rest (complement-restricted, to remove the old entry).
300+
applyOne : Rewards → RewardAddress × Coin → Rewards
301+
applyOne acc (addr , amt) =
302+
case lookupᵐ? acc (stake addr) of λ where
303+
(just bal) → ❴ stake addr , bal ∸ amt ❵ ∪ˡ (acc ∣ ❴ stake addr ❵ ᶜ)
304+
nothing → acc
305+
-- `nothing` case is defensive; the PRE-CERT precondition guarantees the
306+
-- credential is registered, but handling it makes the function total.
307+
297308
applyWithdrawals : Withdrawals → Rewards → Rewards
298-
applyWithdrawals wdrls rwds =
299-
foldl applyOne rwds (setToList (wdrls ˢ))
300-
where
301-
-- For each withdrawal entry `(addr, amt)`, look up `stake addr` in the acc,
302-
-- compute `bal ∸ amt`, create a singleton map with the new balance, and
303-
-- merge it with the rest (complement-restricted, to remove the old entry).
304-
applyOne : Rewards → RewardAddress × Coin → Rewards
305-
applyOne acc (addr , amt) =
306-
case lookupᵐ? acc (stake addr) of λ where
307-
(just bal) → ❴ stake addr , bal ∸ amt ❵ ∪ˡ (acc ∣ ❴ stake addr ❵ ᶜ)
308-
nothing → acc
309-
-- `nothing` case is defensive; the PRE-CERT precondition guarantees the
310-
-- credential is registered, but handling it makes the function total.
309+
applyWithdrawals wdrls rwds = foldl applyOne rwds (setToList (wdrls ˢ))
311310
```
312311

312+
313+
313314
In the Dijkstra era, CIP-159 allows **partial withdrawals**: a transaction may
314315
withdraw any amount up to the current account balance.
315316
`applyWithdrawals`{.AgdaFunction} subtracts each withdrawal amount from the

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,8 @@ module Ledger.Dijkstra.Specification.Certs.Properties where
1313
-->
1414

1515
```agda
16+
open import Ledger.Dijkstra.Specification.Certs.Properties.ApplyWithdrawalsPoV
1617
open import Ledger.Dijkstra.Specification.Certs.Properties.Computational
18+
open import Ledger.Dijkstra.Specification.Certs.Properties.PoV
19+
open import Ledger.Dijkstra.Specification.Certs.Properties.PoVLemmas
1720
```

0 commit comments

Comments
 (0)