Source code on Github
open import Prelude.Init; open SetAsType
open import Prelude.General
open import Prelude.DecEq
open import Prelude.Decidable
open import Prelude.Ord
open import Prelude.Maps.Abstract; open CommandDSL
open import Prelude.Apartness
open import Prelude.Setoid
open import Prelude.Semigroup
open import Prelude.Monoid
module ShallowHoare.Ledger
(Part : Type)
⦃ _ : DecEq Part ⦄
where
variable
A B C D : Part
v v′ v″ : ℕ
instance _ = Semigroup-ℕ-+; _ = SemigroupLaws-ℕ-+; _ = Monoid-ℕ-+; _ = MonoidLaws-ℕ-+
S : Type
S = Map⟨ Part ↦ ℕ ⟩
record Tx : Type where
constructor _—→⟨_⟩_
field
sender : Part
value : ℕ
receiver : Part
open Tx public
L = List Tx
variable
s s′ s″ s₁ s₂ : S
t t′ t″ : Tx
l l′ l″ l₁ l₂ : L
ls ls′ ls″ : L × S
Domain = S → S
record Denotable (A : Type) : Type where
field
⟦_⟧ : A → Domain
open Denotable ⦃...⦄ public
[_∣_↦_] : Part → ℕ → Part → Cmd
[ A ∣ v ↦ B ] =
just? A λ vᵃ →
just? B λ vᵇ →
iff¿ v ≤ vᵃ ¿
((A ≔ vᵃ ∸ v) ∶ (B ≔ vᵇ + v))
instance
⟦Tx⟧ : Denotable Tx
⟦Tx⟧ .⟦_⟧ (A —→⟨ v ⟩ B) = run [ A ∣ v ↦ B ]
⟦L⟧ : Denotable L
⟦L⟧ .⟦_⟧ [] s = s
⟦L⟧ .⟦_⟧ (t ∷ l) = ⟦ l ⟧ ∘ ⟦ t ⟧
comp : ∀ x → ⟦ l ++ l′ ⟧ x ≡ (⟦ l′ ⟧ ∘ ⟦ l ⟧) x
comp {l = []} {l′} x = refl
comp {l = t ∷ l} {l′} x rewrite comp {l}{l′} (⟦ t ⟧ x) = refl
⟦⟧ₗ-mono : KeyMonotonic ⟦ l ⟧
⟦⟧ₗ-mono {[]} _ = id
⟦⟧ₗ-mono {t ∷ l} s = ⟦⟧ₗ-mono {l = l} (⟦ t ⟧ s)
∘ cmd-mon [ sender t ∣ value t ↦ receiver t ] s
[∣↦]-pre : KeyPreserving ⟦ t ⟧
[∣↦]-pre {t = A —→⟨ v ⟩ B} s {k} k∈
with s ⁉ A | ⁉⇒∈ᵈ s {A}
... | nothing | _ = k∈
... | just vᵃ | A∈
with s ⁉ B | ⁉⇒∈ᵈ s {B}
... | nothing | _ = k∈
... | just vᵇ | B∈
with v ≤? vᵃ
... | no _ = k∈
... | yes _
with ∈ᵈ-∪⁻ _ _ _ k∈
... | inj₁ k∈ˡ rewrite singleton∈ k∈ˡ = B∈ auto
... | inj₂ k∈ʳ
with ∈ᵈ-∪⁻ _ _ _ k∈ʳ
... | inj₁ k∈ˡ rewrite singleton∈ k∈ˡ = A∈ auto
... | inj₂ k∈ʳ′ = k∈ʳ′
∉-⟦⟧ₜ : A ∉ᵈ s → A ∉ᵈ ⟦ t ⟧ s
∉-⟦⟧ₜ A∉s = ⊥-elim ∘ A∉s ∘ [∣↦]-pre _
∉-⟦⟧ₗ : A ∉ᵈ s → A ∉ᵈ ⟦ l ⟧ s
∉-⟦⟧ₗ {A}{s}{[]} A∉ = A∉
∉-⟦⟧ₗ {A}{s}{t ∷ l} A∉ = ∉-⟦⟧ₗ {l = l} (∉-⟦⟧ₜ {s = s}{t = t} A∉)
∉-splits : ⟨ s₁ ⊎ s₂ ⟩≡ s → A ∉ᵈ s₁ → A ∉ᵈ s₂ → A ∉ᵈ s
∉-splits {s₁ = s₁}{s₂}{s}{A} (s₁♯s₂ , p) A∉₁ A∉₂ A∈
with ∈ᵈ-∪⁻ _ _ _ (∈ᵈ-cong _ _ _ (≈-sym p) A∈)
... | inj₁ A∈₁ = ⊥-elim $ A∉₁ A∈₁
... | inj₂ A∈₂ = ⊥-elim $ A∉₂ A∈₂
transfer-helper : s₁ ♯ s₂ → B ∉ᵈ s₂ → (run [ A ∣ v ↦ B ] s₁) ♯ s₂
transfer-helper {s₁ = s₁}{s₂}{B}{A}{v} s₁♯s₂ B∉ = ♯-cong-pre _ _ _ [∣↦]-pre s₁♯s₂
drop-[∣↦] : ∀ k → k ≢ A → k ≢ B → (run [ A ∣ v ↦ B ] s) ⁉ k ≡ s ⁉ k
drop-[∣↦] {A}{B}{v}{s} k k≢A k≢B
with s ⁉ A | inspect (s ⁉_) A
... | nothing | _ = refl
... | just vᵃ | ≡[ sᵃ ]
with s ⁉ B | inspect (s ⁉_) B
... | nothing | _ = refl
... | just vᵇ | ≡[ sᵇ ]
with v ≤? vᵃ
... | no _ = refl
... | yes _
with k ≟ A
... | yes eq = ⊥-elim $ k≢A eq
... | no _ with k ≟ B
... | yes eq = ⊥-elim $ k≢B eq
... | no _ = trans (singleton-reject k≢B) (singleton-reject k≢A)
transfer : ∀ {A B v v′}
→ A ≢ B
→ run [ A ∣ v ↦ B ] (singleton (A , v) ∪ singleton (B , v′))
≈ (singleton (A , 0) ∪ singleton (B , v′ + v))
transfer {A}{B}{v}{v′} A≢B =
let
m = singleton (A , v) ∪ singleton (B , v′)
in
begin
run [ A ∣ v ↦ B ] m
≡⟨⟩
run (just? A λ vᵃ → just? B λ vᵇ → iff¿ v ≤ vᵃ ¿ ((A ≔ vᵃ ∸ v) ∶ (B ≔ vᵇ + v))) m
≈⟨ just?-accept (↦-∪⁺ˡ _ _ singleton-law′) ⟩
run (just? B λ vᵇ → iff¿ v ≤ v ¿ ((A ≔ v ∸ v) ∶ (B ≔ vᵇ + v))) m
≈⟨ just?-accept (↦-∪⁺ʳ′ (⊥-elim ∘ A≢B ∘ sym ∘ singleton∈) singleton-law′) ⟩
run (iff¿ v ≤ v ¿ ((A ≔ v ∸ v) ∶ (B ≔ v′ + v))) m
≈⟨ iff-accept {b = v ≤? v} (fromWitness Nat.≤-refl) ⟩
run ((A ≔ v ∸ v) ∶ (B ≔ v′ + v)) m
≈⟨ ≈-cong-cmd (B ≔ v′ + v) update-update ⟩
run (B ≔ (v′ + v)) (singleton (A , v ∸ v) ∪ singleton (B , v′))
≈⟨ ≈-cong-cmd (B ≔ v′ + v) (∪-comm _ _ $ singleton♯ A≢B) ⟩
run (B ≔ (v′ + v)) (singleton (B , v′) ∪ singleton (A , v ∸ v))
≈⟨ update-update ⟩
singleton (B , v′ + v) ∪ singleton (A , v ∸ v)
≈⟨ ∪-comm _ _ $ singleton♯ (≢-sym A≢B) ⟩
singleton (A , v ∸ v) ∪ singleton (B , v′ + v)
≡⟨ cong (λ x → (singleton (A , x) ∪ singleton (B , v′ + v))) (Nat.n∸n≡0 v) ⟩
singleton (A , 0) ∪ singleton (B , v′ + v)
∎ where
open ≈-Reasoning
infix 0 _—→_ _—→⋆_ _—→⋆′_
data _—→_ : L × S → L × S → Type where
singleStep :
t ∷ l , s —→ l , ⟦ t ⟧ s
data _—→⋆_ : L × S → L × S → Type where
base :
ls —→⋆ ls
step :
ls —→ ls′
→ ls′ —→⋆ ls″
→ ls —→⋆ ls″
_—→⋆′_ : L × S → S → Type
ls —→⋆′ s = ls —→⋆ ([] , s)
comp′ :
l , s —→⋆′ s′
→ l′ , s′ —→⋆′ s″
→ l ++ l′ , s —→⋆′ s″
comp′ {l = []} base s′→s″ = s′→s″
comp′ {l = _ ∷ _} (step singleStep s→s′) s′→s″ = step singleStep (comp′ s→s′ s′→s″)
oper-base⋆ : l , s —→⋆′ ⟦ l ⟧ s
oper-base⋆ {l = []} = base
oper-base⋆ {l = _ ∷ _} = step singleStep oper-base⋆
denot⇒oper : (⟦ l ⟧ s ≡ s′) → (l , s —→⋆′ s′)
denot⇒oper {l = []} refl = base
denot⇒oper {l = _ ∷ _} refl = step singleStep (denot⇒oper refl)
oper⇒denot : (l , s —→⋆′ s′) → (⟦ l ⟧ s ≡ s′)
oper⇒denot {l = .[]} base = refl
oper⇒denot {l = _ ∷ _} (step singleStep p) = oper⇒denot p
denot⇔oper : (⟦ l ⟧ s ≡ s′) ⇔ (l , s —→⋆′ s′)
denot⇔oper = denot⇒oper , oper⇒denot