@@ -45,8 +45,8 @@ use stacks::chainstate::stacks::{
45
45
use stacks:: net:: p2p:: NetworkHandle ;
46
46
use stacks:: net:: stackerdb:: StackerDBs ;
47
47
use stacks:: net:: { NakamotoBlocksData , StacksMessageType } ;
48
+ use stacks:: util:: get_epoch_time_secs;
48
49
use stacks:: util:: secp256k1:: MessageSignature ;
49
- use stacks:: util:: { get_epoch_time_secs, sleep_ms} ;
50
50
use stacks_common:: codec:: read_next;
51
51
use stacks_common:: types:: chainstate:: { StacksAddress , StacksBlockId } ;
52
52
use stacks_common:: types:: { PrivateKey , StacksEpochId } ;
@@ -318,10 +318,17 @@ impl BlockMinerThread {
318
318
}
319
319
}
320
320
}
321
- self . wait_min_time_between_blocks ( ) ?;
322
321
323
322
match self . mine_block ( & stackerdbs) {
324
- Ok ( x) => break Some ( x) ,
323
+ Ok ( x) => {
324
+ if !self . validate_timestamp ( & x) ? {
325
+ info ! ( "Block mined too quickly. Will try again." ;
326
+ "block_timestamp" => x. header. timestamp,
327
+ ) ;
328
+ continue ;
329
+ }
330
+ break Some ( x) ;
331
+ }
325
332
Err ( NakamotoNodeError :: MiningFailure ( ChainstateError :: MinerAborted ) ) => {
326
333
info ! ( "Miner interrupted while mining, will try again" ) ;
327
334
// sleep, and try again. if the miner was interrupted because the burnchain
@@ -1040,34 +1047,40 @@ impl BlockMinerThread {
1040
1047
Some ( vrf_proof)
1041
1048
}
1042
1049
1043
- /// Wait the minimum time between blocks before mining a new block (if necessary)
1050
+ /// Check that the provided block is not mined too quickly after the parent block.
1044
1051
/// This is to ensure that the signers do not reject the block due to the block being mined within the same second as the parent block.
1045
- fn wait_min_time_between_blocks ( & self ) -> Result < ( ) , NakamotoNodeError > {
1046
- let burn_db_path = self . config . get_burn_db_file_path ( ) ;
1047
- let mut burn_db =
1048
- SortitionDB :: open ( & burn_db_path, false , self . burnchain . pox_constants . clone ( ) )
1049
- . expect ( "FATAL: could not open sortition DB" ) ;
1050
-
1051
- let mut chain_state = neon_node:: open_chainstate_with_faults ( & self . config )
1052
+ fn validate_timestamp ( & self , x : & NakamotoBlock ) -> Result < bool , NakamotoNodeError > {
1053
+ let chain_state = neon_node:: open_chainstate_with_faults ( & self . config )
1052
1054
. expect ( "FATAL: could not open chainstate DB" ) ;
1053
- let parent_block_info = self . load_block_parent_info ( & mut burn_db, & mut chain_state) ?;
1054
- let time_since_parent_ms = get_epoch_time_secs ( )
1055
- . saturating_sub ( parent_block_info. stacks_parent_header . burn_header_timestamp )
1056
- / 1000 ;
1055
+ let stacks_parent_header =
1056
+ NakamotoChainState :: get_block_header ( chain_state. db ( ) , & x. header . parent_block_id )
1057
+ . map_err ( |e| {
1058
+ error ! (
1059
+ "Could not query header info for parent block ID {}: {:?}" ,
1060
+ & x. header. parent_block_id, & e
1061
+ ) ;
1062
+ NakamotoNodeError :: ParentNotFound
1063
+ } ) ?
1064
+ . ok_or_else ( || {
1065
+ error ! (
1066
+ "No header info for parent block ID {}" ,
1067
+ & x. header. parent_block_id
1068
+ ) ;
1069
+ NakamotoNodeError :: ParentNotFound
1070
+ } ) ?;
1071
+ let current_timestamp = get_epoch_time_secs ( ) ;
1072
+ let time_since_parent_ms =
1073
+ current_timestamp. saturating_sub ( stacks_parent_header. burn_header_timestamp ) * 1000 ;
1057
1074
if time_since_parent_ms < self . config . miner . min_time_between_blocks_ms {
1058
- let wait_ms = self
1059
- . config
1060
- . miner
1061
- . min_time_between_blocks_ms
1062
- . saturating_sub ( time_since_parent_ms) ;
1063
- info ! ( "Parent block mined {} ms ago, waiting {} ms before mining a new block" , time_since_parent_ms, wait_ms;
1064
- "parent_block_id" => %parent_block_info. stacks_parent_header. index_block_hash( ) ,
1065
- "parent_block_height" => parent_block_info. stacks_parent_header. stacks_block_height,
1066
- "parent_block_timestamp" => parent_block_info. stacks_parent_header. burn_header_timestamp,
1075
+ debug ! ( "Parent block mined {time_since_parent_ms} ms ago. Required minimum gap between blocks is {} ms" , self . config. miner. min_time_between_blocks_ms;
1076
+ "current_timestamp" => current_timestamp,
1077
+ "parent_block_id" => %stacks_parent_header. index_block_hash( ) ,
1078
+ "parent_block_height" => stacks_parent_header. stacks_block_height,
1079
+ "parent_block_timestamp" => stacks_parent_header. burn_header_timestamp,
1067
1080
) ;
1068
- sleep_ms ( wait_ms ) ;
1081
+ return Ok ( false ) ;
1069
1082
}
1070
- Ok ( ( ) )
1083
+ Ok ( true )
1071
1084
}
1072
1085
1073
1086
// TODO: add tests from mutation testing results #4869
0 commit comments