{-# OPTIONS --allow-unsolved-metas #-} --------------------------- -- ** Separation logic (SL) module UTxO.SL where open import Prelude.Init; open SetAsType open L.Mem open import Prelude.DecEq open import Prelude.Decidable open import Prelude.Sets open import Prelude.Ord open import Prelude.Functor open import Prelude.Apartness open import UTxO.UTxO open import UTxO.Ledger open import UTxO.HoareLogic -- Which addresses does a ledger modify? mod : Address → L → Type mod A = Any λ tx → A ∈ (address <$> tx .outputs) -- Which addresses does an assertion refer to? addr : Address → Assertion → Type addr A `emp = ⊥ addr A (B `↦ _) = A ≡ B addr A (P `∗ Q) = addr A P ⊎ addr A Q addr A (P `∘⟦ _ ⟧) = addr A P -- Define disjointness between ledgers/states/formulas as disjointness of the participant set they refer to. instance Disjoint-LS : L // S Disjoint-LS ._♯_ l s = ∀ A → mod A l → ¬ ∃ λ utxo → (utxo .UTXO.out .address ≡ A) × (utxo ∈ˢ s) Disjoint-SL : S // L Disjoint-SL ._♯_ s l = ∀ A → (∃ λ utxo → (utxo .UTXO.out .address ≡ A) × (utxo ∈ˢ s)) → ¬ mod A l Disjoint-LA : L // Assertion Disjoint-LA ._♯_ l P = ∀ A → mod A l → ¬ addr A P -- ** Utility lemmas about separation. -- ∈ᵈ-∪ : ⟨ s₁ ⊎ s₂ ⟩≡ s → A ∈ᵈ s → A ∈ᵈ s₁ ⊎ A ∈ᵈ s₂ -- ∈ᵈ-∪ {s₁}{s₂}{s}{A} (s₁♯s₂ , p) A∈ = ∈ᵈ-∪⁻ _ _ _ (∈ᵈ-cong (≈-sym p) A∈) -- ∉ᵈ-∪ : ⟨ s₁ ⊎ s₂ ⟩≡ s → A ∉ᵈ s → A ∉ᵈ s₁ × A ∉ᵈ s₂ -- ∉ᵈ-∪ {s₁}{s₂}{s}{A} (s₁♯s₂ , p) A∉ = A∉ ∘ ∈ᵈ-cong p ∘ ∈ᵈ-∪⁺ˡ _ _ _ , A∉ ∘ ∈ᵈ-cong p ∘ ∈ᵈ-∪⁺ʳ _ _ _ -- ∈⇒addr : A ∈ᵈ s → P ∙ s → addr A P -- ∈⇒addr {A}{s}{P = `emp} A∈ Ps = ⊥-elim $ Ps A A∈ -- ∈⇒addr {A}{s}{P = B `↦ v} A∈ Ps with A ≟ B -- ... | yes A≡B = A≡B -- ... | no A≢B = ⊥-elim $ proj₂ Ps A A≢B A∈ -- ∈⇒addr {A}{s}{P = P `∗ Q} A∈ (s₁ , s₂ , ≡s , Ps₁ , Qs₂) -- with ∈ᵈ-∪ ≡s A∈ -- ... | inj₁ A∈₁ = inj₁ $ ∈⇒addr {P = P} A∈₁ Ps₁ -- ... | inj₂ A∈₂ = inj₂ $ ∈⇒addr {P = Q} A∈₂ Qs₂ -- ∈⇒addr {A}{s}{P = P `∘⟦ l ⟧} A∈ Ps = ∈⇒addr {P = P} (⟦⟧ₗ-mono {l} s A A∈) Ps -- ∉⇒¬addr : A ∉ᵈ s → P ∙ s → ¬ addr A P -- ∉⇒¬addr {A}{s}{P = `emp} A∉ Ps () -- ∉⇒¬addr {A}{s}{P = .A `↦ _} A∉ (Ps , _) refl = A∉ $ ⁉⇒∈ᵈ (subst Is-just (sym Ps) auto) -- ∉⇒¬addr {A}{s}{P = P `∗ Q} A∉ (s₁ , s₂ , ≡s , Ps₁ , Qs₂) A∈ -- with A∉ˡ , A∉ʳ ← ∉ᵈ-∪ ≡s A∉ -- with A∈ -- ... | inj₁ A∈ˡ = ∉⇒¬addr {P = P} A∉ˡ Ps₁ A∈ˡ -- ... | inj₂ A∈ʳ = ∉⇒¬addr {P = Q} A∉ʳ Qs₂ A∈ʳ -- ∉⇒¬addr {A}{s}{P = P `∘⟦ l ⟧} A∉ Ps A∈ = ∉⇒¬addr {P = P} (∉-⟦⟧ₗ {l = l} A∉) Ps A∈ ♯-skip : (t ∷ l) ♯ P → l ♯ P ♯-skip p A = p A ∘ there -- ♯⇒♯ : l ♯ s → s ♯ l -- ♯⇒♯ {s = s} p A A∈ A∈l = p _ A∈l A∈ ♯♯⇒♯ : l ♯ R → R ∙ s → l ♯ s ♯♯⇒♯ {l} {`emp} {s} l♯R s∅ = λ _ _ (_ , _ , utxo∈) → s∅ _ utxo∈ ♯♯⇒♯ {l} {A `↦ v} {s} l♯R Rs = {!!} ♯♯⇒♯ {l} {R `∗ Q} {s} l♯R Rs = {!!} ♯♯⇒♯ {_} {R `∘⟦ l ⟧} {s} l♯R Rs = {!!} -- ♯♯⇒♯ {l}{`emp}{s} l♯R s∅ A A∈ = s∅ A -- ♯♯⇒♯ {l}{B `↦ v}{s} l♯R (_ , B↦) A A∈ A∈′ -- with A ≟ B -- ... | yes refl = l♯R A A∈ refl -- ... | no A≢B = B↦ A A≢B A∈′ -- ♯♯⇒♯ {l}{R `∗ Q}{s} l♯R (s₁ , s₂ , ≡s , Rs₁ , Qs₂) A A∈ -- with s₁ ⁉ A | inspect (s₁ ⁉_) A | s₂ ⁉ A | inspect (s₂ ⁉_) A -- ... | just _ | ≡[ s₁≡ ] | _ | _ -- = ⊥-elim $ l♯R A A∈ $ inj₁ $ ∈⇒addr {A}{s₁}{R} (⁉⇒∈ᵈ $ subst Is-just (sym s₁≡) auto) Rs₁ -- ... | _ | _ | just _ | ≡[ s₂≡ ] -- = ⊥-elim $ l♯R A A∈ $ inj₂ $ ∈⇒addr {A}{s₂}{Q} (⁉⇒∈ᵈ $ subst M.Is-just (sym s₂≡) auto) Qs₂ -- ... | nothing | ≡[ s₁≡ ] | nothing | ≡[ s₂≡ ] -- = ∉-splits ≡s (⊥-elim ∘ ⁉⇒∉ᵈ (subst Is-nothing (sym s₁≡) auto)) -- (⊥-elim ∘ ⁉⇒∉ᵈ (subst Is-nothing (sym s₂≡) auto)) -- ♯♯⇒♯ {_}{R `∘⟦ l ⟧}{s} l♯R Rs A A∈ = ¬A∈ -- where -- A∉ : A ∉ᵈ ⟦ l ⟧ s -- A∉ = ♯♯⇒♯ {R = R} {s = ⟦ l ⟧ s} l♯R Rs A A∈ -- ¬A∈ : A ∉ᵈ s -- ¬A∈ = A∉ ∘ ⟦⟧ₗ-mono {l} s A -- Helper lemma for [FRAME]: pushing ⟦ l ⟧ inside the partition. frame-helper : l ♯ R → R ∙ s₂ → ⟨ s₁ ⊎ s₂ ⟩≡ s ----------------------- → ⟨ ⟦ l ⟧ s₁ ⊎ s₂ ⟩≡ ⟦ l ⟧ s frame-helper {l = []} _ _ p = p frame-helper {l = tx ∷ l}{R}{s₂}{s₁}{s} l♯R Rs₂ (s₁♯s₂ , ≡s) = frame-helper {l}{R}{s₂}{⟦ tx ⟧ s₁}{⟦ tx ⟧ s} (♯-skip {P = R} l♯R) Rs₂ p′ where p₁ : (⟦ tx ⟧ s₁) ♯ s₂ p₁ = {!!} -- p₁ = transfer-helper s₁♯s₂ B∉₂ p₂ : ((⟦ tx ⟧ s₁) ∪ s₂) ≈ˢ (⟦ tx ⟧ s) p₂ = {!!} p′ : ⟨ ⟦ tx ⟧ s₁ ⊎ s₂ ⟩≡ ⟦ tx ⟧ s p′ = p₁ , p₂ {- frame-helper {l = l₀@(A —→⟨ v ⟩ B ∷ l)}{R}{s₂}{s₁}{s} l♯R Rs₂ (s₁♯s₂ , ≡s) = frame-helper {l}{R}{s₂}{run [ A ∣ v ↦ B ] s₁} {run [ A ∣ v ↦ B ] s} (♯-skip {P = R} l♯R) Rs₂ p′ where l♯s₂ : l₀ ♯ s₂ l♯s₂ = ♯♯⇒♯ {R = R} l♯R Rs₂ A∉₂ : A ∉ᵈ s₂ A∉₂ = l♯s₂ A $ here (here refl) B∉₂ : B ∉ᵈ s₂ B∉₂ = l♯s₂ B $ here (there (here refl)) p₁ : (run [ A ∣ v ↦ B ] s₁) Map.♯ s₂ p₁ = transfer-helper s₁♯s₂ B∉₂ ∉⇒≢ : ∀ k → k ∈ᵈ s₂ → (k ≢ A) × (k ≢ B) ∉⇒≢ k k∈ = k≢A , k≢B where k∉ : ¬ mod k l₀ k∉ = ♯⇒♯ l♯s₂ k k∈ k≢A : k ≢ A k≢A refl = ⊥-elim $ k∉ (here (here refl)) k≢B : k ≢ B k≢B refl = ⊥-elim $ k∉ (here (there (here refl))) p₂ : (run [ A ∣ v ↦ B ] s₁) ∪ s₂ ≈ run [ A ∣ v ↦ B ] s p₂ k with eq ← ≡s k with eqᵃ ← ≡s A with eqᵇ ← ≡s B with ¿ k ∈ᵈ s₂ ¿ ... | yes k∈ with k≢A , k≢B ← ∉⇒≢ k k∈ rewrite ∪-chooseᵣ p₁ k∈ | ∪-chooseᵣ s₁♯s₂ k∈ | drop-[∣↦] {v = v} {s = s} k k≢A k≢B = eq ... | no k∉ rewrite ∪-chooseₗ p₁ k∉ | ∪-chooseₗ s₁♯s₂ k∉ with s₁ ⁉ A | inspect (s₁ ⁉_) A | s ⁉ A | inspect (s ⁉_) A | eqᵃ ... | nothing | _ | nothing | _ | _ = eq ... | nothing | ≡[ s₁A≡ ] | just _ | ≡[ sA≡ ] | _ = let p = ↦-∪⁺ʳ {s₂ = s₂} $ ⁉⇒∉ᵈ (subst Is-nothing (sym s₁A≡) auto) in ⊥-elim $ A∉₂ $ ⁉⇒∈ᵈ $ subst Is-just (sym $ trans p (trans eqᵃ sA≡)) auto ... | just vᵃ | ≡[ s₁A≡ ] | nothing | _ | eqᵃ′ = case trans (sym $ (↦-∪⁺ˡ {s₂ = s₂} s₁A≡)) eqᵃ′ of λ () ... | just vᵃ | ≡[ s₁A≡ ] | just vᵃ′ | _ | eqᵃ′ with vᵃ ≟ vᵃ′ ... | no neq = ⊥-elim $ neq $ M.just-injective $ trans (sym $ ↦-∪⁺ˡ {s₂ = s₂} s₁A≡) eqᵃ′ ... | yes refl with s₁ ⁉ B | inspect (s₁ ⁉_) B | s ⁉ B | inspect (s ⁉_) B | eqᵇ ... | nothing | _ | nothing | _ | _ = eq ... | nothing | ≡[ s₁B≡ ] | just _ | ≡[ sB≡ ] | _ = let p = ↦-∪⁺ʳ {s₂ = s₂} $ ⁉⇒∉ᵈ (subst Is-nothing (sym s₁B≡) auto) in ⊥-elim $ B∉₂ $ ⁉⇒∈ᵈ $ subst Is-just (sym $ trans p (trans eqᵇ sB≡)) auto ... | just vᵇ | ≡[ s₁B≡ ] | nothing | _ | eqᵇ′ = case trans (sym $ (↦-∪⁺ˡ {s₂ = s₂} s₁B≡)) eqᵇ′ of λ () ... | just vᵇ | ≡[ s₁B≡ ] | just vᵇ′ | _ | eqᵇ′ with vᵇ ≟ vᵇ′ ... | no neq = ⊥-elim $ neq $ M.just-injective $ trans (sym $ ↦-∪⁺ˡ {s₂ = s₂} s₁B≡) eqᵇ′ ... | yes refl with v ≤? vᵃ ... | no _ = eq ... | yes _ = ≡-cong-update $ ≡-cong-update eq p′ : ⟨ run [ A ∣ v ↦ B ] s₁ ⊎ s₂ ⟩≡ run [ A ∣ v ↦ B ] s p′ = p₁ , p₂ -} -- The proof of the frame rule from separation logic, allowing us to prove formulas in minimal contexts -- and then weaken our results to the desired context (assuming the rest of the context is disjoint). [FRAME] : ∀ R → l ♯ R → ⟨ P ⟩ l ⟨ Q ⟩ ----------------------- → ⟨ P `∗ R ⟩ l ⟨ Q `∗ R ⟩ [FRAME] {l}{P}{Q} R l♯R PlQ = denot⇒axiom d where d : (P `∗ R) `⊢ (Q `∗ R) `∘⟦ l ⟧ d {s} (s₁ , s₂ , s₁♯s₂ , Ps₁ , Rs₂) = ⟦ l ⟧ s₁ , s₂ , p , Qs₁′ , Rs₂ where Qs₁′ : Q ∙ ⟦ l ⟧ s₁ Qs₁′ = axiom⇒denot PlQ Ps₁ p : ⟨ ⟦ l ⟧ s₁ ⊎ s₂ ⟩≡ ⟦ l ⟧ s p = frame-helper {R = R} l♯R Rs₂ s₁♯s₂ open HoareReasoning ℝ[FRAME] : ∀ R → l ♯ R → ⟨ P ⟩ l ⟨ Q ⟩ ----------------------- → ℝ⟨ P `∗ R ⟩ l ⟨ Q `∗ R ⟩ ℝ[FRAME] {l = l} R l♯R PlQ = mkℝ [FRAME] {l = l} R l♯R PlQ