Source code on Githubmodule EUTxOErr.DoubleSatisfaction where
open import Prelude.Init; open SetAsType
open import Prelude.General using (true⇒T)
open import Prelude.DecEq
open import Prelude.Decidable
open import Prelude.Membership
open import Prelude.Allable
open import Prelude.InferenceRules
open import EUTxOErr
hiding (s)
renaming (S to UTxOSet)
renaming (_‼_ to _‼ᵐ_)
open import Prelude.Lists.Indexed using (_‼_)
data S : Type where
◇ ◆ : S
toggleS : S → S
toggleS = λ where
◇ → ◆
◆ → ◇
instance
_ : ToData S
_ = record {serialise = ser; serialise-inj = serInj; deserialise = deser}
where
ser = λ where
◇ → "◇"
◆ → "◆"
deser : _
deser d =
Nullary.map′
Sum.[ ◇ ,_ , ◆ ,_ ]
(λ where (◇ , d≡) → inj₁ d≡; (◆ , d≡) → inj₂ d≡)
¿ (d ≡ "◇") ⊎ (d ≡ "◆") ¿
serInj : Injective≡ ser
serInj {◇}{◇} refl = refl
serInj {◆}{◆} refl = refl
serInj {◇}{◆} ()
serInj {◆}{◇} ()
toggle : Validator
toggle toggle♯ record {inputs = is; outputs = os} _ d
with deserialise {A = S} d
... | no _ = false
... | yes (s , _) = ⌊ consume◇ ∈? is ⌋ ∧ ⌊ produce◆ ∈? os ⌋
where
consume◇ = record
{ outputRef = ⦉ serialise s ♯ ⦊ 1 € at toggle♯
; validatorHash = toggle♯
; redeemerHash = "" ♯ }
produce◆ = ⦉ serialise (toggleS s) ♯ ⦊ 1 € at toggle♯
toggle♯ = toggle ♯
consume◇ = InputInfo ∋ record
{ outputRef = ⦉ serialise ◇ ♯ ⦊ 1 € at toggle♯
; validatorHash = toggle♯
; redeemerHash = "" ♯ }
produce◆ = OutputInfo ∋
⦉ serialise ◆ ♯ ⦊ 1 € at toggle♯
module _
{r : DATA} {txi : TxInfo}
(let d = serialise ◇
record {inputs = is; outputs = os} = txi)
where
toggle≡ :
∙ consume◇ ∈ is
∙ produce◆ ∈ os
──────────────────────────
call toggle txi r d ≡ true
toggle≡ ◇∈is ◆∈os
rewrite deserialise∘serialise ◇
| dec-yes (consume◇ ∈? is) ◇∈is .proj₂
| dec-yes (produce◆ ∈? os) ◆∈os .proj₂
= refl
t₀ = Tx ∋ record
{ inputs = []
; outputs = [ ⦉ serialise ◇ ⦊ 1 € at toggle♯ ]
; forge = 1 € }
t₀₀ = (t₀ ♯) indexed-at 0
o = TxOutput ∋ ⦉ serialise ◇ ⦊ 1 € at toggle♯
i = TxInput ∋ record { outputRef = t₀₀ ; validator = toggle ; redeemer = "" }
ri = ResolvedInput ∋ i , o
t₁ = Tx ∋ record
{ inputs = [ i ]
; outputs = [ ⦉ serialise ◆ ⦊ 1 € at toggle♯ ]
; forge = 0 € }
t₁₀ = (t₁ ♯) indexed-at 0
t₁′ = Tx ∋ record
{ inputs = [ i ]
; outputs = ⦉ serialise ◆ ⦊ 1 € at toggle♯
∷ ⦉ serialise ◆ ⦊ 1 € at toggle♯
∷ []
; forge = 1 € }
t₁′₀ = (t₁′ ♯) indexed-at 0
t₁′₁ = (t₁′ ♯) indexed-at 1
singleSat doubleSat : L
singleSat = t₀ ∷ t₁ ∷ []
doubleSat = t₀ ∷ t₁′ ∷ []
v₀ : VL ∅ [ t₀ ]
v₀ = t₀
⊣ record { noDoubleSpending = []
; validOutputRefs = []
; preservesValues = refl
; allInputsValidate = []
; validateValidHashes = [] }
∷ []
s₀ = ⟦ t₀ ⟧₀ ∅
_ = s₀ ≡ singleton (t₀₀ , o)
∋ refl
module ⦅1⦆ where
vor : ∀[ ref ∈ outputRefs t₁ ] (ref ∈ᵈ s₀)
vor = here refl ∷ []
rt₁ = Resolved t₁
∋ L.All.map (s₀ ‼ᵐ_) vor
_ = mkUtxo t₀ (here refl) ≡ (t₀₀ , o)
∋ refl
rt≡ : rt₁ ≡ [ o ]
rt≡ = cong (_∷ []) $ ‼-singleton {k = t₀₀}{o}
txi = mkTxInfo t₁ rt₁
is = txi .TxInfo.inputs
os = txi .TxInfo.outputs
ris = ResolvedInputs
∋ resolveInputs t₁ rt₁
postulate ris≡ : ris ≡ [ ri ]
val≡ : T (call (i .validator) txi (i .redeemer) (o .datum))
val≡ = true⇒T $
begin
call (i .validator) txi (i .redeemer) (o .datum)
≡⟨⟩
toggle toggle♯ txi "" (serialise ◇)
≡⟨ toggle≡ {""}{txi}
( subst (Any (consume◇ ≡_) ∘ map mkInputInfo) (sym ris≡)
$ here refl
)
(here refl) ⟩
true
∎ where open ≡-Reasoning
_ : VL ∅ singleSat
_ = t₀
⊣ record
{ noDoubleSpending = []
; validOutputRefs = []
; preservesValues = refl
; allInputsValidate = []
; validateValidHashes = []
}
∷ t₁
⊣ record
{ noDoubleSpending = [] ∷ []
; validOutputRefs = vor
; preservesValues = pv
; allInputsValidate = aiv
; validateValidHashes = vvh
}
∷ []
where
pv : t₁ .forge + ∑ ris (value ∘ proj₂) ≡ ∑ (t₁ .outputs) value
pv = cong (λ ⋆ → t₁ .forge + ∑ ⋆ (value ∘ proj₂)) ris≡
aiv : ∀[ (i , o) ∈ ris ]
T (call (i .validator) txi (i .redeemer) (o .datum))
aiv = subst (L.All.All _) (sym ris≡)
$ val≡ ∷ []
vvh : ∀[ (i , o) ∈ ris ]
(o .address ≡ i .validator ♯)
vvh = subst (L.All.All _) (sym ris≡)
$ refl ∷ []
open HoareReasoning
_ =
begin
emp
~⟨ t₀ ∶- 𝟘⇒𝟙 refl ⟩
t₀₀ ↦ ⦉ serialise ◇ ⦊ 1 € at toggle♯
~⟨ t₁ ∶- 𝟙⇒𝟙 rt₁ val≡ refl ⟩
t₁₀ ↦ ⦉ serialise ◆ ⦊ 1 € at toggle♯
∎
module ⦅12⦆ where
vor : ∀[ ref ∈ outputRefs t₁′ ] (ref ∈ᵈ s₀)
vor = here refl ∷ []
rt₁′ = Resolved t₁′
∋ L.All.map (s₀ ‼ᵐ_) vor
_ = mkUtxo t₀ (here refl) ≡ (t₀₀ , o)
∋ refl
rt≡ : rt₁′ ≡ [ o ]
rt≡ = cong (_∷ []) $ ‼-singleton {k = t₀₀}{o}
txi = mkTxInfo t₁′ rt₁′
is = txi .TxInfo.inputs
os = txi .TxInfo.outputs
ris = ResolvedInputs
∋ resolveInputs t₁′ rt₁′
postulate ris≡ : ris ≡ [ i , o ]
val≡ : T (call (i .validator) txi (i .redeemer) (o .datum))
val≡ = true⇒T $
begin
call (i .validator) txi (i .redeemer) (o .datum)
≡⟨⟩
toggle toggle♯ txi "" (serialise ◇)
≡⟨ toggle≡ {""}{txi}
( subst (Any (consume◇ ≡_) ∘ map mkInputInfo) (sym ris≡)
$ here refl
)
(here refl) ⟩
true
∎ where open ≡-Reasoning
_ : VL ∅ doubleSat
_ = t₀
⊣ record
{ noDoubleSpending = []
; validOutputRefs = []
; preservesValues = refl
; allInputsValidate = []
; validateValidHashes = []
}
∷ t₁′
⊣ record
{ noDoubleSpending = [] ∷ []
; validOutputRefs = vor
; preservesValues = pv
; allInputsValidate = aiv
; validateValidHashes = vvh
}
∷ []
where
pv : t₁′ .forge + ∑ ris (value ∘ proj₂) ≡ ∑ (t₁′ .outputs) value
pv = cong (λ ⋆ → t₁′ .forge + ∑ ⋆ (value ∘ proj₂)) ris≡
aiv : ∀[ (i , o) ∈ ris ]
T (call (i .validator) txi (i .redeemer) (o .datum))
aiv = subst (L.All.All _) (sym ris≡)
$ val≡ ∷ []
vvh : ∀[ (i , o) ∈ ris ]
(o .address ≡ i .validator ♯)
vvh = subst (L.All.All _) (sym ris≡)
$ refl ∷ []
open HoareReasoning
_ =
begin
emp
~⟨ t₀ ∶- 𝟘⇒𝟙 refl ⟩
t₀₀ ↦ ⦉ serialise ◇ ⦊ 1 € at toggle♯
~⟨ t₁′ ∶- 𝟙⇒𝟚 rt₁′ val≡ refl ⟩
t₁′₀ ↦ ⦉ serialise ◆ ⦊ 1 € at toggle♯
∗
t₁′₁ ↦ ⦉ serialise ◆ ⦊ 1 € at toggle♯
∎
data YesDP (s₀ : UTxOSet) : Type₁ where
yesDP : ∀ {t txi txi′ txi″ v v′ v″} →
⟨ txi ↦ ⦉ serialise ◇ ⦊ v € at toggle♯ ⟩
[ t ]
⟨ txi′ ↦ ⦉ serialise ◆ ⦊ v′ € at toggle♯
∗ txi″ ↦ ⦉ serialise ◆ ⦊ v″ € at toggle♯
⟩@ s₀
──────────────────────────────────────────────
YesDP s₀
yesDP-toggle : ∀ s₀ → YesDP s₀
yesDP-toggle s₀ = yesDP {t = $t} λ Ps₀ →
let open 𝕄 Ps₀
in 1⇒2 rt val≡ refl Ps₀
where
txi₀ = TxOutputRef ∋ t₀₀
$o = TxOutput ∋ ⦉ serialise ◇ ⦊ 1 € at toggle♯
$i = TxInput ∋ record
{ outputRef = txi₀ ; validator = toggle ; redeemer = "" }
$ri = ResolvedInput ∋ $i , $o
$t = Tx ∋ record
{ inputs = [ $i ]
; outputs = ⦉ serialise ◆ ⦊ 1 € at toggle♯
∷ ⦉ serialise ◆ ⦊ 1 € at toggle♯
∷ []
; forge = 1 € }
module 𝕄 (Ps₀ : (t₀₀ ↦ ⦉ serialise ◇ ⦊ 1 € at toggle♯) s₀) where
postulate vor : ∀[ ref ∈ outputRefs $t ] (ref ∈ᵈ s₀)
rt = Resolved $t
∋ L.All.map (s₀ ‼ᵐ_) vor
txi = mkTxInfo $t rt
is = txi .TxInfo.inputs
os = txi .TxInfo.outputs
ris = resolveInputs $t rt
postulate rt≡ : rt ≡ [ $o ]
postulate ris≡ : ris ≡ [ ri ]
val≡ : T $ call toggle txi "" (serialise ◇)
val≡ = true⇒T $
begin
call toggle txi "" (serialise ◇)
≡⟨ toggle≡ {""}{txi}
( subst (Any (consume◇ ≡_) ∘ map mkInputInfo) (sym ris≡)
$ here refl
)
(here refl) ⟩
true
∎ where open ≡-Reasoning
toggle′ : Validator
toggle′ toggle♯ record {inputs = is; outputs = os} _ d
with deserialise {A = S} d
... | no _ = false
... | yes (s , _) = ⌊ ¿ (is ≡ [ consume◇′ ]) × (os ≡ [ produce◆′ ]) ¿ ⌋
where
consume◇′ = record
{ outputRef = ⦉ serialise ◇ ♯ ⦊ 1 € at toggle♯
; validatorHash = toggle♯
; redeemerHash = "" ♯ }
produce◆′ = ⦉ serialise ◆ ♯ ⦊ 1 € at toggle♯
toggle′♯ = toggle′ ♯
consume◇′ = InputInfo ∋ record
{ outputRef = ⦉ serialise ◇ ♯ ⦊ 1 € at toggle′♯
; validatorHash = toggle′♯
; redeemerHash = "" ♯ }
produce◆′ = OutputInfo ∋
⦉ serialise ◆ ♯ ⦊ 1 € at toggle′♯
module _
{s : S} {r : DATA} {txi : TxInfo}
(let d = serialise s
record {inputs = is; outputs = os} = txi)
where
toggle′≡ :
∙ is ≡ [ consume◇′ ]
∙ os ≡ [ produce◆′ ]
───────────────────────────
call toggle′ txi r d ≡ true
toggle′≡ refl refl
rewrite deserialise∘serialise s
| ≟-refl consume◇′
| ≟-refl produce◆′
= refl
data NoDP : Type₁ where
noDP :
(¬
∃ λ t →
∃ λ txi → ∃ λ txi′ → ∃ λ txi″ →
∃ λ v → ∃ λ v′ → ∃ λ v″ →
⟨ txi ↦ ⦉ serialise ◇ ⦊ v € at toggle′♯ ⟩
[ t ]
⟨ txi′ ↦ ⦉ serialise ◆ ⦊ v′ € at toggle′♯
∗ txi″ ↦ ⦉ serialise ◆ ⦊ v″ € at toggle′♯
⟩)
───────────────────────────────────────────────
NoDP
postulate noDP-toggle′ : NoDP