@@ -17,7 +17,7 @@ mod commands;
17
17
pub mod multiversion;
18
18
pub mod v0;
19
19
20
- use std:: collections:: HashSet ;
20
+ use std:: collections:: { HashMap , HashSet } ;
21
21
use std:: fs:: File ;
22
22
use std:: path:: PathBuf ;
23
23
use std:: sync:: atomic:: { AtomicBool , Ordering } ;
@@ -72,6 +72,7 @@ use super::neon_integrations::{
72
72
copy_dir_all, get_account, get_sortition_info_ch, submit_tx_fallible, Account ,
73
73
} ;
74
74
use crate :: burnchains:: bitcoin:: core_controller:: BitcoinCoreController ;
75
+ use crate :: nakamoto_node:: miner:: TEST_MINE_SKIP ;
75
76
use crate :: neon:: Counters ;
76
77
use crate :: run_loop:: boot_nakamoto;
77
78
use crate :: tests:: nakamoto_integrations:: {
@@ -81,6 +82,7 @@ use crate::tests::neon_integrations::{
81
82
get_chain_info, next_block_and_wait, run_until_burnchain_height, test_observer,
82
83
wait_for_runloop,
83
84
} ;
85
+ use crate :: tests:: signer:: v0:: wait_for_state_machine_update_by_miner_tenure_id;
84
86
use crate :: tests:: to_addr;
85
87
use crate :: BitcoinRegtestController ;
86
88
@@ -544,11 +546,16 @@ impl<Z: SpawnedSignerTrait> SignerTest<Z> {
544
546
}
545
547
546
548
pub fn mine_bitcoin_block ( & self ) {
549
+ let mined_btc_block_time = Instant :: now ( ) ;
547
550
let info = self . get_peer_info ( ) ;
548
551
next_block_and ( & self . running_nodes . btc_regtest_controller , 60 , || {
549
552
Ok ( get_chain_info ( & self . running_nodes . conf ) . burn_block_height > info. burn_block_height )
550
553
} )
551
554
. unwrap ( ) ;
555
+ info ! (
556
+ "Bitcoin block mine time elapsed: {:?}" ,
557
+ mined_btc_block_time. elapsed( )
558
+ ) ;
552
559
}
553
560
554
561
/// Fetch the local signer state machine for all the signers,
@@ -1121,26 +1128,63 @@ impl<Z: SpawnedSignerTrait> SignerTest<Z> {
1121
1128
output
1122
1129
}
1123
1130
1124
- /// Mine a BTC block and wait for a new Stacks block to be mined
1131
+ /// Mine a BTC block and wait for a new Stacks block to be mined, but do not wait for a commit
1125
1132
/// Note: do not use nakamoto blocks mined heuristic if running a test with multiple miners
1126
- fn mine_nakamoto_block ( & self , timeout : Duration , use_nakamoto_blocks_mined : bool ) {
1127
- let mined_block_time = Instant :: now ( ) ;
1128
- let mined_before = self . running_nodes . counters . naka_mined_blocks . get ( ) ;
1129
- let info_before = self . get_peer_info ( ) ;
1130
-
1131
- next_block_and (
1132
- & self . running_nodes . btc_regtest_controller ,
1133
+ fn mine_nakamoto_block_without_commit (
1134
+ & self ,
1135
+ timeout : Duration ,
1136
+ use_nakamoto_blocks_mined : bool ,
1137
+ ) {
1138
+ let info_before = get_chain_info ( & self . running_nodes . conf ) ;
1139
+ info ! ( "Pausing stacks block mining" ) ;
1140
+ TEST_MINE_SKIP . set ( true ) ;
1141
+ let mined_blocks = self . running_nodes . counters . naka_mined_blocks . clone ( ) ;
1142
+ let mined_before = mined_blocks. get ( ) ;
1143
+ self . mine_bitcoin_block ( ) ;
1144
+ wait_for_state_machine_update_by_miner_tenure_id (
1133
1145
timeout. as_secs ( ) ,
1134
- || {
1135
- let info_after = self . get_peer_info ( ) ;
1136
- let blocks_mined = self . running_nodes . counters . naka_mined_blocks . get ( ) ;
1137
- Ok ( info_after. stacks_tip_height > info_before. stacks_tip_height
1138
- && ( !use_nakamoto_blocks_mined || blocks_mined > mined_before) )
1139
- } ,
1146
+ & get_chain_info ( & self . running_nodes . conf ) . pox_consensus ,
1147
+ & self . signer_addresses_versions_majority ( ) ,
1140
1148
)
1141
- . unwrap ( ) ;
1142
- let mined_block_elapsed_time = mined_block_time. elapsed ( ) ;
1143
- info ! ( "Nakamoto block mine time elapsed: {mined_block_elapsed_time:?}" ) ;
1149
+ . expect ( "Failed to update signer state machine" ) ;
1150
+
1151
+ info ! ( "Unpausing stacks block mining" ) ;
1152
+ let mined_block_time = Instant :: now ( ) ;
1153
+ TEST_MINE_SKIP . set ( false ) ;
1154
+ // Do these wait for's in two steps not only for increased timeout but for easier debugging.
1155
+ // Ensure that the tenure change transaction is mined
1156
+ wait_for ( timeout. as_secs ( ) , || {
1157
+ Ok ( get_chain_info ( & self . running_nodes . conf ) . stacks_tip_height
1158
+ > info_before. stacks_tip_height
1159
+ && ( !use_nakamoto_blocks_mined || mined_blocks. get ( ) > mined_before) )
1160
+ } )
1161
+ . expect ( "Failed to mine Tenure Change block" ) ;
1162
+ info ! (
1163
+ "Nakamoto block mine time elapsed: {:?}" ,
1164
+ mined_block_time. elapsed( )
1165
+ ) ;
1166
+ }
1167
+
1168
+ /// Mine a BTC block and wait for a new Stacks block to be mined and commit to be submitted
1169
+ /// Note: do not use nakamoto blocks mined heuristic if running a test with multiple miners
1170
+ fn mine_nakamoto_block ( & self , timeout : Duration , use_nakamoto_blocks_mined : bool ) {
1171
+ let Counters {
1172
+ naka_submitted_commits : commits_submitted,
1173
+ naka_submitted_commit_last_burn_height : commits_last_burn_height,
1174
+ naka_submitted_commit_last_stacks_tip : commits_last_stacks_tip,
1175
+ ..
1176
+ } = self . running_nodes . counters . clone ( ) ;
1177
+ let commits_before = commits_submitted. get ( ) ;
1178
+ let commit_burn_height_before = commits_last_burn_height. get ( ) ;
1179
+ self . mine_nakamoto_block_without_commit ( timeout, use_nakamoto_blocks_mined) ;
1180
+ // Ensure the subsequent block commit confirms the previous Tenure Change block
1181
+ let stacks_tip_height = get_chain_info ( & self . running_nodes . conf ) . stacks_tip_height ;
1182
+ wait_for ( timeout. as_secs ( ) , || {
1183
+ Ok ( commits_submitted. get ( ) > commits_before
1184
+ && commits_last_burn_height. get ( ) > commit_burn_height_before
1185
+ && commits_last_stacks_tip. get ( ) >= stacks_tip_height)
1186
+ } )
1187
+ . expect ( "Failed to update Block Commit" ) ;
1144
1188
}
1145
1189
1146
1190
fn mine_block_wait_on_processing (
@@ -1366,7 +1410,7 @@ impl<Z: SpawnedSignerTrait> SignerTest<Z> {
1366
1410
. collect ( )
1367
1411
}
1368
1412
1369
- /// Get the signer addresses and corresponding versions
1413
+ /// Get the signer addresses and corresponding versions configured versions
1370
1414
pub fn signer_addresses_versions ( & self ) -> Vec < ( StacksAddress , u64 ) > {
1371
1415
self . signer_stacks_private_keys
1372
1416
. iter ( )
@@ -1380,6 +1424,33 @@ impl<Z: SpawnedSignerTrait> SignerTest<Z> {
1380
1424
. collect ( )
1381
1425
}
1382
1426
1427
+ /// Get the signer addresses and corresponding majority versions
1428
+ pub fn signer_addresses_versions_majority ( & self ) -> Vec < ( StacksAddress , u64 ) > {
1429
+ let mut signer_address_versions = self . signer_addresses_versions ( ) ;
1430
+ let majority = ( signer_address_versions. len ( ) * 7 / 10 ) as u64 ;
1431
+ let mut protocol_versions = HashMap :: new ( ) ;
1432
+ for ( _, version) in & self . signer_addresses_versions ( ) {
1433
+ let entry = protocol_versions. entry ( * version) . or_insert_with ( || 0 ) ;
1434
+ * entry += 1 ;
1435
+ }
1436
+
1437
+ // find the highest version number supported by a threshold number of signers
1438
+ let mut protocol_versions: Vec < _ > = protocol_versions. into_iter ( ) . collect ( ) ;
1439
+ protocol_versions. sort_by_key ( |( version, _) | * version) ;
1440
+ let mut total_weight_support = 0 ;
1441
+ for ( version, weight_support) in protocol_versions. into_iter ( ) . rev ( ) {
1442
+ total_weight_support += weight_support;
1443
+ if total_weight_support > majority {
1444
+ // We need to actually overwrite the versions passed in since the signers will go with the majority value if they can
1445
+ signer_address_versions
1446
+ . iter_mut ( )
1447
+ . for_each ( |( _, v) | * v = version) ;
1448
+ break ;
1449
+ }
1450
+ }
1451
+ signer_address_versions
1452
+ }
1453
+
1383
1454
/// Get the signer public keys for the given reward cycle
1384
1455
fn get_signer_public_keys ( & self , reward_cycle : u64 ) -> Vec < StacksPublicKey > {
1385
1456
let entries = self . get_reward_set_signers ( reward_cycle) ;
0 commit comments