@@ -18,6 +18,7 @@ use std::iter::Iterator;
1818use std:: mem;
1919use std:: sync:: { Arc , Weak } ;
2020use std:: thread:: { Builder , JoinHandle } ;
21+ use std:: time:: { Duration , SystemTime , UNIX_EPOCH } ;
2122
2223use ccrypto:: blake256;
2324use ckey:: { public_to_address, verify_schnorr, Address , SchnorrSignature } ;
@@ -651,11 +652,16 @@ impl Worker {
651652 // In the case, self.votes_received is not empty.
652653 self . request_messages_to_all ( vote_step, & BitSet :: all_set ( ) - & self . votes_received ) ;
653654 if !self . already_generated_message ( ) {
654- let block_hash = match & self . last_two_thirds_majority {
655+ let block_hash_candidate = match & self . last_two_thirds_majority {
655656 TwoThirdsMajority :: Empty => self . proposal . imported_block_hash ( ) ,
656657 TwoThirdsMajority :: Unlock ( _) => self . proposal . imported_block_hash ( ) ,
657658 TwoThirdsMajority :: Lock ( _, block_hash) => Some ( * block_hash) ,
658659 } ;
660+ let block_hash = block_hash_candidate. filter ( |hash| {
661+ let block =
662+ self . client ( ) . block ( & BlockId :: Hash ( * hash) ) . expect ( "Already got imported block hash" ) ;
663+ self . is_generation_time_relevant ( & block. decode_header ( ) )
664+ } ) ;
659665 self . generate_and_broadcast_message ( block_hash, is_restoring) ;
660666 }
661667 }
@@ -667,15 +673,10 @@ impl Worker {
667673 self . request_messages_to_all ( vote_step, & BitSet :: all_set ( ) - & self . votes_received ) ;
668674 if !self . already_generated_message ( ) {
669675 let block_hash = match & self . last_two_thirds_majority {
670- TwoThirdsMajority :: Empty => None ,
671- TwoThirdsMajority :: Unlock ( _) => None ,
672- TwoThirdsMajority :: Lock ( locked_view, block_hash) => {
673- if locked_view == & self . view {
674- Some ( * block_hash)
675- } else {
676- None
677- }
676+ TwoThirdsMajority :: Lock ( locked_view, block_hash) if locked_view == & self . view => {
677+ Some ( * block_hash)
678678 }
679+ _ => None ,
679680 } ;
680681 self . generate_and_broadcast_message ( block_hash, is_restoring) ;
681682 }
@@ -686,6 +687,21 @@ impl Worker {
686687 }
687688 }
688689
690+ fn is_generation_time_relevant ( & self , block_header : & Header ) -> bool {
691+ const ACCEPTABLE_FUTURE_GAP : Duration = Duration :: from_secs ( 5 ) ;
692+ const ACCEPTABLE_PAST_GAP : Duration = Duration :: from_secs ( 30 ) ;
693+ let now = SystemTime :: now ( ) ;
694+ let allowed_min = now - ACCEPTABLE_PAST_GAP ;
695+ let allowed_max = now + ACCEPTABLE_FUTURE_GAP ;
696+ let block_generation_time = UNIX_EPOCH . checked_add ( Duration :: from_secs ( block_header. timestamp ( ) ) ) ;
697+
698+ match block_generation_time {
699+ Some ( generation_time) => generation_time <= allowed_max && allowed_min <= generation_time,
700+ // Overflow occurred
701+ None => false ,
702+ }
703+ }
704+
689705 fn locked_proposal_block ( & self , locked_view : View ) -> Result < encoded:: Block , String > {
690706 let vote_step = VoteStep :: new ( self . height , locked_view, Step :: Propose ) ;
691707 let locked_proposal_hash = self . votes . get_block_hashes ( & vote_step) . first ( ) . cloned ( ) ;
0 commit comments