allTCs
function and its propertiesThe function allTCs extracts all TCs in a list of messages.
record TimeoutEvidenceOf (r : Round) (ms : Messages) (ts : List TimeoutEvidence) : Type where
field
sound : ∀ {te} →
te ∈ ts
─────────────────────────────────
∃ λ mtc → Timeout (te , mtc) ∈ ms
complete : ∀ {te} → ⦃ te ∙round ≡ r ⦄ → ⦃ te< : te ∙qcTE ∙round < r ⦄ →
Timeout (te , mtc) ∈ ms
────────────────────────
te ∈ ts
round≡ : All ((_≡ r) ∘ _∙round) ts
qc< : All (λ te → te ∙qcTE ∙round < r) ts
open TimeoutEvidenceOf
open L.All using (lookup) renaming (map to amap)
open L.Any using (tail)
timeoutEvidence⁺ : (r : Round) (ms : Messages) → ∃ (TimeoutEvidenceOf r ms)
timeoutEvidence⁺ r [] = [] , record
{ sound = λ ()
; complete = λ ()
; round≡ = []
; qc< = []
}
timeoutEvidence⁺ r ms₀@(m ∷ ms)
with ts , rte ← timeoutEvidence⁺ r ms
with ts⁺ ← (¬Timeout m → ∃ (TimeoutEvidenceOf r ms₀)) ∋ (λ m≢ →
ts , record
{ sound = map₂ there ∘ rte .sound
; complete = λ where (here refl) → ⊥-elim m≢; (there m∈) → rte .complete m∈
; round≡ = rte .round≡
; qc< = rte .qc<
})
with m
... | Propose _ = ts⁺ tt
... | TCFormed _ = ts⁺ tt
... | Vote _ = ts⁺ tt
... | Timeout (te , mtc)
with (te ∙round) ≟ r | ¿ te ∙qcTE ∙round < r ¿
... | no te≢ | _ = ts , record
{ sound = map₂ there ∘ rte .sound
; complete = λ where (here refl) → ⊥-elim (te≢ it) ; (there m∈) → rte .complete m∈
; round≡ = rte .round≡
; qc< = rte .qc<
}
... | yes _ | no qc≮ = ts , record
{ sound = map₂ there ∘ rte .sound
; complete = λ where (here refl) → ⊥-elim (qc≮ it) ; (there m∈) → rte .complete m∈
; round≡ = rte .round≡
; qc< = rte .qc<
}
... | yes refl | yes qc<r = te ∷ ts , record
{ sound = λ where
(here refl) → mtc , here refl
(there te∈) → map₂ there $ rte .sound te∈
; complete = λ where (here refl) → here it ; (there m∈) → there (rte .complete m∈)
; round≡ = refl ∷ rte .round≡
; qc< = qc<r ∷ rte .qc<
}
module _ r ms (let ts , p = timeoutEvidence⁺ r ms) where
timeoutEvidence : List TimeoutEvidence
timeoutEvidence = ts
open TimeoutEvidenceOf p public renaming
( sound to timeoutEvidence-sound
; complete to timeoutEvidence-complete
; round≡ to timeoutEvidence-≡
; qc< to timeoutEvidence-qc<
)
timeoutEvidence-maximal : ∀ tc ms →
FormedTC tc ms
──────────────────────────────────────────
tc .tes ⊆ˢ timeoutEvidence (tc ∙round) ms
timeoutEvidence-maximal tc ms ftc {te} te∈ with (te ∙round) ≟ (tc ∙round)
... | no ¬eq = ⊥-elim $ ¬eq $ lookup (getAllRound tc) te∈
... | yes refl with ¿ te ∙qcTE ∙round < (tc ∙round) ¿
... | no qc≮ = ⊥-elim $ qc≮ $ lookup (getQCBound tc) te∈
... | yes teqc< = QED
where
m∈ : ∃ λ mtc → Timeout (te , mtc) ∈ ms
m∈ = lookup ftc te∈
QED : te ∈ timeoutEvidence (tc ∙round) ms
QED = timeoutEvidence-complete (te ∙round) ms ⦃ te< = teqc< ⦄ (proj₂ m∈)
-- Decide if it is possible to construct a FormedTC in ms for round r.
Dec-∃FormedTC : ∀ r ms → Dec (∃ λ tc → (tc .roundTC ≡ r) × FormedTC tc ms)
Dec-∃FormedTC r ms with ¿ UniqueByMajority⊆ˢ node (timeoutEvidence r ms) ¿
... | no ¬ums
= no λ where
(tc , refl , ftc) →
¬ums $ tc .tes
, timeoutEvidence-maximal tc ms ftc
, getUniqueTC tc
, getQuorumTC tc
... | yes (ps , ps⊆ , uniq , maj)
= yes (mytc , refl , fmytc)
where
open ≡-Reasoning
open L.All using (tabulate; map⁻; map⁺; lookup)
open L.SubS using (All-resp-⊇)
mytc : TC
mytc =
record
{ roundTC = r
; tes = ps
; quorumTC = maj
; uniqueTC = uniq
; allRound = All-resp-⊇ ps⊆ $ timeoutEvidence-≡ r ms
; qcBound = All-resp-⊇ ps⊆ $ timeoutEvidence-qc< r ms
}
fmytc : FormedTC mytc ms
fmytc = tabulate $ timeoutEvidence-sound r ms ∘ ps⊆
-- Decide if it is possible to construct a FormedTC with the given round from a
-- list of messages.
tryTC : ∀ r ms →
───────────────────────────────────────────────
Dec $ ∃ λ tc → (tc ∙round ≡ r) × FormedTC tc ms
tryTC = Dec-∃FormedTC
record AllTCsOf (ms : Messages) (tcs : TCs) : Type where
field
sound : tc ∈ tcs → tc ∙∈ ms
complete : tc ∙∈ ms → tc .roundTC ∈ map roundTC tcs
open AllTCsOf
open L.All using () renaming (map to amap; zipWith to azipWith)
open L.Any using (tail; ++⁺ˡ)
open L.Mem using (∈-map⁺; ∈-++⁺ˡ; ∈-++⁺ʳ; ∈-++⁻)
allTCs⁺ : (ms : Messages) → ∃ (AllTCsOf ms)
allTCs⁺ [] = [] , record
{ sound = λ ()
; complete = λ where {tc} (formedTC x) → ⊥-elim $ ¬FormedTC tc x
}
where
¬FormedTC : ∀ tc → ¬ FormedTC tc []
¬FormedTC tc ftc with tc .tes in tes≡ | ftc
... | [] | _ = ⊥-elim $ majority⁺ (subst IsMajority tes≡ $ getQuorumTC tc)
... | _ ∷ _ | () ∷ _
allTCs⁺ (m ∷ ms)
with ts , r ← allTCs⁺ ms
with m
... | Propose (⟨ _ , nothing , _ , _ ⟩ signed-by _) = ts , record
{ sound = λ tc∈ → tc∈-monotonic $ r .sound tc∈
; complete = λ where
{tc} (formedTC p) → r .complete {tc} $
formedTC $ amap (λ where (mtc , there tc∈) → mtc , tc∈) p
(receivedTC (here (tc∈-Propose ())))
(receivedTC (there p)) → r .complete (receivedTC p)
}
... | Propose (⟨ bid , just tc , rb , txs ⟩ signed-by _) = tc ∷ ts , record
{ sound = λ where
(here refl) → receivedTC $ here $′ tc∈-Propose refl
(there tc∈) → tc∈-monotonic $ r .sound tc∈
; complete = λ where
{tc} (formedTC p) → there $ r .complete {tc} $
formedTC $ amap (λ where (mtc , there tm∈) → mtc , tm∈) p
(receivedTC (here (tc∈-Propose refl))) → here refl
(receivedTC (there p)) → there $ r .complete $ receivedTC p
}
... | Vote v = ts , record
{ sound = λ tc∈ → tc∈-monotonic $ r .sound tc∈
; complete = λ where
{tc} (formedTC p) → r .complete $ formedTC {tc} $ amap (λ where (mtc , there tm∈) → mtc , tm∈) p
(receivedTC p) → r .complete $ receivedTC $ tail (λ ()) p
}
... | TCFormed tc = tc ∷ ts , record
{ sound = λ where
(here refl) → receivedTC $ here tc∈-TCFormed
(there p) → tc∈-monotonic $ r .sound p
; complete = λ where
{tc} (formedTC p) → there $ r .complete {tc} $
formedTC (amap (λ where (mtc , there tm∈) → mtc , tm∈) p)
(receivedTC (here tc∈-TCFormed)) → here refl
(receivedTC (there p)) → there $ r .complete $ receivedTC p
}
... | Timeout (te , mtc)
with tryTC (te ∙round) (Timeout (te , mtc) ∷ ms) | mtc in mtc≡
... | no ¬tc | nothing = ts , record
{ sound = λ where tc∈ → tc∈-monotonic $ r .sound tc∈
; complete = λ where
{tc} (formedTC p) → case (tc ∙round) ≟ (te ∙round) of λ
where
(yes eq) → ⊥-elim $ ¬tc (tc , eq ,
amap (map₂ (subst (λ ◆ → Any _ (Timeout (te , ◆) ∷ ms)) (sym mtc≡))) p)
(no ¬eq) → r .complete $ formedTC {tc} $
azipWith (λ where ((mtc , te∈) , refl) → mtc , tail (λ where refl → ¬eq refl) te∈ )
(p , getAllRound tc)
(receivedTC p) → r .complete $ receivedTC $ tail (λ where (tc∈-Timeout ())) p
}
... | no ¬tc | (just tc) = tc ∷ ts , record
{ sound = λ where
(here refl) → receivedTC (here (tc∈-Timeout refl))
(there p) → tc∈-monotonic (r .sound p)
; complete = λ where
{tc′} (formedTC p) → case (tc′ ∙round) ≟ (tc ∙round) of λ
where
(yes eq) → here eq
(no ¬eq) → case (tc′ ∙round) ≟ (te ∙round) of λ
where
(yes eq) → ⊥-elim $
¬tc (tc′ , eq , (amap (map₂ (subst (λ ◆ → _ ∈ (Timeout (te , ◆) ∷ ms)) (sym mtc≡))) p))
(no ¬eq) → there $ r .complete {tc′} $ formedTC $
azipWith (λ where ((mtc , te∈) , refl) → mtc , tail (λ where refl → ¬eq refl) te∈ )
(p , getAllRound tc′)
(receivedTC (here (tc∈-Timeout refl))) → here refl
(receivedTC (there p)) → there $ r .complete $ receivedTC p
}
... | yes (tc , refl , tes) | nothing = tc ∷ ts , record
{ sound = λ where
(here refl) → formedTC (amap (map₂ (subst (λ ◆ → _ ∈ (Timeout (te , ◆) ∷ ms)) mtc≡)) tes)
(there tc∈) → tc∈-monotonic (r .sound tc∈)
; complete = λ where
{tc′} (formedTC p) → case (tc′ ∙round) ≟ (te ∙round) of λ
where
(yes eq) → here eq
(no ¬eq) → there $ r .complete $ formedTC {tc′} $
azipWith (λ where ((mtc , te∈) , refl) → mtc , tail (λ where refl → ¬eq refl) te∈ )
(p , getAllRound tc′)
(receivedTC (here (tc∈-Timeout ())))
(receivedTC (there p)) → there $ r .complete (receivedTC p)
}
... | yes (tc , refl , tes) | just tc′ = tc ∷ tc′ ∷ ts , record
{ sound = λ where
(here refl) → formedTC (amap (map₂ (subst (λ ◆ → _ ∈ (Timeout (te , ◆) ∷ ms)) mtc≡)) tes)
(there (here refl)) → receivedTC (here (tc∈-Timeout refl))
(there (there tc∈)) → tc∈-monotonic $ r .sound tc∈
; complete = λ where
{tc} (formedTC p) → case (tc ∙round) ≟ (te ∙round) of λ
where
(yes eq) → here eq
(no ¬eq) → there $′ there $′ r .complete {tc} $ formedTC $
azipWith (λ where ((mtc , te∈) , refl) → mtc , tail (λ where refl → ¬eq refl) te∈ )
(p , getAllRound tc)
(receivedTC (here (tc∈-Timeout refl))) → there $′ here refl
(receivedTC (there p)) → there $′ there $ r .complete $ receivedTC p
}
module _ (ms : Messages) (let qs , r = allTCs⁺ ms) where
allTCs : TCs
allTCs = qs
open AllTCsOf r public renaming
( sound to allTCs-sound
; complete to allTCs-complete
)
instance
Dec-AllTC : ∀ {r} → AllTC (λ tc → tc ∙round < r) ⁇¹
Dec-AllTC {r = r} {x = ms} .dec = mapDec All⇒AllTC AllTC⇒All dec
where
P = λ tc → tc ∙round < r
All⇒AllTC : All P (allTCs ms) → AllTC P ms
All⇒AllTC allP = mk (lookup (L.All.map⁺ allP) ∘′ allTCs-complete ms)
AllTC⇒All : AllTC P ms → All P (allTCs ms)
AllTC⇒All (mk allP) = L.All.tabulate (allP ∘ allTCs-sound _)