Skip to content

Commit 28fc444

Browse files
authored
Merge pull request #6161 from orsissimo/test/refactor-commands
test: add disallow_reorg_within_first_proposal_burn_block_timing_secs_but_more_than_one_block_scenario and refactor commands
2 parents 202bc61 + 3a2b125 commit 28fc444

File tree

15 files changed

+1025
-625
lines changed

15 files changed

+1025
-625
lines changed

Cargo.lock

Lines changed: 5 additions & 24 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

testnet/stacks-node/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ tempfile = "3.3"
5252
mockito = "1.5"
5353
serial_test = "3.2.0"
5454
pinny = { git = "https://github.com/BitcoinL2-Labs/pinny-rs.git", rev = "54ba9d533a7b84525a5e65a3eae1a3ae76b9ea49" } #v0.0.2
55-
madhouse = { git = "https://github.com/stacks-network/madhouse-rs.git", rev = "fc651ddcbaf85e888b06d4a87aa788c4b7ba9309" }
56-
proptest = { git = "https://github.com/proptest-rs/proptest.git", rev = "c9bdf18c232665b2b740c667c81866b598d06dc7" }
55+
madhouse = { git = "https://github.com/stacks-network/madhouse-rs.git", tag = "0.2.0" }
56+
proptest = "1.6.*"
5757
stdext = "0.3.1"
5858

5959
[[bin]]
Lines changed: 73 additions & 188 deletions
Original file line numberDiff line numberDiff line change
@@ -1,244 +1,129 @@
1-
use std::sync::atomic::Ordering;
2-
use std::sync::{Arc, Mutex};
1+
use std::sync::Arc;
32

43
use madhouse::{Command, CommandWrapper};
5-
use proptest::prelude::{Just, Strategy};
6-
use stacks::chainstate::stacks::TenureChangeCause;
4+
use proptest::strategy::Strategy;
75
use tracing::info;
86

97
use super::context::{SignerTestContext, SignerTestState};
10-
use crate::tests::neon_integrations::get_chain_info;
11-
use crate::tests::signer::v0::{wait_for_block_pushed_by_miner_key, MultipleMinerTest};
128

