Skip to content

Commit cdcee4d

Browse files
committed
test: add integration test checking burn-block-height behavior
1 parent 88a946a commit cdcee4d

File tree

1 file changed

+208
-0
lines changed
  • testnet/stacks-node/src/tests/signer

1 file changed

+208
-0
lines changed

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

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13549,3 +13549,211 @@ fn verify_mempool_caches() {
1354913549

1355013550
signer_test.shutdown();
1355113551
}
13552+
13553+
#[test]
13554+
#[ignore]
13555+
/// This test checks the behavior of `burn-block-height` within a normal
13556+
/// Nakamoto block and within a tenure-extend block.
13557+
fn burn_block_height_behavior() {
13558+
if env::var("BITCOIND_TEST") != Ok("1".into()) {
13559+
return;
13560+
}
13561+
13562+
tracing_subscriber::registry()
13563+
.with(fmt::layer())
13564+
.with(EnvFilter::from_default_env())
13565+
.init();
13566+
13567+
info!("------------------------- Test Setup -------------------------");
13568+
let num_signers = 5;
13569+
let sender_sk = Secp256k1PrivateKey::random();
13570+
let sender_addr = tests::to_addr(&sender_sk);
13571+
let send_amt = 100;
13572+
let send_fee = 180;
13573+
let deployer_sk = Secp256k1PrivateKey::random();
13574+
let deployer_addr = tests::to_addr(&deployer_sk);
13575+
let tx_fee = 10000;
13576+
let deploy_fee = 200000;
13577+
let block_proposal_timeout = Duration::from_secs(20);
13578+
let mut signer_test: SignerTest<SpawnedSigner> = SignerTest::new_with_config_modifications(
13579+
num_signers,
13580+
vec![
13581+
(sender_addr, send_amt + send_fee),
13582+
(deployer_addr, deploy_fee + tx_fee * 3),
13583+
],
13584+
|config| {
13585+
// make the duration long enough that the miner will be marked as malicious
13586+
config.block_proposal_timeout = block_proposal_timeout;
13587+
},
13588+
|_| {},
13589+
None,
13590+
None,
13591+
);
13592+
let http_origin = format!("http://{}", &signer_test.running_nodes.conf.node.rpc_bind);
13593+
13594+
signer_test.boot_to_epoch_3();
13595+
13596+
let Counters {
13597+
naka_skip_commit_op: skip_commit_op,
13598+
..
13599+
} = signer_test.running_nodes.counters.clone();
13600+
13601+
info!("------------------------- Test Mine Regular Tenure A -------------------------");
13602+
13603+
let contract_src = "(define-public (foo) (ok burn-block-height))";
13604+
13605+
// First, lets deploy the contract
13606+
let mut deployer_nonce = 0;
13607+
let contract_tx = make_contract_publish(
13608+
&deployer_sk,
13609+
deployer_nonce,
13610+
deploy_fee,
13611+
signer_test.running_nodes.conf.burnchain.chain_id,
13612+
"foo",
13613+
&contract_src,
13614+
);
13615+
submit_tx(&http_origin, &contract_tx);
13616+
deployer_nonce += 1;
13617+
13618+
// Wait for this transaction to be mined in a block
13619+
info!("----- Submitted deploy txs, waiting for block -----");
13620+
wait_for(60, || {
13621+
Ok(get_account(&http_origin, &deployer_addr).nonce == deployer_nonce)
13622+
})
13623+
.unwrap();
13624+
13625+
// Stall block commits, so the next block will have no sortition
13626+
skip_commit_op.set(true);
13627+
13628+
// Mine a regular tenure
13629+
let info_before = signer_test.get_peer_info();
13630+
next_block_and(
13631+
&mut signer_test.running_nodes.btc_regtest_controller,
13632+
60,
13633+
|| {
13634+
let chain_info = get_chain_info(&signer_test.running_nodes.conf);
13635+
Ok(chain_info.stacks_tip_height > info_before.stacks_tip_height)
13636+
},
13637+
)
13638+
.expect("Timed out waiting for block");
13639+
13640+
let info = get_chain_info(&signer_test.running_nodes.conf);
13641+
let stacks_height_before = info.stacks_tip_height;
13642+
let burn_height_before = info.burn_block_height;
13643+
13644+
info!("------------------------- submit contract call 1 -------------------------");
13645+
let call_tx = make_contract_call(
13646+
&deployer_sk,
13647+
deployer_nonce,
13648+
tx_fee,
13649+
signer_test.running_nodes.conf.burnchain.chain_id,
13650+
&deployer_addr,
13651+
"foo",
13652+
"foo",
13653+
&[],
13654+
);
13655+
let txid = submit_tx(&http_origin, &call_tx);
13656+
deployer_nonce += 1;
13657+
13658+
info!("------------------------- wait for the call tx to be mined -------------------------");
13659+
// Wait for the call tx to be mined in a new Nakamoto block
13660+
wait_for(60, || {
13661+
test_observer::get_mined_nakamoto_blocks()
13662+
.last()
13663+
.and_then(|block| {
13664+
block.tx_events.iter().find_map(|tx| match tx {
13665+
TransactionEvent::Success(tx) if tx.txid.to_string() == txid => {
13666+
let result = tx
13667+
.result
13668+
.clone()
13669+
.expect_result_ok()
13670+
.ok()?
13671+
.expect_u128()
13672+
.ok()?;
13673+
Some(result)
13674+
}
13675+
_ => None,
13676+
})
13677+
})
13678+
.map_or(Ok(false), |result_height| {
13679+
assert_eq!(result_height, burn_height_before as u128);
13680+
Ok(true)
13681+
})
13682+
})
13683+
.expect("Timed out waiting for call tx to be mined");
13684+
13685+
info!("------------------------- Wait for the block to be processed -------------------------");
13686+
// Wait for the block to be processed
13687+
wait_for(60, || {
13688+
let info = get_chain_info(&signer_test.running_nodes.conf);
13689+
Ok(info.stacks_tip_height > stacks_height_before)
13690+
})
13691+
.expect("Timed out waiting for block to be processed");
13692+
13693+
// Stall mining, so that the next call will get included in the tenure extend block
13694+
TEST_MINE_STALL.set(true);
13695+
13696+
info!("------------------------- submit contract call 2 -------------------------");
13697+
let call_tx = make_contract_call(
13698+
&deployer_sk,
13699+
deployer_nonce,
13700+
tx_fee,
13701+
signer_test.running_nodes.conf.burnchain.chain_id,
13702+
&deployer_addr,
13703+
"foo",
13704+
"foo",
13705+
&[],
13706+
);
13707+
let txid = submit_tx(&http_origin, &call_tx);
13708+
13709+
info!(
13710+
"------------------------- mine bitcoin block with no sortition -------------------------"
13711+
);
13712+
let info = get_chain_info(&signer_test.running_nodes.conf);
13713+
let stacks_height_before = info.stacks_tip_height;
13714+
let burn_height_before = info.burn_block_height;
13715+
13716+
signer_test
13717+
.running_nodes
13718+
.btc_regtest_controller
13719+
.build_next_block(1);
13720+
13721+
wait_for(60, || {
13722+
let info = get_chain_info(&signer_test.running_nodes.conf);
13723+
Ok(info.burn_block_height == burn_height_before + 1)
13724+
})
13725+
.expect("Failed to advance chain tip");
13726+
13727+
info!("------------------------- wait for tenure change block -------------------------");
13728+
13729+
// Resume mining and wait for the next block to be mined
13730+
TEST_MINE_STALL.set(false);
13731+
wait_for_tenure_change_tx(30, TenureChangeCause::Extended, stacks_height_before + 1)
13732+
.expect("Timed out waiting for tenure extend");
13733+
13734+
let blocks = test_observer::get_mined_nakamoto_blocks();
13735+
let last_block = blocks.last().unwrap();
13736+
let txs = &last_block.tx_events;
13737+
assert_eq!(txs.len(), 2, "Expected 2 txs in the tenure extend block");
13738+
let _tenure_extend_tx = txs.first().unwrap();
13739+
let call_tx = txs.last().unwrap();
13740+
match call_tx {
13741+
TransactionEvent::Success(tx) => {
13742+
if tx.txid.to_string() == txid {
13743+
let result_height = tx
13744+
.result
13745+
.clone()
13746+
.expect_result_ok()
13747+
.unwrap()
13748+
.expect_u128()
13749+
.unwrap();
13750+
assert_eq!(result_height, burn_height_before as u128 + 1);
13751+
}
13752+
}
13753+
_ => {}
13754+
}
13755+
13756+
info!("------------------------- shutdown -------------------------");
13757+
13758+
signer_test.shutdown();
13759+
}

0 commit comments

Comments
 (0)