{-# OPTIONS --safe #-}
open import Prelude
open import Hash
open import Jolteon.Assumptions

module Jolteon.Properties.Safety.Lemma1 (⋯ : _) (open Assumptions ⋯) where

open import Jolteon ⋯
open import Jolteon.Properties.Core ⋯
open import Jolteon.Properties.State ⋯
open import Jolteon.Properties.Votes ⋯
open import Jolteon.Properties.Steps ⋯

open import Jolteon.Properties.Safety.Core ⋯

private
  GlobalDirectCommit-broadcast : let t = s .currentTime in
    GloballyDirectCommitted s b
    ──────────────────────────────────────────────
    GloballyDirectCommitted (broadcast t menv s) b
  GlobalDirectCommit-broadcast {s}{b}{me} (B′ , r≡ , ←B , maj) =
    B′ , r≡ , ←B , maj′
    where
    maj′ :  MoreThanF-Honest B′ (broadcast (s .currentTime) me s)
    maj′ with ⟫ me
    ... | ⟫ nothing = maj
    ... | ⟫ just e  = honest-≤ (honestVotes-mono (s . history) (e ∙message)) maj

-- Lemma 1
Commit⇒GlobalDirectCommit : ∀ {s} (Rs : Reachable s) →
  -- If an honest replica successfully performs the Commit step on block B...
  Rs ∋⋯ StepCommits b
  ───────────────────────────
  -- ...then B is globally direct-committed.
  GloballyDirectCommitted s b
Commit⇒GlobalDirectCommit
  (_ , init , (_ ⟨ WaitUntil _ _ _ ⟩←— tr)) ∃step
  = Commit⇒GlobalDirectCommit (_ , init , tr) ∃step
Commit⇒GlobalDirectCommit
  (_ , init , (_ ⟨ Deliver _ ⟩←— tr)) ∃step
  = Commit⇒GlobalDirectCommit (_ , init , tr) ∃step
Commit⇒GlobalDirectCommit
  (_ , init , (_ ⟨ DishonestLocalStep {env = env} _ _ ∣ s ⟩←— tr)) ∃step
  = GlobalDirectCommit-broadcast {s = s} {menv = just env}
  $ Commit⇒GlobalDirectCommit (_ , init , tr) ∃step
Commit⇒GlobalDirectCommit {b}
  (_ , init , (_ ⟨ LocalStep {p = p} {menv = me} {ls′ = ls′} _ ⟩←— tr))
  (there ∃step)
  = GlobalDirectCommit-broadcast {s = (tr ∙end) @ p ≔ ls′} {b = b} {menv = me}
  $ Commit⇒GlobalDirectCommit {b = b} {s = _} (_ , init , tr) ∃step
Commit⇒GlobalDirectCommit
  ( s₀
  , s-init
  -- By the Commit condition...
  , (_ ⟨ LocalStep (Commit _
  -- ...there exists a chain B ←— QCᴮ ←— B′ ←— QCᴮ′ with B′.r = B.r + 1.
      ( final∈ {b = b} {b′ = b′} _ cb∈′
               (_ ∷ (_ ∷ _ ⊣ connects∶ b′←b″ᵢ b′←b″ᵣ _) ⊣ connects∶ b←b′ᵢ b←b′ᵣ _)
               r≡
      , _
      )) ∣ s ⟩←— tr))
  (here refl)
  = QED
  where
  -- cb∈′ : b′ -certified-∈- (s @ p) .db
  -- b←b′ : b′ -connects-to- b ∷ ch
  -- r≡   : b ∙round ≡ 1 + b′ ∙round
  Rs = s₀ , s-init , tr

  -- The existence of QCᴮ′ implies that f+1 honest replicas did vote for B′.
  maj : MoreThanF-Honest b′ s
  maj with ⟫ certified {qc = qcᵇ′} qcᵇ′∈ cb′ᵢ cb′ᵣ  ← ⟫ cb∈′
    = GCB⇒MoreThanF Rs (qcᵇ′ , (cb′ᵢ , cb′ᵣ) , qc-db⊆history Rs qcᵇ′∈)

  QED : GloballyDirectCommitted s b
  QED = b′ , r≡ , (b←b′ᵢ , b←b′ᵣ) , maj