{-# OPTIONS --allow-unsolved-metas #-}
-------------------------------------
-- ** Properties for Hoare triples.
module UTxOErr.HoareProperties where
open import Prelude.Init
open import Prelude.General
open import Prelude.DecEq
open import Prelude.Decidable
open import Prelude.InferenceRules
open import Prelude.Apartness
open import Prelude.Setoid
open import UTxOErr.UTxO
open import UTxOErr.Ledger
open import UTxOErr.HoareLogic
-- open import UTxOErr.Maps
open import Prelude.Maps
postulate
  ⊎≡-comm : Symmetric (⟨_⊎_⟩≡ s)
  ⊎≈-assocʳ :
    ∙ ⟨ s₁ ⊎ s₂₃ ⟩≡ s
    ∙ ⟨ s₂ ⊎ s₃  ⟩≡ s₂₃
      ─────────────────────
      ⟨ (s₁ ∪ s₂) ⊎ s₃ ⟩≡ s
    × (s₁ ♯ s₂)
  ⊎≈-assocˡ : ∀ {s₁₂} →
    ∙ ⟨ s₁₂ ⊎ s₃ ⟩≡ s
    ∙ ⟨ s₁ ⊎ s₂  ⟩≡ s₁₂
      ───────────────────
      ⟨ s₁ ⊎ (s₂ ∪ s₃) ⟩≡ s
    × (s₂ ♯ s₃)
-- ** Lemmas about separating conjunction.
-- commutativity
∗↔ : P ∗ Q ⊢ Q ∗ P
∗↔ (s₁ , s₂ , ≡s , Ps₁ , Qs₂) = s₂ , s₁ , ⊎≡-comm {x = s₁}{s₂} ≡s , Qs₂ , Ps₁
-- associativity
∗↝ : P ∗ Q ∗ R ⊢ (P ∗ Q) ∗ R
∗↝ {x = s} (s₁ , s₂₃ , ≡s , Ps₁ , (s₂ , s₃ , ≡s₂₃ , Qs₂ , Rs₃)) =
  let ≡s₁₂ , s₁♯s₂ = ⊎≈-assocʳ ≡s ≡s₂₃ in
  (s₁ ∪ s₂) , s₃ , ≡s₁₂ , (s₁ , s₂ , (s₁♯s₂ , ≈-refl) , Ps₁ , Qs₂) , Rs₃
↜∗ : (P ∗ Q) ∗ R ⊢ P ∗ Q ∗ R
↜∗ {x = s} (s₁₂ , s₃ , ≡s , (s₁ , s₂ , ≡s₁₂ , Ps₁ , Qs₂) , Rs₃) =
  let ≡s₂₃ , s₂♯s₃ = ⊎≈-assocˡ ≡s ≡s₁₂ in
  s₁ , s₂ ∪ s₃ , ≡s₂₃ , Ps₁ , (s₂ , s₃ , (s₂♯s₃ , ≈-refl) , Qs₂ , Rs₃)
-- ** Useful lemmas when transferring a value between participants in the minimal context.
transfer : ∀ {tx : Tx} {v : Value} {B : Address} {or : TxOutputRef}
             {rdm : DATA} {val : TxInfo → DATA → Bool} {vtx : Resolved tx} →
  ∙ T (val (mkTxInfo tx vtx) rdm)
  ∙ tx ≡ record { inputs  = [ record {outputRef = or; validator = val; redeemer = rdm} ]
                ; outputs = [ v at B ]
                ; forge   = 0 }
    ────────────────────────────────────
    ⟨ or ↦ v at (val ♯) ⟩
    [ tx ]
    ⟨ (tx ♯) indexed-at 0 ↦ v at B ⟩
transfer = {!!}
open HoareReasoning
transferℝ : ∀ {tx : Tx} {v : Value} {B : Address} {or : TxOutputRef}
              {rdm : DATA} {val : TxInfo → DATA → Bool} {vtx : Resolved tx} →
  ∙ T (val (mkTxInfo tx vtx) rdm)
  ∙ tx ≡ record { inputs  = [ record {outputRef = or; validator = val; redeemer = rdm} ]
                ; outputs = [ v at B ]
                ; forge   = 0 }
    ────────────────────────────────────
    ℝ⟨ or ↦ v at (val ♯) ⟩
    [ tx ]
    ⟨ (tx ♯) indexed-at 0 ↦ v at B ⟩
transferℝ val tx≡ = mkℝ transfer val tx≡
-- _↝⟨_⟩_ : ∀ A v B {vᵃ}{vᵇ}{v≤ : v ≤ vᵃ} → ⟨ A ↦ vᵃ ∗ B ↦ vᵇ ⟩ [ A —→⟨ v ⟩ B ] ⟨ A ↦ (vᵃ ∸ v) ∗ B ↦ (vᵇ + v) ⟩
-- (A ↝⟨ v ⟩ B) {vᵃ}{vᵇ}{vᵃ≤v} {s} (s₁ , s₂ , ≡s , As₁ , Bs₂)
--   with s₁ A | As₁ | ↦-⊎ˡ {s₁ = s₁}{A}{vᵃ}{s₂} As₁ | ≡s A
-- ... | .(just vᵃ) | refl | .(s₂ ⁉⁰ A) , refl , p | sA≡
--   with s₂ B | Bs₂ | ↦-⊎ʳ {s₂ = s₂}{B}{vᵇ}{s₁} Bs₂ | ≡s B
-- ... | .(just vᵇ) | refl | .(s₁ ⁉⁰ B) , refl , q | sB≡
--   with s A | trans (sym sA≡) p
-- ... | .(just (vᵃ ⊎ (s₂ ⁉⁰ A))) | refl
--   with s B | trans (sym sB≡) q
-- ... | .(just ((s₁ ⁉⁰ B) ⊎ vᵇ)) | refl
--   with v ≤? vᵃ ⊎ (s₂ ⁉⁰ A)
-- ... | no  v≰ = ⊥-elim $ v≰ $ Nat.≤-stepsʳ (s₂ ⁉⁰ A) $ vᵃ≤v
-- ... | yes v≤
--   = ret↑ (_s₁′ , _s₂′ , ≡s′ , As₁′ , Bs₂′)
--   where
--     sA≡′ : s A ≡ just (vᵃ ⊎ (s₂ ⁉⁰ A))
--     sA≡′ = trans (sym sA≡) p
--     sB≡′ : s B ≡ just ((s₁ ⁉⁰ B) ⊎ vᵇ)
--     sB≡′ = trans (sym sB≡) q
--     _s₁′ = s₁ [ A ↝ (_∸ v) ]
--     _s₂′ = s₂ [ B ↝ (_+ v) ]
--     _s′ = s [ A ↝ (_∸ v) ]
--             [ B ↝ (_+ v) ]
--     As₁′ : _s₁′ A ≡ just (vᵃ ∸ v)
--     As₁′ rewrite As₁ | ≟-refl A = refl
--     Bs₂′ : _s₂′ B ≡ just (vᵇ + v)
--     Bs₂′ rewrite Bs₂ | ≟-refl B = refl
--     ≡s′ : ⟨ _s₁′ ⊎ _s₂′ ⟩≡ _s′
--     ≡s′ k
--       rewrite sym $ ≡s k
--       with k ≟ A | k ≟ B
--     ≡s′ k | yes refl | yes refl -- ∙ k ≡ A ≡ B
--       rewrite ≟-refl A | ≟-refl B | As₁ | Bs₂
--       = cong just
--       $ begin (vᵃ ∸ v) + (vᵇ + v) ≡⟨ sym $ Nat.+-∸-comm _ vᵃ≤v ⟩
--               vᵃ + (vᵇ + v) ∸ v   ≡⟨ cong (_∸ v) $ sym $ Nat.+-assoc _ vᵇ v ⟩
--               (vᵃ + vᵇ) + v ∸ v   ≡⟨ Nat.m+n∸n≡m _ v ⟩
--               (vᵃ + vᵇ)           ≡⟨ sym $ Nat.m∸n+n≡m v≤ ⟩
--               (vᵃ + vᵇ) ∸ v + v   ∎ where open ≡-Reasoning
--     ≡s′ k | yes refl | no k≢B -- ∙ k ≡ A
--       rewrite ≟-refl A | As₁
--       with s₂ A
--     ... | nothing = refl
--     ... | just _  = cong just $ sym $ Nat.+-∸-comm _ vᵃ≤v
--     ≡s′ k | no k≢A   | yes refl -- ∙ k ≡ B
--       rewrite ≟-refl B | Bs₂
--       with s₁ B
--     ... | nothing  = refl
--     ... | just _   = cong just $ sym $ Nat.+-assoc _ vᵇ v
--     ≡s′ k | no k≢A   | no k≢B -- ∙ k ∉ {A, B}
--       rewrite M.map-id (s₁ k) | M.map-id (s₂ k) | M.map-id (s₁ k ⊎ s₂ k) | M.map-id (s₁ k ⊎ s₂ k)
--       = refl
-- _↝⁰_ : ∀ A B → ⟨ A ↦ v ∗ B ↦ v′ ⟩ [ A —→⟨ v ⟩ B ] ⟨ A ↦ 0 ∗ B ↦ (v′ + v) ⟩
-- _↝⁰_ {v = v} {v′ = v′} A B with p ← (A ↝⟨ v ⟩ B) {vᵇ = v′} {v≤ = ≤-refl {x = v}} rewrite Nat.n∸n≡0 v = p
-- _↜⟨_⟩_ : ∀ A v B {vᵃ}{vᵇ}{v≤ : v ≤ vᵇ} → ⟨ A ↦ vᵃ ∗ B ↦ vᵇ ⟩ [ B —→⟨ v ⟩ A ] ⟨ A ↦ (vᵃ + v) ∗ B ↦ (vᵇ ∸ v) ⟩
-- (A ↜⟨ v ⟩ B) {vᵃ}{vᵇ}{v≤} (s₁ , s₂ , ≡s , As₁ , Bs₂)
--   = map↑ (λ where (s₁′ , s₂′ , ≡s′ , As₁′ , Bs₂′) → s₂′ , s₁′ , ⊎≡-comm {x = s₁′} ≡s′ , Bs₂′ , As₁′)
--          ((B ↝⟨ v ⟩ A) {v≤ = v≤} (s₂ , s₁ , ⊎≡-comm {x = s₁} ≡s , Bs₂ , As₁))
-- _↜⁰_ : ∀ A B → ⟨ A ↦ v′ ∗ B ↦ v ⟩ [ B —→⟨ v ⟩ A ] ⟨ A ↦ (v′ + v) ∗ B ↦ 0 ⟩
-- _↜⁰_ {v′ = v′} {v = v} A B with p ← (A ↜⟨ v ⟩ B) {vᵃ = v′} {v≤ = ≤-refl {x = v}} rewrite Nat.n∸n≡0 v = p