@@ -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 } ;
@@ -667,15 +668,17 @@ impl Worker {
667668 self . request_messages_to_all ( vote_step, & BitSet :: all_set ( ) - & self . votes_received ) ;
668669 if !self . already_generated_message ( ) {
669670 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- }
671+ TwoThirdsMajority :: Lock ( locked_view, block_hash)
672+ if locked_view == & self . view && {
673+ let locked_proposal_block = self
674+ . locked_proposal_block ( * locked_view)
675+ . expect ( "In precommit step, block was imported and we have hash" ) ;
676+ self . is_generation_time_relevant ( & locked_proposal_block. decode_header ( ) )
677+ } =>
678+ {
679+ Some ( * block_hash)
678680 }
681+ _ => None ,
679682 } ;
680683 self . generate_and_broadcast_message ( block_hash, is_restoring) ;
681684 }
@@ -686,6 +689,21 @@ impl Worker {
686689 }
687690 }
688691
692+ fn is_generation_time_relevant ( & self , proposal : & Header ) -> bool {
693+ const ACCEPTABLE_FUTURE_GAP : Duration = Duration :: from_secs ( 5 ) ;
694+ const ACCEPTABLE_PAST_GAP : Duration = Duration :: from_secs ( 30 ) ;
695+ let now = SystemTime :: now ( ) ;
696+ let allowed_min = now - ACCEPTABLE_PAST_GAP ;
697+ let allowed_max = now + ACCEPTABLE_FUTURE_GAP ;
698+ let block_generation_time = UNIX_EPOCH . checked_add ( Duration :: from_secs ( proposal. timestamp ( ) ) ) ;
699+
700+ match block_generation_time {
701+ Some ( generation_time) => generation_time <= allowed_max && allowed_min <= generation_time,
702+ // Overflow occurred
703+ None => false ,
704+ }
705+ }
706+
689707 fn locked_proposal_block ( & self , locked_view : View ) -> Result < encoded:: Block , String > {
690708 let vote_step = VoteStep :: new ( self . height , locked_view, Step :: Propose ) ;
691709 let locked_proposal_hash = self . votes . get_block_hashes ( & vote_step) . first ( ) . cloned ( ) ;
0 commit comments