Skip to content

Commit f677e1b

Browse files
committed
simplifications
1 parent e304e52 commit f677e1b

2 files changed

Lines changed: 58 additions & 116 deletions

File tree

src/Ledger/Dijkstra/Specification/Entities/Properties/ApplyToRewardsPoV.lagda.md

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ source_branch: master
33
source_path: src/Ledger/Dijkstra/Specification/Entities/Properties/ApplyToRewardsPoV.lagda.md
44
---
55

6-
# `applyToRewards` Preservation of Value {#sec:apply-to-rewards-pov}
6+
## `applyToRewards` Preservation of Value {#sec:apply-to-rewards-pov}
77

88
This module proves preservation of value for the two specializations of
99
`applyToRewards`{.AgdaFunction} used inside the `ENTITIES`{.AgdaDatatype} rule.
@@ -38,12 +38,12 @@ open import Ledger.Dijkstra.Specification.Gov.Base using (GovStructure)
3838
module Ledger.Dijkstra.Specification.Entities.Properties.ApplyToRewardsPoV
3939
(gs : GovStructure) (open GovStructure gs) where
4040
41-
open import Data.Nat.Properties using (+-identityʳ; +-comm; +-assoc; m∸n+n≡m; n≤0⇒n≡0)
42-
open import Data.Maybe.Properties using (just-injective)
4341
open import Data.List.Membership.Propositional.Properties using (∈-map⁺)
4442
open import Data.List.Relation.Unary.Any using (Any)
4543
open import Data.List.Relation.Unary.All using (lookup)
4644
open import Data.List.Relation.Unary.Unique.Propositional using (Unique) renaming (_∷_ to _::_)
45+
open import Data.Maybe.Properties using (just-injective)
46+
open import Data.Nat.Properties using (+-identityʳ; +-comm; +-assoc; m∸n+n≡m; n≤0⇒n≡0)
4747
open import Relation.Binary using (IsEquivalence)
4848
4949
open import Ledger.Prelude hiding (lookup)
@@ -61,7 +61,7 @@ open ≡-Reasoning
6161
```
6262
-->
6363

64-
## Shared helpers
64+
### Shared helpers
6565

6666
```agda
6767
getCoin-∪ˡ-overwrite : (acc : Rewards) (c : Credential) (v : Coin)
@@ -70,9 +70,6 @@ getCoin-∪ˡ-overwrite : (acc : Rewards) (c : Credential) (v : Coin)
7070

7171
<!--
7272
```agda
73-
-- The new applyToRewards writes to its accumulator via ❴ k , v ❵ ∪ˡ acc;
74-
-- left-biasedness of ∪ˡ makes this extensionally equal to the older
75-
-- ❴ k , v ❵ ∪ˡ (acc ∣ ❴ k ❵ ᶜ) form; the following proves this at the getCoin level.
7673
getCoin-∪ˡ-overwrite acc c v =
7774
begin
7875
getCoin (❴ c , v ❵ ∪ˡ acc)
@@ -143,7 +140,7 @@ split-by-lookup acc c bal lookup-eq =
143140
```
144141
-->
145142

146-
## The `ApplyToRewards-PoV` module
143+
### The `ApplyToRewards-PoV` module
147144

148145
The three assumed identities below are the same set/map identities used by the Conway
149146
PoV proofs; they are stated as module parameters here, to be discharged in a
@@ -183,9 +180,9 @@ lambda body of `applyToRewards f`.
183180
maybe (λ bal → ❴ stake addr , f bal amt ❵ ∪ˡ acc) acc (lookupᵐ? acc (stake addr))
184181
```
185182

186-
## Withdrawal preservation of value
183+
### Withdrawal preservation of value
187184

188-
### `applyOne-pov`: one withdrawal step decreases `getCoin` by `amt`
185+
#### `applyOne-pov`: one withdrawal step decreases `getCoin` by `amt`
189186

190187
When `lookupᵐ? acc (stake addr) ≡ just bal` and `amt ≤ bal`, applying a single
191188
withdrawal reduces the total by exactly `amt`.
@@ -215,16 +212,16 @@ withdrawal reduces the total by exactly `amt`.
215212
```
216213
-->
217214

218-
### `foldl-applyOne-pov` (fold induction)
215+
#### `foldl-applyOne-pov` (fold induction)
219216

