@@ -1460,6 +1460,7 @@ fn multiple_miners() {
1460
1460
let node_2_rpc_bind = format ! ( "{localhost}:{node_2_rpc}" ) ;
1461
1461
let mut node_2_listeners = Vec :: new ( ) ;
1462
1462
1463
+ let max_nakamoto_tenures = 30 ;
1463
1464
// partition the signer set so that ~half are listening and using node 1 for RPC and events,
1464
1465
// and the rest are using node 2
1465
1466
@@ -1481,6 +1482,7 @@ fn multiple_miners() {
1481
1482
config. node . p2p_address = format ! ( "{localhost}:{node_1_p2p}" ) ;
1482
1483
config. miner . wait_on_interim_blocks = Duration :: from_secs ( 5 ) ;
1483
1484
config. node . pox_sync_sample_secs = 30 ;
1485
+ config. burnchain . pox_reward_length = Some ( max_nakamoto_tenures) ;
1484
1486
1485
1487
config. node . seed = btc_miner_1_seed. clone ( ) ;
1486
1488
config. node . local_peer_seed = btc_miner_1_seed. clone ( ) ;
@@ -1560,8 +1562,6 @@ fn multiple_miners() {
1560
1562
1561
1563
info ! ( "------------------------- Reached Epoch 3.0 -------------------------" ) ;
1562
1564
1563
- let max_nakamoto_tenures = 20 ;
1564
-
1565
1565
// due to the random nature of mining sortitions, the way this test is structured
1566
1566
// is that we keep track of how many tenures each miner produced, and once enough sortitions
1567
1567
// have been produced such that each miner has produced 3 tenures, we stop and check the
@@ -1645,11 +1645,11 @@ fn multiple_miners() {
1645
1645
assert_eq ! ( peer_1_height, peer_2_height) ;
1646
1646
assert_eq ! (
1647
1647
peer_1_height,
1648
- pre_nakamoto_peer_1_height + btc_blocks_mined - 1
1648
+ pre_nakamoto_peer_1_height + btc_blocks_mined as u64 - 1
1649
1649
) ;
1650
1650
assert_eq ! (
1651
1651
btc_blocks_mined,
1652
- u64 :: try_from( miner_1_tenures + miner_2_tenures) . unwrap( )
1652
+ u32 :: try_from( miner_1_tenures + miner_2_tenures) . unwrap( )
1653
1653
) ;
1654
1654
1655
1655
rl2_coord_channels
@@ -1664,7 +1664,7 @@ fn multiple_miners() {
1664
1664
/// Read processed nakamoto block IDs from the test observer, and use `config` to open
1665
1665
/// a chainstate DB and returns their corresponding StacksHeaderInfos
1666
1666
fn get_nakamoto_headers ( config : & Config ) -> Vec < StacksHeaderInfo > {
1667
- let nakamoto_block_ids: Vec < _ > = test_observer:: get_blocks ( )
1667
+ let nakamoto_block_ids: HashSet < _ > = test_observer:: get_blocks ( )
1668
1668
. into_iter ( )
1669
1669
. filter_map ( |block_json| {
1670
1670
if block_json
@@ -1746,6 +1746,8 @@ fn miner_forking() {
1746
1746
let node_2_rpc_bind = format ! ( "{localhost}:{node_2_rpc}" ) ;
1747
1747
let mut node_2_listeners = Vec :: new ( ) ;
1748
1748
1749
+ let max_sortitions = 30 ;
1750
+
1749
1751
// partition the signer set so that ~half are listening and using node 1 for RPC and events,
1750
1752
// and the rest are using node 2
1751
1753
@@ -1776,6 +1778,7 @@ fn miner_forking() {
1776
1778
config. burnchain . local_mining_public_key = Some ( btc_miner_1_pk. to_hex ( ) ) ;
1777
1779
config. miner . mining_key = Some ( Secp256k1PrivateKey :: from_seed ( & [ 1 ] ) ) ;
1778
1780
config. node . pox_sync_sample_secs = 30 ;
1781
+ config. burnchain . pox_reward_length = Some ( max_sortitions as u32 ) ;
1779
1782
1780
1783
config. events_observers . retain ( |listener| {
1781
1784
let Ok ( addr) = std:: net:: SocketAddr :: from_str ( & listener. endpoint ) else {
@@ -1797,11 +1800,10 @@ fn miner_forking() {
1797
1800
) ;
1798
1801
let conf = signer_test. running_nodes . conf . clone ( ) ;
1799
1802
let mut conf_node_2 = conf. clone ( ) ;
1800
- let localhost = "127.0.0.1" ;
1801
- conf_node_2. node . rpc_bind = format ! ( "{}:{}" , localhost, node_2_rpc) ;
1802
- conf_node_2. node . p2p_bind = format ! ( "{}:{}" , localhost, node_2_p2p) ;
1803
- conf_node_2. node . data_url = format ! ( "http://{}:{}" , localhost, node_2_rpc) ;
1804
- conf_node_2. node . p2p_address = format ! ( "{}:{}" , localhost, node_2_p2p) ;
1803
+ conf_node_2. node . rpc_bind = node_2_rpc_bind;
1804
+ conf_node_2. node . p2p_bind = format ! ( "{localhost}:{node_2_p2p}" ) ;
1805
+ conf_node_2. node . data_url = format ! ( "http://{localhost}:{node_2_rpc}" ) ;
1806
+ conf_node_2. node . p2p_address = format ! ( "{localhost}:{node_2_p2p}" ) ;
1805
1807
conf_node_2. node . seed = btc_miner_2_seed. clone ( ) ;
1806
1808
conf_node_2. burnchain . local_mining_public_key = Some ( btc_miner_2_pk. to_hex ( ) ) ;
1807
1809
conf_node_2. node . local_peer_seed = btc_miner_2_seed. clone ( ) ;
@@ -1931,7 +1933,6 @@ fn miner_forking() {
1931
1933
// (a) its the first nakamoto tenure
1932
1934
// (b) the prior sortition didn't have a tenure (because by this time RL2 will have up-to-date block processing)
1933
1935
let mut expects_miner_2_to_be_valid = true ;
1934
- let max_sortitions = 20 ;
1935
1936
// due to the random nature of mining sortitions, the way this test is structured
1936
1937
// is that keeps track of two scenarios that we want to cover, and once enough sortitions
1937
1938
// have been produced to cover those scenarios, it stops and checks the results at the end.
@@ -3242,7 +3243,8 @@ fn signer_set_rollover() {
3242
3243
3243
3244
#[ test]
3244
3245
#[ ignore]
3245
- /// This test checks that the signers will broadcast a block once they receive enough signatures.
3246
+ /// This test checks that the miners and signers will not produce Nakamoto blocks
3247
+ /// until the minimum time has passed between blocks.
3246
3248
fn min_gap_between_blocks ( ) {
3247
3249
if env:: var ( "BITCOIND_TEST" ) != Ok ( "1" . into ( ) ) {
3248
3250
return ;
@@ -3259,11 +3261,14 @@ fn min_gap_between_blocks() {
3259
3261
let sender_addr = tests:: to_addr ( & sender_sk) ;
3260
3262
let send_amt = 100 ;
3261
3263
let send_fee = 180 ;
3264
+
3265
+ let mut sender_nonce = 0 ;
3266
+ let interim_blocks = 5 ;
3262
3267
let recipient = PrincipalData :: from ( StacksAddress :: burn_address ( false ) ) ;
3263
3268
let time_between_blocks_ms = 10_000 ;
3264
3269
let mut signer_test: SignerTest < SpawnedSigner > = SignerTest :: new_with_config_modifications (
3265
3270
num_signers,
3266
- vec ! [ ( sender_addr. clone( ) , send_amt + send_fee) ] ,
3271
+ vec ! [ ( sender_addr. clone( ) , ( send_amt + send_fee) * interim_blocks ) ] ,
3267
3272
|_config| { } ,
3268
3273
|config| {
3269
3274
config. miner . min_time_between_blocks_ms = time_between_blocks_ms;
@@ -3276,73 +3281,81 @@ fn min_gap_between_blocks() {
3276
3281
3277
3282
signer_test. boot_to_epoch_3 ( ) ;
3278
3283
3279
- info ! ( "Ensure that the first Nakamoto block is mined after the gap is exceeded " ) ;
3284
+ info ! ( "Ensure that the first Nakamoto block was mined" ) ;
3280
3285
let blocks = get_nakamoto_headers ( & signer_test. running_nodes . conf ) ;
3281
3286
assert_eq ! ( blocks. len( ) , 1 ) ;
3282
- let first_block = blocks. last ( ) . unwrap ( ) ;
3283
- let blocks = test_observer:: get_blocks ( ) ;
3284
- let parent = blocks
3285
- . iter ( )
3286
- . find ( |b| b. get ( "block_height" ) . unwrap ( ) == first_block. stacks_block_height - 1 )
3287
- . unwrap ( ) ;
3288
- let first_block_time = first_block
3289
- . anchored_header
3290
- . as_stacks_nakamoto ( )
3291
- . unwrap ( )
3292
- . timestamp ;
3293
- let parent_block_time = parent. get ( "burn_block_time" ) . unwrap ( ) . as_u64 ( ) . unwrap ( ) ;
3294
- assert ! (
3295
- Duration :: from_secs( first_block_time - parent_block_time)
3296
- >= Duration :: from_millis( time_between_blocks_ms) ,
3297
- "First block proposed before gap was exceeded: {}s - {}s > {}ms" ,
3298
- first_block_time,
3299
- parent_block_time,
3300
- time_between_blocks_ms
3301
- ) ;
3287
+ // mine the interim blocks
3288
+ info ! ( "Mining interim blocks" ) ;
3289
+ for interim_block_ix in 0 ..interim_blocks {
3290
+ let blocks_processed_before = signer_test
3291
+ . running_nodes
3292
+ . nakamoto_blocks_mined
3293
+ . load ( Ordering :: SeqCst ) ;
3294
+ // submit a tx so that the miner will mine an extra block
3295
+ let transfer_tx = make_stacks_transfer (
3296
+ & sender_sk,
3297
+ sender_nonce,
3298
+ send_fee,
3299
+ signer_test. running_nodes . conf . burnchain . chain_id ,
3300
+ & recipient,
3301
+ send_amt,
3302
+ ) ;
3303
+ sender_nonce += 1 ;
3304
+ submit_tx ( & http_origin, & transfer_tx) ;
3302
3305
3303
- // Submit a tx so that the miner will mine a block
3304
- let sender_nonce = 0 ;
3305
- let transfer_tx = make_stacks_transfer (
3306
- & sender_sk ,
3307
- sender_nonce ,
3308
- send_fee ,
3309
- signer_test . running_nodes . conf . burnchain . chain_id ,
3310
- & recipient ,
3311
- send_amt ,
3312
- ) ;
3313
- submit_tx ( & http_origin , & transfer_tx ) ;
3306
+ info ! ( "Submitted transfer tx and waiting for block to be processed" ) ;
3307
+ wait_for ( 60 , || {
3308
+ let blocks_processed = signer_test
3309
+ . running_nodes
3310
+ . nakamoto_blocks_mined
3311
+ . load ( Ordering :: SeqCst ) ;
3312
+ Ok ( blocks_processed > blocks_processed_before )
3313
+ } )
3314
+ . unwrap ( ) ;
3315
+ info ! ( "Mined interim block:{}" , interim_block_ix ) ;
3316
+ }
3314
3317
3315
- info ! ( "Submitted transfer tx and waiting for block to be processed. Ensure it does not arrive before the gap is exceeded" ) ;
3316
3318
wait_for ( 60 , || {
3317
- let blocks = get_nakamoto_headers ( & signer_test. running_nodes . conf ) ;
3318
- Ok ( blocks . len ( ) >= 2 )
3319
+ let new_blocks = get_nakamoto_headers ( & signer_test. running_nodes . conf ) ;
3320
+ Ok ( new_blocks . len ( ) == blocks . len ( ) + interim_blocks as usize )
3319
3321
} )
3320
3322
. unwrap ( ) ;
3321
3323
3322
- // Verify that the second Nakamoto block is mined after the gap is exceeded
3323
- let blocks = get_nakamoto_headers ( & signer_test. running_nodes . conf ) ;
3324
- let last_block = blocks. last ( ) . unwrap ( ) ;
3325
- let last_block_time = last_block
3326
- . anchored_header
3327
- . as_stacks_nakamoto ( )
3328
- . unwrap ( )
3329
- . timestamp ;
3330
- assert ! ( blocks. len( ) >= 2 , "Expected at least 2 mined blocks" ) ;
3331
- let penultimate_block = blocks. get ( blocks. len ( ) - 2 ) . unwrap ( ) ;
3332
- let penultimate_block_time = penultimate_block
3333
- . anchored_header
3334
- . as_stacks_nakamoto ( )
3335
- . unwrap ( )
3336
- . timestamp ;
3337
- assert ! (
3338
- Duration :: from_secs( last_block_time - penultimate_block_time)
3339
- >= Duration :: from_millis( time_between_blocks_ms) ,
3340
- "Block proposed before gap was exceeded: {}s - {}s > {}ms" ,
3341
- last_block_time,
3342
- penultimate_block_time,
3343
- time_between_blocks_ms
3344
- ) ;
3345
-
3324
+ // Verify that every Nakamoto block is mined after the gap is exceeded between each
3325
+ let mut blocks = get_nakamoto_headers ( & signer_test. running_nodes . conf ) ;
3326
+ blocks. sort_by ( |a, b| a. stacks_block_height . cmp ( & b. stacks_block_height ) ) ;
3327
+ for i in 1 ..blocks. len ( ) {
3328
+ let block = & blocks[ i] ;
3329
+ let parent_block = & blocks[ i - 1 ] ;
3330
+ assert_eq ! (
3331
+ block. stacks_block_height,
3332
+ parent_block. stacks_block_height + 1
3333
+ ) ;
3334
+ info ! (
3335
+ "Checking that the time between blocks {} and {} is respected" ,
3336
+ parent_block. stacks_block_height, block. stacks_block_height
3337
+ ) ;
3338
+ let block_time = block
3339
+ . anchored_header
3340
+ . as_stacks_nakamoto ( )
3341
+ . unwrap ( )
3342
+ . timestamp ;
3343
+ let parent_block_time = parent_block
3344
+ . anchored_header
3345
+ . as_stacks_nakamoto ( )
3346
+ . unwrap ( )
3347
+ . timestamp ;
3348
+ assert ! (
3349
+ block_time > parent_block_time,
3350
+ "Block time is BEFORE parent block time"
3351
+ ) ;
3352
+ assert ! (
3353
+ Duration :: from_secs( block_time - parent_block_time)
3354
+ >= Duration :: from_millis( time_between_blocks_ms) ,
3355
+ "Block mined before gap was exceeded: {block_time}s - {parent_block_time}s > {time_between_blocks_ms}ms" ,
3356
+ ) ;
3357
+ }
3358
+ debug ! ( "Shutting down min_gap_between_blocks test" ) ;
3346
3359
signer_test. shutdown ( ) ;
3347
3360
}
3348
3361
@@ -5316,7 +5329,19 @@ fn signing_in_0th_tenure_of_reward_cycle() {
5316
5329
} )
5317
5330
. unwrap ( ) ;
5318
5331
5319
- for signer in & signer_public_keys {
5332
+ let block_mined = test_observer:: get_mined_nakamoto_blocks ( )
5333
+ . last ( )
5334
+ . unwrap ( )
5335
+ . clone ( ) ;
5336
+ // Must ensure that the signers that signed the block have their blocks_signed updated appropriately
5337
+ for signature in & block_mined. signer_signature {
5338
+ let signer = signer_public_keys
5339
+ . iter ( )
5340
+ . find ( |pk| {
5341
+ pk. verify ( block_mined. signer_signature_hash . as_bytes ( ) , signature)
5342
+ . unwrap ( )
5343
+ } )
5344
+ . expect ( "Unknown signer signature" ) ;
5320
5345
let blocks_signed = get_v3_signer ( & signer, next_reward_cycle) ;
5321
5346
assert_eq ! ( blocks_signed, 1 ) ;
5322
5347
}
0 commit comments