Skip to content

Commit fca589f

Browse files
committed
cleanup
1 parent 042fe31 commit fca589f

2 files changed

Lines changed: 41 additions & 126 deletions

File tree

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
source_branch: master
33
source_path: src/Ledger/Dijkstra/Specification/Certs/Properties/PoV.lagda.md
44
---
5-
# The Preservation-of-Value Property for `CERTS`{.AgdaDatatype}
5+
6+
# The Preservation-of-Value Property for <span class="AgdaDatatype">`CERTS`</span>
67

78
This module lifts the per-step results from `Certs.Properties.PoVLemmas`{.AgdaModule}
89
across the reflexive-transitive closure `CERTS`{.AgdaDatatype} of `CERT`{.AgdaDatatype}.

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

Lines changed: 39 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ transition rule `CERT`{.AgdaDatatype}:
1313
(`CERT-coinFromDeposits-step`{.AgdaFunction}): the post-step
1414
`coinFromDeposits`{.AgdaFunction} is equal to the coin-valuation of the
1515
closed-form `updateCertDeposit`{.AgdaFunction} applied to the pre-step
16-
deposit-pot triple.
16+
deposits triple.
1717

1818
The first is the per-step ingredient of `CERTS-pov`{.AgdaFunction} in
1919
`Certs.Properties.PoV`{.AgdaModule}. The second is the per-step ingredient
@@ -26,32 +26,21 @@ quantities appearing in the UTXO batch-balance equation.
2626
## Why coin form, and why the `≡ᵐ`-componentwise scaffolding
2727

2828
A naïve triple-form bridging lemma would say
29-
30-
pots s' ≡ updateCertDeposit pp dCert (pots s)
31-
32-
**propositionally**. For the `POOL-rereg` case, the rule leaves the
33-
pool-deposit pot unchanged, but `updateCertDeposit`{.AgdaFunction} appends
34-
`❴ kh , poolDeposit ❵`. Closing this gap requires the equation
35-
36-
m ∪ˡ ❴ k , v ❵ ≡ m (when k ∈ dom m),
37-
38-
which `agda-sets` only provides up to `≡ᵐ`{.AgdaFunction} (extensional map
39-
equality), **not** propositional ``.
29+
`pots s' ≡ updateCertDeposit pp dCert (pots s)` **propositionally**.
30+
For the `POOL-rereg` case, the rule leaves the pool-deposit pot unchanged, but
31+
`updateCertDeposit`{.AgdaFunction} appends `❴ kh , poolDeposit ❵`. Closing this gap
32+
requires the equation `m ∪ˡ ❴ k , v ❵ ≡ m` (when `k ∈ dom m`), which `agda-sets` only
33+
provides up to `≡ᵐ` (extensional map equality), **not** propositional ``.
4034

4135
To avoid introducing a deferred propositional version of that fact, we work
4236
at two levels:
4337

4438
+ The **per-step triple-form bridge** `CERT-pots-≡ᵐᵗ`{.AgdaFunction} states
45-
`pots s'`{.AgdaFunction} and the closed-form output agree
46-
**componentwise modulo `≡ᵐ`**. The `POOL-rereg` case uses
47-
`singleton-∈-∪ˡ`{.AgdaFunction} from `agda-sets`
48-
49-
a ∈ dom m → m ∪ˡ ❴ (a , b) ❵ᵐ ≡ᵐ m
50-
51-
— a parameter-free fact.
39+
`pots s'`{.AgdaFunction} and the `updateCertDeposits` output agree
40+
**componentwise modulo `≡ᵐ`**.
5241
+ The **per-step coin-form bridge** `CERT-coinFromDeposits-step`{.AgdaFunction}
5342
is derived from `CERT-pots-≡ᵐᵗ`{.AgdaFunction} by collapsing each
54-
`≡ᵐ`{.AgdaFunction} component to a coin equality via `≡ᵉ-getCoin`{.AgdaFunction},
43+
`≡ᵐ` component to a coin equality via `≡ᵉ-getCoin`{.AgdaFunction},
5544
and summing the three resulting equalities.
5645

5746
The `≡ᵐ`-componentwise relation `_≡ᵐᵗ_` threads through the list-iterated closed
@@ -66,35 +55,6 @@ pool-deposit-alignment invariant under one `CERT` step), consumed in
6655
`Certs.Properties.PoV`{.AgdaModule} and discharged at the `CHAIN`-invariant
6756
layer in a follow-up issue.
6857

