|
1 | | -// Copyright (C) 2013-2020 Blockstack PBC, a public benefit corporation |
2 | | -// Copyright (C) 2020 Stacks Open Internet Foundation |
| 1 | +// Copyright (C) 2025 Stacks Open Internet Foundation |
3 | 2 | // |
4 | 3 | // This program is free software: you can redistribute it and/or modify |
5 | 4 | // it under the terms of the GNU General Public License as published by |
|
14 | 13 | // You should have received a copy of the GNU General Public License |
15 | 14 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | 15 |
|
17 | | -//! Subcommands used by `stacks-inspect` binary |
18 | | -
|
19 | 16 | use std::path::PathBuf; |
20 | 17 | use std::time::Instant; |
21 | 18 | use std::{fs, process}; |
22 | 19 |
|
23 | 20 | use clarity::types::chainstate::SortitionId; |
24 | | -use clarity::util::hash::{to_hex, Sha512Trunc256Sum}; |
25 | | -use db::blocks::DummyEventDispatcher; |
26 | | -use db::ChainstateTx; |
| 21 | +use clarity::util::hash::{Sha512Trunc256Sum, to_hex}; |
27 | 22 | use regex::Regex; |
28 | 23 | use rusqlite::{Connection, OpenFlags}; |
29 | 24 | use stacks_common::types::chainstate::{BlockHeaderHash, StacksBlockId}; |
30 | 25 | use stacks_common::types::sqlite::NO_PARAMS; |
31 | 26 | use stacks_common::util::hash::Hash160; |
32 | 27 | use stacks_common::util::vrf::VRFProof; |
33 | | - |
34 | | -use crate::burnchains::Burnchain; |
35 | | -use crate::chainstate::burn::db::sortdb::{ |
36 | | - get_ancestor_sort_id, SortitionDB, SortitionHandleContext, |
| 28 | +use stacks_common::{debug, info, warn}; |
| 29 | +use stackslib::burnchains::Burnchain; |
| 30 | +use stackslib::chainstate::burn::ConsensusHash; |
| 31 | +use stackslib::chainstate::burn::db::sortdb::{ |
| 32 | + SortitionDB, SortitionHandleContext, get_ancestor_sort_id, |
| 33 | +}; |
| 34 | +use stackslib::chainstate::coordinator::OnChainRewardSetProvider; |
| 35 | +use stackslib::chainstate::nakamoto::miner::{ |
| 36 | + BlockMetadata, NakamotoBlockBuilder, NakamotoTenureInfo, |
| 37 | +}; |
| 38 | +use stackslib::chainstate::nakamoto::{NakamotoBlock, NakamotoChainState}; |
| 39 | +use stackslib::chainstate::stacks::db::blocks::DummyEventDispatcher; |
| 40 | +use stackslib::chainstate::stacks::db::{ |
| 41 | + ChainstateTx, StacksBlockHeaderTypes, StacksChainState, StacksHeaderInfo, |
37 | 42 | }; |
38 | | -use crate::chainstate::burn::ConsensusHash; |
39 | | -use crate::chainstate::coordinator::OnChainRewardSetProvider; |
40 | | -use crate::chainstate::nakamoto::miner::{BlockMetadata, NakamotoBlockBuilder, NakamotoTenureInfo}; |
41 | | -use crate::chainstate::nakamoto::{NakamotoBlock, NakamotoChainState}; |
42 | | -use crate::chainstate::stacks::db::{StacksBlockHeaderTypes, StacksChainState, StacksHeaderInfo}; |
43 | | -use crate::chainstate::stacks::miner::*; |
44 | | -use crate::chainstate::stacks::{Error as ChainstateError, *}; |
45 | | -use crate::clarity_vm::clarity::ClarityInstance; |
46 | | -use crate::clarity_vm::database::GetTenureStartId; |
47 | | -use crate::config::{Config, ConfigFile, DEFAULT_MAINNET_CONFIG}; |
48 | | -use crate::core::*; |
49 | | -use crate::cost_estimates::metrics::UnitMetric; |
50 | | -use crate::cost_estimates::UnitEstimator; |
51 | | -use crate::util_lib::db::IndexDBTx; |
| 43 | +use stackslib::chainstate::stacks::miner::*; |
| 44 | +use stackslib::chainstate::stacks::{Error as ChainstateError, *}; |
| 45 | +use stackslib::clarity_vm::clarity::ClarityInstance; |
| 46 | +use stackslib::clarity_vm::database::GetTenureStartId; |
| 47 | +use stackslib::config::{Config, ConfigFile, DEFAULT_MAINNET_CONFIG}; |
| 48 | +use stackslib::core::*; |
| 49 | +use stackslib::cost_estimates::UnitEstimator; |
| 50 | +use stackslib::cost_estimates::metrics::UnitMetric; |
| 51 | +use stackslib::util_lib::db::IndexDBTx; |
52 | 52 |
|
53 | 53 | /// Options common to many `stacks-inspect` subcommands |
54 | 54 | /// Returned by `process_common_opts()` |
@@ -141,34 +141,38 @@ pub fn command_replay_block(argv: &[String], conf: Option<&Config>) { |
141 | 141 |
|
142 | 142 | let query = match mode { |
143 | 143 | Some("prefix") => format!( |
144 | | - "SELECT index_block_hash FROM staging_blocks WHERE orphaned = 0 AND index_block_hash LIKE \"{}%\"", |
145 | | - argv[3] |
146 | | - ), |
| 144 | + "SELECT index_block_hash FROM staging_blocks WHERE orphaned = 0 AND index_block_hash LIKE \"{}%\"", |
| 145 | + argv[3] |
| 146 | + ), |
147 | 147 | Some("first") => format!( |
148 | | - "SELECT index_block_hash FROM staging_blocks WHERE orphaned = 0 ORDER BY height ASC LIMIT {}", |
149 | | - argv[3] |
150 | | - ), |
| 148 | + "SELECT index_block_hash FROM staging_blocks WHERE orphaned = 0 ORDER BY height ASC LIMIT {}", |
| 149 | + argv[3] |
| 150 | + ), |
151 | 151 | Some("range") => { |
152 | 152 | let arg4 = argv[3] |
153 | 153 | .parse::<u64>() |
154 | 154 | .expect("<start_block> not a valid u64"); |
155 | 155 | let arg5 = argv[4].parse::<u64>().expect("<end-block> not a valid u64"); |
156 | 156 | let start = arg4.saturating_sub(1); |
157 | 157 | let blocks = arg5.saturating_sub(arg4); |
158 | | - format!("SELECT index_block_hash FROM staging_blocks WHERE orphaned = 0 ORDER BY height ASC LIMIT {start}, {blocks}") |
| 158 | + format!( |
| 159 | + "SELECT index_block_hash FROM staging_blocks WHERE orphaned = 0 ORDER BY height ASC LIMIT {start}, {blocks}" |
| 160 | + ) |
159 | 161 | } |
160 | 162 | Some("index-range") => { |
161 | 163 | let start = argv[3] |
162 | 164 | .parse::<u64>() |
163 | 165 | .expect("<start_block> not a valid u64"); |
164 | 166 | let end = argv[4].parse::<u64>().expect("<end-block> not a valid u64"); |
165 | 167 | let blocks = end.saturating_sub(start); |
166 | | - format!("SELECT index_block_hash FROM staging_blocks WHERE orphaned = 0 ORDER BY index_block_hash ASC LIMIT {start}, {blocks}") |
| 168 | + format!( |
| 169 | + "SELECT index_block_hash FROM staging_blocks WHERE orphaned = 0 ORDER BY index_block_hash ASC LIMIT {start}, {blocks}" |
| 170 | + ) |
167 | 171 | } |
168 | 172 | Some("last") => format!( |
169 | | - "SELECT index_block_hash FROM staging_blocks WHERE orphaned = 0 ORDER BY height DESC LIMIT {}", |
170 | | - argv[3] |
171 | | - ), |
| 173 | + "SELECT index_block_hash FROM staging_blocks WHERE orphaned = 0 ORDER BY height DESC LIMIT {}", |
| 174 | + argv[3] |
| 175 | + ), |
172 | 176 | Some(_) => print_help_and_exit(), |
173 | 177 | // Default to ALL blocks |
174 | 178 | None => "SELECT index_block_hash FROM staging_blocks WHERE orphaned = 0".into(), |
@@ -229,34 +233,38 @@ pub fn command_replay_block_nakamoto(argv: &[String], conf: Option<&Config>) { |
229 | 233 |
|
230 | 234 | let query = match mode { |
231 | 235 | Some("prefix") => format!( |
232 | | - "SELECT index_block_hash FROM nakamoto_staging_blocks WHERE orphaned = 0 AND index_block_hash LIKE \"{}%\"", |
233 | | - argv[3] |
234 | | - ), |
| 236 | + "SELECT index_block_hash FROM nakamoto_staging_blocks WHERE orphaned = 0 AND index_block_hash LIKE \"{}%\"", |
| 237 | + argv[3] |
| 238 | + ), |
235 | 239 | Some("first") => format!( |
236 | | - "SELECT index_block_hash FROM nakamoto_staging_blocks WHERE orphaned = 0 ORDER BY height ASC LIMIT {}", |
237 | | - argv[3] |
238 | | - ), |
| 240 | + "SELECT index_block_hash FROM nakamoto_staging_blocks WHERE orphaned = 0 ORDER BY height ASC LIMIT {}", |
| 241 | + argv[3] |
| 242 | + ), |
239 | 243 | Some("range") => { |
240 | 244 | let arg4 = argv[3] |
241 | 245 | .parse::<u64>() |
242 | 246 | .expect("<start_block> not a valid u64"); |
243 | 247 | let arg5 = argv[4].parse::<u64>().expect("<end-block> not a valid u64"); |
244 | 248 | let start = arg4.saturating_sub(1); |
245 | 249 | let blocks = arg5.saturating_sub(arg4); |
246 | | - format!("SELECT index_block_hash FROM nakamoto_staging_blocks WHERE orphaned = 0 ORDER BY height ASC LIMIT {start}, {blocks}") |
| 250 | + format!( |
| 251 | + "SELECT index_block_hash FROM nakamoto_staging_blocks WHERE orphaned = 0 ORDER BY height ASC LIMIT {start}, {blocks}" |
| 252 | + ) |
247 | 253 | } |
248 | 254 | Some("index-range") => { |
249 | 255 | let start = argv[3] |
250 | 256 | .parse::<u64>() |
251 | 257 | .expect("<start_block> not a valid u64"); |
252 | 258 | let end = argv[4].parse::<u64>().expect("<end-block> not a valid u64"); |
253 | 259 | let blocks = end.saturating_sub(start); |
254 | | - format!("SELECT index_block_hash FROM nakamoto_staging_blocks WHERE orphaned = 0 ORDER BY index_block_hash ASC LIMIT {start}, {blocks}") |
| 260 | + format!( |
| 261 | + "SELECT index_block_hash FROM nakamoto_staging_blocks WHERE orphaned = 0 ORDER BY index_block_hash ASC LIMIT {start}, {blocks}" |
| 262 | + ) |
255 | 263 | } |
256 | 264 | Some("last") => format!( |
257 | | - "SELECT index_block_hash FROM nakamoto_staging_blocks WHERE orphaned = 0 ORDER BY height DESC LIMIT {}", |
258 | | - argv[3] |
259 | | - ), |
| 265 | + "SELECT index_block_hash FROM nakamoto_staging_blocks WHERE orphaned = 0 ORDER BY height DESC LIMIT {}", |
| 266 | + argv[3] |
| 267 | + ), |
260 | 268 | Some(_) => print_help_and_exit(), |
261 | 269 | // Default to ALL blocks |
262 | 270 | None => "SELECT index_block_hash FROM nakamoto_staging_blocks WHERE orphaned = 0".into(), |
@@ -386,8 +394,12 @@ pub fn command_try_mine(argv: &[String], conf: Option<&Config>) { |
386 | 394 | let n = &argv[0]; |
387 | 395 | eprintln!("Usage: {n} <working-dir> [min-fee [max-time]]"); |
388 | 396 | eprintln!(""); |
389 | | - eprintln!("Given a <working-dir>, try to ''mine'' an anchored block. This invokes the miner block"); |
390 | | - eprintln!("assembly, but does not attempt to broadcast a block commit. This is useful for determining"); |
| 397 | + eprintln!( |
| 398 | + "Given a <working-dir>, try to ''mine'' an anchored block. This invokes the miner block" |
| 399 | + ); |
| 400 | + eprintln!( |
| 401 | + "assembly, but does not attempt to broadcast a block commit. This is useful for determining" |
| 402 | + ); |
391 | 403 | eprintln!("what transactions a given chain state would include in an anchor block,"); |
392 | 404 | eprintln!("or otherwise simulating a miner."); |
393 | 405 | process::exit(1); |
@@ -523,11 +535,11 @@ pub fn command_try_mine(argv: &[String], conf: Option<&Config>) { |
523 | 535 | let elapsed = start.elapsed(); |
524 | 536 | let summary = format!( |
525 | 537 | "block @ height = {h} off of {pid} ({pch}/{pbh}) in {t}ms. Min-fee: {min_fee}, Max-time: {max_time}", |
526 | | - h=parent_stacks_header.stacks_block_height + 1, |
527 | | - pid=&parent_stacks_header.index_block_hash(), |
528 | | - pch=&parent_stacks_header.consensus_hash, |
529 | | - pbh=&parent_stacks_header.anchored_header.block_hash(), |
530 | | - t=elapsed.as_millis(), |
| 538 | + h = parent_stacks_header.stacks_block_height + 1, |
| 539 | + pid = &parent_stacks_header.index_block_hash(), |
| 540 | + pch = &parent_stacks_header.consensus_hash, |
| 541 | + pbh = &parent_stacks_header.anchored_header.block_hash(), |
| 542 | + t = elapsed.as_millis(), |
531 | 543 | ); |
532 | 544 |
|
533 | 545 | let code = match result { |
@@ -770,7 +782,9 @@ fn replay_block( |
770 | 782 | ), |
771 | 783 | None => { |
772 | 784 | // shouldn't happen |
773 | | - panic!("CORRUPTION: staging block {block_consensus_hash}/{block_hash} does not correspond to a burn block"); |
| 785 | + panic!( |
| 786 | + "CORRUPTION: staging block {block_consensus_hash}/{block_hash} does not correspond to a burn block" |
| 787 | + ); |
774 | 788 | } |
775 | 789 | }; |
776 | 790 |
|
@@ -835,8 +849,10 @@ fn replay_block( |
835 | 849 | ) { |
836 | 850 | Ok((receipt, _, _)) => { |
837 | 851 | if receipt.anchored_block_cost != cost { |
838 | | - println!("Failed processing block! block = {block_id}. Unexpected cost. expected = {cost}, evaluated = {}", |
839 | | - receipt.anchored_block_cost); |
| 852 | + println!( |
| 853 | + "Failed processing block! block = {block_id}. Unexpected cost. expected = {cost}, evaluated = {}", |
| 854 | + receipt.anchored_block_cost |
| 855 | + ); |
840 | 856 | process::exit(1); |
841 | 857 | } |
842 | 858 |
|
@@ -1153,7 +1169,9 @@ fn replay_block_nakamoto( |
1153 | 1169 | // check the cost |
1154 | 1170 | let evaluated_cost = receipt.anchored_block_cost.clone(); |
1155 | 1171 | if evaluated_cost != expected_cost { |
1156 | | - println!("Failed processing block! block = {block_id}. Unexpected cost. expected = {expected_cost}, evaluated = {evaluated_cost}"); |
| 1172 | + println!( |
| 1173 | + "Failed processing block! block = {block_id}. Unexpected cost. expected = {expected_cost}, evaluated = {evaluated_cost}" |
| 1174 | + ); |
1157 | 1175 | process::exit(1); |
1158 | 1176 | } |
1159 | 1177 | } |
@@ -1197,7 +1215,7 @@ pub mod test { |
1197 | 1215 | "stacks-inspect try-mine --config my_config.toml /tmp/chainstate/mainnet", |
1198 | 1216 | ); |
1199 | 1217 | let argv_init = argv.clone(); |
1200 | | - let opts = drain_common_opts(&mut argv, 0); |
| 1218 | + let _opts = drain_common_opts(&mut argv, 0); |
1201 | 1219 | let opts = drain_common_opts(&mut argv, 1); |
1202 | 1220 |
|
1203 | 1221 | assert_eq!(argv, argv_init); |
|
0 commit comments