Source code on Githubmodule UTxO.TxUtilities where
open import Data.List.Properties
open import Data.List.Membership.Propositional.Properties using (∈-++⁻; ∈-filter⁻)
open import Prelude.Init
open import Prelude.Lists
open import Prelude.Lists.Postulates
open import Prelude.DecEq
open import Prelude.Sets
open import Prelude.Membership hiding (_∈_)
open L.Mem using (_∈_)
open import Prelude.ToN
open import Prelude.Functor
open import Prelude.Bifunctor
open import Prelude.Monad
open import UTxO.Hashing
open import UTxO.Value
open import UTxO.Types
record UTXO : Set where
field
outRef : TxOutputRef
out : TxOutput
prevTx : Tx
open UTXO public
mkUtxo : ∀ {out} tx → out ∈ outputs tx → UTXO
outRef (mkUtxo tx out∈) = (tx ♯ₜₓ) indexed-at toℕ (L.Any.index out∈)
out (mkUtxo {out} _ _) = out
prevTx (mkUtxo tx _ ) = tx
utxo : Ledger → List UTXO
utxo [] = []
utxo (tx ∷ l) = filter ((_∉? outputRefs tx) ∘ outRef) (utxo l)
++ mapWith∈ (outputs tx) (mkUtxo tx)
open ≡-Reasoning
map-out≡ : ∀ tx → map out (mapWith∈ (outputs tx) (mkUtxo tx)) ≡ outputs tx
map-out≡ tx =
begin map out (mapWith∈ (outputs tx) (mkUtxo tx)) ≡⟨ map∘mapWith∈ out (outputs tx) (mkUtxo tx) ⟩
mapWith∈ (outputs tx) (out ∘ mkUtxo tx) ≡⟨⟩
mapWith∈ (outputs tx) (λ {o} _ → o) ≡⟨ mapWith∈-id {xs = outputs tx} ⟩
outputs tx ∎
∑utxo≥∑out : ∀ tx l → T $ ∑ (utxo $ tx ∷ l) (value ∘ out) ≥ᶜ ∑ (outputs tx) value
∑utxo≥∑out tx l
rewrite ∑-++ {xs = filter ((_∉? outputRefs tx) ∘ outRef) (utxo l)}
{ys = mapWith∈ (outputs tx) (mkUtxo tx)} {fv = value ∘ out}
= ≥ᶜ-+ᶜ {x = x} {y = y} {z = z} (≥ᶜ-refl′ ∑≡)
where
x = ∑ (filter ((_∉? outputRefs tx) ∘ outRef) (utxo l)) (value ∘ out)
y = ∑ (mapWith∈ (outputs tx) (mkUtxo tx)) (value ∘ out)
z = ∑ (outputs tx) value
∑≡ : y ≡ z
∑≡ rewrite map-compose {g = value} {f = out} (mapWith∈ (outputs tx) (mkUtxo tx))
| map-out≡ tx
= refl
∈utxo⇒outRef≡ : ∀ {u l}
→ u ∈ utxo l
→ prevTx u ∈ l
× Σ[ out∈ ∈ (out u ∈ outputs (prevTx u)) ]
outRef u ≡ ((prevTx u) ♯ₜₓ) indexed-at toℕ (L.Any.index out∈)
∈utxo⇒outRef≡ {l = tx ∷ l} u∈
with ∈-++⁻ (filter ((_∉? outputRefs tx) ∘ outRef) (utxo l)) u∈
... | inj₁ u∈ˡ = map₁ there (∈utxo⇒outRef≡ (proj₁ (∈-filter⁻ ((_∉? outputRefs tx) ∘ outRef) u∈ˡ)))
... | inj₂ u∈ʳ = (mapWith∈-∀ {P = λ u → prevTx u ∈ (tx ∷ l)
× Σ[ out∈ ∈ (out u ∈ outputs (prevTx u)) ]
outRef u ≡ ((prevTx u) ♯ₜₓ) indexed-at toℕ (L.Any.index out∈)}
(λ x∈ → here refl , x∈ , refl))
u∈ʳ
_⟨_⟩ : Ledger → TxOutputRef → Maybe Tx
[] ⟨ or ⟩ = nothing
(tx ∷ l) ⟨ or ⟩
with hid or ≟ tx ♯ₜₓ
... | yes _ = just tx
... | no _ = l ⟨ or ⟩
⟨⟩≡just : ∀ {l or tx}
→ l ⟨ or ⟩ ≡ just tx
→ hid or ≡ tx ♯ₜₓ
⟨⟩≡just {l = []} ()
⟨⟩≡just {l = tx′ ∷ l}{or}{tx} eq
with hid or ≟ tx′ ♯ₜₓ | eq
... | yes refl | refl = refl
... | no _ | eq′ = ⟨⟩≡just {l}{or}{tx} eq′
utxo-outRef↔prevTx : ∀ {u l}
→ u ∈ utxo l
→ hid (outRef u) ≡ prevTx u ♯ₜₓ
utxo-outRef↔prevTx {u} {l} u∈
rewrite proj₂ (proj₂ (∈utxo⇒outRef≡ {u} {l} u∈))
= refl
utxo-∈ʳ : ∀ {u tx}
→ u ∈ mapWith∈ (outputs tx) (mkUtxo tx)
→ tx ≡ prevTx u
utxo-∈ʳ {u} {tx} = mapWith∈-∀ {P = (tx ≡_) ∘ prevTx} λ _ → refl
utxo-≢ : ∀ {l u tx}
→ u ∈ utxo (tx ∷ l)
→ hid (outRef u) ≢ tx ♯ₜₓ
→ u ∈ utxo l
utxo-≢ {l} {u} {tx} u∈ ¬p
with ∈-++⁻ (filter ((_∉? outputRefs tx) ∘ outRef) (utxo l)) u∈
... | inj₁ u∈ˡ
= proj₁ (∈-filter⁻ ((_∉? outputRefs tx) ∘ outRef) {v = u} {xs = utxo l} u∈ˡ)
... | inj₂ u∈ʳ
= ⊥-elim (¬p (trans (utxo-outRef↔prevTx {u} {tx ∷ l} u∈) (sym (cong _♯ₜₓ (utxo-∈ʳ {u} {tx} u∈ʳ)))))
utxo-[] : ∀ {l u}
→ u ∈ utxo l
→ l ⟨ outRef u ⟩ ≡ just (prevTx u)
utxo-[] {l = tx ∷ l} {u} u∈
with hid (outRef u) ≟ tx ♯ₜₓ
... | yes p
rewrite injective♯ₜₓ {x = prevTx u} {y = tx} (trans (sym (utxo-outRef↔prevTx {u} {tx ∷ l} u∈)) p)
= refl
... | no ¬p = utxo-[] {l} (utxo-≢ {l} {u} {tx} u∈ ¬p)
_⟦_⟧ : {X : Set} → List X → ℕ → Maybe X
_⟦_⟧ = _⁉_
utxo-⟨⟩ : ∀ {l u}
→ u ∈ utxo l
→ outputs (prevTx u) ⟦ index (outRef u) ⟧ ≡ just (out u)
utxo-⟨⟩ {tx ∷ l} {u} u∈
with ∈-++⁻ (filter ((_∉? outputRefs tx) ∘ outRef) (utxo l)) u∈
... | inj₁ u∈ˡ
= utxo-⟨⟩ {l} {u} (proj₁ (∈-filter⁻ ((_∉? outputRefs tx) ∘ outRef) {v = u} {xs = utxo l} u∈ˡ))
... | inj₂ u∈ʳ
= mapWith∈-∀ {P = λ u → outputs (prevTx u) ⟦ index (outRef u) ⟧ ≡ just (out u)}
(λ x∈ → trans (sym (‼→⁉ {xs = outputs tx} {ix = L.Any.index x∈})) (cong just (‼-index x∈))) u∈ʳ
getSpentOutputRef : Ledger → TxOutputRef → Maybe TxOutput
getSpentOutputRef l oRef =
outputs <$> (l ⟨ oRef ⟩) >>= _⟦ index oRef ⟧
getSpentOutput : Ledger → TxInput → Maybe TxOutput
getSpentOutput l i = getSpentOutputRef l (outputRef i)
utxo-getSpent : ∀ {l u}
→ u ∈ utxo l
→ getSpentOutputRef l (outRef u) ≡ just (out u)
utxo-getSpent {l} {u} u∈
rewrite utxo-[] {l} {u} u∈
| utxo-⟨⟩ {l} {u} u∈
= refl
utxo-getSpentᵛ : ∀ {l u i}
→ u ∈ utxo l
→ outRef u ≡ outputRef i
→ (value <$> getSpentOutput l i) ≡ just (value $ out u)
utxo-getSpentᵛ {l} {u} {i} u∈ refl = cong (_<$>_ value) (utxo-getSpent {l} {u} u∈)
mkInputInfo : Ledger → TxInput → InputInfo
mkInputInfo l i = record
{ outputRef = outputRef i
; validatorHash = (validator i) ♯
; datumHash = (datum i) ♯ᵈ
; redeemerHash = (redeemer i) ♯ᵈ
; value = maybe value [] (getSpentOutput l i) }
mkTxInfo : Ledger → Tx → TxInfo
mkTxInfo l tx = record
{ inputInfo = map (mkInputInfo l) (inputs tx)
; outputInfo = outputs tx
; datumWitnesses = datumWitnesses tx
; range = range tx
; policies = map _♯ (policies tx)
; forge = forge tx }
toPendingTx : Ledger → (tx : Tx) → Index (inputs tx) → PendingTx
toPendingTx l tx i = record
{ thisTx = ‼-map {xs = inputs tx} {f = mkInputInfo l} i
; txInfo = mkTxInfo l tx }
toPendingMPS : Ledger → Tx → HashId → PendingMPS
toPendingMPS l tx i = record
{ thisTx = i
; txInfo = mkTxInfo l tx }
ptx-‼ : ∀ {l tx i} {i∈ : i ∈ inputs tx} →
let ptx = toPendingTx l tx (L.Any.index i∈)
in (TxInfo.inputInfo (txInfo ptx) ‼ thisTx ptx) ≡ mkInputInfo l i
ptx-‼ {l = l} {i∈ = i∈} rewrite map-‼ {f = mkInputInfo l} i∈ = refl
∑₁ᶜ : ∀ {H : Value → Set} → List (∃ H) → Value
∑₁ᶜ = flip ∑ proj₁
∑ᵥ : List TxOutput → Value
∑ᵥ = flip ∑ value
outRef∈txi : ∀ {tx l o}
→ o ∈ map InputInfo.outputRef (TxInfo.inputInfo $ mkTxInfo l tx)
→ o ∈ outputRefs tx
outRef∈txi {tx}{l}{o} o∈ with inputs tx | o∈
... | [] | ()
... | i ∷ is | here refl = here refl
... | i ∷ is | there o∈′ = there (outRef∈txi {tx = record tx {inputs = is}}{l} o∈′)
lookup-⟨⟩ : ∀ {tx l i}
→ Is-just (getSpentOutput l i)
→ hid (outputRef i) ≡ tx ♯ₜₓ
→ l ⟨ outputRef i ⟩ ≡ just tx
lookup-⟨⟩ {tx}{l}{i@(record{outputRef = or})} getSpent≡ id≡
with l | getSpent≡
... | [] | ()
... | tx′ ∷ l′ | getSpent≡′
with hid or ≟ tx′ ♯ₜₓ
... | yes refl
rewrite injective♯ₜₓ {x = tx′} {y = tx} id≡
= refl
... | no _
= lookup-⟨⟩ {tx}{l′}{i} getSpent≡′ id≡
lookup-⟦⟧ : ∀ {tx l i o}
→ Is-just (getSpentOutput l i)
→ hid (outputRef i) ≡ tx ♯ₜₓ
→ outputs tx ⟦ index (outputRef i) ⟧ ≡ just o
→ getSpentOutput l i ≡ just o
lookup-⟦⟧ {tx = tx}{l}{i}{o} vvh id≡ p rewrite lookup-⟨⟩ {tx = tx}{l}{i} vvh id≡ = p
postulate
wits♯ : ∀ {txi d♯ d}
→ (d♯ , d) ∈ TxInfo.datumWitnesses txi
→ d♯ ≡ d ♯ᵈ
lookupDatum≡ : ∀ {A : Set} {{_ : IsData A}} {x : A} {d♯ : HashId} {txi : TxInfo} {wits : List (HashId × DATA)}
→ TxInfo.datumWitnesses txi ≡ wits
→ (lookupDatum d♯ wits >>= fromData) ≡ just x
→ d♯ ≡ toData x ♯ᵈ
lookupDatum≡ {x = x}{d♯}{txi}{[]} _ ()
lookupDatum≡ {x = x}{d♯}{txi}{(h , d) ∷ wits} wits≡ eq
with d♯ ≟ h
... | yes p
rewrite filter-accept ((d♯ ≟_) ∘ proj₁) {x = h , d} {xs = wits} p
= begin d♯ ≡⟨ p ⟩
h ≡⟨ wits♯ {txi}{h}{d} (subst ((h , d) ∈_) (sym wits≡) (here refl)) ⟩
d ♯ᵈ ≡⟨ cong (_♯ᵈ) (from-inj _ _ eq) ⟩
toData x ♯ᵈ ∎
... | no ¬p
rewrite filter-reject ((d♯ ≟_) ∘ proj₁) {x = h , d} {xs = wits} ¬p
= lookupDatum≡ {x = x}{d♯}{record txi {datumWitnesses = wits}}{wits} refl eq