Source code on Githubmodule UTxO.GlobalPreservation where
open import Data.List.Properties using (map-compose)
open import Data.List.Membership.Propositional.Properties using (∈-map⁻)
open import Data.List.Relation.Binary.Permutation.Propositional.Properties using (map⁺)
open import Prelude.Init
open import Prelude.Lists.Postulates using (mapWith∈↭filter; ↭⇒≡)
open import Prelude.DecEq
open import Prelude.Sets
open import Prelude.Membership using (_∈?_; _∉?_)
open L.Mem
open import Prelude.Applicative
open import Prelude.Monad
open import UTxO.Hashing
open import UTxO.Value
open import UTxO.Types
open import UTxO.TxUtilities
open import UTxO.Validity
open import UTxO.Uniqueness
globalPreservation : ∀ {l} {vl : ValidLedger l} →
∑ l forge ≡ ∑ (utxo l) (value ∘ out)
globalPreservation {[]} {vl} = refl
globalPreservation {l₀@(tx ∷ l)} {vl₀@(vl ⊕ .tx ∶- vtx)} = h″
where
open ≡-Reasoning
view-pv : ∀ {A : Set} {mx : Maybe A} {P : A → Set}
→ M.Any.Any P mx
→ ∃[ x ] ((mx ≡ pure x) × P x)
view-pv (M.Any.just p) = _ , refl , p
∑in : ∀ {l tx} → ValidLedger (tx ∷ l) → Value
∑in (_ ⊕ _ ∶- vtx) = (proj₁ ∘ view-pv ∘ preservesValues) vtx
∑-outRef : ∀ {l} {tx} {vl : ValidLedger (tx ∷ l)}
→ ∑in vl
≡ ∑ (filter ((_∈? outputRefs tx) ∘ outRef) (utxo l)) (value ∘ out)
∑-outRef {l} {tx} {vl₀@(vl ⊕ _ ∶- vtx@(record { validOutputRefs = vor
; preservesValues = pv
; noDoubleSpending = ndp }))}
= M.just-injective (begin
pure (∑in vl₀)
≡⟨ sym (proj₁ (proj₂ (view-pv pv))) ⟩
∑M (map (getSpentOutput l) (inputs tx)) value
≡⟨⟩
∑M (map (getSpentOutputRef l ∘ outputRef) (inputs tx)) value
≡⟨ cong (λ x → ∑M x value) (map-compose {g = getSpentOutputRef l} {f = outputRef} (inputs tx)) ⟩
∑M (map (getSpentOutputRef l) (outputRefs tx)) value
≡⟨ ∑M-just getSpent≡ ⟩
pure (∑ (mapWith∈ (outputRefs tx) (out ∘ getUTXO)) value)
≡⟨ cong pure (begin
∑ (mapWith∈ (outputRefs tx) (out ∘ getUTXO)) value
≡⟨ ∑-∘ {xs = outputRefs tx} {g = getUTXO} {g′ = out} {f = value} ⟩
∑ (mapWith∈ (outputRefs tx) getUTXO) (value ∘ out)
≡⟨ ∑map≡∑filter ⟩
∑ (filter ((_∈? outputRefs tx) ∘ outRef) (utxo l)) (value ∘ out)
∎) ⟩
pure (∑ (filter ((_∈? outputRefs tx) ∘ outRef) (utxo l)) (value ∘ out))
∎)
where
getUTXO : ∀ {o} → o ∈ outputRefs tx → UTXO
getUTXO = proj₁ ∘ ∈-map⁻ outRef ∘ vor
getSpent≡ : ∀ {o} → (o∈ : o ∈ outputRefs tx) → getSpentOutputRef l o ≡ pure ((out ∘ getUTXO) o∈)
getSpent≡ o∈
with ∈-map⁻ outRef (vor o∈)
... | u , u∈ , refl
= utxo-getSpent {l} {u} u∈
map↭filter : mapWith∈ (outputRefs tx) getUTXO
↭ filter ((_∈? outputRefs tx) ∘ outRef) (utxo l)
map↭filter = mapWith∈↭filter {_∈?_ = _∈?_} vor (Unique-utxo vl)
∑map≡∑filter : ∑ (mapWith∈ (outputRefs tx) getUTXO) (value ∘ out)
≡ ∑ (filter ((_∈? outputRefs tx) ∘ outRef) (utxo l)) (value ∘ out)
∑map≡∑filter = ↭⇒≡ +ᶜ-identity +ᶜ-comm (map⁺ (value ∘ out) map↭filter)
pv : forge tx +ᶜ ∑in vl₀ ≡ ∑ (outputs tx) value
pv = proj₂ (proj₂ (view-pv (preservesValues vtx)))
gpv : ∑ l forge ≡ ∑ (utxo l) (value ∘ out)
gpv = globalPreservation {l} {vl}
+ᶜ-helper : ∀ {x x′ y y′ : Value} → x ≡ x′ → y ≡ y′ → x +ᶜ y ≡ x′ +ᶜ y′
+ᶜ-helper refl refl = refl
pv-gpv : forge tx +ᶜ ∑in vl₀ +ᶜ ∑ l forge
≡ ∑ (outputs tx) value +ᶜ ∑ (utxo l) (value ∘ out)
pv-gpv = +ᶜ-helper {x = forge tx +ᶜ ∑in vl₀} {x′ = ∑ (outputs tx) value}
{y = ∑ l forge} {y′ = ∑ (utxo l) (value ∘ out)}
pv gpv
pv-gpv′ : forge tx +ᶜ ∑ l forge +ᶜ ∑in vl₀
≡ ∑ (utxo l) (value ∘ out) +ᶜ ∑ (outputs tx) value
pv-gpv′ rewrite +ᶜ-assoc (forge tx) (∑ l forge) (∑in vl₀)
| +ᶜ-comm (∑ l forge) (∑in vl₀)
| sym $ +ᶜ-assoc (forge tx) (∑in vl₀) (∑ l forge)
| +ᶜ-comm (∑ (utxo l) (value ∘ out)) (∑ (outputs tx) value)
= pv-gpv
pv-gpv″ : ∑ l₀ forge +ᶜ ∑in vl₀
≡ ∑ (outputs tx) value +ᶜ ∑ (utxo l) (value ∘ out)
pv-gpv″
rewrite +ᶜ-comm (∑ (outputs tx) value) (∑ (utxo l) (value ∘ out))
= pv-gpv′
helper : ∀ {l tx} {vl : ValidLedger (tx ∷ l)} {x y : Value}
→ x +ᶜ ∑in vl ≡ y +ᶜ ∑ (utxo l) (value ∘ out)
→ x ≡ y +ᶜ ∑ (filter ((_∉? outputRefs tx) ∘ outRef) (utxo l)) (value ∘ out)
helper {l} {tx} {vl} {x} {y} p
rewrite ∑-outRef {l} {tx} {vl}
| ∑-filter {xs = utxo l} {q = (_∈? outputRefs tx) ∘ outRef}
{f = value ∘ out} {x = x} {y = y} p
= refl
h : ∑ l₀ forge
≡ ∑ (outputs tx) value
+ᶜ ∑ (filter ((_∉? outputRefs tx) ∘ outRef) (utxo l)) (value ∘ out)
h = helper {l = l} {tx = tx} {vl = vl₀}
{x = ∑ l₀ forge}
{y = ∑ (outputs tx) value} pv-gpv″
h′ : ∑ l₀ forge
≡ ( ∑ (filter ((_∉? outputRefs tx) ∘ outRef) (utxo l)) (value ∘ out)
+ᶜ ∑ (outputs tx) value )
h′ rewrite +ᶜ-comm (∑ (filter ((_∉? outputRefs tx) ∘ outRef) (utxo l)) (value ∘ out))
(∑ (outputs tx) value)
= h
∑-utxo : ∀ {l tx}
→ ∑ (utxo (tx ∷ l)) (value ∘ out)
≡ ∑ (filter ((_∉? outputRefs tx) ∘ outRef) (utxo l)) (value ∘ out) +ᶜ ∑ (outputs tx) value
∑-utxo {l} {tx}
rewrite ∑-++ {xs = filter ((_∉? outputRefs tx) ∘ outRef) (utxo l)}
{ys = mapWith∈ (outputs tx) (mkUtxo tx)}
{fv = value ∘ out}
| ∑-mapWith∈ {xs = outputs tx} {fv = value} {gv = out} {f = mkUtxo tx} (λ _ → refl)
= refl
h″ : ∑ l₀ forge ≡ ∑ (utxo l₀) (value ∘ out)
h″ rewrite ∑-utxo {l} {tx} = h′