Skip to content

Commit 18ec305

Browse files
authored
Merge pull request #5034 from stacks-network/test/miner-forking-signers
Test: 2 miners with one attempting forks
2 parents 6b05a3f + 13e73fb commit 18ec305

File tree

6 files changed

+477
-37
lines changed

6 files changed

+477
-37
lines changed

.github/workflows/bitcoin-tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ jobs:
9393
- tests::signer::v0::bitcoind_forking_test
9494
- tests::signer::v0::multiple_miners
9595
- tests::signer::v0::mock_sign_epoch_25
96+
- tests::signer::v0::miner_forking
9697
- tests::nakamoto_integrations::stack_stx_burn_op_integration_test
9798
- tests::nakamoto_integrations::check_block_heights
9899
- tests::nakamoto_integrations::clarity_burn_state

testnet/stacks-node/src/nakamoto_node/relayer.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,6 @@ use crate::run_loop::nakamoto::{Globals, RunLoop};
6666
use crate::run_loop::RegisteredKey;
6767
use crate::BitcoinRegtestController;
6868

69-
#[cfg(test)]
70-
lazy_static::lazy_static! {
71-
pub static ref TEST_SKIP_COMMIT_OP: std::sync::Mutex<Option<bool>> = std::sync::Mutex::new(None);
72-
}
73-
7469
/// Command types for the Nakamoto relayer thread, issued to it by other threads
7570
pub enum RelayerDirective {
7671
/// Handle some new data that arrived on the network (such as blocks, transactions, and
@@ -937,7 +932,15 @@ impl RelayerThread {
937932
let mut last_committed = self.make_block_commit(&tip_block_ch, &tip_block_bh)?;
938933
#[cfg(test)]
939934
{
940-
if TEST_SKIP_COMMIT_OP.lock().unwrap().unwrap_or(false) {
935+
if self
936+
.globals
937+
.counters
938+
.naka_skip_commit_op
939+
.0
940+
.lock()
941+
.unwrap()
942+
.unwrap_or(false)
943+
{
941944
warn!("Relayer: not submitting block-commit to bitcoin network due to test directive.");
942945
return Ok(());
943946
}

testnet/stacks-node/src/run_loop/neon.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,17 @@ impl std::ops::Deref for RunLoopCounter {
8282
}
8383
}
8484

85+
#[cfg(test)]
86+
#[derive(Clone)]
87+
pub struct TestFlag(pub Arc<std::sync::Mutex<Option<bool>>>);
88+
89+
#[cfg(test)]
90+
impl Default for TestFlag {
91+
fn default() -> Self {
92+
Self(Arc::new(std::sync::Mutex::new(None)))
93+
}
94+
}
95+
8596
#[derive(Clone, Default)]
8697
pub struct Counters {
8798
pub blocks_processed: RunLoopCounter,
@@ -95,6 +106,9 @@ pub struct Counters {
95106
pub naka_mined_blocks: RunLoopCounter,
96107
pub naka_proposed_blocks: RunLoopCounter,
97108
pub naka_mined_tenures: RunLoopCounter,
109+
110+
#[cfg(test)]
111+
pub naka_skip_commit_op: TestFlag,
98112
}
99113

100114
impl Counters {

testnet/stacks-node/src/tests/nakamoto_integrations.rs

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ use wsts::net::Message;
9595
use super::bitcoin_regtest::BitcoinCoreController;
9696
use crate::config::{EventKeyType, EventObserverConfig, InitialBalance};
9797
use crate::nakamoto_node::miner::TEST_BROADCAST_STALL;
98-
use crate::nakamoto_node::relayer::TEST_SKIP_COMMIT_OP;
9998
use crate::neon::{Counters, RunLoopCounter};
10099
use crate::operations::BurnchainOpSigner;
101100
use crate::run_loop::boot_nakamoto;
@@ -626,6 +625,21 @@ where
626625
Ok(())
627626
}
628627

628+
pub fn wait_for<F>(timeout_secs: u64, mut check: F) -> Result<(), String>
629+
where
630+
F: FnMut() -> Result<bool, String>,
631+
{
632+
let start = Instant::now();
633+
while !check()? {
634+
if start.elapsed() > Duration::from_secs(timeout_secs) {
635+
error!("Timed out waiting for check to process");
636+
return Err("Timed out".into());
637+
}
638+
thread::sleep(Duration::from_millis(100));
639+
}
640+
Ok(())
641+
}
642+
629643
/// Mine a bitcoin block, and wait until:
630644
/// (1) a new block has been processed by the coordinator
631645
pub fn next_block_and_process_new_stacks_block(
@@ -1627,6 +1641,10 @@ fn multiple_miners() {
16271641

16281642
let (mut naka_conf, _miner_account) = naka_neon_integration_conf(None);
16291643
naka_conf.node.local_peer_seed = vec![1, 1, 1, 1];
1644+
naka_conf.miner.mining_key = Some(Secp256k1PrivateKey::from_seed(&[1]));
1645+
1646+
let node_2_rpc = 51026;
1647+
let node_2_p2p = 51025;
16301648
let http_origin = format!("http://{}", &naka_conf.node.rpc_bind);
16311649
naka_conf.miner.wait_on_interim_blocks = Duration::from_secs(1);
16321650
let sender_sk = Secp256k1PrivateKey::new();
@@ -1651,7 +1669,11 @@ fn multiple_miners() {
16511669
let stacker_sk = setup_stacker(&mut naka_conf);
16521670

16531671
let mut conf_node_2 = naka_conf.clone();
1654-
set_random_binds(&mut conf_node_2);
1672+
let localhost = "127.0.0.1";
1673+
conf_node_2.node.rpc_bind = format!("{}:{}", localhost, node_2_rpc);
1674+
conf_node_2.node.p2p_bind = format!("{}:{}", localhost, node_2_p2p);
1675+
conf_node_2.node.data_url = format!("http://{}:{}", localhost, node_2_rpc);
1676+
conf_node_2.node.p2p_address = format!("{}:{}", localhost, node_2_p2p);
16551677
conf_node_2.node.seed = vec![2, 2, 2, 2];
16561678
conf_node_2.burnchain.local_mining_public_key = Some(
16571679
Keychain::default(conf_node_2.node.seed.clone())
@@ -1660,6 +1682,8 @@ fn multiple_miners() {
16601682
);
16611683
conf_node_2.node.local_peer_seed = vec![2, 2, 2, 2];
16621684
conf_node_2.node.miner = true;
1685+
conf_node_2.miner.mining_key = Some(Secp256k1PrivateKey::from_seed(&[2]));
1686+
conf_node_2.events_observers.clear();
16631687

16641688
let node_1_sk = Secp256k1PrivateKey::from_seed(&naka_conf.node.local_peer_seed);
16651689
let node_1_pk = StacksPublicKey::from_private(&node_1_sk);
@@ -1799,16 +1823,14 @@ fn multiple_miners() {
17991823
make_stacks_transfer(&sender_sk, sender_nonce, send_fee, &recipient, send_amt);
18001824
submit_tx(&http_origin, &transfer_tx);
18011825

1802-
loop {
1826+
wait_for(20, || {
18031827
let blocks_processed = coord_channel
18041828
.lock()
18051829
.expect("Mutex poisoned")
18061830
.get_stacks_blocks_processed();
1807-
if blocks_processed > blocks_processed_before {
1808-
break;
1809-
}
1810-
thread::sleep(Duration::from_millis(100));
1811-
}
1831+
Ok(blocks_processed > blocks_processed_before)
1832+
})
1833+
.unwrap();
18121834

18131835
let info = get_chain_info_result(&naka_conf).unwrap();
18141836
assert_ne!(info.stacks_tip, last_tip);
@@ -1818,13 +1840,10 @@ fn multiple_miners() {
18181840
last_tip_height = info.stacks_tip_height;
18191841
}
18201842

1821-
let start_time = Instant::now();
1822-
while commits_submitted.load(Ordering::SeqCst) <= commits_before {
1823-
if start_time.elapsed() >= Duration::from_secs(20) {
1824-
panic!("Timed out waiting for block-commit");
1825-
}
1826-
thread::sleep(Duration::from_millis(100));
1827-
}
1843+
wait_for(20, || {
1844+
Ok(commits_submitted.load(Ordering::SeqCst) > commits_before)
1845+
})
1846+
.unwrap();
18281847
}
18291848

18301849
// load the chain tip, and assert that it is a nakamoto block and at least 30 blocks have advanced in epoch 3
@@ -3723,6 +3742,7 @@ fn forked_tenure_is_ignored() {
37233742
naka_submitted_commits: commits_submitted,
37243743
naka_proposed_blocks: proposals_submitted,
37253744
naka_mined_blocks: mined_blocks,
3745+
naka_skip_commit_op: test_skip_commit_op,
37263746
..
37273747
} = run_loop.counters();
37283748

@@ -3791,7 +3811,7 @@ fn forked_tenure_is_ignored() {
37913811
info!("Commit op is submitted; unpause tenure B's block");
37923812

37933813
// Unpause the broadcast of Tenure B's block, do not submit commits.
3794-
TEST_SKIP_COMMIT_OP.lock().unwrap().replace(true);
3814+
test_skip_commit_op.0.lock().unwrap().replace(true);
37953815
TEST_BROADCAST_STALL.lock().unwrap().replace(false);
37963816

37973817
// Wait for a stacks block to be broadcasted
@@ -3816,7 +3836,7 @@ fn forked_tenure_is_ignored() {
38163836
let commits_before = commits_submitted.load(Ordering::SeqCst);
38173837
let blocks_before = mined_blocks.load(Ordering::SeqCst);
38183838
next_block_and(&mut btc_regtest_controller, 60, || {
3819-
TEST_SKIP_COMMIT_OP.lock().unwrap().replace(false);
3839+
test_skip_commit_op.0.lock().unwrap().replace(false);
38203840
let commits_count = commits_submitted.load(Ordering::SeqCst);
38213841
let blocks_count = mined_blocks.load(Ordering::SeqCst);
38223842
Ok(commits_count > commits_before && blocks_count > blocks_before)
@@ -5478,6 +5498,7 @@ fn continue_tenure_extend() {
54785498
blocks_processed,
54795499
naka_submitted_commits: commits_submitted,
54805500
naka_proposed_blocks: proposals_submitted,
5501+
naka_skip_commit_op: test_skip_commit_op,
54815502
..
54825503
} = run_loop.counters();
54835504

@@ -5549,7 +5570,7 @@ fn continue_tenure_extend() {
55495570
);
55505571

55515572
info!("Pausing commit ops to trigger a tenure extend.");
5552-
TEST_SKIP_COMMIT_OP.lock().unwrap().replace(true);
5573+
test_skip_commit_op.0.lock().unwrap().replace(true);
55535574

55545575
next_block_and(&mut btc_regtest_controller, 60, || Ok(true)).unwrap();
55555576

@@ -5604,7 +5625,7 @@ fn continue_tenure_extend() {
56045625
);
56055626

56065627
info!("Resuming commit ops to mine regular tenures.");
5607-
TEST_SKIP_COMMIT_OP.lock().unwrap().replace(false);
5628+
test_skip_commit_op.0.lock().unwrap().replace(false);
56085629

56095630
// Mine 15 more regular nakamoto tenures
56105631
for _i in 0..15 {

testnet/stacks-node/src/tests/signer/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ use wsts::state_machine::PublicKeys;
5757

5858
use crate::config::{Config as NeonConfig, EventKeyType, EventObserverConfig, InitialBalance};
5959
use crate::event_dispatcher::MinedNakamotoBlockEvent;
60-
use crate::neon::Counters;
60+
use crate::neon::{Counters, TestFlag};
6161
use crate::run_loop::boot_nakamoto;
6262
use crate::tests::bitcoin_regtest::BitcoinCoreController;
6363
use crate::tests::nakamoto_integrations::{
@@ -81,6 +81,7 @@ pub struct RunningNodes {
8181
pub blocks_processed: Arc<AtomicU64>,
8282
pub nakamoto_blocks_proposed: Arc<AtomicU64>,
8383
pub nakamoto_blocks_mined: Arc<AtomicU64>,
84+
pub nakamoto_test_skip_commit_op: TestFlag,
8485
pub coord_channel: Arc<Mutex<CoordinatorChannels>>,
8586
pub conf: NeonConfig,
8687
}
@@ -91,6 +92,8 @@ pub struct SignerTest<S> {
9192
pub running_nodes: RunningNodes,
9293
// The spawned signers and their threads
9394
pub spawned_signers: Vec<S>,
95+
// The spawned signers and their threads
96+
pub signer_configs: Vec<SignerConfig>,
9497
// the private keys of the signers
9598
pub signer_stacks_private_keys: Vec<StacksPrivateKey>,
9699
// link to the stacks node
@@ -208,6 +211,7 @@ impl<S: Signer<T> + Send + 'static, T: SignerEventTrait + 'static> SignerTest<Sp
208211
signer_stacks_private_keys,
209212
stacks_client,
210213
run_stamp,
214+
signer_configs,
211215
}
212216
}
213217

@@ -679,6 +683,7 @@ fn setup_stx_btc_node<G: FnMut(&mut NeonConfig) -> ()>(
679683
naka_submitted_commits: commits_submitted,
680684
naka_proposed_blocks: naka_blocks_proposed,
681685
naka_mined_blocks: naka_blocks_mined,
686+
naka_skip_commit_op: nakamoto_test_skip_commit_op,
682687
..
683688
} = run_loop.counters();
684689

@@ -711,6 +716,7 @@ fn setup_stx_btc_node<G: FnMut(&mut NeonConfig) -> ()>(
711716
blocks_processed: blocks_processed.0,
712717
nakamoto_blocks_proposed: naka_blocks_proposed.0,
713718
nakamoto_blocks_mined: naka_blocks_mined.0,
719+
nakamoto_test_skip_commit_op,
714720
coord_channel,
715721
conf: naka_conf,
716722
}

0 commit comments

Comments
 (0)