69-
## A note on unresolved-implicit hygiene
70-
71-
Several lemmas in this module rely on `agda-sets` `Map`-respecting cong
72-
operations (`∪ˡ-cong`{.AgdaFunction}, `restrict-cong`{.AgdaFunction},
73-
`∪⁺-cong-r`{.AgdaFunction}, `≡ᵐ-refl`{.AgdaFunction}, `≡ᵉ-getCoin`{.AgdaFunction}).
74-
A subtle interaction with the definition of `_≡ᵐ_`{.AgdaFunction} —
75-
`m ≡ᵐ m'` unfolds to `m ˢ ≡ᵉ m' ˢ`, which only constrains the **relation**
76-
projection of the `Map` Σ — means that unification through `_≡ᵐ_` does not
77-
propagate `left-unique`{.AgdaFunction} witnesses. Two patterns avoid the
78-
resulting unresolved metas:
79-
80-
+ When a lemma has **implicit** `Map` arguments (like the four maps of `∪ˡ-cong`),
81-
we pass them explicitly at the call site:
82-
`∪ˡ-cong {m = b} {m' = sing} {m'' = b'} {m''' = sing} …`.
83-
+ When defining lemmas whose implicit `Triple` arguments would be decomposed
84-
by an LHS pattern (`{a , b , g}`), we instead bind the triple variable
85-
directly (`{t}`) and project explicitly in the body (`proj₁ t`, etc.).
86-
Pattern destructuring at an **implicit** position introduces three fresh
87-
implicit Map metas — one per component — whose `.proj₂` (`left-unique`)
88-
doesn't get pinned by the usual `_≡ᵐ_`-based unification. Projection
89-
terms have no such gap because the `Map` Σ remains atomically referenced
90-
through `t`.
91-
92-
The two patterns combined keep all `Σ`-level facts concrete at every call
93-
site — relation **and** `left-unique` — and the module typechecks meta-free.
94-
(`pots s'` for `≡ᵐᵗ-refl` in the seven refl cases of `CERT-pots-≡ᵐᵗ`, and
95-
explicit `depᵖ`/`depᵖ ∪ˡ ❴ kh , pp .poolDeposit ❵ᵐ` to `≡ᵐ-sym` in the
96-
`POOL-rereg` case, follow the same principle.)
97-
9858
<!--
9959
```agda
10060
{-# OPTIONS --safe #-}
@@ -104,24 +64,19 @@ open import Ledger.Dijkstra.Specification.Gov.Base using (GovStructure)
10464
module Ledger.Dijkstra.Specification.Certs.Properties.PoVLemmas
10565
(gs : GovStructure) (open GovStructure gs) where
10666
107-
open import Ledger.Prelude
108-
open import Ledger.Dijkstra.Specification.Certs gs
109-
open import Ledger.Dijkstra.Specification.Gov.Actions gs hiding (yes; no)
110-
111-
-- `_∪⁺_`- and `_∣_ᶜ`-respecting `≡ᵐ`-cong lemmas. These live in the
112-
-- `Extra` module of `abstract-set-theory`; named explicitly so we don't
113-
-- depend on whichever subset `Ledger.Prelude` re-exports today.
114-
open import abstract-set-theory.Axiom.Set.Map.Extra
115-
using (∪⁺-cong-r; restrict-cong)
116-
117-
open import Axiom.Set.Properties th
11867
open import Algebra using (CommutativeMonoid)
11968
import Algebra.Structures as AlgStruct
12069
open import Data.Maybe using (Is-just)
12170
open import Data.Nat.Properties using (+-0-monoid; +-identityʳ)
12271
open import Relation.Binary using (IsEquivalence)
12372
open import Relation.Nullary.Decidable
12473
74+
open import Ledger.Prelude
75+
open import Ledger.Dijkstra.Specification.Certs gs
76+
open import Ledger.Dijkstra.Specification.Gov.Actions gs hiding (yes; no)
77+
open import abstract-set-theory.Axiom.Set.Map.Extra using (∪⁺-cong-r; restrict-cong)
78+
open import Axiom.Set.Properties th
79+
12580
-- TODO: some hoop-jumping required since the Map proofs need the
12681
-- stdlib IsCommutativeSemigroup for Coin.
12782
open AlgStruct {A = Coin} _≡_ using (IsCommutativeSemigroup)
@@ -147,39 +102,15 @@ open Equivalence
147102
```
148103
-->
149104

150-
## Deposit-pot triple and closed-form helpers {#sec:triple-helpers}
151-
152-
The three deposit pots carried by a `CertState`{.AgdaRecord} live in
153-
distinct map types (`Credential ⇀ Coin`, `KeyHash ⇀ Coin`, `Credential ⇀ Coin`),
154-
so we package them as a single `Triple`{.AgdaFunction}, inhabitants of which are
155-
constructed via `pots`{.AgdaFunction}, and values of which are computed via
156-
`coinFromDeposits-pots`{.AgdaFunction}. By definition,
157-
158-
coinFromDeposits cs ≡ coinFromDeposits-pots (pots cs).
159-
160-
```agda
161-
Triple : Type
162-
Triple = (Credential ⇀ Coin) × (KeyHash ⇀ Coin) × (Credential ⇀ Coin)
163-
164-
pots : CertState → Triple
165-
pots cs =
166-
( DepositsOf (DStateOf cs)
167-
, DepositsOf (PStateOf cs)
168-
, DepositsOf (GStateOf cs)
169-
)
170-
171-
coinFromDeposits-pots : Triple → Coin
172-
coinFromDeposits-pots (depᵈ , depᵖ , depᵍ) =
173-
getCoin depᵈ + getCoin depᵖ + getCoin depᵍ
174-
```
105+
## Deposit triple and helpers {#sec:triple-helpers}
175106

