Skip to content

Commit 8d90bfb

Browse files
committed
feat: Add --reset-tenure option to stacks-inspect try-mine
1 parent f3d6c96 commit 8d90bfb

File tree

2 files changed

+60
-13
lines changed

2 files changed

+60
-13
lines changed

stackslib/src/cli.rs

+59-11
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use stacks_common::types::chainstate::{BlockHeaderHash, BurnchainHeaderHash, Sta
3131
use stacks_common::types::sqlite::NO_PARAMS;
3232
use stacks_common::util::get_epoch_time_ms;
3333
use stacks_common::util::hash::Hash160;
34+
use stacks_common::util::secp256k1::Secp256k1PublicKey;
3435
use stacks_common::util::vrf::VRFProof;
3536

3637
use crate::burnchains::db::BurnchainDB;
@@ -462,8 +463,7 @@ pub fn command_try_mine(mut argv: Vec<String>, opts: &StacksInspectOpts) {
462463
let try_mine_opts = drain_try_mine_opts(&mut argv, 1);
463464

464465
let print_help_and_exit = || {
465-
let n = &argv[0];
466-
eprintln!("Usage: {n} [options...] <data-dir>");
466+
eprintln!("Usage: {n} [options...] <data-dir>", n = &argv[0]);
467467
eprintln!("");
468468
eprintln!("Options:");
469469
eprintln!(" --min-fee <u64>: Minimum fee for miner to include transaction");
@@ -485,7 +485,7 @@ pub fn command_try_mine(mut argv: Vec<String>, opts: &StacksInspectOpts) {
485485
let min_fee = try_mine_opts.min_fee.unwrap_or(0);
486486
let max_time = try_mine_opts.max_time.unwrap_or(u64::MAX);
487487
let _max_blocks = try_mine_opts.max_blocks.unwrap_or(1);
488-
let _reset_tenure = try_mine_opts.reset_tenure.unwrap_or(false);
488+
let reset_tenure = try_mine_opts.reset_tenure.unwrap_or(false);
489489

490490
let start = Instant::now();
491491

@@ -525,17 +525,24 @@ pub fn command_try_mine(mut argv: Vec<String>, opts: &StacksInspectOpts) {
525525
NakamotoChainState::get_canonical_block_header(chainstate.db(), &sort_db)
526526
.unwrap_or_else(|e| panic!("Error looking up chain tip: {e}"))
527527
.expect("No chain tip found");
528+
let parent_consensus_hash = parent_stacks_header.consensus_hash;
529+
let parent_block_id = parent_stacks_header.index_block_hash();
528530

529531
let burn_dbconn = sort_db.index_handle(&chain_tip.sortition_id);
530532

531533
let mut settings = BlockBuilderSettings::limited();
532534
settings.max_miner_time_ms = max_time;
533535

536+
// In case we need to submit transactions
537+
let miner_privk = StacksPrivateKey::new();
538+
let miner_pubkey = Secp256k1PublicKey::from_private(&miner_privk);
539+
let miner_pubkey_hash = Hash160::from_node_public_key(&miner_pubkey);
540+
let miner_nonce = 0;
541+
534542
let result = match &parent_stacks_header.anchored_header {
535543
StacksBlockHeaderTypes::Epoch2(..) => {
536-
let sk = StacksPrivateKey::new();
537-
let mut tx_auth = TransactionAuth::from_p2pkh(&sk).unwrap();
538-
tx_auth.set_origin_nonce(0);
544+
let mut tx_auth = TransactionAuth::from_p2pkh(&miner_privk).unwrap();
545+
tx_auth.set_origin_nonce(miner_nonce);
539546

540547
let mut coinbase_tx = StacksTransaction::new(
541548
TransactionVersion::Mainnet,
@@ -546,7 +553,7 @@ pub fn command_try_mine(mut argv: Vec<String>, opts: &StacksInspectOpts) {
546553
coinbase_tx.chain_id = conf.burnchain.chain_id;
547554
coinbase_tx.anchor_mode = TransactionAnchorMode::OnChainOnly;
548555
let mut tx_signer = StacksTransactionSigner::new(&coinbase_tx);
549-
tx_signer.sign_origin(&sk).unwrap();
556+
tx_signer.sign_origin(&miner_privk).unwrap();
550557
let coinbase_tx = tx_signer.get_tx().unwrap();
551558

552559
StacksBlockBuilder::build_anchored_block(
@@ -570,6 +577,49 @@ pub fn command_try_mine(mut argv: Vec<String>, opts: &StacksInspectOpts) {
570577
.map(|(block, cost, size)| (block.block_hash(), block.txs, cost, size))
571578
}
572579
StacksBlockHeaderTypes::Nakamoto(..) => {
580+
let tenure_info = if reset_tenure {
581+
let num_blocks_so_far = NakamotoChainState::get_nakamoto_tenure_length(
582+
chainstate.db(),
583+
&parent_block_id,
584+
)
585+
.unwrap_or_else(|e| panic!("Error getting tenure length: {e}"));
586+
let payload = TenureChangePayload {
587+
tenure_consensus_hash: parent_consensus_hash,
588+
prev_tenure_consensus_hash: parent_consensus_hash,
589+
burn_view_consensus_hash: parent_consensus_hash,
590+
previous_tenure_end: parent_block_id,
591+
previous_tenure_blocks: num_blocks_so_far,
592+
cause: TenureChangeCause::Extended,
593+
pubkey_hash: miner_pubkey_hash,
594+
};
595+
let tenure_change_tx_payload = TransactionPayload::TenureChange(payload);
596+
597+
let mut tx_auth = TransactionAuth::from_p2pkh(&miner_privk).unwrap();
598+
tx_auth.set_origin_nonce(miner_nonce);
599+
600+
let version = if conf.is_mainnet() {
601+
TransactionVersion::Mainnet
602+
} else {
603+
TransactionVersion::Testnet
604+
};
605+
606+
let mut tx = StacksTransaction::new(version, tx_auth, tenure_change_tx_payload);
607+
608+
tx.chain_id = conf.burnchain.chain_id;
609+
tx.anchor_mode = TransactionAnchorMode::OnChainOnly;
610+
let mut tx_signer = StacksTransactionSigner::new(&tx);
611+
tx_signer
612+
.sign_origin(&miner_privk)
613+
.unwrap_or_else(|e| panic!("Failed to sign transaction: {e}"));
614+
615+
let tenure_change_tx = Some(tx_signer.get_tx().expect("Failed to get tx"));
616+
NakamotoTenureInfo {
617+
coinbase_tx: None,
618+
tenure_change_tx,
619+
}
620+
} else {
621+
NakamotoTenureInfo::default()
622+
};
573623
NakamotoBlockBuilder::build_nakamoto_block(
574624
&chainstate,
575625
&burn_dbconn,
@@ -579,7 +629,7 @@ pub fn command_try_mine(mut argv: Vec<String>, opts: &StacksInspectOpts) {
579629
&parent_stacks_header.consensus_hash,
580630
// the burn so far on the burnchain (i.e. from the last burnchain block)
581631
chain_tip.total_burn,
582-
NakamotoTenureInfo::default(),
632+
tenure_info,
583633
settings,
584634
None,
585635
0,
@@ -590,10 +640,8 @@ pub fn command_try_mine(mut argv: Vec<String>, opts: &StacksInspectOpts) {
590640

591641
let elapsed = start.elapsed();
592642
let summary = format!(
593-
"block @ height = {h} off of {pid} ({pch}/{pbh}) in {t}ms. Min-fee: {min_fee}, Max-time: {max_time}",
643+
"block @ height = {h} off of {parent_block_id} ({parent_consensus_hash}/{pbh}) in {t}ms. Min-fee: {min_fee}, Max-time: {max_time}",
594644
h=parent_stacks_header.stacks_block_height + 1,
595-
pid=&parent_stacks_header.index_block_hash(),
596-
pch=&parent_stacks_header.consensus_hash,
597645
pbh=&parent_stacks_header.anchored_header.block_hash(),
598646
t=elapsed.as_millis(),
599647
);

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

+1-2
Original file line numberDiff line numberDiff line change
@@ -1113,14 +1113,13 @@ impl BlockMinerThread {
11131113
Some(&self.event_dispatcher),
11141114
signer_bitvec_len.unwrap_or(0),
11151115
)
1116-
.map_err(|e| {
1116+
.inspect_err(|e| {
11171117
if !matches!(
11181118
e,
11191119
ChainstateError::MinerAborted | ChainstateError::NoTransactionsToMine
11201120
) {
11211121
error!("Relayer: Failure mining anchored block: {e}");
11221122
}
1123-
e
11241123
})?;
11251124

11261125
if block.txs.is_empty() {

0 commit comments

Comments
 (0)