@@ -17,7 +17,7 @@ use crate::{
1717 model:: {
1818 BlockId , Endorsement , EndorserBlockId , LinearEndorserBlock as EndorserBlock ,
1919 LinearRankingBlock as RankingBlock , LinearRankingBlockHeader as RankingBlockHeader ,
20- Transaction , TransactionId , VoteBundle , VoteBundleId ,
20+ NoVoteReason , Transaction , TransactionId , VoteBundle , VoteBundleId ,
2121 } ,
2222 sim:: { MiniProtocol , NodeImpl , SimCpuTask , SimMessage , lottery} ,
2323} ;
@@ -116,7 +116,7 @@ pub enum CpuTask {
116116 /// An endorser block has been received, and its header has been validated. It is ready to propagate.
117117 EBHeaderValidated ( NodeId , Arc < EndorserBlock > ) ,
118118 /// An endorser block has been received and validated, and is ready to propagate
119- EBBlockValidated ( Arc < EndorserBlock > ) ,
119+ EBBlockValidated ( Arc < EndorserBlock > , Timestamp ) ,
120120 /// A bundle of votes has been generated and is ready to propagate
121121 VTBundleGenerated ( VoteBundle , Arc < EndorserBlock > ) ,
122122 /// A bundle of votes has been received and validated, and is ready to propagate
@@ -131,7 +131,7 @@ impl SimCpuTask for CpuTask {
131131 Self :: RBHeaderValidated ( _, _, _, _) => "ValRH" ,
132132 Self :: RBBlockValidated ( _) => "ValRB" ,
133133 Self :: EBHeaderValidated ( _, _) => "ValEH" ,
134- Self :: EBBlockValidated ( _) => "ValEB" ,
134+ Self :: EBBlockValidated ( _, _ ) => "ValEB" ,
135135 Self :: VTBundleGenerated ( _, _) => "GenVote" ,
136136 Self :: VTBundleValidated ( _, _) => "ValVote" ,
137137 }
@@ -145,7 +145,7 @@ impl SimCpuTask for CpuTask {
145145 Self :: RBHeaderValidated ( _, _, _, _) => "" . to_string ( ) ,
146146 Self :: RBBlockValidated ( _) => "" . to_string ( ) ,
147147 Self :: EBHeaderValidated ( _, _) => "" . to_string ( ) ,
148- Self :: EBBlockValidated ( _) => "" . to_string ( ) ,
148+ Self :: EBBlockValidated ( _, _ ) => "" . to_string ( ) ,
149149 Self :: VTBundleGenerated ( _, _) => "" . to_string ( ) ,
150150 Self :: VTBundleValidated ( _, _) => "" . to_string ( ) ,
151151 }
@@ -165,7 +165,7 @@ impl SimCpuTask for CpuTask {
165165 vec ! [ time]
166166 }
167167 Self :: EBHeaderValidated ( _, _) => vec ! [ config. eb_header_validation] ,
168- Self :: EBBlockValidated ( eb) => {
168+ Self :: EBBlockValidated ( eb, _ ) => {
169169 let mut time = config. eb_body_validation_constant ;
170170 let bytes: u64 = eb. txs . iter ( ) . map ( |tx| tx. bytes ) . sum ( ) ;
171171 time += config. eb_body_validation_per_byte * ( bytes as u32 ) ;
@@ -351,7 +351,7 @@ impl NodeImpl for LinearLeiosNode {
351351 }
352352 CpuTask :: RBBlockValidated ( rb) => self . finish_validating_rb ( rb) ,
353353 CpuTask :: EBHeaderValidated ( from, eb) => self . finish_validating_eb_header ( from, eb) ,
354- CpuTask :: EBBlockValidated ( eb) => self . finish_validating_eb ( eb) ,
354+ CpuTask :: EBBlockValidated ( eb, seen ) => self . finish_validating_eb ( eb, seen ) ,
355355 CpuTask :: VTBundleGenerated ( votes, _) => self . finish_generating_vote_bundle ( votes) ,
356356 CpuTask :: VTBundleValidated ( from, votes) => {
357357 self . finish_validating_vote_bundle ( from, votes)
@@ -748,7 +748,7 @@ impl LinearLeiosNode {
748748 for peer in & self . consumers {
749749 self . queued . send_to ( * peer, Message :: AnnounceEB ( eb_id) ) ;
750750 }
751- self . vote_for_endorser_block ( & eb) ;
751+ self . vote_for_endorser_block ( & eb, self . clock . now ( ) ) ;
752752 }
753753 fn receive_announce_eb ( & mut self , from : NodeId , id : EndorserBlockId ) {
754754 self . leios
@@ -801,11 +801,12 @@ impl LinearLeiosNode {
801801 self . queued . send_to ( * peer, Message :: AnnounceEB ( eb. id ( ) ) ) ;
802802 }
803803
804- self . queued . schedule_cpu_task ( CpuTask :: EBBlockValidated ( eb) ) ;
804+ self . queued
805+ . schedule_cpu_task ( CpuTask :: EBBlockValidated ( eb, self . clock . now ( ) ) ) ;
805806 }
806807
807- fn finish_validating_eb ( & mut self , eb : Arc < EndorserBlock > ) {
808- self . vote_for_endorser_block ( & eb) ;
808+ fn finish_validating_eb ( & mut self , eb : Arc < EndorserBlock > , seen : Timestamp ) {
809+ self . vote_for_endorser_block ( & eb, seen ) ;
809810 }
810811
811812 fn process_certified_ebs ( & mut self , slot : u64 ) {
@@ -837,14 +838,14 @@ impl LinearLeiosNode {
837838
838839// Voting
839840impl LinearLeiosNode {
840- fn vote_for_endorser_block ( & mut self , eb : & Arc < EndorserBlock > ) {
841- if !self . try_vote_for_endorser_block ( eb) && self . sim_config . emit_conformance_events {
841+ fn vote_for_endorser_block ( & mut self , eb : & Arc < EndorserBlock > , seen : Timestamp ) {
842+ if !self . try_vote_for_endorser_block ( eb, seen ) && self . sim_config . emit_conformance_events {
842843 self . tracker
843844 . track_linear_no_vote_generated ( self . id , eb. id ( ) ) ;
844845 }
845846 }
846847
847- fn try_vote_for_endorser_block ( & mut self , eb : & Arc < EndorserBlock > ) -> bool {
848+ fn try_vote_for_endorser_block ( & mut self , eb : & Arc < EndorserBlock > , seen : Timestamp ) -> bool {
848849 let vrf_wins = lottery:: vrf_probabilities ( self . sim_config . vote_probability )
849850 . filter_map ( |f| self . run_vrf ( f) )
850851 . count ( ) ;
@@ -859,7 +860,11 @@ impl LinearLeiosNode {
859860 } ;
860861 self . tracker . track_vote_lottery_won ( id) ;
861862
862- // TODO: sometimes, don't vote
863+ if let Err ( reason) = self . should_vote_for ( eb, seen) {
864+ self . tracker
865+ . track_no_vote ( eb. slot , 0 , self . id , eb. id ( ) , reason) ;
866+ return false ;
867+ }
863868
864869 let mut ebs = BTreeMap :: new ( ) ;
865870 ebs. insert ( eb. id ( ) , vrf_wins) ;
@@ -873,6 +878,23 @@ impl LinearLeiosNode {
873878 true
874879 }
875880
881+ fn should_vote_for ( & self , eb : & EndorserBlock , seen : Timestamp ) -> Result < ( ) , NoVoteReason > {
882+ let must_be_received_by =
883+ Timestamp :: from_secs ( eb. slot + self . sim_config . linear_vote_stage_length ) ;
884+ if seen > must_be_received_by {
885+ // An EB must be received within L_vote slots of its creation.
886+ return Err ( NoVoteReason :: LateEB ) ;
887+ }
888+ if self
889+ . latest_rb ( )
890+ . is_none_or ( |rb| rb. header . eb_announcement != eb. id ( ) )
891+ {
892+ // We only vote for whichever EB we was referenced by the head of the current chain.
893+ return Err ( NoVoteReason :: WrongEB ) ;
894+ }
895+ Ok ( ( ) )
896+ }
897+
876898 fn finish_generating_vote_bundle ( & mut self , votes : VoteBundle ) {
877899 self . tracker . track_votes_generated ( & votes) ;
878900 self . count_votes ( & votes) ;
0 commit comments