176-
The per-step pots equation
107+
The per-step deposit update equation
177108

178109
pots (updateCertDepositsStep pp s c) ≡ updateCertDeposit pp c (pots s)
179110

180-
is **propositional**: by Σ-η on `Triple`{.AgdaFunction} and record-η on the three
181-
`record dState { deposits = ... }` updates inside
182-
`updateCertDepositsStep`{.AgdaFunction}, both sides reduce to the same expression.
111+
is **propositional**: by Σ-η on `DepositTriple`{.AgdaDatatype} and record-η on the three
112+
record updates inside `updateCertDepositsStep`{.AgdaFunction}, both sides reduce to
113+
the same expression.
183114

184115
```agda
185116
pots-updateCertDepositsStep : (pp : PParams) (s : CertState) (c : DCert)
@@ -192,7 +123,7 @@ The triple-level closed-form iteration mirrors the rule-level
192123
over a list of certificates.
193124

194125
```agda
195-
updateCertDeposit-list : PParams → Triple → List DCert → Triple
126+
updateCertDeposit-list : PParams → DepositsTriple → List DCert → DepositsTriple
196127
updateCertDeposit-list pp t = foldl (λ t' c → updateCertDeposit pp c t') t
197128
```
198129

@@ -217,7 +148,7 @@ pots-updateCertDeposits pp s (c ∷ cs') =
217148

218149
```agda
219150
-- Componentwise extensional map equality on `Triple`.
220-
_≡ᵐᵗ_ : TripleTriple → Type
151+
_≡ᵐᵗ_ : DepositsTripleDepositsTriple → Type
221152
(a₁ , b₁ , c₁) ≡ᵐᵗ (a₂ , b₂ , c₂) =
222153
(a₁ ≡ᵐ a₂) × (b₁ ≡ᵐ b₂) × (c₁ ≡ᵐ c₂)
223154
@@ -261,41 +192,30 @@ and `kh` explicitly and pass the fully-constructed singleton
261192
`❴ kh , pp .poolDeposit ❵ᵐ` to `≡ᵐ-refl`{.AgdaFunction}.
262193

