|
| 1 | +--- |
| 2 | +source_branch: master |
| 3 | +source_path: src/Ledger/Dijkstra/Specification/Utxo/Properties/Base.lagda.md |
| 4 | +--- |
| 5 | + |
| 6 | +# UTxO Properties: Base Lemmas |
| 7 | + |
| 8 | +This module collects the pure `UTxO`{.AgdaFunction} algebra used by the |
| 9 | +preservation-of-value proofs in `Utxo.Properties.PoV`{.AgdaModule} and |
| 10 | +`Utxow.Properties.PoV`{.AgdaModule}: |
| 11 | + |
| 12 | ++ `∙-homo-Coin`{.AgdaFunction}: `coin`{.AgdaField} distributes over `Value`{.AgdaField} |
| 13 | + addition (the `_∙_` law of the `coin`{.AgdaField} monoid homomorphism). |
| 14 | ++ `coin-∑ˡ`{.AgdaFunction}: `coin`{.AgdaField} distributes over a list-indexed sum of |
| 15 | + `Value`{.AgdaField}s. |
| 16 | ++ `newTxid⇒disj`{.AgdaFunction} / `outs-disjoint`{.AgdaFunction}: freshness of |
| 17 | + `TxIdOf tx` in a UTxO implies the outputs of `tx` are disjoint from it. |
| 18 | ++ `balance-cong`{.AgdaFunction} / `balance-cong-coin`{.AgdaFunction}: |
| 19 | + `balance`{.AgdaFunction} is invariant under extensional equality of UTxOs. |
| 20 | ++ `balance-∪`{.AgdaFunction}: `cbalance`{.AgdaFunction} is additive on disjoint unions. |
| 21 | ++ `split-balance`{.AgdaFunction}: `cbalance`{.AgdaFunction} splits along a key-set |
| 22 | + restriction and its complement. |
| 23 | + |
| 24 | +The balance lemmas are ports of their Conway counterparts (in |
| 25 | +`Ledger.Conway.Specification.Utxo.Properties.Base`{.AgdaModule}): the Dijkstra |
| 26 | +`balance`{.AgdaFunction} is again an indexed sum over a finite map of transaction |
| 27 | +outputs (`∑[ x ← mapValues txOutToValue utxo ] x`), so the Conway proofs via |
| 28 | +`indexedSumᵐ-cong`{.AgdaFunction} and `indexedSumᵐ-∪`{.AgdaFunction} carry over, |
| 29 | +with `txOutToValue`{.AgdaFunction} in place of Conway's hashed outputs. The |
| 30 | +statements of `balance-∪`{.AgdaFunction}, `split-balance`{.AgdaFunction} and |
| 31 | +`outs-disjoint`{.AgdaFunction} match the corresponding module parameters of |
| 32 | +`Ledger.Properties.PoV`{.AgdaModule}, which they are intended to discharge. |
| 33 | + |
| 34 | +<!-- |
| 35 | +```agda |
| 36 | +{-# OPTIONS --safe #-} |
| 37 | +
|
| 38 | +open import Ledger.Dijkstra.Specification.Abstract using (AbstractFunctions) |
| 39 | +open import Ledger.Dijkstra.Specification.Transaction |
| 40 | +
|
| 41 | +module Ledger.Dijkstra.Specification.Utxo.Properties.Base |
| 42 | + (txs : _) (open TransactionStructure txs) |
| 43 | + (abs : AbstractFunctions txs) (open AbstractFunctions abs) |
| 44 | + where |
| 45 | +
|
| 46 | +open import Prelude; open Equivalence |
| 47 | +open import Ledger.Prelude hiding (≤-trans; ≤-antisym; All); open Properties |
| 48 | +open import Ledger.Dijkstra.Specification.Utxo txs abs |
| 49 | +
|
| 50 | +open import Algebra.Morphism using (module MonoidMorphisms; IsMagmaHomomorphism) |
| 51 | +open import Relation.Binary using (IsEquivalence) |
| 52 | +
|
| 53 | +open MonoidMorphisms.IsMonoidHomomorphism |
| 54 | +
|
| 55 | +private variable |
| 56 | + ℓ : TxLevel |
| 57 | +``` |
| 58 | +--> |
| 59 | + |
| 60 | +## `∙-homo-Coin` |
| 61 | + |
| 62 | +```agda |
| 63 | +∙-homo-Coin : ∀ (x y : Value) → coin (x + y) ≡ coin x + coin y |
| 64 | +∙-homo-Coin = IsMagmaHomomorphism.homo (isMagmaHomomorphism coinIsMonoidHomomorphism) |
| 65 | +``` |
| 66 | + |
| 67 | +## `coin-∑ˡ` |
| 68 | + |
| 69 | +`coin`{.AgdaField} is a monoid homomorphism from `Value`{.AgdaField} (under `+ᵛ`/`ε`) to |
| 70 | +`ℕ`{.AgdaDatatype} (under `+`/`0`), so it distributes over a list-indexed sum. This |
| 71 | +is the "coin version" of the generic fact that a monoid homomorphism commutes with |
| 72 | +`foldr _∙_ ε`. |
| 73 | + |
| 74 | +```agda |
| 75 | +coin-∑ˡ : ∀ {A : Type} (f : A → Value) (xs : List A) |
| 76 | + → coin (∑ˡ[ x ← xs ] f x) ≡ sum (map (coin ∘ f) xs) |
| 77 | +coin-∑ˡ f [] = ε-homo coinIsMonoidHomomorphism |
| 78 | +coin-∑ˡ f (x ∷ xs) = trans (∙-homo-Coin (f x) (∑ˡ[ z ← xs ] f z)) |
| 79 | + (cong (coin (f x) +_) (coin-∑ˡ f xs)) |
| 80 | +``` |
| 81 | + |
| 82 | +## Freshness ⇒ disjointness |
| 83 | + |
| 84 | +If the id of a transaction `tx` does not occur in `utxo`, then the outputs of |
| 85 | +`tx` (whose keys all have first component `TxIdOf tx`) are disjoint from |
| 86 | +`utxo`. The specialisation `outs-disjoint`{.AgdaFunction} is the form used by |
| 87 | +the PoV proofs: the restriction `utxo ∣ SpendInputsOf tx ᶜ` only shrinks the |
| 88 | +domain, so disjointness with `outs tx` persists. |
| 89 | + |
| 90 | +```agda |
| 91 | +module _ (tx : Tx ℓ) (let open Tx tx; open TxBody txBody) |
| 92 | + {utxo : UTxO} where |
| 93 | +
|
| 94 | + newTxid⇒disj : TxIdOf tx ∉ mapˢ proj₁ (dom utxo) |
| 95 | + → disjoint' (dom utxo) (dom (outs tx)) |
| 96 | + newTxid⇒disj id∉utxo = |
| 97 | + disjoint⇒disjoint' λ h h' → id∉utxo $ to ∈-map |
| 98 | + (-, (case from ∈-map h' of λ where |
| 99 | + (_ , refl , h'') → case from ∈-map h'' of λ where (_ , refl , _) → refl) , h) |
| 100 | +
|
| 101 | + outs-disjoint : TxIdOf tx ∉ mapˢ proj₁ (dom utxo) |
| 102 | + → disjoint (dom (utxo ∣ SpendInputsOf tx ᶜ)) (dom (outs tx)) |
| 103 | + outs-disjoint fresh = |
| 104 | + λ h₁ h₂ → ∉-∅ $ proj₁ (newTxid⇒disj fresh) $ to ∈-∩ (res-comp-domᵐ h₁ , h₂) |
| 105 | +``` |
| 106 | + |
| 107 | +## Balance arithmetic |
| 108 | + |
| 109 | +`balance`{.AgdaFunction} is the indexed sum of `txOutToValue`{.AgdaFunction} over the |
| 110 | +UTxO map, so it is invariant under extensional equality of the underlying maps |
| 111 | +(`balance-cong`{.AgdaFunction}), and — via `indexedSumᵐ-∪`{.AgdaFunction} — |
| 112 | +additive on unions with disjoint domains (`balance-∪`{.AgdaFunction}). |
| 113 | + |
| 114 | +```agda |
| 115 | +module _ {utxo utxo' : UTxO} where |
| 116 | +
|
| 117 | + balance-cong : ∣ utxo ∣ ≡ᵉ ∣ utxo' ∣ → balance utxo ≈ balance utxo' |
| 118 | + balance-cong eq = |
| 119 | + indexedSumᵐ-cong {M = Value} {x = (mapValues txOutToValue utxo) ᶠᵐ} |
| 120 | + {(mapValues txOutToValue utxo') ᶠᵐ} (map-≡ᵉ eq) |
| 121 | +
|
| 122 | + balance-cong-coin : ∣ utxo ∣ ≡ᵉ ∣ utxo' ∣ → cbalance utxo ≡ cbalance utxo' |
| 123 | + balance-cong-coin eq = ⟦⟧-cong coinIsMonoidHomomorphism (balance-cong eq) |
| 124 | +
|
| 125 | + balance-∪ : disjoint (dom utxo) (dom utxo') |
| 126 | + → cbalance (utxo ∪ˡ utxo') ≡ cbalance utxo + cbalance utxo' |
| 127 | + balance-∪ h = begin |
| 128 | + cbalance (utxo ∪ˡ utxo') |
| 129 | + ≡⟨ ⟦⟧-cong coinIsMonoidHomomorphism |
| 130 | + $ indexedSumᵐ-cong {f = proj₂} |
| 131 | + {x = (mapValues txOutToValue (utxo ∪ˡ utxo')) ᶠᵐ} |
| 132 | + {((mapValues txOutToValue utxo) ᶠᵐ) ∪ˡᶠ ((mapValues txOutToValue utxo') ᶠᵐ)} |
| 133 | + (disjoint-∪ˡ-mapValues {M = utxo} {utxo'} _ h) ⟩ |
| 134 | + coin (indexedSumᵐ _ (((mapValues txOutToValue utxo) ᶠᵐ) ∪ˡᶠ ((mapValues txOutToValue utxo') ᶠᵐ))) |
| 135 | + ≡⟨ ⟦⟧-cong coinIsMonoidHomomorphism |
| 136 | + $ indexedSumᵐ-∪ {M = Value} {X = (mapValues txOutToValue utxo) ᶠᵐ} |
| 137 | + {(mapValues txOutToValue utxo') ᶠᵐ} |
| 138 | + (λ x x₁ → h (dom-mapʳ⊆ x) (dom-mapʳ⊆ x₁)) ⟩ |
| 139 | + coin (balance utxo + balance utxo') |
| 140 | + ≡⟨ ∙-homo-Coin _ _ ⟩ |
| 141 | + cbalance utxo + cbalance utxo' |
| 142 | + ∎ |
| 143 | + where open ≡-Reasoning |
| 144 | +``` |
| 145 | + |
| 146 | +Splitting a UTxO along a key set: restricting to a key set and to its |
| 147 | +complement partitions the map, so the two restricted balances add up to the |
| 148 | +whole. |
| 149 | + |
| 150 | +```agda |
| 151 | +split-balance : ∀ (u : UTxO) (keys : ℙ TxIn) |
| 152 | + → cbalance u ≡ cbalance (u ∣ keys ᶜ) + cbalance (u ∣ keys) |
| 153 | +split-balance u keys = begin |
| 154 | + cbalance u |
| 155 | + ≡˘⟨ balance-cong-coin {utxo = (u ∣ keys ᶜ) ∪ˡ (u ∣ keys)} {u} |
| 156 | + $ disjoint-∪ˡ-∪ (disjoint-sym res-ex-disjoint) |
| 157 | + ≡ᵉ-∘ ∪-sym |
| 158 | + ≡ᵉ-∘ res-ex-∪ (_∈? keys) ⟩ |
| 159 | + cbalance ((u ∣ keys ᶜ) ∪ˡ (u ∣ keys)) |
| 160 | + ≡⟨ balance-∪ {u ∣ keys ᶜ} {u ∣ keys} $ flip res-ex-disjoint ⟩ |
| 161 | + cbalance (u ∣ keys ᶜ) + cbalance (u ∣ keys) |
| 162 | + ∎ |
| 163 | + where |
| 164 | + open ≡-Reasoning |
| 165 | + open IsEquivalence ≡ᵉ-isEquivalence renaming (trans to infixl 4 _≡ᵉ-∘_) |
| 166 | +``` |
0 commit comments