{-# OPTIONS --safe #-}
open import Prelude
open import Hash
open import Jolteon.Assumptions
module Jolteon.Properties.Votes.Core (⋯ : _) (open Assumptions ⋯) where
open import Jolteon ⋯
getHonestVoteFor : Block → Message → Maybe Pid
getHonestVoteFor b m = case m of λ where
(Vote vs) → M.when (isHonest (vs ∙pid) ∧ (vs ∙blockId == b ∙blockId)) (vs ∙pid)
(Propose _) → nothing
(TCFormed _) → nothing
(Timeout _) → nothing
honestVotes' : Block → Messages → List Pid
honestVotes' b ms = flip L.mapMaybe ms $ getHonestVoteFor b
honestVotes : Block → Messages → List Pid
honestVotes = nub ∘₂ honestVotes'
MoreThanF-Honest : Block → GlobalState → Type
MoreThanF-Honest b s = MoreThanF $ honestVotes b (s .history)
Honest-honestVotes' : ∀ b ms → All Honest (honestVotes' b ms)
Honest-honestVotes' b [] = []
Honest-honestVotes' b (Propose _ ∷ ms) = Honest-honestVotes' b ms
Honest-honestVotes' b (Vote vs ∷ ms) with honest? (vs ∙pid) | vs ∙blockId ≟ b ∙blockId
... | no _ | _ = Honest-honestVotes' b ms
... | yes hp | no _ = Honest-honestVotes' b ms
... | yes hp | yes _ = hp ∷ Honest-honestVotes' b ms
Honest-honestVotes' b (TCFormed _ ∷ ms) = Honest-honestVotes' b ms
Honest-honestVotes' b (Timeout _ ∷ ms) = Honest-honestVotes' b ms
Honest-honestVotes : ∀ b ms → All Honest (honestVotes b ms)
Honest-honestVotes b ms = All-nub⁺ (Honest-honestVotes' b ms)
honestVotes-mono : ∀ ms m →
length (honestVotes b ms) ≤ length (honestVotes b (m ∷ ms))
honestVotes-mono {b} ms m with getHonestVoteFor b m
... | nothing = Nat.≤-refl
... | just p = nub-length {xs = honestVotes' b ms}{p}
getVoteFor : Block → Message → Maybe Pid
getVoteFor b m = case m of λ where
(Vote vs) → M.when (vs ∙blockId == b ∙blockId) (vs ∙pid)
(Propose _) → nothing
(TCFormed _) → nothing
(Timeout _) → nothing
votes' : Block → Messages → List Pid
votes' b ms = L.mapMaybe (getVoteFor b) ms
honestVotes'≡ : ∀ b ms → honestVotes' b ms ≡ filter honest? (votes' b ms)
honestVotes'≡ b [] = refl
honestVotes'≡ b (Propose _ ∷ ms) = honestVotes'≡ b ms
honestVotes'≡ b (Vote vs ∷ ms) with honest? (vs ∙pid) | vs ∙blockId ≟ b ∙blockId
... | no _ | no _ = honestVotes'≡ b ms
... | no ¬p | yes _ =
trans (honestVotes'≡ b ms)
(sym $ L.filter-reject honest? ¬p)
... | yes hp | no _ = honestVotes'≡ b ms
... | yes hp | yes _ =
trans (cong ((vs ∙pid) ∷_) $ honestVotes'≡ b ms)
(sym $ L.filter-accept honest? hp)
honestVotes'≡ b (TCFormed _ ∷ ms) = honestVotes'≡ b ms
honestVotes'≡ b (Timeout _ ∷ ms) = honestVotes'≡ b ms
votes : Block → Messages → List Pid
votes = nub ∘₂ votes'
honestVotes≡ : ∀ b ms → honestVotes b ms ≡ filter honest? (votes b ms)
honestVotes≡ b ms
rewrite sym $ nub-filter {xs = votes' b ms} honest?
rewrite honestVotes'≡ b ms = refl
p∈⇒hp : ∀ b ms →
p ∈ honestVotes b ms
────────────────────
p ∈ votes b ms × Honest p
p∈⇒hp b ms p∈ rewrite honestVotes≡ b ms = L.Mem.∈-filter⁻ honest? p∈
MajorityVotes : Block → GlobalState → Type
MajorityVotes b s = IsMajority $ votes b (s .history)
Majority⇒MoreThanF : ∀ (ps : List Pid) →
∙ Unique ps
∙ IsMajority ps
─────────────────────────────
MoreThanF (filter honest? ps)
Majority⇒MoreThanF ps u maj =
*-cancelˡ-< 2 nodes (3 * hvs) $
begin-strict
2 * nodes
≤⟨ maj ⟩
3 * _vs
<⟨ *-monoʳ-< 3 vs<2*hvs ⟩
3 * (2 * hvs)
≡⟨ (sym $ *-assoc 3 2 hvs) ⟩
6 * hvs
≡⟨ *-assoc 2 3 hvs ⟩
2 * (3 * hvs)
■
where
open Nat ; open ≤-Reasoning renaming (_∎ to _■)
_vs = length $ ps
hvs = length $ filter honest? ps
vs<2*hvs : _vs < 2 * hvs
vs<2*hvs = majority⇒honest-majority u maj