263194
```agda
264-
updateCertDeposit-≡ᵐᵗ : (pp : PParams) (c : DCert) {t t' : Triple}
265-
→ t ≡ᵐᵗ t'
266-
→ updateCertDeposit pp c t ≡ᵐᵗ updateCertDeposit pp c t'
267-
updateCertDeposit-≡ᵐᵗ _ (delegate _ _ _ _) (a≡ , b≡ , g≡) =
268-
∪⁺-cong-r a≡ , b≡ , g≡
269-
updateCertDeposit-≡ᵐᵗ _ (dereg _ _) {a , _ , _} {a' , _ , _} (a≡ , b≡ , g≡) =
195+
updateCertDeposit-≡ᵐᵗ : (pp : PParams) (c : DCert) {t t' : DepositsTriple}
196+
→ t ≡ᵐᵗ t' → updateCertDeposit pp c t ≡ᵐᵗ updateCertDeposit pp c t'
197+
updateCertDeposit-≡ᵐᵗ _ (delegate _ _ _ _) (a≡ , b≡ , g≡) = ∪⁺-cong-r a≡ , b≡ , g≡
198+
updateCertDeposit-≡ᵐᵗ _ (dereg _ _) {a , _ , _} {a' , _ , _} (a≡ , b≡ , g≡) =
270199
restrict-cong a a' a≡ , b≡ , g≡
271-
updateCertDeposit-≡ᵐᵗ pp (regpool kh _) {t = t} {t' = t'} (a≡ , b≡ , g≡) =
272-
-- `∪ˡ-cong` has four **implicit** Map arguments {m m' m'' m'''}. Inferring
273-
-- them only from `b≡ : … ≡ᵐ …` and `≡ᵐ-refl sing : sing ≡ᵐ sing` pins each
274-
-- meta's `.proj₁` (the relation) but leaves its `.proj₂` (`left-unique`)
275-
-- as a separate meta — `_≡ᵐ_`'s definition `m ˢ ≡ᵉ m' ˢ` simply doesn't
276-
-- mention the Σ-tail. We pass all four explicitly: `b` and `b'` projected
277-
-- from `t` and `t'` (the projection form keeps the Σ atomically referenced
278-
-- and avoids the implicit-pattern-meta issue), and the singleton itself
279-
-- for both `m'` and `m'''`.
280-
let sing = ❴ kh , pp .poolDeposit ❵ᵐ
281-
b = proj₁ (proj₂ t)
282-
b' = proj₁ (proj₂ t')
283-
in a≡ , ∪ˡ-cong {m = b} {m' = sing} {m'' = b'} {m''' = sing} b≡ (≡ᵐ-refl sing) , g≡
284-
updateCertDeposit-≡ᵐᵗ _ (regdrep _ _ _) (a≡ , b≡ , g≡) =
285-
a≡ , b≡ , ∪⁺-cong-r g≡
286-
updateCertDeposit-≡ᵐᵗ _ (deregdrep _ _) {_ , _ , g} {_ , _ , g'} (a≡ , b≡ , g≡) =
200+
updateCertDeposit-≡ᵐᵗ
201+
pp (regpool kh _) {t = (_ , b , _)} {t' = (_ , b' , _)} (a≡ , b≡ , g≡) =
202+
a≡ , ∪ˡ-cong {m = b} {m' = sngl} {m'' = b'} {m''' = sngl} b≡ (≡ᵐ-refl sngl) , g≡
203+
where
204+
sngl : KeyHash ⇀ Coin
205+
sngl = ❴ kh , pp .poolDeposit ❵ᵐ
206+
updateCertDeposit-≡ᵐᵗ _ (regdrep _ _ _) (a≡ , b≡ , g≡) = a≡ , b≡ , ∪⁺-cong-r g≡
207+
updateCertDeposit-≡ᵐᵗ _ (deregdrep _ _) {_ , _ , g} {_ , _ , g'} (a≡ , b≡ , g≡) =
287208
a≡ , b≡ , restrict-cong g g' g≡
288-
updateCertDeposit-≡ᵐᵗ _ (retirepool _ _) eq = eq
289-
updateCertDeposit-≡ᵐᵗ _ (ccreghot _ _) eq = eq
209+
updateCertDeposit-≡ᵐᵗ _ (retirepool _ _) eq = eq
210+
updateCertDeposit-≡ᵐᵗ _ (ccreghot _ _) eq = eq
290211
```
291212

292213
The list-iterated version is straightforward induction on the list,
293214
delegating to `updateCertDeposit-≡ᵐᵗ`{.AgdaFunction} at each step.
294215

295216
```agda
296-
updateCertDeposit-list-≡ᵐᵗ : (pp : PParams) (cs : List DCert) {t t' : Triple}
297-
→ t ≡ᵐᵗ t'
298-
→ updateCertDeposit-list pp t cs ≡ᵐᵗ updateCertDeposit-list pp t' cs
217+
updateCertDeposit-list-≡ᵐᵗ : (pp : PParams) (cs : List DCert) {t t' : DepositsTriple}
218+
→ t ≡ᵐᵗ t' → updateCertDeposit-list pp t cs ≡ᵐᵗ updateCertDeposit-list pp t' cs
299219
updateCertDeposit-list-≡ᵐᵗ _ [] eq = eq
300220
updateCertDeposit-list-≡ᵐᵗ pp (c ∷ cs') eq =
301221
updateCertDeposit-list-≡ᵐᵗ pp cs' (updateCertDeposit-≡ᵐᵗ pp c eq)
@@ -305,15 +225,9 @@ Finally, `≡ᵐᵗ`-equal triples have equal coin valuations: collapse each
305225
component via `≡ᵉ-getCoin`{.AgdaFunction} and sum.
306226

307227
```agda
308-
coinFromDeposits-pots-cong : {t t' : Triple}
228+
coinFromDeposits-pots-cong : {t t' : DepositsTriple}
309229
→ t ≡ᵐᵗ t' → coinFromDeposits-pots t ≡ coinFromDeposits-pots t'
310230
coinFromDeposits-pots-cong {t} {t'} (a≡ , b≡ , g≡) =
311-
-- We bind `{t}` `{t'}` and project, rather than pattern-matching
312-
-- `{a , b , g}` `{a' , b' , g'}`. An implicit-position pattern on a
313-
-- `Triple` introduces three fresh implicit Map metas (one per component)
314-
-- whose `left-unique` Σ-fields aren't propagated by Agda's unification;
315-
-- the projection form leaves each component as a concrete projection
316-
-- term, fully determining both Σ-fields.
317231
cong₂ _+_
318232
(cong₂ _+_ (≡ᵉ-getCoin (proj₁ t) (proj₁ t') a≡)
319233
(≡ᵉ-getCoin (proj₁ (proj₂ t)) (proj₁ (proj₂ t')) b≡))

0 commit comments

Comments
 (0)