13-
pub struct MineBitcoinBlockTenureChangeMiner1 {
14-
miners: Arc<Mutex<MultipleMinerTest>>,
9+
/// Command to mine a single Bitcoin block in the test environment and wait for its confirmation.
10+
/// This command simulates the process of mining a new Bitcoin block in the Stacks blockchain
11+
/// testing framework. Unlike the tenure change variant, this command simply advances the
12+
/// Bitcoin chain by one block without explicitly triggering a tenure change transaction.
13+
pub struct MinerMineBitcoinBlocks {
14+
ctx: Arc<SignerTestContext>,
15+
num_blocks: u64,
1516
}
1617

17-
impl MineBitcoinBlockTenureChangeMiner1 {
18-
pub fn new(miners: Arc<Mutex<MultipleMinerTest>>) -> Self {
19-
Self { miners }
18+
impl MinerMineBitcoinBlocks {
19+
fn new(ctx: Arc<SignerTestContext>, num_blocks: u64) -> Self {
20+
Self { ctx, num_blocks }
2021
}
21-
}
22-
23-
impl Command<SignerTestState, SignerTestContext> for MineBitcoinBlockTenureChangeMiner1 {
24-
fn check(&self, state: &SignerTestState) -> bool {
25-
let (conf_1, _) = self.miners.lock().unwrap().get_node_configs();
26-
let burn_height = get_chain_info(&conf_1).burn_block_height;
27-
let miner_1_submitted_commit_last_burn_height = self
28-
.miners
29-
.lock()
30-
.unwrap()
31-
.get_primary_submitted_commit_last_burn_height()
32-
.0
33-
.load(Ordering::SeqCst);
34-
let miner_2_submitted_commit_last_burn_height = self
35-
.miners
36-
.lock()
37-
.unwrap()
38-
.get_secondary_submitted_commit_last_burn_height()
39-
.0
40-
.load(Ordering::SeqCst);
41-
42-
info!(
43-
"Checking: Miner 1 mining Bitcoin block and tenure change tx. Result: {:?} && {:?} && {:?}",
44-
state.is_booted_to_nakamoto, burn_height == miner_1_submitted_commit_last_burn_height, burn_height > miner_2_submitted_commit_last_burn_height
45-
);
46-
state.is_booted_to_nakamoto
47-
&& burn_height == miner_1_submitted_commit_last_burn_height
48-
&& burn_height > miner_2_submitted_commit_last_burn_height
49-
}
50-
51-
fn apply(&self, _state: &mut SignerTestState) {
52-
info!("Applying: Miner 1 mining Bitcoin block and tenure change tx");
53-
54-
let (stacks_height_before, conf_1, miner_pk_1) = {
55-
let mut miners = self.miners.lock().unwrap();
56-
let stacks_height_before = miners.get_peer_stacks_tip_height();
57-
let (conf_1, _) = miners.get_node_configs();
58-
let burnchain = conf_1.get_burnchain();
59-
let sortdb = burnchain.open_sortition_db(true).unwrap();
60-
61-
miners
62-
.mine_bitcoin_block_and_tenure_change_tx(&sortdb, TenureChangeCause::BlockFound, 60)
63-
.expect("Failed to mine BTC block");
64-
65-
let (miner_pk_1, _) = miners.get_miner_public_keys();
6622

67-
(stacks_height_before, conf_1, miner_pk_1)
68-
};
69-
70-
info!(
71-
"Waiting for Nakamoto block {} pushed by miner 1",
72-
stacks_height_before + 1
73-
);
74-
75-
let miner_1_block =
76-
wait_for_block_pushed_by_miner_key(30, stacks_height_before + 1, &miner_pk_1)
77-
.expect("Failed to get block");
78-
79-
let mined_block_height = miner_1_block.header.chain_length;
80-
info!(
81-
"Miner 1 mined Nakamoto block height: {}",
82-
mined_block_height
83-
);
84-
85-
let info_after = get_chain_info(&conf_1);
86-
assert_eq!(info_after.stacks_tip, miner_1_block.header.block_hash());
87-
assert_eq!(info_after.stacks_tip_height, mined_block_height);
88-
assert_eq!(mined_block_height, stacks_height_before + 1);
23+
pub fn one(ctx: Arc<SignerTestContext>) -> Self {
24+
Self::new(ctx, 1)
8925
}
9026

91-
fn label(&self) -> String {
92-
"MINE_BITCOIN_BLOCK_AND_TENURE_CHANGE_MINER_1".to_string()
27+
pub fn multiple(ctx: Arc<SignerTestContext>, num_blocks: u64) -> Self {
28+
Self::new(ctx, num_blocks)
9329
}
94-
95-
fn build(
96-
ctx: Arc<SignerTestContext>,
97-
) -> impl Strategy<Value = CommandWrapper<SignerTestState, SignerTestContext>> {
98-
Just(CommandWrapper::new(
99-
MineBitcoinBlockTenureChangeMiner1::new(ctx.miners.clone()),
100-
))
101-
}
102-
}
103-
104-
pub struct MineBitcoinBlockTenureChangeMiner2 {
105-
miners: Arc<Mutex<MultipleMinerTest>>,
10630
}
10731

108-
impl MineBitcoinBlockTenureChangeMiner2 {
109-
pub fn new(miners: Arc<Mutex<MultipleMinerTest>>) -> Self {
110-
Self { miners }
32+
impl Command<SignerTestState, SignerTestContext> for MinerMineBitcoinBlocks {
33+
fn check(&self, _state: &SignerTestState) -> bool {
34+
info!("Checking: Mining tenure. Result: {}", true);
35+
true
11136
}
112-
}
11337

114-
impl Command<SignerTestState, SignerTestContext> for MineBitcoinBlockTenureChangeMiner2 {
115-
fn check(&self, state: &SignerTestState) -> bool {
116-
let (conf_1, _) = self.miners.lock().unwrap().get_node_configs();
117-
let burn_height = get_chain_info(&conf_1).burn_block_height;
118-
let miner_1_submitted_commit_last_burn_height = self
119-
.miners
120-
.lock()
121-
.unwrap()
122-
.get_primary_submitted_commit_last_burn_height()
123-
.0
124-
.load(Ordering::SeqCst);
125-
let miner_2_submitted_commit_last_burn_height = self
126-
.miners
127-
.lock()
128-
.unwrap()
129-
.get_secondary_submitted_commit_last_burn_height()
130-
.0
131-
.load(Ordering::SeqCst);
38+
fn apply(&self, state: &mut SignerTestState) {
39+
info!("Applying: Mining {} Bitcoin block(s)", self.num_blocks);
13240

133-
info!(
134-
"Checking: Miner 2 mining Bitcoin block and tenure change tx. Result: {:?} && {:?} && {:?}",
135-
state.is_booted_to_nakamoto, burn_height == miner_1_submitted_commit_last_burn_height, burn_height > miner_2_submitted_commit_last_burn_height
136-
);
137-
state.is_booted_to_nakamoto
138-
&& burn_height == miner_2_submitted_commit_last_burn_height
139-
&& burn_height > miner_1_submitted_commit_last_burn_height
140-
}
141-
142-
fn apply(&self, _state: &mut SignerTestState) {
143-
info!("Applying: Miner 2 mining Bitcoin block and tenure change tx");
41+
state.last_stacks_block_height = Some(self.ctx.get_peer_stacks_tip_height());
14442

145-
let stacks_height_before = self.miners.lock().unwrap().get_peer_stacks_tip_height();
43+
// We can use miner 1 sortition db - it's the same for both miners
44+
let sortdb = self.ctx.get_sortition_db(1);
14645

147-
let (conf_1, conf_2) = self.miners.lock().unwrap().get_node_configs();
148-
let burnchain = conf_1.get_burnchain();
149-
let sortdb = burnchain.open_sortition_db(true).unwrap();
150-
self.miners
46+
self.ctx
47+
.miners
15148
.lock()
15249
.unwrap()
153-
.mine_bitcoin_block_and_tenure_change_tx(&sortdb, TenureChangeCause::BlockFound, 60)
50+
.mine_bitcoin_blocks_and_confirm(&sortdb, self.num_blocks, 30)
15451
.expect("Failed to mine BTC block");
155-
156-
let (_, miner_pk_2) = self.miners.lock().unwrap().get_miner_public_keys();
157-
158-
info!(
159-
"Waiting for Nakamoto block {} pushed by miner 2",
160-
stacks_height_before + 1
161-
);
162-
163-
let secondary_miner_block =
164-
wait_for_block_pushed_by_miner_key(30, stacks_height_before + 1, &miner_pk_2)
165-
.expect("Failed to get block N");
166-
167-
let mined_block_height = secondary_miner_block.header.chain_length;
168-
169-
let info_after = get_chain_info(&conf_2);
170-
assert_eq!(
171-
info_after.stacks_tip,
172-
secondary_miner_block.header.block_hash()
173-
);
174-
assert_eq!(info_after.stacks_tip_height, mined_block_height);
175-
assert_eq!(mined_block_height, stacks_height_before + 1);
17652
}
17753

17854
fn label(&self) -> String {
179-
"MINE_BITCOIN_BLOCK_AND_TENURE_CHANGE_MINER_2".to_string()
55+
format!("MINE_{}_BITCOIN_BLOCK(S)", self.num_blocks)
18056
}
18157

18258
fn build(
18359
ctx: Arc<SignerTestContext>,
18460
) -> impl Strategy<Value = CommandWrapper<SignerTestState, SignerTestContext>> {
185-
Just(CommandWrapper::new(
186-
MineBitcoinBlockTenureChangeMiner2::new(ctx.miners.clone()),
187-
))
61+
(1u64..5u64).prop_map({
62+
move |num_blocks| {
63+
CommandWrapper::new(MinerMineBitcoinBlocks::multiple(ctx.clone(), num_blocks))
64+
}
65+
})
18866
}
18967
}
19068

191-
pub struct MineBitcoinBlock {
192-
miners: Arc<Mutex<MultipleMinerTest>>,
193-
timeout_secs: u64,
69+
/// Command to generate a specified number of Bitcoin blocks in the regtest environment.
70+
/// Unlike other mining commands, this command directly instructs the Bitcoin regtest
71+
/// controller to generate between 1-5 blocks without waiting for confirmations or
72+
/// monitoring their effect on the Stacks chain. It represents a low-level operation
73+
/// to advance the Bitcoin chain state.
74+
pub struct ChainGenerateBitcoinBlocks {
75+
ctx: Arc<SignerTestContext>,
76+
num_blocks: u64,
19477
}
19578

196-
impl MineBitcoinBlock {
197-
pub fn new(miners: Arc<Mutex<MultipleMinerTest>>, timeout_secs: u64) -> Self {
198-
Self {
199-
miners,
200-
timeout_secs,
201-
}
79+
impl ChainGenerateBitcoinBlocks {
80+
fn new(ctx: Arc<SignerTestContext>, num_blocks: u64) -> Self {
81+
Self { ctx, num_blocks }
82+
}
83+
84+
pub fn one(ctx: Arc<SignerTestContext>) -> Self {
85+
Self::new(ctx, 1)
86+
}
87+
88+
pub fn multiple(ctx: Arc<SignerTestContext>, num_blocks: u64) -> Self {
89+
Self::new(ctx, num_blocks)
20290
}
20391
}
20492

205-
impl Command<SignerTestState, SignerTestContext> for MineBitcoinBlock {
93+
impl Command<SignerTestState, SignerTestContext> for ChainGenerateBitcoinBlocks {
20694
fn check(&self, _state: &SignerTestState) -> bool {
207-
info!("Checking: Mining tenure. Result: {:?}", true);
95+
info!(
96+
"Checking: Build next {} Bitcoin block(s). Result: {}",
97+
self.num_blocks, true
98+
);
20899
true
209100
}
210101

211102
fn apply(&self, _state: &mut SignerTestState) {
212-
info!(
213-
"Applying: Mining tenure and waiting for it for {:?} seconds",
214-
self.timeout_secs
215-
);
103+
info!("Applying: Build next {} Bitcoin block(s)", self.num_blocks);
216104

217-
let sortdb = {
218-
let miners = self.miners.lock().unwrap();
219-
let (conf_1, _) = miners.get_node_configs();
220-
let burnchain = conf_1.get_burnchain();
221-
let sortdb = burnchain.open_sortition_db(true).unwrap();
222-
sortdb
223-
};
224-
225-
{
226-
let mut miners = self.miners.lock().unwrap();
227-
miners
228-
.mine_bitcoin_blocks_and_confirm(&sortdb, 1, self.timeout_secs)
229-
.expect("Failed to mine BTC block");
230-
}
105+
self.ctx
106+
.miners
107+
.lock()
108+
.unwrap()
109+
.btc_regtest_controller_mut()
110+
.build_next_block(self.num_blocks);
231111
}
232112

233113
fn label(&self) -> String {
234-
"MINE_BITCOIN_BLOCK".to_string()
114+
format!("BUILD_NEXT_{}_BITCOIN_BLOCKS", self.num_blocks)
235115
}
236116

237117
fn build(
238118
ctx: Arc<SignerTestContext>,
239119
) -> impl Strategy<Value = CommandWrapper<SignerTestState, SignerTestContext>> {
240-
(60u64..90u64).prop_map(move |timeout_secs| {
241-
CommandWrapper::new(MineBitcoinBlock::new(ctx.miners.clone(), timeout_secs))
120+
(1u64..=5u64).prop_map({
121+
move |num_blocks| {
122+
CommandWrapper::new(ChainGenerateBitcoinBlocks::multiple(
123+
ctx.clone(),
124+
num_blocks,
125+
))
126+
}
242127
})
243128
}
244129
}

0 commit comments

Comments
 (0)