We consider traces of the (global) step relation, defined as its reflexive-transitive closure, and use these to prove invariants as state predicates:
open import Prelude.Closures _—→_ public using ( begin_; _∎ ; _↞—_; _⟨_⟩←—_; _⟨_∣_⟩←—_; ↞—-trans ; _—↠_; —↠-trans; _—→⟨_⟩_; _—→⟨_∣_⟩_; _`—→⟨_⟩_; factor; factor⁺; Reachable-inj ; Reachable; Invariant; StepPreserved; Step⇒Invariant ; Trace; TraceProperty; TraceInvariant ; viewLeft; viewRight; viewLeft∘viewRight ; states⁺; states; states⁺-↞—; states-↞—; states⁺∘viewLeft ) renaming (_←—_ to _¹←—_) StateProperty = GlobalState → Type
Now, we can consider a specific local step occurring within a sequence of global transitions:
record Step : Type where constructor _⊢_ field stepArgs : _ × _ × _ × _ × _ theStep : let p , t , ls , menv , ls′ = stepArgs in p ⦂ t ⊢ ls — menv —→ ls′ ⦃ hp ⦄ : Honest (stepArgs .proj₁) open Step public hiding (hp) -- doStep : Step → Op₁ GlobalState -- doStep st s = let p , _ , _ , menv , ls′ = st .stepArgs in -- broadcast menv (s @ p ≔ ls′) LocalStepProperty = Step → Type allLocalSteps : (s′ ↞— s) → List Step allLocalSteps = λ where (_ ∎) → [] (_ ⟨ LocalStep st ⟩←— tr) → (_ ⊢ st) ∷ allLocalSteps tr (_ ⟨ _ ⟩←— tr) → allLocalSteps tr _∋⋯_ : Reachable s → LocalStepProperty → Type (_ , _ , tr) ∋⋯ P = Any P (allLocalSteps tr) record Segment (A B : Type) : Type where constructor from_to_ field _∙start _∙end : B → A open Segment ⦃...⦄ public instance Segment-↞ : Segment GlobalState (s′ ↞— s) Segment-↞ {s′}{s} = from (const s) to (const s′) Segment-→ : Segment LocalState (p ⦂ t ⊢ ls — menv —→ ls′) Segment-→ {ls = ls} {ls′ = ls′} = from (const ls) to (const ls′) Segment-Step : Segment LocalState Step Segment-Step = from (_∙start ∘ theStep) to (_∙end ∘ theStep)
extendRs : (Rs : Reachable s) → s′ ↞— s → Reachable s′ extendRs (_ , init , tr) tr′ = _ , init , ↞—-trans tr′ tr _▷_ : GlobalState → LocalStepProperty → Type s ▷ P = ∃ λ st → let p , t , ls , _ , _ = stepArgs st in t ≡ s .currentTime × s @ p ≡ ls × P st ▷-doStep : ∀ {P} → s ▷ P → GlobalState ▷-doStep {s = s} (st , _) = let p , t , _ , menv , ls′ = st .stepArgs in broadcast t menv (s @ p ≔ ls′) _◃_ : LocalStepProperty → GlobalState → Type P ◃ s′ = ∃ λ st → ∃ λ s → let p , t , ls , menv , ls′ = stepArgs st in t ≡ s .currentTime × s @ p ≡ ls × s′ ≡ broadcast t menv (s @ p ≔ ls′) × P st record TraceExtension (Rs : Reachable s) : Type where constructor ⟨_,_,_,_⟩ field intState : GlobalState reachable′ : Reachable intState extension : s ↞— intState traceAgree : Rs ≡ extendRs reachable′ extension open TraceExtension traceRs◃ : ∀ (Rs : Reachable s){P} → (trP : Rs ∋⋯ P) → ──────────────────────────────────────────────── Σ (TraceExtension Rs) (λ trE → P ◃ intState trE) traceRs◃ (_ , init , (s ⟨ Deliver tpm∈ ⟩←— tr)) trP with ⟨ s⟪ , Rs⟪ , tr⟪ , refl ⟩ , p ← traceRs◃ (_ , init , tr) trP = ⟨ s⟪ , Rs⟪ , (s ⟨ Deliver tpm∈ ⟩←— tr⟪) , refl ⟩ , p traceRs◃ Rs@(_ , init , tr@(s′ ⟨ LocalStep st ∣ s ⟩←— _)) (here px) = ⟨ s′ , Rs , s′ ∎ , refl ⟩ , ( _ ⊢ st) , s , refl , refl , refl , px traceRs◃ (_ , init , (s ⟨ LocalStep st ⟩←— tr)) (there trP) with ⟨ s⟪ , Rs⟪ , tr⟪ , refl ⟩ , p ← traceRs◃ (_ , init , tr) trP = ⟨ s⟪ , Rs⟪ , (s ⟨ LocalStep st ⟩←— tr⟪) , refl ⟩ , p traceRs◃ (_ , init , (s ⟨ DishonestLocalStep {env = env} ¬hp st ⟩←— tr)) trP with ⟨ s⟪ , Rs⟪ , tr⟪ , refl ⟩ , p ← traceRs◃ (_ , init , tr) trP = ⟨ s⟪ , Rs⟪ , (s ⟨ DishonestLocalStep {env = env} ¬hp st ⟩←— tr⟪) , refl ⟩ , p traceRs◃ (_ , init , (s ⟨ WaitUntil t <Δ now≤t ⟩←— tr)) trP with ⟨ s⟪ , Rs⟪ , tr⟪ , refl ⟩ , p ← traceRs◃ (_ , init , tr) trP = ⟨ s⟪ , Rs⟪ , (s ⟨ WaitUntil t <Δ now≤t ⟩←— tr⟪) , refl ⟩ , p traceRs▷ : ∀ (Rs : Reachable s){P} → (trP : Rs ∋⋯ P) → ──────────────────────────────────────────────── Σ (TraceExtension Rs) (λ trE → intState trE ▷ P) traceRs▷ (_ , init , (s ⟨ Deliver tpm∈ ⟩←— tr)) trP with ⟨ s⟪ , Rs⟪ , tr⟪ , refl ⟩ , p ← traceRs▷ (_ , init , tr) trP = ⟨ s⟪ , Rs⟪ , (s ⟨ Deliver tpm∈ ⟩←— tr⟪) , refl ⟩ , p traceRs▷ (_ , init , (s′ ⟨ LocalStep st ∣ s ⟩←— tr)) (here px) = ⟨ s , (_ , init , tr) , (s′ ⟨ LocalStep st ⟩←— s ∎) , refl ⟩ , ( _ ⊢ st) , refl , refl , px traceRs▷ (_ , init , (s ⟨ LocalStep st ⟩←— tr)) (there trP) with ⟨ s⟪ , Rs⟪ , tr⟪ , refl ⟩ , p ← traceRs▷ (_ , init , tr) trP = ⟨ s⟪ , Rs⟪ , (s ⟨ LocalStep st ⟩←— tr⟪) , refl ⟩ , p traceRs▷ (_ , init , (s ⟨ DishonestLocalStep {env = env} ¬hp st ⟩←— tr)) trP with ⟨ s⟪ , Rs⟪ , tr⟪ , refl ⟩ , p ← traceRs▷ (_ , init , tr) trP = ⟨ s⟪ , Rs⟪ , (s ⟨ DishonestLocalStep {env = env} ¬hp st ⟩←— tr⟪) , refl ⟩ , p traceRs▷ (_ , init , (s ⟨ WaitUntil t <Δ now≤t ⟩←— tr)) trP with ⟨ s⟪ , Rs⟪ , tr⟪ , refl ⟩ , p ← traceRs▷ (_ , init , tr) trP = ⟨ s⟪ , Rs⟪ , (s ⟨ WaitUntil t <Δ now≤t ⟩←— tr⟪) , refl ⟩ , p -- TODO: traceRs ⇒ non-empty extension (traceRs⁺) -- _≺_ : S → S → Type where -- ∼ non-reflexive transitive closure -- -- s′ ⁺↞— s -- ──────── -- s ≺ s′ -- eventually: ≺-rec (traceRs⁺ st-proposes) Rs′ ... ∃→ : Type ∃→ = ∃ λ s → ∃ λ s′ → s —→ s′ data IsLocal : ∃→ → Type where LocalStep : ∀ ⦃ _ : Honest p ⦄ {st : p ⦂ s .currentTime ⊢ s @ p — menv —→ ls′} → IsLocal (s , -, LocalStep st) record _ᴸ←—_ (s′ s : GlobalState) : Type where constructor _⊣ᴸ_ field {_p _menv _ls′} : _ ⦃ hp ⦄ : Honest _p _ls = s @ _p field localStep : _p ⦂ s .currentTime ⊢ _ls — _menv —→ _ls′ s≡ : s′ ≡ broadcast (s .currentTime) _menv (s @ _p ≔ _ls′) open _ᴸ←—_ instance Dec-IsLocal : IsLocal ⁇¹ Dec-IsLocal {_ , _ , st} .dec with st ... | LocalStep _ = yes LocalStep ... | DishonestLocalStep _ _ = no λ () ... | Deliver _ = no λ () ... | WaitUntil _ _ _ = no λ () Local→Global : s′ ᴸ←— s → s′ ¹←— s Local→Global st = subst (_¹←— _) (sym $ st .s≡) $ LocalStep (st . localStep) Local→Global⇒IsLocal : ∀ {st : s′ ᴸ←— s} → IsLocal (-, -, Local→Global st) Local→Global⇒IsLocal {st = _ ⊣ᴸ refl} = LocalStep record ∃IsLocal : Type where constructor _,_ field stl : ∃→ .loc : IsLocal stl ∃IsLocal≡ : ∀ {r r′} → r .∃IsLocal.stl ≡ r′ .∃IsLocal.stl ────────────────── r ≡ r′ ∃IsLocal≡ refl = refl module _ (r : ∃IsLocal) (let stl , loc = r) where getLoc : IsLocal stl getLoc = recompute dec loc getP : Pid getP with stl | getLoc ... | _ , _ , LocalStep {p = p} _ | LocalStep = p getM : Maybe Envelope getM with stl | getLoc ... | _ , _ , LocalStep {menv = menv} _ | LocalStep = menv getL : LocalState getL with stl | getLoc ... | _ , _ , LocalStep {ls′ = ls′} _ | LocalStep = ls′ getP≡ : ∀ (st : s′ ᴸ←— s) → getP ((-, -, Local→Global st) , Local→Global⇒IsLocal) ≡ st ._p getP≡ (_ ⊣ᴸ refl) = refl getM≡ : ∀ (st : s′ ᴸ←— s) → getM ((-, -, Local→Global st) , Local→Global⇒IsLocal) ≡ st ._menv getM≡ (_ ⊣ᴸ refl) = refl getL≡ : ∀ (st : s′ ᴸ←— s) → getL ((-, -, Local→Global st) , Local→Global⇒IsLocal) ≡ st ._ls′ getL≡ (_ ⊣ᴸ refl) = refl Local→Global-inj : ∀ (st st′ : s′ ᴸ←— s) → Local→Global st ≡ Local→Global st′ ────────────────────────────────── st ≡ st′ Local→Global-inj {s′}{s} st@(_ ⊣ᴸ s≡) st′@(_ ⊣ᴸ s≡′) st≡ = QED where ∃st ∃st′ : ∃→ ∃st = -, -, Local→Global st ∃st′ = -, -, Local→Global st′ ∃st≡ : ∃st ≡ ∃st′ ∃st≡ = cong (λ ◆ → s , s′ , ◆) st≡ ∃stl ∃stl′ : ∃IsLocal ∃stl = ∃st , Local→Global⇒IsLocal ∃stl′ = ∃st′ , Local→Global⇒IsLocal ∃stl≡ : ∃stl ≡ ∃stl′ ∃stl≡ = ∃IsLocal≡ ∃st≡ p≡ : st ._p ≡ st′ ._p p≡ = subst (_≡ _) (getP≡ st) $ subst (_ ≡_) (getP≡ st′) $ cong getP ∃stl≡ m≡ : st ._menv ≡ st′ ._menv m≡ = subst (_≡ _) (getM≡ st) $ subst (_ ≡_) (getM≡ st′) $ cong getM ∃stl≡ l≡ : st ._ls′ ≡ st′ ._ls′ l≡ = subst (_≡ _) (getL≡ st) $ subst (_ ≡_) (getL≡ st′) $ cong getL ∃stl≡ QED : st ≡ st′ QED with st ._p ≟ st′ ._p ... | no p≢ = ⊥-elim $ p≢ p≡ ... | yes refl with st ._menv ≟ st′ ._menv ... | no m≢ = ⊥-elim $ m≢ m≡ ... | yes refl with st ._ls′ ≟ st′ ._ls′ ... | no l≢ = ⊥-elim $ l≢ l≡ ... | yes refl with ⟫ s≡ | ⟫ s≡′ | ⟫ st≡ ... | ⟫ refl | ⟫ refl | ⟫ refl = refl _⟨_⟩←—ᴿ_ : ∀ s′ → s′ ¹←— s → Reachable s → Reachable s′ _ ⟨ st ⟩←—ᴿ (_ , s-init , tr) = (_ , s-init , (_ ⟨ st ⟩←— tr)) record TraceExtension⁺ {z} (Rz : Reachable z) : Type where constructor ⟨_,_,_,_⟩ field {x y} : GlobalState Rx : Reachable x y←x : y ᴸ←— x z↞y : z ↞— y y¹←x : y ¹←— x y¹←x = Local→Global y←x z↞x : z ↞— x z↞x = _ `—→⟨ y¹←x ⟩ z↞y Ry : Reachable y Ry = _ ⟨ y¹←x ⟩←—ᴿ Rx field Rz≡ : Rz ≡ extendRs Ry z↞y -- Rz≡ : Rz ≡ extendRs Rx z↞x step : Step step = _ ⊢ y←x ._ᴸ←—_.localStep open TraceExtension⁺ private UIP : (p q : s ≡ s′) → p ≡ q UIP refl refl = refl open Prod hiding (,-injectiveʳ) step≡-TE⁺ : ∀ {s} (Rs : Reachable s) (trE trE′ : TraceExtension⁺ Rs) → _≡_ {A = ∃ λ x → ∃ λ y → y ¹←— x} (-, -, y¹←x trE) (-, -, y¹←x trE′) ──────────────────────────────────────────────────────────────────── step trE ≡ step trE′ step≡-TE⁺ Rs trE trE′ eq with refl ← ,-injectiveˡ eq with refl ← ,-injectiveˡ $ ,-injectiveʳ-≡ UIP eq refl with eq′ ← ,-injectiveʳ-≡ UIP (,-injectiveʳ-≡ UIP eq refl) refl with refl ← Local→Global-inj _ _ eq′ = refl traceRs⁺ : ∀ (Rs : Reachable s) {P} → (trP : Rs ∋⋯ P) → ──────────────────────────────── Σ (TraceExtension⁺ Rs) (P ∘ TraceExtension⁺.step) traceRs⁺ (_ , init , (s ⟨ Deliver tpm∈ ⟩←— tr)) trP with ⟨ s , Rs , tr , refl ⟩ , P ← traceRs⁺ (_ , init , tr) trP = ⟨ s , Rs , (_ ⟨ Deliver tpm∈ ⟩←— tr) , refl ⟩ , P traceRs⁺ (_ , init , (s′ ⟨ LocalStep st ∣ s ⟩←— tr)) (here px) = ⟨ (_ , init , tr) , (st ⊣ᴸ refl) , (s′ ∎) , refl ⟩ , px traceRs⁺ (_ , init , (_ ⟨ LocalStep st ⟩←— tr)) (there trP) with ⟨ s , Rs , tr , refl ⟩ , P ← traceRs⁺ (_ , init , tr) trP = ⟨ s , Rs , (_ ⟨ LocalStep st ⟩←— tr) , refl ⟩ , P traceRs⁺ (_ , init , (_ ⟨ DishonestLocalStep {env = env} ¬hp st ⟩←— tr)) trP with ⟨ s , Rs , tr , refl ⟩ , P ← traceRs⁺ (_ , init , tr) trP = ⟨ s , Rs , (_ ⟨ DishonestLocalStep {env = env} ¬hp st ⟩←— tr) , refl ⟩ , P traceRs⁺ (_ , init , (_ ⟨ WaitUntil t <Δ now≤t ⟩←— tr)) trP with ⟨ s , Rs , tr , refl ⟩ , P ← traceRs⁺ (_ , init , tr) trP = ⟨ s , Rs , (_ ⟨ WaitUntil t <Δ now≤t ⟩←— tr) , refl ⟩ , P {- TraceExtension⁺⁻ : ∀ {Rs : Reachable s} → TraceExtension⁺ Rs → TraceExtension Rs TraceExtension⁺⁻ tr@(⟨ Rs , st , sts , refl ⟩) = ⟨ tr .x , Rs , _ `—→⟨ Local→Global st ⟩ sts , refl ⟩ TraceExtension⁺⁻⁺ : ∀ {Rs : Reachable s} → TraceExtension⁺ Rs → TraceExtension Rs TraceExtension⁺⁻⁺ tr@(⟨ Rs , st@(_ ⊣ᴸ eq) , sts , refl ⟩) = ⟨ tr .y , _ ⟨ Local→Global st ⟩←—ᴿ Rs , sts , {!refl!} ⟩ -} factorRs : ∀ (Rs : Reachable s) (trE₁ trE₂ : TraceExtension Rs) → ───────────────────────────────────── let s₁ = trE₁ .intState s₂ = trE₂ .intState in (s₁ ↞— s₂) ⊎ (s₂ ↞— s₁) factorRs Rs ⟨ s₁ , (_ , _ , tr₁) , ext₁ , refl ⟩ ⟨ s₂ , (_ , _ , tr₂) , ext₂ , eq₂ ⟩ with refl ← cong proj₁ eq₂ = factor tr₁ ext₁ tr₂ ext₂ (Reachable-inj eq₂) open import Data.Product.Properties.WithK using (,-injectiveʳ) factorRs⁺ : ∀ (Rs : Reachable s) → let open TraceExtension⁺ in (tr tr′ : TraceExtension⁺ Rs) → ──────────────────────────── (step tr ≡ step tr′) ⊎ (tr′ .x ↞— tr .y) ⊎ (tr .x ↞— tr′ .y) factorRs⁺ Rs trE@(⟨ (_ , init , tr) , (st ⊣ᴸ refl) , st∗ , refl ⟩) trE′@(⟨ (_ , _ , tr′) , (st′ ⊣ᴸ refl) , st∗′ , eq₃ ⟩) with refl ← cong proj₁ eq₃ with refl ← cong proj₁ $ ,-injectiveʳ eq₃ with eq ← ,-injectiveʳ $ ,-injectiveʳ eq₃ with factor⁺ tr (y¹←x trE) st∗ tr′ (y¹←x trE′) st∗′ (Reachable-inj $ cong (_ ,_) $ cong (init ,_) eq) ... | inj₁ st≡ = inj₁ $ step≡-TE⁺ Rs trE trE′ st≡ ... | inj₂ (inj₁ P) = inj₂ $ inj₂ P ... | inj₂ (inj₂ P) = inj₂ $ inj₁ P