Skip to content

Commit 4fb4460

Browse files
committed
test: add e2e test for burn reorgs with split
1 parent 5db0847 commit 4fb4460

File tree

1 file changed

+117
-22
lines changed
  • testnet/stacks-node/src/tests/signer

1 file changed

+117
-22
lines changed

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

Lines changed: 117 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -505,12 +505,41 @@ impl MultipleMinerTest {
505505
F: FnMut(&mut SignerConfig),
506506
G: FnMut(&mut NeonConfig),
507507
H: FnMut(&mut NeonConfig),
508+
>(
509+
num_signers: usize,
510+
num_transfer_txs: u64,
511+
signer_config_modifier: F,
512+
node_1_config_modifier: G,
513+
node_2_config_modifier: H,
514+
) -> MultipleMinerTest {
515+
Self::new_with_signer_dist(
516+
num_signers,
517+
num_transfer_txs,
518+
signer_config_modifier,
519+
node_1_config_modifier,
520+
node_2_config_modifier,
521+
|port| u8::try_from(port % 2).unwrap(),
522+
)
523+
}
524+
525+
/// Create a new test harness for running multiple miners with num_signers underlying signers and enough funds to send
526+
/// num_txs transfer transactions.
527+
///
528+
/// Will also modify the signer config and the node 1 and node 2 configs with the provided
529+
/// modifiers. Will partition the signer set so that ~half are listening and using node 1 for RPC and events,
530+
/// and the rest are using node 2 unless otherwise specified via the signer config modifier.
531+
pub fn new_with_signer_dist<
532+
F: FnMut(&mut SignerConfig),
533+
G: FnMut(&mut NeonConfig),
534+
H: FnMut(&mut NeonConfig),
535+
S: Fn(u16) -> u8,
508536
>(
509537
num_signers: usize,
510538
num_transfer_txs: u64,
511539
mut signer_config_modifier: F,
512540
mut node_1_config_modifier: G,
513541
mut node_2_config_modifier: H,
542+
signer_distributor: S,
514543
) -> MultipleMinerTest {
515544
let sender_sk = Secp256k1PrivateKey::random();
516545
let sender_addr = tests::to_addr(&sender_sk);
@@ -538,10 +567,10 @@ impl MultipleMinerTest {
538567
num_signers,
539568
vec![(sender_addr, (send_amt + send_fee) * num_transfer_txs)],
540569
|signer_config| {
541-
let node_host = if signer_config.endpoint.port() % 2 == 0 {
542-
&node_1_rpc_bind
543-
} else {
544-
&node_2_rpc_bind
570+
let node_host = match signer_distributor(signer_config.endpoint.port()) {
571+
0 => &node_1_rpc_bind,
572+
1 => &node_2_rpc_bind,
573+
o => panic!("Multiminer test can't distribute signer to node #{o}"),
545574
};
546575
signer_config.node_host = node_host.to_string();
547576
signer_config_modifier(signer_config);
@@ -567,11 +596,17 @@ impl MultipleMinerTest {
567596
);
568597
return true;
569598
};
570-
if addr.port() % 2 == 0 || addr.port() == test_observer::EVENT_OBSERVER_PORT {
599+
if addr.port() == test_observer::EVENT_OBSERVER_PORT {
571600
return true;
572601
}
573-
node_2_listeners.push(listener.clone());
574-
false
602+
match signer_distributor(addr.port()) {
603+
0 => true,
604+
1 => {
605+
node_2_listeners.push(listener.clone());
606+
false
607+
}
608+
o => panic!("Multiminer test can't distribute signer to node #{o}"),
609+
}
575610
});
576611
node_1_config_modifier(config);
577612
},
@@ -15260,9 +15295,9 @@ fn bitcoin_reorg_extended_tenure() {
1526015295
if env::var("BITCOIND_TEST") != Ok("1".into()) {
1526115296
return;
1526215297
}
15263-
let num_signers = 6;
15298+
let num_signers = 5;
1526415299

15265-
let mut miners = MultipleMinerTest::new_with_config_modifications(
15300+
let mut miners = MultipleMinerTest::new_with_signer_dist(
1526615301
num_signers,
1526715302
60,
1526815303
|signer_config| {
@@ -15271,10 +15306,38 @@ fn bitcoin_reorg_extended_tenure() {
1527115306
signer_config.block_proposal_timeout = Duration::from_secs(600);
1527215307
},
1527315308
|_| {},
15274-
|_| {},
15309+
|config| {
15310+
config.burnchain.rpc_port = 28132;
15311+
config.burnchain.peer_port = 28133;
15312+
},
15313+
|signer_port| {
15314+
// only put 1 out of 5 signers on the second node.
15315+
// this way, the 4 out of 5 signers can approve a block in bitcoin fork
15316+
// that the fifth signer does not witness
15317+
if signer_port % 5 == 0 {
15318+
1
15319+
} else {
15320+
0
15321+
}
15322+
},
1527515323
);
1527615324

1527715325
let (conf_1, _conf_2) = miners.get_node_configs();
15326+
let btc_p2p_proxy = TestProxy {
15327+
bind_port: 28133,
15328+
forward_port: conf_1.burnchain.peer_port,
15329+
drop_control: Arc::new(Mutex::new(false)),
15330+
keep_running: Arc::new(Mutex::new(true)),
15331+
};
15332+
let btc_rpc_proxy = TestProxy {
15333+
bind_port: 28132,
15334+
forward_port: conf_1.burnchain.rpc_port,
15335+
drop_control: Arc::new(Mutex::new(false)),
15336+
keep_running: Arc::new(Mutex::new(true)),
15337+
};
15338+
15339+
btc_p2p_proxy.spawn();
15340+
btc_rpc_proxy.spawn();
1527815341

1527915342
let rl1_counters = miners.signer_test.running_nodes.counters.clone();
1528015343

@@ -15315,7 +15378,9 @@ fn bitcoin_reorg_extended_tenure() {
1531515378

1531615379
let tenure_0_stacks_height = get_chain_info(&conf_1).stacks_tip_height;
1531715380
miners.pause_commits_miner_1();
15318-
miners.signer_test.mine_bitcoin_block();
15381+
miners
15382+
.mine_bitcoin_blocks_and_confirm(&sortdb, 1, 60)
15383+
.unwrap();
1531915384
miners.signer_test.check_signer_states_normal();
1532015385
let tip_sn = SortitionDB::get_canonical_burn_chain_tip(sortdb.conn()).unwrap();
1532115386
assert_eq!(tip_sn.miner_pk_hash, Some(mining_pkh_1));
@@ -15336,7 +15401,13 @@ fn bitcoin_reorg_extended_tenure() {
1533615401
assert!(last_active_sortition.was_sortition);
1533715402

1533815403
let tenure_1_info = get_chain_info(&conf_1);
15404+
1533915405
info!("Mining empty block!");
15406+
// make sure that the second node *doesn't* get this bitcoin block
15407+
// that way they will never see the losing side of the btc fork.
15408+
*btc_p2p_proxy.drop_control.lock().unwrap() = true;
15409+
*btc_rpc_proxy.drop_control.lock().unwrap() = true;
15410+
1534015411
miners.btc_regtest_controller_mut().build_next_block(1);
1534115412

1534215413
wait_for(60, || {
@@ -15357,10 +15428,6 @@ fn bitcoin_reorg_extended_tenure() {
1535715428
.expect("Timed out waiting for contract-call");
1535815429
}
1535915430

15360-
miners
15361-
.signer_test
15362-
.check_signer_states_normal_missed_sortition();
15363-
1536415431
info!("------------------------- Triggering Bitcoin Fork -------------------------");
1536515432

1536615433
let burn_block_height = get_chain_info(&conf_1).burn_block_height;
@@ -15382,6 +15449,9 @@ fn bitcoin_reorg_extended_tenure() {
1538215449
.btc_regtest_controller
1538315450
.build_next_block(2);
1538415451

15452+
*btc_p2p_proxy.drop_control.lock().unwrap() = false;
15453+
*btc_rpc_proxy.drop_control.lock().unwrap() = false;
15454+
1538515455
info!("Bitcoin fork triggered"; "ch" => %before_fork, "btc_height" => burn_block_height);
1538615456
info!("Chain info before fork: {:?}", get_chain_info(&conf_1));
1538715457

@@ -15393,15 +15463,40 @@ fn bitcoin_reorg_extended_tenure() {
1539315463

1539415464
info!("Chain info after fork: {:?}", get_chain_info(&conf_1));
1539515465

15396-
for _ in 0..2 {
15397-
miners
15398-
.signer_test
15399-
.submit_burn_block_call_and_wait(&miners.sender_sk)
15400-
.expect("Timed out waiting for contract-call");
15401-
}
15466+
miners
15467+
.signer_test
15468+
.submit_burn_block_call_and_wait(&miners.sender_sk)
15469+
.expect("Timed out waiting for contract-call");
15470+
15471+
let latest = get_chain_info(&conf_1);
15472+
15473+
let rc = miners.signer_test.get_current_reward_cycle();
15474+
let slot_ids = miners.signer_test.get_signer_indices(rc);
15475+
let mut block_responses: Vec<_> = vec![];
15476+
wait_for(60, || {
15477+
block_responses = slot_ids
15478+
.iter()
15479+
.filter_map(|slot_id| {
15480+
let latest_br = miners.signer_test.get_latest_block_response(slot_id.0);
15481+
if latest_br.get_signer_signature_hash().0 == latest.stacks_tip.0 {
15482+
Some(latest_br)
15483+
} else {
15484+
None
15485+
}
15486+
})
15487+
.collect();
15488+
Ok(block_responses.len() == num_signers)
15489+
})
15490+
.unwrap();
15491+
15492+
assert!(block_responses
15493+
.iter()
15494+
.all(|resp| resp.as_block_accepted().is_some()));
1540215495

1540315496
miners.submit_commit_miner_1(&sortdb);
15404-
miners.signer_test.mine_bitcoin_block();
15497+
miners
15498+
.mine_bitcoin_blocks_and_confirm(&sortdb, 1, 60)
15499+
.unwrap();
1540515500

1540615501
let last_active_sortition = get_sortition_info(&conf_1);
1540715502
assert!(last_active_sortition.was_sortition);

0 commit comments

Comments
 (0)