VotedOnlyOncePerEpoch¹ : StateProperty VotedOnlyOncePerEpoch¹ s = ∀ {p} ⦃ _ : Honest p ⦄ → let ms = (s @ p) .db in ∀ {b b′} → ∙ p ∈ voteIds ms b ∙ p ∈ voteIds ms b′ ∙ b .epoch ≡ b′ .epoch ──────────────────── b ≡ b′ votedOnlyOncePerEpoch¹ : Invariant VotedOnlyOncePerEpoch¹ votedOnlyOncePerEpoch¹ (_ , refl , (_ ∎)) {p} p∈ _ _ rewrite let open ∣Base∣ p in lookup✓ = case p∈ of λ () votedOnlyOncePerEpoch¹ {s′} (_ , refl , (_ ⟨ s→ ∣ s ⟩←— tr)) {p} ⦃ hp ⦄ {b} {b′} p∈ p∈′ refl with Rs ← -, refl , tr with IH ← votedOnlyOncePerEpoch¹ Rs {p}{b}{b′} with s→ ... | Deliver {env = [ p′ ∣ m′ ⟩} env∈ = uncurry IH ≪p∈ refl where open ∣Deliver∣ p s env∈ ≪p∈ : p ∈ voteIds ((s @ p) .db) b × p ∈ voteIds ((s @ p) .db) b′ ≪p∈ rewrite db≡ = p∈ , p∈′ ... | AdvanceEpoch rewrite let open ∣AdvanceEpoch∣ p s in lookup✓ = IH p∈ p∈′ refl ... | Drop _ = IH p∈ p∈′ refl ... | LocalStep {p = p′}{mm}{ls′} ls→ = QED where open ∣LocalStep∣ p p′ s mm ls′ nfo = noFutureOwnVotes Rs QED : b ≡ b′ QED with p ≟ p′ QED | no p≢ = IH p∈✖ p∈′✖ refl where p∈✖ : p ∈ voteIds ((s @ p) .db) b p∈✖ with ⟫ mm ... | ⟫ just _ rewrite lookup✖ p≢ = p∈ ... | ⟫ nothing rewrite lookup✖ p≢ = p∈ p∈′✖ : p ∈ voteIds ((s @ p) .db) b′ p∈′✖ with ⟫ mm ... | ⟫ just _ rewrite lookup✖ p≢ = p∈′ ... | ⟫ nothing rewrite lookup✖ p≢ = p∈′ QED | yes refl rewrite lookup✓ with ⟫ ls→ QED | yes refl | ⟫ ProposeBlock {ch} {txs} ready pLeader _ _ rewrite lookup✓ with s .e-now ≟ b .epoch ... | no b≢ = IH (voteIds-∷˘′ {b = b} (b≢ ∘ cong epoch) p∈) (voteIds-∷˘′ {b = b′} (b≢ ∘ cong epoch) p∈′) refl ... | yes refl = let ≡b , _ = voteIds-head b p∉ p∈ ≡b′ , _ = voteIds-head b′ p∉′ p∈′ in trans (sym ≡b) ≡b′ where open ∣ProposeBlock∣ p ⦃ hp ⦄ s ch txs m∉ : ∀ {m} → m ∙block ≡ b → p ≡ m ∙pid → m ∉ ≪db m∉ refl p≡ = nfo ⦃ hp ⦄ refl ready p≡ m∉′ : ∀ {m} → m ∙block ≡ b′ → p ≡ m ∙pid → m ∉ ≪db m∉′ refl p≡ = nfo ⦃ hp ⦄ refl ready p≡ findMessage : ∀ {b} → p ∈ voteIds ≪db b → ∃ λ m → m ∙block ≡ b × p ≡ m ∙pid × m ∈ ≪db findMessage p∈b with mᵇ , m∈filter , refl ← L.Mem.∈-map⁻ _∙pid p∈b with m∈ , q ← L.Mem.∈-filter⁻ _ m∈filter = mᵇ , sym q , refl , m∈ p∉ : p ∉ voteIds ≪db b p∉ p∈ with m , refl , refl , m∈ ← findMessage p∈ = ⊥-elim $ m∉ refl refl m∈ p∉′ : p ∉ voteIds ≪db b′ p∉′ p∈ with m , refl , refl , m∈ ← findMessage p∈ = ⊥-elim $ m∉′ refl refl m∈ QED | yes refl | ⟫ VoteBlock {H} {txs} _ _ ready ¬L _ _ rewrite lookup✓ with s .e-now ≟ b .epoch ... | no b≢ = IH ( voteIds-∷˘ {b = b} (Eq.≢-sym ¬L) $ voteIds-∷˘′ {b = b} (b≢ ∘ cong epoch) p∈) ( voteIds-∷˘ {b = b′} (Eq.≢-sym ¬L) $ voteIds-∷˘′ {b = b′} (b≢ ∘ cong epoch) p∈′) refl ... | yes refl = let ≡b , _ = voteIds-head b p∉ p∈ ≡b′ , _ = voteIds-head b′ p∉′ p∈′ in trans (sym ≡b) ≡b′ where open ∣VoteBlock∣ p ⦃ hp ⦄ s H txs m∉ : ∀ {m} → m ∙block ≡ b → p ≡ m ∙pid → m ∉ ≪db m∉ refl p≡ = nfo ⦃ hp ⦄ refl ready p≡ m∉′ : ∀ {m} → m ∙block ≡ b′ → p ≡ m ∙pid → m ∉ ≪db m∉′ refl p≡ = nfo ⦃ hp ⦄ refl ready p≡ findMessage : ∀ {b} → p ∈ voteIds ≪db b → ∃ λ m → m ∙block ≡ b × p ≡ m ∙pid × m ∈ ≪db findMessage p∈b with mᵇ , m∈filter , refl ← L.Mem.∈-map⁻ _∙pid p∈b with m∈ , q ← L.Mem.∈-filter⁻ _ m∈filter = mᵇ , sym q , refl , m∈ p∉b : p ∉ voteIds ≪db b p∉b p∈b with m , refl , refl , m∈ ← findMessage p∈b = ⊥-elim $ m∉ refl refl m∈ p∉b′ : p ∉ voteIds ≪db b′ p∉b′ p∈ with m , refl , refl , m∈ ← findMessage p∈ = ⊥-elim $ m∉′ refl refl m∈ p∉ : p ∉ voteIds (Mᵖ ∷ ≪db) b p∉ p∈ = ⊥-elim $ p∉b $ voteIds-∷˘ {b = b} (Eq.≢-sym ¬L) p∈ p∉′ : p ∉ voteIds (Mᵖ ∷ ≪db) b′ p∉′ p∈ = ⊥-elim $ p∉b′ $ voteIds-∷˘ {b = b′} (Eq.≢-sym ¬L) p∈ QED | yes refl | ⟫ RegisterVote {sb} m∈inbox sb∉db rewrite lookup✓ = IH (voteIds-∷˘ {b = b} p≢ p∈) (voteIds-∷˘ {b = b′} p≢ p∈′) refl where m∉ : Vote sb ∉ (s @ p′) .db m∉ m∈ = sb∉db (L.Mem.∈-map⁺ _∙signedBlock m∈) p≢ : (Vote sb) ∙pid ≢ p p≢ with sb ∙pid ≟ p ... | yes p≡ = ⊥-elim $ m∉ $ unforgeability Rs ⦃ hp ⦄ m∈inbox $ sym p≡ ... | no p≢ = p≢ QED | yes refl | ⟫ FinalizeBlock ch b x x₁ rewrite lookup✓ = IH p∈ p∈′ refl ... | DishonestLocalStep {p = p′}{mm} ¬hp′ h⇒m∈ = uncurry IH ≪p∈ refl where open ∣DishonestLocalStep∣ p p′ ¬hp′ s mm ≪p∈ : p ∈ voteIds ((s @ p) .db) b × p ∈ voteIds ((s @ p) .db) b′ ≪p∈ rewrite db≡ = p∈ , p∈′
VotedOnlyOncePerEpoch : StateProperty VotedOnlyOncePerEpoch s = ∀ {p p′} ⦃ _ : Honest p ⦄ ⦃ _ : Honest p′ ⦄ → let ms = (s @ p) .db in ∀ {b b′} → ∙ p′ ∈ voteIds ms b ∙ p′ ∈ voteIds ms b′ ∙ b .epoch ≡ b′ .epoch ──────────────────── b ≡ b′ votedOnlyOncePerEpoch : Invariant VotedOnlyOncePerEpoch votedOnlyOncePerEpoch Rs p∈ p∈′ = votedOnlyOncePerEpoch¹ Rs (messageSharing Rs p∈) (messageSharing Rs p∈′)