{-# OPTIONS --safe #-}
open import Prelude
open import Hash
open import Jolteon.Assumptions
module Jolteon.Properties.QuorumIntersection (⋯ : _) (open Assumptions ⋯) where
open import Jolteon ⋯
open import Jolteon.Properties.Core ⋯
open import Jolteon.Properties.Votes ⋯
open import Jolteon.Properties.Steps.Core ⋯
open import Jolteon.Properties.Steps.RVote ⋯
quorumIntersection : ∀ {vs hs : List Pid} →
∙ Unique vs
∙ Unique hs
∙ IsMajority vs
∙ MoreThanF hs
∙ All Honest hs
─────────────────────────────────────────
∃ λ p → Honest p × (p ∈ vs) × (p ∈ hs)
quorumIntersection {vs} {hs} u u′ maj maj′ ah′ =
let
vs∩ = hs ∩ vs
u∩ : Unique vs∩
u∩ = Unique-∩ u′
open Nat; open ≤-Reasoning renaming (_∎ to _◻)
len+ : length hs + length vs > nodes
len+ = *-cancelˡ-< 3 _ _ $
begin-strict
3 * nodes
≡⟨⟩
nodes + 2 * nodes
≤⟨ +-monoʳ-≤ nodes maj ⟩
nodes + 3 * length vs
<⟨ +-monoˡ-< _ maj′ ⟩
3 * length hs + 3 * length vs
≡˘⟨ *-distribˡ-+ 3 (length hs) _ ⟩
3 * (length hs + length vs)
◻
len∩ : length vs∩ > 0
len∩ =
begin-strict
0
≡˘⟨ n∸n≡0 nodes ⟩
nodes ∸ nodes
<⟨ ∸-monoˡ-< len+ ≤-refl ⟩
(length hs + length vs) ∸ nodes
≤⟨ length-∩ u′ u ⟩
length vs∩
◻
p , p∈vs∩ = nonEmpty∈ {xs = vs∩} len∩
p∈′ , p∈ = ∈-∩⁻ p hs vs p∈vs∩
hp : Honest p
hp = L.All.lookup ah′ p∈′
in p , hp , p∈ , p∈′
private
step-b≡ : ∀ {st st′ : Step} →
∙ StepVotes p b st
∙ StepVotes p b′ st′
∙ st ≡ st′
────────────────────
b ≡ b′
step-b≡ {st = _ ⊢ VoteBlock _ _ _} {st′ = _ ⊢ VoteBlock _ _ _}
(_ , refl) (_ , refl) refl
= refl
votedOnlyOnce' : ∀ {s} ⦃ _ : Honest p ⦄ → (Rs : Reachable s) →
∙ Rs ∋⋯ StepVotes p b
∙ Rs ∋⋯ StepVotes p b′
∙ b ∙round ≡ b′ ∙round
────────────────────
b ≡ b′
votedOnlyOnce' {p}{b}{b′} ⦃ hp ⦄ Rs st∈ st∈′ br≡
with b ≟ b′
... | yes b≡ = b≡
... | no b≢
with trE , st-votes ← traceRs⁺ Rs st∈
with trE′ , st-votes′ ← traceRs⁺ Rs st∈′
with factorRs⁺ Rs trE trE′
... | inj₁ st≡ = step-b≡ st-votes st-votes′ st≡
... | inj₂ (inj₁ b↝b′)
= ⊥-elim QED
where
open TraceExtension⁺ trE
using ()
renaming (x to ≪s; y to ≫s; Ry to R≫s; step to st; y←x to s→)
open TraceExtension⁺ trE′
using ()
renaming (x to ≪s′; y to ≫s′; step to st′)
≪ls = ≪s @ p
≪ls′ = ≪s′ @ p
≫ls = ≫s @ p
sv : ShouldVote (≪s @ p) b
sv = StepVotes⇒ShouldVote′ {s = ≪s} (st , refl , refl , st-votes)
r≡ : b ∙round ≡ ≪ls .r-cur
r≡ = sv .proj₁
r> : b ∙round > ≪ls .r-vote
r> = sv .proj₂ .proj₁
rv≡b : b ∙round ≡ ≫ls .r-vote
rv≡b = StepVotes⇒r≡ (st , ≪s , refl , refl , s→ ._ᴸ←—_.s≡ , st-votes)
sv′ : ShouldVote (≪s′ @ p) b′
sv′ = StepVotes⇒ShouldVote′ {s = ≪s′} (st′ , refl , refl , st-votes′)
r≡′ : b′ ∙round ≡ ≪ls′ .r-cur
r≡′ = sv′ .proj₁
r>′ : b′ ∙round > ≪ls′ .r-vote
r>′ = sv′ .proj₂ .proj₁
s′←s : ≪s′ ↞— ≫s
s′←s = b↝b′
r≤′ : b′ ∙round ≤ ≪ls′ .r-vote
r≤′ =
Nat.≤-Reasoning.begin
b′ ∙round
≡⟨ sym br≡ ⟩
b ∙round
≡⟨ rv≡b ⟩
≫ls .r-vote
≤⟨ r-vote-mono R≫s s′←s ⟩
≪ls′ .r-vote
Nat.≤-Reasoning.∎ where open Nat.≤-Reasoning
QED : ⊥
QED = Nat.<⇒≱ r>′ r≤′
... | inj₂ (inj₂ b′↝b)
= ⊥-elim QED
where
open TraceExtension⁺ trE
using ()
renaming (x to ≪s; y to ≫s; step to st)
open TraceExtension⁺ trE′
using ()
renaming (x to ≪s′; y to ≫s′; Ry to R≫s′; step to st′; y←x to s→′)
≪ls = ≪s @ p
≪ls′ = ≪s′ @ p
≫ls = ≫s @ p
≫ls′ = ≫s′ @ p
sv : ShouldVote (≪s @ p) b
sv = StepVotes⇒ShouldVote′ {s = ≪s} (st , refl , refl , st-votes)
r≡ : b ∙round ≡ ≪ls .r-cur
r≡ = sv .proj₁
r> : b ∙round > ≪ls .r-vote
r> = sv .proj₂ .proj₁
sv′ : ShouldVote (≪s′ @ p) b′
sv′ = StepVotes⇒ShouldVote′ {s = ≪s′} (st′ , refl , refl , st-votes′)
r≡′ : b′ ∙round ≡ ≪ls′ .r-cur
r≡′ = sv′ .proj₁
r>′ : b′ ∙round > ≪ls′ .r-vote
r>′ = sv′ .proj₂ .proj₁
rv≡b′ : b′ ∙round ≡ ≫ls′ .r-vote
rv≡b′ = StepVotes⇒r≡ (st′ , ≪s′ , refl , refl , s→′ ._ᴸ←—_.s≡ , st-votes′)
s←s′ : ≪s ↞— ≫s′
s←s′ = b′↝b
r≤ : b ∙round ≤ ≪ls .r-vote
r≤ =
Nat.≤-Reasoning.begin
b ∙round
≡⟨ br≡ ⟩
b′ ∙round
≡⟨ rv≡b′ ⟩
≫ls′ .r-vote
≤⟨ r-vote-mono R≫s′ s←s′ ⟩
≪ls .r-vote
Nat.≤-Reasoning.∎ where open Nat.≤-Reasoning
QED : ⊥
QED = Nat.<⇒≱ r> r≤
votedOnlyOnce : ∀ {s} ⦃ _ : Honest p ⦄ → Reachable s → let ms = s .history in
∙ p ∈ votes b ms
∙ p ∈ votes b′ ms
∙ b ∙round ≡ b′ ∙round
────────────────────
b ≡ b′
votedOnlyOnce ⦃ hp ⦄ Rs p∈ p∈′ r≡ =
votedOnlyOnce' Rs
(honest∈votes⇒StepVotes Rs hp p∈)
(honest∈votes⇒StepVotes Rs hp p∈′)
r≡
uniqueCertification : ∀ {s} → Reachable s →
∙ GloballyCertifiedBlockIn s b
∙ MoreThanF-Honest b′ s
∙ b ∙round ≡ b′ ∙round
─────────────────────
b ≡ b′
uniqueCertification {b}{b′}{s} Rs gcb@(qc , cb , qc∈) maj′ r≡ =
let
ms = s .history
p , hp , p∈ , p∈′ = quorumIntersection (getUnique qc)
(Unique-nub {xs = honestVotes' b′ ms})
(getQuorum qc)
maj′
(Honest-honestVotes b′ ms)
v∈ = qc⇒vote {qc = qc} ⦃ hp ⦄ Rs qc∈ p∈ cb
p∈′ , _ = p∈⇒hp b′ ms p∈′
in
votedOnlyOnce ⦃ hp ⦄ Rs v∈ p∈′ r≡