@@ -83,6 +83,17 @@ pub(crate) enum Step {
8383 Precommit ,
8484}
8585
86+ /// Status of a vote when checking if it has been received.
87+ #[ derive( Debug , PartialEq ) ]
88+ pub ( crate ) enum VoteStatus {
89+ /// Vote is new and has not been received yet.
90+ New ,
91+ /// Vote is a duplicate (same proposal_commitment) - already received or queued.
92+ Duplicate ,
93+ /// Vote conflicts with an existing vote (different proposal_commitment).
94+ Conflict ( Vote , Vote ) ,
95+ }
96+
8697/// State Machine. Major assumptions:
8798/// 1. SHC handles: authentication, replays, and conflicts.
8899/// 2. SM must handle "out of order" messages (E.g. vote arrives before proposal).
@@ -167,10 +178,6 @@ impl StateMachine {
167178 self . height
168179 }
169180
170- pub ( crate ) fn prevotes_ref ( & self ) -> & VotesMap {
171- & self . prevotes
172- }
173-
174181 pub ( crate ) fn precommits_ref ( & self ) -> & VotesMap {
175182 & self . precommits
176183 }
@@ -191,6 +198,44 @@ impl StateMachine {
191198 self . last_self_precommit . clone ( )
192199 }
193200
201+ /// Check if a vote has already been received (either in the vote maps or queued).
202+ /// Returns the status of the vote: NotReceived, Duplicate, or Conflict.
203+ pub ( crate ) fn received_vote ( & self , vote : & Vote ) -> VoteStatus {
204+ let determine_status = |old : & Vote , new : & Vote | {
205+ if old. proposal_commitment == new. proposal_commitment {
206+ VoteStatus :: Duplicate
207+ } else {
208+ VoteStatus :: Conflict ( old. clone ( ) , new. clone ( ) )
209+ }
210+ } ;
211+
212+ // Check Map
213+ let key = ( vote. round , vote. voter ) ;
214+ let map_entry = match vote. vote_type {
215+ VoteType :: Prevote => self . prevotes . get ( & key) ,
216+ VoteType :: Precommit => self . precommits . get ( & key) ,
217+ } ;
218+
219+ if let Some ( ( old_vote, _) ) = map_entry {
220+ return determine_status ( old_vote, vote) ;
221+ }
222+
223+ // Check Queue
224+ for event in & self . events_queue {
225+ let queued_vote = match ( event, vote. vote_type ) {
226+ ( StateMachineEvent :: Prevote ( v) , VoteType :: Prevote ) => v,
227+ ( StateMachineEvent :: Precommit ( v) , VoteType :: Precommit ) => v,
228+ _ => continue ,
229+ } ;
230+
231+ if queued_vote. round == vote. round && queued_vote. voter == vote. voter {
232+ return determine_status ( queued_vote, vote) ;
233+ }
234+ }
235+
236+ VoteStatus :: New
237+ }
238+
194239 fn make_self_vote (
195240 & mut self ,
196241 vote_type : VoteType ,
@@ -274,10 +319,7 @@ impl StateMachine {
274319 self . handle_enqueued_events ( leader_fn)
275320 }
276321
277- pub ( crate ) fn handle_enqueued_events < LeaderFn > (
278- & mut self ,
279- leader_fn : & LeaderFn ,
280- ) -> VecDeque < SMRequest >
322+ fn handle_enqueued_events < LeaderFn > ( & mut self , leader_fn : & LeaderFn ) -> VecDeque < SMRequest >
281323 where
282324 LeaderFn : Fn ( Round ) -> ValidatorId ,
283325 {
@@ -311,7 +353,7 @@ impl StateMachine {
311353 output_requests
312354 }
313355
314- pub ( crate ) fn handle_event_internal < LeaderFn > (
356+ fn handle_event_internal < LeaderFn > (
315357 & mut self ,
316358 event : StateMachineEvent ,
317359 leader_fn : & LeaderFn ,
@@ -344,7 +386,7 @@ impl StateMachine {
344386 }
345387 }
346388
347- pub ( crate ) fn handle_finished_building < LeaderFn > (
389+ fn handle_finished_building < LeaderFn > (
348390 & mut self ,
349391 proposal_id : Option < ProposalCommitment > ,
350392 round : u32 ,
@@ -362,7 +404,7 @@ impl StateMachine {
362404 self . map_round_to_upons ( round, leader_fn)
363405 }
364406
365- pub ( crate ) fn handle_finished_validation < LeaderFn > (
407+ fn handle_finished_validation < LeaderFn > (
366408 & mut self ,
367409 proposal_id : Option < ProposalCommitment > ,
368410 round : u32 ,
@@ -377,7 +419,7 @@ impl StateMachine {
377419 self . map_round_to_upons ( round, leader_fn)
378420 }
379421
380- pub ( crate ) fn handle_timeout_propose ( & mut self , round : u32 ) -> VecDeque < SMRequest > {
422+ fn handle_timeout_propose ( & mut self , round : u32 ) -> VecDeque < SMRequest > {
381423 if self . step != Step :: Propose || round != self . round {
382424 return VecDeque :: new ( ) ;
383425 } ;
@@ -392,11 +434,7 @@ impl StateMachine {
392434 }
393435
394436 // A prevote from a peer node.
395- pub ( crate ) fn handle_prevote < LeaderFn > (
396- & mut self ,
397- vote : Vote ,
398- leader_fn : & LeaderFn ,
399- ) -> VecDeque < SMRequest >
437+ fn handle_prevote < LeaderFn > ( & mut self , vote : Vote , leader_fn : & LeaderFn ) -> VecDeque < SMRequest >
400438 where
401439 LeaderFn : Fn ( Round ) -> ValidatorId ,
402440 {
@@ -411,7 +449,7 @@ impl StateMachine {
411449 self . map_round_to_upons ( round, leader_fn)
412450 }
413451
414- pub ( crate ) fn handle_timeout_prevote ( & mut self , round : u32 ) -> VecDeque < SMRequest > {
452+ fn handle_timeout_prevote ( & mut self , round : u32 ) -> VecDeque < SMRequest > {
415453 if self . step != Step :: Prevote || round != self . round {
416454 return VecDeque :: new ( ) ;
417455 } ;
0 commit comments