Source code on Github
module 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′