220-
The fold invariant tracks three things through the induction:
217+
The fold invariant tracks three things through the induction.
221218

222-
1. every remaining withdrawal credential is in the current accumulator's domain;
219+
1. Every remaining withdrawal credential is in the current accumulator's domain.
223220

224-
2. every remaining withdrawal amount is bounded by the current balance at that
225-
credential;
221+
2. Every remaining withdrawal amount is bounded by the current balance at that
222+
credential.
226223

227-
3. no credential is revisited (the `Unique`{.AgdaDatatype} witness on the
224+
3. No credential is revisited (the `Unique`{.AgdaDatatype} witness on the
228225
stake-projected list).
229226

230227
Uniqueness is essential here precisely because `applyOne _∸_` *modifies* the balance
@@ -235,8 +232,7 @@ holds.
235232
```agda
236233
foldl-applyOne-pov : (acc : Rewards) (entries : List (RewardAddress × Coin))
237234
→ ( ∀ {addr amt} → (addr , amt) ∈ˡ entries
238-
→ stake addr ∈ dom acc
239-
× amt ≤ maybe id 0 (lookupᵐ? acc (stake addr)) )
235+
→ stake addr ∈ dom acc × amt ≤ maybe id 0 (lookupᵐ? acc (stake addr)) )
240236
→ Unique (map (stake ∘ proj₁) entries)
241237
→ getCoin acc ≡ getCoin (foldl (applyOne _∸_) acc entries) + sum (map proj₂ entries)
242238
```
@@ -246,15 +242,13 @@ holds.
246242
foldl-applyOne-pov acc [] _ _ = sym (+-identityʳ (indexedSumᵛ' id acc))
247243
foldl-applyOne-pov acc ((addr , amt) ∷ xs) h (c∉xs :: uniq-xs)
248244
with lookupᵐ? acc (stake addr) in eq
249-
-- Nothing case: applyOne is the identity; the bound `h (here refl) .proj₂`
250-
-- forces `amt ≡ 0`, which makes the recursive call's right-hand side equal
251-
-- to ours.
245+
-- Nothing case: applyOne is the identity; the bound `h (here refl) .proj₂` forces
246+
-- `amt ≡ 0`, which makes the recursive call's right-hand side equal to ours.
252247
... | nothing =
253248
let amt≤0 = subst (amt ≤_) (cong (maybe id 0) eq) (h (here refl) .proj₂)
254-
amt≡0 = n≤0⇒n≡0 amt≤0
255249
in
256250
subst (λ a → getCoin acc ≡ getCoin (foldl (applyOne _∸_) acc xs) + (a + sum (map proj₂ xs)))
257-
(sym amt≡0)
251+
(sym (n≤0⇒n≡0 amt≤0))
258252
(foldl-applyOne-pov acc xs (λ mem → h (there mem)) uniq-xs)
259253
-- Just case: per-step decrease via `applyOne-pov`, then chain with the IH.
260254
... | just bal = begin
@@ -270,7 +264,9 @@ holds.
270264
getCoin (foldl (applyOne _∸_) acc' xs) + (amt + sum (map proj₂ xs))
271265
272266
where
267+
c : Credential
273268
c = stake addr
269+
274270
acc' : Rewards
275271
acc' = ❴ c , bal ∸ amt ❵ ∪ˡ acc
276272
@@ -302,8 +298,7 @@ holds.
302298
applyWithdrawals-pov : (wdrls : Withdrawals) (rwds : Rewards)
303299
→ mapˢ stake (dom wdrls) ⊆ dom rwds
304300
→ ∀[ a ∈ dom wdrls ] NetworkIdOf a ≡ NetworkId
305-
→ ∀[ (addr , amt) ∈ wdrls ˢ ]
306-
amt ≤ maybe id 0 (lookupᵐ? rwds (stake addr))
301+
→ ∀[ (addr , amt) ∈ wdrls ˢ ] amt ≤ maybe id 0 (lookupᵐ? rwds (stake addr))
307302
→ getCoin rwds ≡ getCoin (applyWithdrawals wdrls rwds) + getCoin wdrls
308303
```
309304

@@ -429,7 +424,7 @@ Note the slimmed-down signature relative to `applyWithdrawals-pov`: no
429424
applyDirectDeposits-pov dd rwds creds∈ =
430425
begin
431426
getCoin (applyDirectDeposits dd rwds)
432-
≡⟨ refl ⟩ -- by definition of `applyDirectDeposits = applyToRewards _+_`
427+
≡⟨ refl ⟩
433428
getCoin (foldl (applyOne _+_) rwds (setToList (dd ˢ)))
434429
≡⟨ foldl-applyOne-pov-add rwds (setToList (dd ˢ)) inv ⟩
435430
getCoin rwds + sum (map proj₂ (setToList (dd ˢ)))
@@ -438,8 +433,7 @@ Note the slimmed-down signature relative to `applyWithdrawals-pov`: no
438433
439434
where
440435
open Equivalence
441-
inv : ∀ {addr amt} → (addr , amt) ∈ˡ setToList (dd ˢ)
442-
→ stake addr ∈ dom rwds
436+
inv : ∀ {addr amt} → (addr , amt) ∈ˡ setToList (dd ˢ) → stake addr ∈ dom rwds
443437
inv {addr} {amt} mem = creds∈ c∈dom-dd
444438
where
445439
addr-amt∈dd : (addr , amt) ∈ dd ˢ

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

Lines changed: 36 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,16 @@ source_branch: master
33
source_path: src/Ledger/Dijkstra/Specification/Entities/Properties/PoV.lagda.md
44
---
55

6-
# Properties of `ENTITIES`: Preservation of Value {#thm:ENTITIES-PoV}
6+
## Properties of `ENTITIES`: Preservation of Value {#thm:ENTITIES-PoV}
77

8-
This module proves preservation of value for the `ENTITIES`{.AgdaDatatype} rule
9-
introduced in [CIP-159-11d][PR-1201]. In the Dijkstra era, `ENTITIES`{.AgdaDatatype}
10-
wraps the inner `CERTS`{.AgdaDatatype} step with per-transaction withdrawal- and
11-
direct-deposit-handling: withdrawals are applied to the rewards balance *before*
12-
`CERTS`{.AgdaDatatype}, direct deposits *after*. The value-flow equation captures
13-
the net effect of all three components on the cert-state rewards balance
14-
(`coinFromRewards`{.AgdaFunction}; the deposit pots are accounted separately):
8+
This module proves preservation of value for the `ENTITIES`{.AgdaDatatype} rule.
159

16-
coinFromRewards s + getCoin (DirectDepositsOf Γ) ≡ coinFromRewards s' + getCoin (WithdrawalsOf Γ)
17-
18-
Intuitively, the deposits added on the right are matched by the withdrawals removed
19-
on the left — they "pass through" the rule.
20-
21-
## Proof Strategy
22-
23-
Case-split on the single `ENTITIES`{.AgdaInductiveConstructor} constructor to expose
24-
the three internal phases. Letting `r₀`{.AgdaBound} denote the initial rewards map
25-
and `r₁`{.AgdaBound} the rewards map after `CERTS`{.AgdaDatatype}, the equational
26-
chain is
27-
28-
+ `applyWithdrawals-pov`{.AgdaFunction} on `(wdrls, r₀)` rewrites `getCoin r₀` as
29-
`getCoin (applyWithdrawals wdrls r₀) + getCoin wdrls`.
30-
+ `CERTS-pov`{.AgdaFunction} on the inner step rewrites
31-
`getCoin (applyWithdrawals wdrls r₀)` as `getCoin r₁` (the rewards balance is
32-
preserved by the closure of `CERT`{.AgdaDatatype}).
33-
+ `applyDirectDeposits-pov`{.AgdaFunction} on `(dd, r₁)` rewrites
34-
`getCoin (applyDirectDeposits dd r₁)` as `getCoin r₁ + getCoin dd`.
35-
36-
The three rewrites compose into the desired equation modulo associativity and
37-
commutativity of `+` on `Coin`.
38-
39-
[PR-1201]: https://github.com/IntersectMBO/formal-ledger-specifications/pull/1201
10+
In the Dijkstra era, `ENTITIES`{.AgdaDatatype} wraps the inner `CERTS`{.AgdaDatatype}
11+
step with per-transaction withdrawal and direct-deposit handling. Withdrawals and
12+
deposits are applied to the rewards balance before and after `CERTS`{.AgdaDatatype},
13+
respectively. The "value-flow" equation proved below captures the net effect of all
14+
three components on the cert-state rewards balance (`coinFromRewards`{.AgdaFunction};
15+
the deposits are accounted separately).
4016

4117
<!--
4218
```agda
@@ -48,11 +24,12 @@ module Ledger.Dijkstra.Specification.Entities.Properties.PoV
4824
(gs : GovStructure) (open GovStructure gs) where
4925
5026
open import Data.List.Relation.Unary.Unique.Propositional using (Unique)
51-
open import Data.Nat.Properties using (+-comm; +-assoc; +-0-monoid)
27+
open import Data.Nat.Properties using (+-comm; +-assoc)
5228
5329
open import Ledger.Prelude
5430
55-
open import Ledger.Dijkstra.Specification.Account gs using (DirectDeposits; DirectDepositsOf)
31+
open import Ledger.Dijkstra.Specification.Account gs
32+
using (DirectDeposits; DirectDepositsOf)
5633
open import Ledger.Dijkstra.Specification.Certs gs
5734
open import Ledger.Dijkstra.Specification.Entities gs
5835
open import Ledger.Dijkstra.Specification.Entities.Properties.ApplyToRewardsPoV gs
@@ -62,20 +39,17 @@ open RewardAddress
6239
open ≡-Reasoning
6340
6441
private variable
65-
A : Type
66-
dCerts : List DCert
42+
A : Type
43+
dCerts : List DCert
6744
68-
instance
69-
_ = +-0-monoid
7045
```
7146
-->
7247

7348
## The `ENTITIES-pov` module
7449

75-
`ENTITIES-pov`{.AgdaFunction} inherits the three set/map module parameters of
76-
`ApplyToRewards-PoV`{.AgdaModule} — they are needed by
77-
`applyWithdrawals-pov`{.AgdaFunction} and `applyDirectDeposits-pov`{.AgdaFunction} —
78-
and threads them through unchanged.
50+
`ENTITIES-pov`{.AgdaFunction} inherits the three module parameters of
51+
`ApplyToRewards-PoV`{.AgdaModule} (which are "obvious" facts which probably ought to
52+
be proved upstream in the `agda-sets` library).
7953

8054
```agda
8155
module ENTITIES-PoV
@@ -84,18 +58,14 @@ module ENTITIES-PoV
8458
→ c' ≢ c → lookupᵐ? (❴ c , v ❵ ∪ˡ m) c' ≡ lookupᵐ? m c' )
8559
8660
( sum-map-proj₂≡getCoin :
87-
(m : RewardAddress ⇀ Coin)
88-
→ sum (map proj₂ (setToList (m ˢ))) ≡ getCoin m )
61+
(m : RewardAddress ⇀ Coin) → sum (map proj₂ (setToList (m ˢ))) ≡ getCoin m )
8962
9063
( setToList-Unique :
9164
(m : RewardAddress ⇀ Coin)
9265
→ ∀[ a ∈ dom (m ˢ) ] NetworkIdOf a ≡ NetworkId
9366
→ Unique (map (stake ∘ proj₁) (setToList (m ˢ))) )
9467
95-
-- Certs-PoV stub (discharged later by PR #1210): preservation of value across
96-
-- the reflexive-transitive `CERTS` closure. Formerly proved in
97-
-- `Certs.Properties.PoV`; lifted to a module parameter so this PR proves only
98-
-- the `ENTITIES`/`LEDGER` layer (top-down strategy).
68+
-- Value preservation of the `CERTS` rule to be proved in `Certs.Properties.PoV`.
9969
( CERTS-pov : ∀ {Γ : CertEnv} {s s' : CertState} {dCerts : List DCert}
10070
→ Γ ⊢ s ⇀⦇ dCerts ,CERTS⦈ s' → coinFromRewards s ≡ coinFromRewards s' )
10171
where
@@ -123,53 +93,31 @@ per-batch `NetworkId`{.AgdaFunction} witnesses for `WithdrawalsOf Γ`{.AgdaBound
12393
→ coinFromRewards s + getCoin (DirectDepositsOf Γ) ≡ coinFromRewards s' + getCoin (WithdrawalsOf Γ)
12494
```
12595

126-
**Proof**. Case-split on the single `ENTITIES`{.AgdaInductiveConstructor}
127-
constructor to expose the inner `CERTS`{.AgdaDatatype} step and the threaded states.
96+
**Proof**.
12897

129-
<!--
13098
```agda
13199
ENTITIES-pov {Γ = Γ}
132100
{s = ⟦ ⟦ _ , _ , r₀ , _ ⟧ᵈ , _ , _ ⟧ᶜˢ} {s' = ⟦ ⟦ _ , _ , _ , _ ⟧ᵈ , _ , _ ⟧ᶜˢ}
133101
wd-netId dd-netId (ENTITIES { rewards₁ = r₁ } (fst , wdrls⊆ , amts≤ , certsStep , ddCreds⊆ )) =
134102
begin
135-
G r₀ + DD
136-
≡⟨ cong (_+ DD) (applyWithdrawals-pov wdrls r₀ wdrls⊆ wd-netId amts≤) ⟩
137-
(G aw + W) + DD
138-
≡⟨ +-assoc (G aw) W DD
139-
G aw + (W + DD)
140-
≡⟨ cong (G aw +_) (+-comm W DD) ⟩
141-
G aw + (DD + W)
142-
≡˘⟨ +-assoc (G aw) DD W
143-
(G aw + DD) + W
144-
≡⟨ cong (λ x → (x + DD) + W) (CERTS-pov certsStep) ⟩
145-
(G r₁ + DD) + W
146-
≡˘⟨ cong (_+ W) (applyDirectDeposits-pov dd r₁ ddCreds⊆) ⟩
147-
G (applyDirectDeposits dd r₁) + W
103+
getCoin r₀ + dd
104+
≡⟨ cong (_+ dd) (applyWithdrawals-pov (WithdrawalsOf Γ) r₀ wdrls⊆ wd-netId amts≤) ⟩
105+
getCoin aw + wdrls + dd
106+
≡⟨ +-assoc (getCoin aw) wdrls dd
107+
getCoin aw + (wdrls + dd)
108+
≡⟨ cong (getCoin aw +_) (+-comm wdrls dd) ⟩
109+
getCoin aw + (dd + wdrls)
110+
≡˘⟨ +-assoc (getCoin aw) dd wdrls
111+
getCoin aw + dd + wdrls
112+
≡⟨ cong (λ x → (x + dd) + wdrls) (CERTS-pov certsStep) ⟩
113+
(getCoin r₁ + dd) + wdrls
114+
≡˘⟨ cong (_+ wdrls) (applyDirectDeposits-pov (DirectDepositsOf Γ) r₁ ddCreds⊆) ⟩
115+
getCoin (applyDirectDeposits (DirectDepositsOf Γ) r₁) + wdrls
148116
149117
where
150-
wdrls : Withdrawals
151-
wdrls = WithdrawalsOf Γ
152-
dd : DirectDeposits
153-
dd = CertEnv.directDeposits Γ
118+
dd wdrls : Coin
119+
dd = getCoin (DirectDepositsOf Γ)
120+
wdrls = getCoin (WithdrawalsOf Γ)
154121
aw : Rewards
155-
aw = applyWithdrawals wdrls r₀
156-
G : Rewards → Coin
157-
G = getCoin
158-
W DD : Coin
159-
W = getCoin wdrls
160-
DD = getCoin dd
122+
aw = applyWithdrawals (WithdrawalsOf Γ) r₀
161123
```
162-
-->
163-
164-
The first three rewrites move `W` past `DD` to set up the
165-
`CERTS-pov`{.AgdaFunction} application; the `CERTS-pov`{.AgdaFunction}
166-
step then preserves `getCoin`{.AgdaFunction} through the inner closure;
167-
and the final rewrite folds `applyDirectDeposits`{.AgdaFunction} back
168-
into the LHS of the goal.
169-
170-
Equivalences used implicitly: `coinFromRewards`{.AgdaFunction} is
171-
`rewardsBalance ∘ DStateOf`{.AgdaFunction} by definition, which is why `G r₀`, `G aw`,
172-
`G r₁`, and `G (applyDirectDeposits dd r₁)` are interchangeable with
173-
`coinFromRewards s`, `coinFromRewards <intermediate>`, `coinFromRewards <post-CERTS>`,
174-
and `coinFromRewards s'` respectively — both sides project to the `rewards`{.AgdaField}
175-
field, which is exactly what the chain manipulates.

0 commit comments

Comments
 (0)