Skip to content

Commit

Permalink
test: naka::mine_multiple to mine 9 interim blocks. move empty block …
Browse files Browse the repository at this point in the history
…check to stackslib::miner assembly.

chore: fix typo
  • Loading branch information
kantai committed Dec 19, 2023
1 parent c358427 commit 3cef3b4
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 54 deletions.
4 changes: 4 additions & 0 deletions stackslib/src/chainstate/nakamoto/miner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,10 @@ impl NakamotoBlockBuilder {
return Err(Error::MinerAborted);
}

if builder.txs.is_empty() {
return Err(Error::NoTransactionsToMine);
}

// save the block so we can build microblocks off of it
let block = builder.mine_nakamoto_block(&mut tenure_tx);
let size = builder.bytes_so_far;
Expand Down
25 changes: 17 additions & 8 deletions testnet/stacks-node/src/nakamoto_node/miner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,20 @@ impl BlockMinerThread {
loop {
let new_block = loop {
match self.mine_block() {
Ok(x) => break x,
Ok(x) => break Some(x),
Err(NakamotoNodeError::MiningFailure(ChainstateError::MinerAborted)) => {
info!("Miner interrupted while mining, will try again");
// sleep, and try again. if the miner was interrupted because the burnchain
// view changed, the next `mine_block()` invocation will error
thread::sleep(Duration::from_millis(ABORT_TRY_AGAIN_MS));
continue;
}
Err(NakamotoNodeError::MiningFailure(
ChainstateError::NoTransactionsToMine,
)) => {
debug!("Miner did not find any transactions to mine");
break None;
}
Err(e) => {
warn!("Failed to mine block: {e:?}");
return;
Expand Down Expand Up @@ -408,10 +414,8 @@ impl BlockMinerThread {
}

/// Try to mine a Stacks block by assembling one from mempool transactions and sending a
/// burnchain block-commit transaction. If we succeed, then return the assembled block data as
/// well as the microblock private key to use to produce microblocks.
/// Return None if we couldn't build a block for whatever reason.
fn mine_block(&mut self) -> Result<Option<NakamotoBlock>, NakamotoNodeError> {
/// burnchain block-commit transaction. If we succeed, then return the assembled block.
fn mine_block(&mut self) -> Result<NakamotoBlock, NakamotoNodeError> {
debug!("block miner thread ID is {:?}", thread::current().id());

let burn_db_path = self.config.get_burn_db_file_path();
Expand Down Expand Up @@ -501,14 +505,19 @@ impl BlockMinerThread {
Some(&self.event_dispatcher),
)
.map_err(|e| {
if !matches!(e, ChainstateError::MinerAborted) {
if !matches!(
e,
ChainstateError::MinerAborted | ChainstateError::NoTransactionsToMine
) {
error!("Relayer: Failure mining anchored block: {e}");
}
NakamotoNodeError::MiningFailure(e)
})?;

if block.txs.is_empty() {
return Ok(None);
return Err(NakamotoNodeError::MiningFailure(
ChainstateError::NoTransactionsToMine,
));
}

let mining_key = self.keychain.get_nakamoto_sk();
Expand Down Expand Up @@ -539,7 +548,7 @@ impl BlockMinerThread {
// enough to build this block that another block could have arrived), and confirm that all
// Stacks blocks with heights higher than the canoincal tip are processed.
self.check_burn_tip_changed(&burn_db)?;
Ok(Some(block))
Ok(block)
}

/// Check if the tenure needs to change -- if so, return a BurnchainTipChanged error
Expand Down
83 changes: 37 additions & 46 deletions testnet/stacks-node/src/tests/nakamoto_integrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,24 +503,27 @@ fn simple_neon_integration() {
/// to Nakamoto operation (activating pox-4 by submitting a stack-stx tx). The BootLoop
/// struct handles the epoch-2/3 tear-down and spin-up.
/// This test makes three assertions:
/// * 10 tenures are mined after 3.0 starts
/// * Each tenure has 2 blocks
/// * 5 tenures are mined after 3.0 starts
/// * Each tenure has 10 blocks (the coinbase block and 9 interim blocks)
fn mine_multiple_per_tenure_integration() {
if env::var("BITCOIND_TEST") != Ok("1".into()) {
return;
}

let (mut naka_conf, _miner_account) = naka_neon_integration_conf(None);
naka_conf.miner.wait_on_interim_blocks = Duration::from_secs(5);
let http_origin = format!("http://{}", &naka_conf.node.rpc_bind);
naka_conf.miner.wait_on_interim_blocks = Duration::from_secs(1);
let sender_sk = Secp256k1PrivateKey::new();
// setup sender + recipient for a test stx transfer
let tenure_count = 10;
let tenure_count = 5;
let inter_blocks_per_tenure = 9;
// setup sender + recipient for some test stx transfers
// these are necessary for the interim blocks to get mined at all
let sender_addr = tests::to_addr(&sender_sk);
let send_amt = 1000;
let send_fee = 100;
let send_amt = 100;
let send_fee = 180;
naka_conf.add_initial_balance(
PrincipalData::from(sender_addr.clone()).to_string(),
(send_amt + send_fee) * tenure_count,
(send_amt + send_fee) * tenure_count * inter_blocks_per_tenure,
);
let recipient = PrincipalData::from(StacksAddress::burn_address(false));
let stacker_sk = setup_stacker(&mut naka_conf);
Expand Down Expand Up @@ -566,7 +569,7 @@ fn mine_multiple_per_tenure_integration() {

let burnchain = naka_conf.get_burnchain();
let sortdb = burnchain.open_sortition_db(true).unwrap();
let (mut chainstate, _) = StacksChainState::open(
let (chainstate, _) = StacksChainState::open(
naka_conf.is_mainnet(),
naka_conf.burnchain.chain_id,
&naka_conf.get_chainstate_path_str(),
Expand Down Expand Up @@ -595,8 +598,8 @@ fn mine_multiple_per_tenure_integration() {
})
.unwrap();

// Mine 10 nakamoto tenures
for sender_nonce in 0..tenure_count {
// Mine `tenure_count` nakamoto tenures
for tenure_ix in 0..tenure_count {
next_block_and_mine_commit(
&mut btc_regtest_controller,
60,
Expand All @@ -605,44 +608,28 @@ fn mine_multiple_per_tenure_integration() {
)
.unwrap();

let blocks_processed_before = coord_channel
.lock()
.expect("Mutex poisoned")
.get_stacks_blocks_processed();

// submit a tx so that the miner will mine an extra block
let transfer_tx =
make_stacks_transfer(&sender_sk, sender_nonce, send_fee, &recipient, send_amt);
// let transfer_tx_hex = format!("0x{}", to_hex(&transfer_tx));
let tip = NakamotoChainState::get_canonical_block_header(chainstate.db(), &sortdb)
.unwrap()
.unwrap();

let mut mempool = naka_conf
.connect_mempool_db()
.expect("Database failure opening mempool");

mempool
.submit_raw(
&mut chainstate,
&sortdb,
&tip.consensus_hash,
&tip.anchored_header.block_hash(),
transfer_tx.clone(),
&ExecutionCost::max_value(),
&StacksEpochId::Epoch30,
)
.unwrap();

loop {
let blocks_processed = coord_channel
// mine the interim blocks
for interim_block_ix in 0..inter_blocks_per_tenure {
let blocks_processed_before = coord_channel
.lock()
.expect("Mutex poisoned")
.get_stacks_blocks_processed();
if blocks_processed > blocks_processed_before {
break;
// submit a tx so that the miner will mine an extra block
let sender_nonce = tenure_ix * inter_blocks_per_tenure + interim_block_ix;
let transfer_tx =
make_stacks_transfer(&sender_sk, sender_nonce, send_fee, &recipient, send_amt);
submit_tx(&http_origin, &transfer_tx);

loop {
let blocks_processed = coord_channel
.lock()
.expect("Mutex poisoned")
.get_stacks_blocks_processed();
if blocks_processed > blocks_processed_before {
break;
}
thread::sleep(Duration::from_millis(100));
}
thread::sleep(Duration::from_millis(100));
}
}

Expand All @@ -657,7 +644,11 @@ fn mine_multiple_per_tenure_integration() {
);

assert!(tip.anchored_header.as_stacks_nakamoto().is_some());
assert!(tip.stacks_block_height >= block_height_pre_3_0 + 20);
assert_eq!(
tip.stacks_block_height,
block_height_pre_3_0 + ((inter_blocks_per_tenure + 1) * tenure_count),
"Should have mined (1 + interim_blocks_per_tenure) * tenure_count nakamoto blocks"
);

coord_channel
.lock()
Expand Down

0 comments on commit 3cef3b4

Please sign in to comment.