{-# OPTIONS --safe #-}
open import Prelude
open import Hash
open import Jolteon.Assumptions
module Jolteon.Properties.Steps.Timeouts (⋯ : _) (open Assumptions ⋯) where
open import Jolteon ⋯
open import Jolteon.Global.NoForging ⋯
open import Jolteon.Properties.State ⋯
open import Jolteon.Properties.Steps.Core ⋯
open import Jolteon.Properties.Steps.RCur ⋯
mutual
telast∈ᴹ⇒te∈ : ∀ {s} → Reachable s → ⦃ _ : Honest p ⦄ ⦃ _ : Honest p′ ⦄ →
∙ te .node ≡ p
∙ (s @ p′) .tc-last ≡ just tc
∙ (RQ ∶ te -∈-TC- tc)
───────────────────────────
te ∙∈ s .history
telast∈ᴹ⇒te∈ {p}{p′}{te}{tc}{s} Rs te≡ tc≡ te∈
= te∈ᴹ⇒te∈ Rs te≡ te∈′
where
tc∈ : tc ∙∈ s .history
tc∈ = M.All.drop-just $ subst (All _) tc≡ $ tc-last∈history Rs
te∈′ : Any (RQ ∶ te -∈ᴹ-_) (s .history)
te∈′
with tc∈
... | receivedTC tc∈ = L.Any.map tc∈m⇒te∈m tc∈
where
tc∈m⇒te∈m : ∀ {m} → tc tc∈-Message m → te -∈ᴹ- m
tc∈m⇒te∈m = λ where
(tc∈-Propose refl) → ∈-Propose-TC (just te∈)
(tc∈-TCFormed) → ∈-TCFormed te∈
(tc∈-Timeout refl) → ∈-Timeout-TC (just te∈)
... | formedTC ftc
with ⟫ ∈-TC te∈ ← ⟫ te∈
with te∈ ← te ∈ tc .tes
∋ L.Any.map (λ where ∈-TE → refl) te∈
with mtc , tc∈ ← te -te-∈- s .history
∋ L.All.lookup ftc te∈
= L.Any.map (λ where refl → ∈-Timeout-TE ∈-TE) tc∈
te∈ᴹ⇒te∈ : ∀ {s} → Reachable s → ⦃ Honest p ⦄ →
∙ te .node ≡ p
∙ Any (RQ ∶ te -∈ᴹ-_) (s .history)
────────────────────────────────
te ∙∈ s .history
te∈ᴹ⇒te∈ (_ , refl , (_ ∎)) ⦃ hp ⦄ _ ()
te∈ᴹ⇒te∈ {p}{te} (_ , s-init , (_ ⟨ st ∣ s ⟩←— tr)) ⦃ hp ⦄ te≡ te∈
with Rs ← _ , s-init , tr
with IH ← te∈ᴹ⇒te∈ {p}{te} Rs te≡
with IHₗ ← (λ {p′} ⦃ _ : Honest p′ ⦄ {tc} → telast∈ᴹ⇒te∈ {p}{p′}{te}{tc} Rs te≡)
with st
... | WaitUntil _ _ _ = IH te∈
... | Deliver _ = IH te∈
... | DishonestLocalStep {env = env} {p = p′} ¬hp′ ¬frg
= te∈-monotonic QED
where
QED : te ∙∈ s .history
QED with ⟫ te∈
... | ⟫ there te∈ = IH te∈
... | ⟫ here te∈M = IH $ ¬frg te te∈M (subst Honest (sym te≡) hp)
... | LocalStep {p = p} {ls′ = ls′} st
with st
... | InitTC {tc = tc′} _ tc≡ = te∈-monotonic QED
where
QED : te ∙∈ s .history
QED with ⟫ te∈
... | ⟫ there te∈ = IH te∈
... | ⟫ here (∈-TCFormed (∈-TC te∈tc′)) = telast∈ᴹ⇒te∈ Rs te≡ tc≡ (∈-TC te∈tc′)
... | InitNoTC _ _ = IH te∈
... | ProposeBlock {txn = txn} _ _ = te∈-monotonic QED
where
QED : te ∙∈ s .history
QED with ⟫ te∈
... | ⟫ there te∈ = IH te∈
... | ⟫ here (∈-Propose-TC te∈tc) =
let tc , tc≡ = destruct-Is-just $ Any⇒Is-just te∈tc
in telast∈ᴹ⇒te∈ Rs te≡ tc≡ (Any-just tc≡ te∈tc)
... | ProposeBlockNoOp _ _ = IH te∈
... | EnoughTimeouts _ _ _ _ = QED
where
_ls = s @ p
_m = Timeout $ signData p (_ls .r-cur , _ls .qc-high) , _ls .tc-last
QED : te ∙∈ (_m ∷ s .history)
QED with ⟫ te∈
... | ⟫ there te∈ = te∈-monotonic $ IH te∈
... | ⟫ here (∈-Timeout-TE ∈-TE) = -, here refl
... | ⟫ here (∈-Timeout-TC te∈tc) = te∈-monotonic QED′
where
QED′ : te ∙∈ s .history
QED′ = let tc , tc≡ = destruct-Is-just $ Any⇒Is-just te∈tc
in telast∈ᴹ⇒te∈ Rs te≡ tc≡ (Any-just tc≡ te∈tc)
... | TimerExpired _ _ = QED
where
QED : te ∙∈ (_ ∷ s .history)
QED with ⟫ te∈
... | ⟫ there te∈ = te∈-monotonic $ IH te∈
... | ⟫ here (∈-Timeout-TE ∈-TE) = -, here refl
... | ⟫ here (∈-Timeout-TC te∈tc) = te∈-monotonic QED′
where
QED′ : te ∙∈ s .history
QED′ = let tc , tc≡ = destruct-Is-just $ Any⇒Is-just te∈tc
in telast∈ᴹ⇒te∈ Rs te≡ tc≡ (Any-just tc≡ te∈tc)
... | AdvanceRoundQC _ _ _ = IH te∈
... | AdvanceRoundTC _ _ _ = IH te∈
... | AdvanceRoundNoOp _ _ _ = IH te∈
... | Lock _ _ = IH te∈
... | Commit _ _ = IH te∈
... | CommitNoOp _ _ = IH te∈
... | VoteBlock {b = b} _ _ _ = te∈-monotonic QED
where
QED : te ∙∈ s .history
QED with ⟫ there te∈ ← ⟫ te∈ = IH te∈
... | VoteBlockNoOp _ _ = IH te∈
... | RegisterProposal _ _ _ _ _ = IH te∈
... | RegisterTimeout _ _ _ _ = IH te∈
... | RegisterTC _ _ _ _ = IH te∈
... | RegisterVote _ _ _ _ _ _ = IH te∈
MessageTimeout⇒StepTimeout : ∀ {te r} ⦃ _ : Honest p ⦄ →
(st : p ⦂ s .currentTime ⊢ ls — menv —→ ls′) →
∙ (∃ λ mtc → just [ r ?∣ Timeout (te , mtc) ⟩ ≡ menv)
─────────────────────────────────────────────────────
StepTimeout p te (_ ⊢ st)
MessageTimeout⇒StepTimeout (EnoughTimeouts _ _ _ _) (_ , refl) = refl , refl
MessageTimeout⇒StepTimeout (TimerExpired _ _) (_ , refl) = refl , refl
TimeoutMsg⇒TimeoutStep : ∀ {s} (Rs : Reachable s) ⦃ _ : Honest p ⦄ →
∙ te .node ≡ p
∙ te ∙∈ s .history
───────────────────────────────
Rs ∋⋯ StepTimeout p te
TimeoutMsg⇒TimeoutStep (_ , refl , (_ ∎)) te≡ (_ , ())
TimeoutMsg⇒TimeoutStep (_ , init , (_ ⟨ WaitUntil _ _ _ ⟩←— tr)) te≡ tm∈ =
TimeoutMsg⇒TimeoutStep (_ , init , tr) te≡ tm∈
TimeoutMsg⇒TimeoutStep (_ , init , (_ ⟨ Deliver _ ⟩←— tr)) te≡ tm∈ =
TimeoutMsg⇒TimeoutStep (_ , init , tr) te≡ tm∈
TimeoutMsg⇒TimeoutStep {p = p} {te = te}
(_ , init , (_ ⟨ DishonestLocalStep {env = env} {p = p′} ¬hp′ ¬frg ∣ s ⟩←— tr))
⦃ hp ⦄ te≡ tm∈
= TimeoutMsg⇒TimeoutStep (_ , init , tr) te≡ ≪tm∈
where
≪tm∈ : te ∙∈ s .history
≪tm∈ with ⟫ tm∈
... | ⟫ _ , there tm∈ = -, tm∈
... | ⟫ mtc , here refl = QED
where
M = Timeout (te , mtc)
te∈m : te -∈ᴹ- M
te∈m = ∈-Timeout-TE ∈-TE
te∈ : Any (te -∈ᴹ-_) (s .history)
te∈ = ¬frg te te∈m (subst Honest (sym te≡) hp)
QED : te ∙∈ s .history
QED = te∈ᴹ⇒te∈ (_ , init , tr) te≡ te∈
TimeoutMsg⇒TimeoutStep {p = p}{te = te}
(_ , init , (s′ ⟨ LocalStep {p = p′} {menv = menv}{ls′} st ∣ s ⟩←— tr))
⦃ hp ⦄ te≡ (mtc , tm∈)
with IH ← TimeoutMsg⇒TimeoutStep {p = p}{te = te} (_ , init , tr) te≡
with p ≟ p′
... | no p≢ = there $ IH m∈history
where
m∈history : te ∙∈ s .history
m∈history with ⟫ menv
... | ⟫ nothing = -, tm∈
... | ⟫ just env = -, flip L.Any.tail tm∈ (λ where
refl → p≢ $ trans (sym te≡)
(M.All.drop-just $ M.All.drop-just $ ownMessage {s = s} st))
... | yes refl
with StepTimeout? p te ((_ ⊢ st) ⦃ hp ⦄)
... | yes stT = here stT
... | no ¬stT with menv
... | nothing = there $ IH (-, tm∈)
... | just env = there $ IH $ -, L.Any.tail (λ where
refl → ¬stT $ MessageTimeout⇒StepTimeout {s = s} ⦃ hp ⦄ st (-, refl)) tm∈
mutual
tclast∈m⇒te∈ : ∀ {s} → Reachable s → ⦃ _ : Honest p ⦄ ⦃ _ : Honest p′ ⦄ →
∙ te .node ≡ p
∙ te ∈ tc .tes
∙ (s @ p′) .tc-last ≡ just tc
───────────────────────────
te ∙∈ s .history
tclast∈m⇒te∈ {tc = tc} {s = s} Rs te≡ te∈ tc≡ =
tc∈⇒te∈ Rs te≡ te∈ tc∈
where
tc∈ : tc ∙∈ s .history
tc∈ = M.All.drop-just $ subst (All _) tc≡ $ tc-last∈history Rs
tc∈m⇒te∈ : ∀ {s} → Reachable s → ⦃ Honest p ⦄ →
∙ te .node ≡ p
∙ te ∈ tc .tes
∙ Any (tc tc∈-Message_) (s .history)
──────────────────────────────────
te ∙∈ s .history
tc∈m⇒te∈ {p}{te}{tc} (_ , refl , (_ ∎)) _ _ ()
tc∈m⇒te∈ {p}{te}{tc} (_ , s-init , (_ ⟨ st ∣ s ⟩←— tr)) ⦃ hp ⦄ te≡@refl te∈ tc∈
with Rs ← _ , s-init , tr
with IH ← tc∈m⇒te∈ {p}{te}{tc} Rs te≡ te∈
with IHₗ ← (λ {p′} ⦃ _ : Honest p′ ⦄ → tclast∈m⇒te∈ {p}{p′}{te}{tc} Rs te≡ te∈)
with st
... | WaitUntil _ _ _ = IH tc∈
... | Deliver _ = IH tc∈
... | DishonestLocalStep {env = env} {p = p′} ¬hp′ ¬frg
= te∈-monotonic QED
where
QED : te ∙∈ s .history
QED with ⟫ tc∈
... | ⟫ there tc∈ = IH tc∈
... | ⟫ here tc∈M = te∈ᴹ⇒te∈ Rs te≡ $ ¬frg te (tc∈⇒te∈ᴹ tc∈M) hp
where
te∈tc : te -∈-TC- tc
te∈tc = ∈-TC (L.Any.map (λ where refl → ∈-TE) te∈)
tc∈⇒te∈ᴹ : tc tc∈-Message_ ⊆¹ te -∈ᴹ-_
tc∈⇒te∈ᴹ = λ where
(tc∈-Propose refl) → ∈-Propose-TC (just te∈tc)
tc∈-TCFormed → ∈-TCFormed te∈tc
(tc∈-Timeout refl) → ∈-Timeout-TC (just te∈tc)
... | LocalStep {p = p} {ls′ = ls′} st
with st
... | InitTC _ tc≡ = te∈-monotonic QED
where
QED : te ∙∈ s .history
QED with ⟫ tc∈
... | ⟫ here tc∈-TCFormed = IHₗ tc≡
... | ⟫ there tc∈ = IH tc∈
... | InitNoTC _ _ = IH tc∈
... | ProposeBlock {txn = txn} _ _ = te∈-monotonic $ case tc∈ of λ where
(here (tc∈-Propose tc≡)) → IHₗ tc≡
(there tc∈) → IH tc∈
... | ProposeBlockNoOp _ _ = IH tc∈
... | EnoughTimeouts _ _ _ _ = te∈-monotonic $ case tc∈ of λ where
(here (tc∈-Timeout tc≡)) → IHₗ tc≡
(there tc∈) → IH tc∈
... | TimerExpired _ _ = te∈-monotonic $ case tc∈ of λ where
(here (tc∈-Timeout tc≡)) → IHₗ tc≡
(there tc∈) → IH tc∈
... | AdvanceRoundQC _ _ _ = IH tc∈
... | AdvanceRoundTC _ _ _ = IH tc∈
... | AdvanceRoundNoOp _ _ _ = IH tc∈
... | Lock _ _ = IH tc∈
... | Commit _ _ = IH tc∈
... | CommitNoOp _ _ = IH tc∈
... | VoteBlock {b = b} _ _ _ with ⟫ there tc∈ ← ⟫ tc∈ = te∈-monotonic $ IH tc∈
... | VoteBlockNoOp _ _ = IH tc∈
... | RegisterProposal _ _ _ _ _ = IH tc∈
... | RegisterTimeout _ _ _ _ = IH tc∈
... | RegisterTC _ _ _ _ = IH tc∈
... | RegisterVote _ _ _ _ _ _ = IH tc∈
tc∈⇒te∈ : ∀ {s} → Reachable s → ⦃ Honest p ⦄ →
∙ te .node ≡ p
∙ te ∈ tc .tes
∙ tc ∙∈ s .history
────────────────
te ∙∈ s .history
tc∈⇒te∈ Rs te≡ te∈ = λ where
(formedTC ftc) → L.All.lookup ftc te∈
(receivedTC tc∈) → tc∈m⇒te∈ Rs te≡ te∈ tc∈
te∈tc⇒Timeout : ∀ {s} (Rs : Reachable s) ⦃ _ : Honest p ⦄ →
∙ tc ∙∈ s .history
∙ te .node ≡ p
∙ te ∈ tc .tes
──────────────────────
Rs ∋⋯ StepTimeout p te
te∈tc⇒Timeout Rs tc∈ te≡ te∈ =
TimeoutMsg⇒TimeoutStep Rs te≡ $ tc∈⇒te∈ Rs te≡ te∈ tc∈
sameRound-lemma : ∀ {s s′} → ⦃ _ : Honest p ⦄ → ⦃ _ : Honest p′ ⦄ → Reachable s →
let ls = s @ p
ls′ = s′ @ p
in
∙ 1 + ls .r-cur ≡ ls .r-vote
∙ s′ ↞— s
∙ ls .r-cur ≡ ls′ .r-cur
────────────────────────────
1 + ls′ .r-cur ≡ ls′ .r-vote
sameRound-lemma Rs 1+r-cur≡r-vote (_ ∎) _ = 1+r-cur≡r-vote
sameRound-lemma {p = p}{s = s₀} ⦃ hp ⦄ ⦃ hp′ ⦄ Rs₀ 1+r-cur≡r-vote (_ ⟨ st ∣ s ⟩←— tr) ls≡
with IH ← sameRound-lemma {s′ = s} ⦃ hp ⦄ ⦃ hp′ ⦄ Rs₀ 1+r-cur≡r-vote tr
with st
... | WaitUntil _ _ _
= IH ls≡
... | Deliver {tpm} _
rewrite receiveMsg-ls≡ {p}{s .stateMap} (honestTPMessage tpm)
= IH ls≡
... | DishonestLocalStep _ _ = IH ls≡
... | LocalStep {p = p′}{ls′ = ls′} st
with lookup✓ ← pLookup∘updateAt p ⦃ hp ⦄ {const ls′} (s .stateMap)
with lookup✖ ← (λ p≢ → pLookup∘updateAt′ p p′ {const ls′} (p≢ ∘ ↑-injective) (s .stateMap))
with p ≟ p′
... | no p≢ rewrite lookup✖ p≢ | sym (lookup✖ p≢) = IH ls≡
... | yes refl
with st
... | InitTC _ _ rewrite lookup✓ = IH ls≡
... | InitNoTC _ _ rewrite lookup✓ = IH ls≡
... | ProposeBlockNoOp _ _ rewrite lookup✓ = IH ls≡
... | RegisterProposal _ _ _ _ _ rewrite lookup✓ = IH ls≡
... | EnoughTimeouts _ _ _ _ rewrite lookup✓ = refl
... | RegisterTimeout _ _ _ _ rewrite lookup✓ = IH ls≡
... | RegisterTC _ _ _ _ rewrite lookup✓ = IH ls≡
... | TimerExpired _ _ rewrite lookup✓ = refl
... | RegisterVote _ _ _ _ _ _ rewrite lookup✓ = IH ls≡
... | AdvanceRoundQC _ _ qc> rewrite lookup✓
= ⊥-elim (Nat.<⇒≢ ls′> ls≡)
where
open Nat.≤-Reasoning renaming (_∎ to _■)
ls₀ = s₀ @ʰ hp
_ls = s @ʰ hp
ls′> : ls′ .r-cur > ls₀ .r-cur
ls′> = begin-strict
ls₀ .r-cur
≤⟨ r-cur-mono {s′ = s}{s₀} ⦃ hp ⦄ tr ⟩
_ls .r-cur
<⟨ Nat.s≤s qc> ⟩
ls′ .r-cur
■
... | AdvanceRoundTC _ _ tc≥ rewrite lookup✓
= ⊥-elim (Nat.<⇒≢ ls′> ls≡)
where
open Nat.≤-Reasoning renaming (_∎ to _■)
ls₀ = s₀ @ʰ hp
_ls = s @ʰ hp
ls′> : ls′ .r-cur > ls₀ .r-cur
ls′> = begin-strict
ls₀ .r-cur
≤⟨ r-cur-mono {s′ = s}{s₀} ⦃ hp ⦄ tr ⟩
_ls .r-cur
<⟨ Nat.s≤s tc≥ ⟩
ls′ .r-cur
■
... | AdvanceRoundNoOp _ _ _ rewrite lookup✓ = IH ls≡
... | Lock _ (isHighest qc∈ _) rewrite lookup✓ = IH ls≡
... | CommitNoOp _ _ rewrite lookup✓ = IH ls≡
... | VoteBlockNoOp _ _ rewrite lookup✓ = IH ls≡
... | Commit _ _ rewrite lookup✓ = IH ls≡
... | ProposeBlock _ _ rewrite lookup✓ = IH ls≡
... | VoteBlock _ _ (refl , r> , _) rewrite lookup✓
with ih ← IH ls≡
= let r = (s @ʰ hp) .r-cur in
⊥-elim $ Nat.<⇒≯ r> $ subst (1 + r ≤_) ih (Nat.n<1+n r)
timedOut?⇒r-cur-vote : ∀ {s s′ te} → ⦃ _ : Honest p ⦄ → Reachable s → let ls′ = s′ @ p in
∙ StepTimeout p te ◃ s
∙ s′ ↞— s
∙ te ∙round ≡ ls′ .r-cur
────────────────────────────
1 + ls′ .r-cur ≡ ls′ .r-vote
timedOut?⇒r-cur-vote {p = p} {s = s} {s′}{te} ⦃ hp ⦄ Rs
st-timeout@(st , ⟪s , refl , refl , refl , tst-timeout) tr r≡
= sameRound-lemma {p = p} {s = s} ⦃ hp ⦄ ⦃ hp ⦄ Rs r-cur-vote tr ≪r≡
where
tst = st .theStep
ls₁ = s @ p
_ls′ = s′ @ p
r-cur-vote : 1 + ls₁ .r-cur ≡ ls₁ .r-vote
r-cur-vote
with ⟫ tst | ⟫ tst-timeout
... | ⟫ EnoughTimeouts ph≡ _ _ _ | ⟫ refl , _
rewrite pLookup∘updateAt p ⦃ hp ⦄ {const $ recordTimeout (⟪s @ʰ hp)} (⟪s .stateMap)
= refl
... | ⟫ TimerExpired ph≡ _ | ⟫ refl , _
rewrite pLookup∘updateAt p ⦃ hp ⦄ {const $ recordTimeout (⟪s @ʰ hp)} (⟪s .stateMap)
= refl
r-cur-te : ls₁ .r-cur ≡ te ∙round
r-cur-te
with ⟫ tst | ⟫ tst-timeout
... | ⟫ EnoughTimeouts ph≡ _ _ _ | ⟫ refl , refl
rewrite pLookup∘updateAt p ⦃ hp ⦄ {const $ recordTimeout (⟪s @ʰ hp)} (⟪s .stateMap)
= refl
... | ⟫ TimerExpired ph≡ _ | ⟫ refl , refl
rewrite pLookup∘updateAt p ⦃ hp ⦄ {const $ recordTimeout (⟪s @ʰ hp)} (⟪s .stateMap)
= refl
≪r≡ : ls₁ .r-cur ≡ _ls′ .r-cur
≪r≡ = trans r-cur-te r≡