@@ -17,7 +17,7 @@ mod commands;
1717pub mod multiversion;
1818pub mod v0;
1919
20- use std:: collections:: HashSet ;
20+ use std:: collections:: { HashMap , HashSet } ;
2121use std:: fs:: File ;
2222use std:: path:: PathBuf ;
2323use std:: sync:: atomic:: { AtomicBool , Ordering } ;
@@ -72,6 +72,7 @@ use super::neon_integrations::{
7272 copy_dir_all, get_account, get_sortition_info_ch, submit_tx_fallible, Account ,
7373} ;
7474use crate :: burnchains:: bitcoin:: core_controller:: BitcoinCoreController ;
75+ use crate :: nakamoto_node:: miner:: TEST_MINE_SKIP ;
7576use crate :: neon:: Counters ;
7677use crate :: run_loop:: boot_nakamoto;
7778use crate :: tests:: nakamoto_integrations:: {
@@ -81,6 +82,7 @@ use crate::tests::neon_integrations::{
8182 get_chain_info, next_block_and_wait, run_until_burnchain_height, test_observer,
8283 wait_for_runloop,
8384} ;
85+ use crate :: tests:: signer:: v0:: wait_for_state_machine_update_by_miner_tenure_id;
8486use crate :: tests:: to_addr;
8587use crate :: BitcoinRegtestController ;
8688
@@ -544,11 +546,16 @@ impl<Z: SpawnedSignerTrait> SignerTest<Z> {
544546 }
545547
546548 pub fn mine_bitcoin_block ( & self ) {
549+ let mined_btc_block_time = Instant :: now ( ) ;
547550 let info = self . get_peer_info ( ) ;
548551 next_block_and ( & self . running_nodes . btc_regtest_controller , 60 , || {
549552 Ok ( get_chain_info ( & self . running_nodes . conf ) . burn_block_height > info. burn_block_height )
550553 } )
551554 . unwrap ( ) ;
555+ info ! (
556+ "Bitcoin block mine time elapsed: {:?}" ,
557+ mined_btc_block_time. elapsed( )
558+ ) ;
552559 }
553560
554561 /// Fetch the local signer state machine for all the signers,
@@ -1121,26 +1128,63 @@ impl<Z: SpawnedSignerTrait> SignerTest<Z> {
11211128 output
11221129 }
11231130
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
11251132 /// 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 (
11331145 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 ( ) ,
11401148 )
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" ) ;
11441188 }
11451189
11461190 fn mine_block_wait_on_processing (
@@ -1366,7 +1410,7 @@ impl<Z: SpawnedSignerTrait> SignerTest<Z> {
13661410 . collect ( )
13671411 }
13681412
1369- /// Get the signer addresses and corresponding versions
1413+ /// Get the signer addresses and corresponding versions configured versions
13701414 pub fn signer_addresses_versions ( & self ) -> Vec < ( StacksAddress , u64 ) > {
13711415 self . signer_stacks_private_keys
13721416 . iter ( )
@@ -1380,6 +1424,33 @@ impl<Z: SpawnedSignerTrait> SignerTest<Z> {
13801424 . collect ( )
13811425 }
13821426
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+
13831454 /// Get the signer public keys for the given reward cycle
13841455 fn get_signer_public_keys ( & self , reward_cycle : u64 ) -> Vec < StacksPublicKey > {
13851456 let entries = self . get_reward_set_signers ( reward_cycle) ;
0 commit comments