From eda8c544cdefd5b29d2ba297779deaefeef5784d Mon Sep 17 00:00:00 2001 From: Aaron Blankstein Date: Sat, 6 May 2023 15:40:03 -0500 Subject: [PATCH 1/4] add replay-block stacks-inspect method --- src/chainstate/stacks/db/blocks.rs | 10 +- src/main.rs | 154 +++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+), 5 deletions(-) diff --git a/src/chainstate/stacks/db/blocks.rs b/src/chainstate/stacks/db/blocks.rs index 440029166..2510ac815 100644 --- a/src/chainstate/stacks/db/blocks.rs +++ b/src/chainstate/stacks/db/blocks.rs @@ -5941,7 +5941,7 @@ impl StacksChainState { /// necessary so that the Headers database and Clarity database's /// transactions can commit very close to one another, after the /// event observer has emitted. - fn append_block<'a>( + pub fn append_block<'a>( chainstate_tx: &mut ChainstateTx, clarity_instance: &'a mut ClarityInstance, burn_dbconn: &mut SortitionHandleTx, @@ -6371,7 +6371,7 @@ impl StacksChainState { /// Verify that a Stacks anchored block attaches to its parent anchored block. /// * checks .header.total_work.work /// * checks .header.parent_block - fn check_block_attachment( + pub fn check_block_attachment( parent_block_header: &StacksBlockHeader, block_header: &StacksBlockHeader, ) -> bool { @@ -6398,7 +6398,7 @@ impl StacksChainState { /// The header info will be pulled from the headers DB, so this method only succeeds if the /// parent block has been processed. /// If it's not known, return None. - fn get_parent_header_info( + pub fn get_parent_header_info( chainstate_tx: &mut ChainstateTx, next_staging_block: &StagingBlock, ) -> Result, Error> { @@ -6440,7 +6440,7 @@ impl StacksChainState { } /// Extract and parse the block from a loaded staging block, and verify its integrity. - fn extract_stacks_block(next_staging_block: &StagingBlock) -> Result { + pub fn extract_stacks_block(next_staging_block: &StagingBlock) -> Result { let block = { StacksBlock::consensus_deserialize(&mut &next_staging_block.block_data[..]) .map_err(Error::CodecError)? @@ -6462,7 +6462,7 @@ impl StacksChainState { /// header info), determine which branch connects to the given block. If there are multiple /// branches, punish the parent. Return the portion of the branch that actually connects to /// the given block. - fn extract_connecting_microblocks( + pub fn extract_connecting_microblocks( parent_block_header_info: &StacksHeaderInfo, next_staging_block: &StagingBlock, block: &StacksBlock, diff --git a/src/main.rs b/src/main.rs index fcf8abb7e..373e8d57c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1005,6 +1005,160 @@ simulating a miner. return; } + if argv[1] == "replay-block" { + let index_block_hash = &argv[3]; + let index_block_hash = StacksBlockId::from_hex(&index_block_hash).unwrap(); + let chain_state_path = format!("{}/mainnet/chainstate/", &argv[2]); + let sort_db_path = format!("{}/mainnet/burnchain/sortition", &argv[2]); + let burn_db_path = format!("{}/mainnet/burnchain/burnchain.sqlite", &argv[2]); + let burnchain_blocks_db = BurnchainDB::open(&burn_db_path, false).unwrap(); + + let (mut chainstate, _) = + StacksChainState::open(true, CHAIN_ID_MAINNET, &chain_state_path, None).unwrap(); + + let mut sortdb = + SortitionDB::open(&sort_db_path, true, PoxConstants::mainnet_default()).unwrap(); + let mut sort_tx = sortdb.tx_begin_at_tip(); + + let (mut chainstate_tx, clarity_instance) = chainstate + .chainstate_tx_begin() + .expect("Failed to start chainstate tx"); + let next_staging_block = + StacksChainState::load_staging_block_info(&chainstate_tx.tx, &index_block_hash) + .expect("Failed to load staging block data") + .expect("No such index block hash in block database"); + let next_microblocks = + StacksChainState::find_parent_microblock_stream(&chainstate_tx.tx, &next_staging_block) + .unwrap() + .unwrap(); + + let (burn_header_hash, burn_header_height, burn_header_timestamp, winning_block_txid) = + match SortitionDB::get_block_snapshot_consensus( + &sort_tx, + &next_staging_block.consensus_hash, + ) + .unwrap() + { + Some(sn) => ( + sn.burn_header_hash, + sn.block_height as u32, + sn.burn_header_timestamp, + sn.winning_block_txid, + ), + None => { + // shouldn't happen + panic!( + "CORRUPTION: staging block {}/{} does not correspond to a burn block", + &next_staging_block.consensus_hash, &next_staging_block.anchored_block_hash + ); + } + }; + + info!( + "Process block {}/{} = {} in burn block {}, parent microblock {}", + next_staging_block.consensus_hash, + next_staging_block.anchored_block_hash, + &index_block_hash, + &burn_header_hash, + &next_staging_block.parent_microblock_hash, + ); + + let parent_header_info = + match StacksChainState::get_parent_header_info(&mut chainstate_tx, &next_staging_block) + .unwrap() + { + Some(hinfo) => hinfo, + None => panic!("Failed to load parent head info for block"), + }; + + let block = StacksChainState::extract_stacks_block(&next_staging_block).unwrap(); + let block_size = next_staging_block.block_data.len() as u64; + + if !StacksChainState::check_block_attachment( + &parent_header_info.anchored_header, + &block.header, + ) { + let msg = format!( + "Invalid stacks block {}/{} -- does not attach to parent {}/{}", + &next_staging_block.consensus_hash, + block.block_hash(), + parent_header_info.anchored_header.block_hash(), + &parent_header_info.consensus_hash + ); + warn!("{}", &msg); + process::exit(1); + } + + // validation check -- validate parent microblocks and find the ones that connect the + // block's parent to this block. + let next_microblocks = StacksChainState::extract_connecting_microblocks( + &parent_header_info, + &next_staging_block, + &block, + next_microblocks, + ) + .unwrap(); + let (last_microblock_hash, last_microblock_seq) = match next_microblocks.len() { + 0 => (EMPTY_MICROBLOCK_PARENT_HASH.clone(), 0), + _ => { + let l = next_microblocks.len(); + ( + next_microblocks[l - 1].block_hash(), + next_microblocks[l - 1].header.sequence, + ) + } + }; + assert_eq!( + next_staging_block.parent_microblock_hash, + last_microblock_hash + ); + assert_eq!( + next_staging_block.parent_microblock_seq, + last_microblock_seq + ); + + // user supports were never activated + let user_supports = vec![]; + + let block_am = StacksChainState::find_stacks_tip_affirmation_map( + &burnchain_blocks_db, + sort_tx.tx(), + &next_staging_block.consensus_hash, + &next_staging_block.anchored_block_hash, + ) + .unwrap(); + + let pox_constants = sort_tx.context.pox_constants.clone(); + + let epoch_receipt = match StacksChainState::append_block( + &mut chainstate_tx, + clarity_instance, + &mut sort_tx, + &pox_constants, + &parent_header_info, + &next_staging_block.consensus_hash, + &burn_header_hash, + burn_header_height, + burn_header_timestamp, + &block, + block_size, + &next_microblocks, + next_staging_block.commit_burn, + next_staging_block.sortition_burn, + &user_supports, + block_am.weight(), + ) { + Ok((receipt, _)) => { + info!("Block processed successfully!"); + receipt + } + Err(e) => { + error!("Failed processing block"; "error" => ?e); + process::exit(1) + } + }; + } + if argv[1] == "replay-chainstate" { if argv.len() < 7 { eprintln!("Usage: {} OLD_CHAINSTATE_PATH OLD_SORTITION_DB_PATH OLD_BURNCHAIN_DB_PATH NEW_CHAINSTATE_PATH NEW_BURNCHAIN_DB_PATH", &argv[0]); From 55a41203c00b2e1b31cadc96a58cf62d3ed0ab36 Mon Sep 17 00:00:00 2001 From: Aaron Blankstein Date: Wed, 10 May 2023 10:12:02 -0500 Subject: [PATCH 2/4] working replay-block command --- src/chainstate/stacks/db/blocks.rs | 20 ++++++++++++++++++++ src/main.rs | 25 ++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/chainstate/stacks/db/blocks.rs b/src/chainstate/stacks/db/blocks.rs index 2510ac815..c986f4bc1 100644 --- a/src/chainstate/stacks/db/blocks.rs +++ b/src/chainstate/stacks/db/blocks.rs @@ -5958,6 +5958,7 @@ impl StacksChainState { burnchain_sortition_burn: u64, user_burns: &[StagingUserBurnSupport], affirmation_weight: u64, + do_not_advance: bool, ) -> Result<(StacksEpochReceipt, PreCommitClarityBlock<'a>), Error> { debug!( "Process block {:?} with {} transactions", @@ -6323,6 +6324,24 @@ impl StacksChainState { .as_ref() .map(|(_, _, _, info)| info.clone()); + if do_not_advance { + let epoch_receipt = StacksEpochReceipt { + header: StacksHeaderInfo::regtest_genesis(), + tx_receipts, + matured_rewards, + matured_rewards_info, + parent_microblocks_cost: microblock_execution_cost, + anchored_block_cost: block_execution_cost, + parent_burn_block_hash, + parent_burn_block_height, + parent_burn_block_timestamp, + evaluated_epoch, + epoch_transition: applied_epoch_transition, + }; + + return Ok((epoch_receipt, clarity_commit)); + } + let new_tip = StacksChainState::advance_tip( &mut chainstate_tx.tx, &parent_chain_tip.anchored_header, @@ -6707,6 +6726,7 @@ impl StacksChainState { next_staging_block.sortition_burn, &user_supports, block_am.weight(), + false, ) { Ok(next_chain_tip_info) => next_chain_tip_info, Err(e) => { diff --git a/src/main.rs b/src/main.rs index 373e8d57c..1abfd24b1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1016,17 +1016,35 @@ simulating a miner. let (mut chainstate, _) = StacksChainState::open(true, CHAIN_ID_MAINNET, &chain_state_path, None).unwrap(); - let mut sortdb = - SortitionDB::open(&sort_db_path, true, PoxConstants::mainnet_default()).unwrap(); + let mut sortdb = SortitionDB::connect( + &sort_db_path, + BITCOIN_MAINNET_FIRST_BLOCK_HEIGHT, + &BurnchainHeaderHash::from_hex(BITCOIN_MAINNET_FIRST_BLOCK_HASH).unwrap(), + BITCOIN_MAINNET_FIRST_BLOCK_TIMESTAMP.into(), + STACKS_EPOCHS_MAINNET.as_ref(), + PoxConstants::mainnet_default(), + true, + ) + .unwrap(); let mut sort_tx = sortdb.tx_begin_at_tip(); + let blocks_path = chainstate.blocks_path.clone(); let (mut chainstate_tx, clarity_instance) = chainstate .chainstate_tx_begin() .expect("Failed to start chainstate tx"); - let next_staging_block = + let mut next_staging_block = StacksChainState::load_staging_block_info(&chainstate_tx.tx, &index_block_hash) .expect("Failed to load staging block data") .expect("No such index block hash in block database"); + + next_staging_block.block_data = StacksChainState::load_block_bytes( + &blocks_path, + &next_staging_block.consensus_hash, + &next_staging_block.anchored_block_hash, + ) + .unwrap() + .unwrap_or(vec![]); + let next_microblocks = StacksChainState::find_parent_microblock_stream(&chainstate_tx.tx, &next_staging_block) .unwrap() @@ -1147,6 +1165,7 @@ simulating a miner. next_staging_block.sortition_burn, &user_supports, block_am.weight(), + true, ) { Ok((receipt, _)) => { info!("Block processed successfully!"); From 8bb3863001ffdf695f079d8eadbca569d54f78f9 Mon Sep 17 00:00:00 2001 From: Aaron Blankstein Date: Wed, 10 May 2023 16:26:19 -0500 Subject: [PATCH 3/4] allow replay-block to use a block prefix --- src/main.rs | 368 +++++++++++++++++++--------------- stacks-common/src/util/log.rs | 2 + 2 files changed, 205 insertions(+), 165 deletions(-) diff --git a/src/main.rs b/src/main.rs index 1abfd24b1..d7b09ccaf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1006,176 +1006,43 @@ simulating a miner. } if argv[1] == "replay-block" { - let index_block_hash = &argv[3]; - let index_block_hash = StacksBlockId::from_hex(&index_block_hash).unwrap(); - let chain_state_path = format!("{}/mainnet/chainstate/", &argv[2]); - let sort_db_path = format!("{}/mainnet/burnchain/sortition", &argv[2]); - let burn_db_path = format!("{}/mainnet/burnchain/burnchain.sqlite", &argv[2]); - let burnchain_blocks_db = BurnchainDB::open(&burn_db_path, false).unwrap(); - - let (mut chainstate, _) = - StacksChainState::open(true, CHAIN_ID_MAINNET, &chain_state_path, None).unwrap(); - - let mut sortdb = SortitionDB::connect( - &sort_db_path, - BITCOIN_MAINNET_FIRST_BLOCK_HEIGHT, - &BurnchainHeaderHash::from_hex(BITCOIN_MAINNET_FIRST_BLOCK_HASH).unwrap(), - BITCOIN_MAINNET_FIRST_BLOCK_TIMESTAMP.into(), - STACKS_EPOCHS_MAINNET.as_ref(), - PoxConstants::mainnet_default(), - true, - ) - .unwrap(); - let mut sort_tx = sortdb.tx_begin_at_tip(); - - let blocks_path = chainstate.blocks_path.clone(); - let (mut chainstate_tx, clarity_instance) = chainstate - .chainstate_tx_begin() - .expect("Failed to start chainstate tx"); - let mut next_staging_block = - StacksChainState::load_staging_block_info(&chainstate_tx.tx, &index_block_hash) - .expect("Failed to load staging block data") - .expect("No such index block hash in block database"); - - next_staging_block.block_data = StacksChainState::load_block_bytes( - &blocks_path, - &next_staging_block.consensus_hash, - &next_staging_block.anchored_block_hash, - ) - .unwrap() - .unwrap_or(vec![]); - - let next_microblocks = - StacksChainState::find_parent_microblock_stream(&chainstate_tx.tx, &next_staging_block) - .unwrap() - .unwrap(); - - let (burn_header_hash, burn_header_height, burn_header_timestamp, winning_block_txid) = - match SortitionDB::get_block_snapshot_consensus( - &sort_tx, - &next_staging_block.consensus_hash, - ) - .unwrap() - { - Some(sn) => ( - sn.burn_header_hash, - sn.block_height as u32, - sn.burn_header_timestamp, - sn.winning_block_txid, - ), - None => { - // shouldn't happen - panic!( - "CORRUPTION: staging block {}/{} does not correspond to a burn block", - &next_staging_block.consensus_hash, &next_staging_block.anchored_block_hash - ); - } - }; - - info!( - "Process block {}/{} = {} in burn block {}, parent microblock {}", - next_staging_block.consensus_hash, - next_staging_block.anchored_block_hash, - &index_block_hash, - &burn_header_hash, - &next_staging_block.parent_microblock_hash, - ); - - let parent_header_info = - match StacksChainState::get_parent_header_info(&mut chainstate_tx, &next_staging_block) - .unwrap() - { - Some(hinfo) => hinfo, - None => panic!("Failed to load parent head info for block"), - }; - - let block = StacksChainState::extract_stacks_block(&next_staging_block).unwrap(); - let block_size = next_staging_block.block_data.len() as u64; - - if !StacksChainState::check_block_attachment( - &parent_header_info.anchored_header, - &block.header, - ) { - let msg = format!( - "Invalid stacks block {}/{} -- does not attach to parent {}/{}", - &next_staging_block.consensus_hash, - block.block_hash(), - parent_header_info.anchored_header.block_hash(), - &parent_header_info.consensus_hash + if argv.len() < 3 { + eprintln!( + "Usage: {} chainstate_path index-block-hash-prefix", + &argv[0] ); - warn!("{}", &msg); process::exit(1); } + let stacks_path = &argv[2]; + let index_block_hash_prefix = &argv[3]; + let staging_blocks_db_path = format!("{}/mainnet/chainstate/vm/index.sqlite", stacks_path); + let conn = + Connection::open_with_flags(&staging_blocks_db_path, OpenFlags::SQLITE_OPEN_READ_ONLY) + .unwrap(); + let mut stmt = conn + .prepare(&format!( + "SELECT index_block_hash FROM staging_blocks WHERE index_block_hash LIKE \"{}%\"", + index_block_hash_prefix + )) + .unwrap(); + let mut hashes_set = stmt.query(rusqlite::NO_PARAMS).unwrap(); - // validation check -- validate parent microblocks and find the ones that connect the - // block's parent to this block. - let next_microblocks = StacksChainState::extract_connecting_microblocks( - &parent_header_info, - &next_staging_block, - &block, - next_microblocks, - ) - .unwrap(); - let (last_microblock_hash, last_microblock_seq) = match next_microblocks.len() { - 0 => (EMPTY_MICROBLOCK_PARENT_HASH.clone(), 0), - _ => { - let l = next_microblocks.len(); - ( - next_microblocks[l - 1].block_hash(), - next_microblocks[l - 1].header.sequence, - ) + let mut index_block_hashes: Vec = vec![]; + while let Ok(Some(row)) = hashes_set.next() { + index_block_hashes.push(row.get(0).unwrap()); + } + + let total = index_block_hashes.len(); + let mut i = 1; + println!("Will check {} blocks.", total); + for index_block_hash in index_block_hashes.iter() { + if i % 100 == 0 { + println!("Checked {}...", i); } - }; - assert_eq!( - next_staging_block.parent_microblock_hash, - last_microblock_hash - ); - assert_eq!( - next_staging_block.parent_microblock_seq, - last_microblock_seq - ); - - // user supports were never activated - let user_supports = vec![]; - - let block_am = StacksChainState::find_stacks_tip_affirmation_map( - &burnchain_blocks_db, - sort_tx.tx(), - &next_staging_block.consensus_hash, - &next_staging_block.anchored_block_hash, - ) - .unwrap(); - - let pox_constants = sort_tx.context.pox_constants.clone(); - - let epoch_receipt = match StacksChainState::append_block( - &mut chainstate_tx, - clarity_instance, - &mut sort_tx, - &pox_constants, - &parent_header_info, - &next_staging_block.consensus_hash, - &burn_header_hash, - burn_header_height, - burn_header_timestamp, - &block, - block_size, - &next_microblocks, - next_staging_block.commit_burn, - next_staging_block.sortition_burn, - &user_supports, - block_am.weight(), - true, - ) { - Ok((receipt, _)) => { - info!("Block processed successfully!"); - receipt - } - Err(e) => { - error!("Failed processing block"; "error" => ?e); - process::exit(1) - } - }; + i += 1; + replay_block(stacks_path, index_block_hash); + } + process::exit(0); } if argv[1] == "replay-chainstate" { @@ -1708,3 +1575,174 @@ simulating a miner. process::exit(0); } + +fn replay_block(stacks_path: &str, index_block_hash_hex: &str) { + let index_block_hash = StacksBlockId::from_hex(index_block_hash_hex).unwrap(); + let chain_state_path = format!("{}/mainnet/chainstate/", stacks_path); + let sort_db_path = format!("{}/mainnet/burnchain/sortition", stacks_path); + let burn_db_path = format!("{}/mainnet/burnchain/burnchain.sqlite", stacks_path); + let burnchain_blocks_db = BurnchainDB::open(&burn_db_path, false).unwrap(); + + let (mut chainstate, _) = + StacksChainState::open(true, CHAIN_ID_MAINNET, &chain_state_path, None).unwrap(); + + let mut sortdb = SortitionDB::connect( + &sort_db_path, + BITCOIN_MAINNET_FIRST_BLOCK_HEIGHT, + &BurnchainHeaderHash::from_hex(BITCOIN_MAINNET_FIRST_BLOCK_HASH).unwrap(), + BITCOIN_MAINNET_FIRST_BLOCK_TIMESTAMP.into(), + STACKS_EPOCHS_MAINNET.as_ref(), + PoxConstants::mainnet_default(), + true, + ) + .unwrap(); + let mut sort_tx = sortdb.tx_begin_at_tip(); + + let blocks_path = chainstate.blocks_path.clone(); + let (mut chainstate_tx, clarity_instance) = chainstate + .chainstate_tx_begin() + .expect("Failed to start chainstate tx"); + let mut next_staging_block = + StacksChainState::load_staging_block_info(&chainstate_tx.tx, &index_block_hash) + .expect("Failed to load staging block data") + .expect("No such index block hash in block database"); + + next_staging_block.block_data = StacksChainState::load_block_bytes( + &blocks_path, + &next_staging_block.consensus_hash, + &next_staging_block.anchored_block_hash, + ) + .unwrap() + .unwrap_or(vec![]); + + let next_microblocks = + StacksChainState::find_parent_microblock_stream(&chainstate_tx.tx, &next_staging_block) + .unwrap() + .unwrap(); + + let (burn_header_hash, burn_header_height, burn_header_timestamp, _winning_block_txid) = + match SortitionDB::get_block_snapshot_consensus( + &sort_tx, + &next_staging_block.consensus_hash, + ) + .unwrap() + { + Some(sn) => ( + sn.burn_header_hash, + sn.block_height as u32, + sn.burn_header_timestamp, + sn.winning_block_txid, + ), + None => { + // shouldn't happen + panic!( + "CORRUPTION: staging block {}/{} does not correspond to a burn block", + &next_staging_block.consensus_hash, &next_staging_block.anchored_block_hash + ); + } + }; + + info!( + "Process block {}/{} = {} in burn block {}, parent microblock {}", + next_staging_block.consensus_hash, + next_staging_block.anchored_block_hash, + &index_block_hash, + &burn_header_hash, + &next_staging_block.parent_microblock_hash, + ); + + let parent_header_info = + match StacksChainState::get_parent_header_info(&mut chainstate_tx, &next_staging_block) + .unwrap() + { + Some(hinfo) => hinfo, + None => panic!("Failed to load parent head info for block"), + }; + + let block = StacksChainState::extract_stacks_block(&next_staging_block).unwrap(); + let block_size = next_staging_block.block_data.len() as u64; + + if !StacksChainState::check_block_attachment(&parent_header_info.anchored_header, &block.header) + { + let msg = format!( + "Invalid stacks block {}/{} -- does not attach to parent {}/{}", + &next_staging_block.consensus_hash, + block.block_hash(), + parent_header_info.anchored_header.block_hash(), + &parent_header_info.consensus_hash + ); + println!("{}", &msg); + return; + } + + // validation check -- validate parent microblocks and find the ones that connect the + // block's parent to this block. + let next_microblocks = StacksChainState::extract_connecting_microblocks( + &parent_header_info, + &next_staging_block, + &block, + next_microblocks, + ) + .unwrap(); + let (last_microblock_hash, last_microblock_seq) = match next_microblocks.len() { + 0 => (EMPTY_MICROBLOCK_PARENT_HASH.clone(), 0), + _ => { + let l = next_microblocks.len(); + ( + next_microblocks[l - 1].block_hash(), + next_microblocks[l - 1].header.sequence, + ) + } + }; + assert_eq!( + next_staging_block.parent_microblock_hash, + last_microblock_hash + ); + assert_eq!( + next_staging_block.parent_microblock_seq, + last_microblock_seq + ); + + // user supports were never activated + let user_supports = vec![]; + + let block_am = StacksChainState::find_stacks_tip_affirmation_map( + &burnchain_blocks_db, + sort_tx.tx(), + &next_staging_block.consensus_hash, + &next_staging_block.anchored_block_hash, + ) + .unwrap(); + + let pox_constants = sort_tx.context.pox_constants.clone(); + + let epoch_receipt = match StacksChainState::append_block( + &mut chainstate_tx, + clarity_instance, + &mut sort_tx, + &pox_constants, + &parent_header_info, + &next_staging_block.consensus_hash, + &burn_header_hash, + burn_header_height, + burn_header_timestamp, + &block, + block_size, + &next_microblocks, + next_staging_block.commit_burn, + next_staging_block.sortition_burn, + &user_supports, + block_am.weight(), + true, + ) { + Ok((_receipt, _)) => { + info!("Block processed successfully! block = {}", index_block_hash); + } + Err(e) => { + println!( + "Failed processing block! block = {}, error = {:?}", + index_block_hash, e + ); + } + }; +} diff --git a/stacks-common/src/util/log.rs b/stacks-common/src/util/log.rs index 26de14e67..ef3ee7c0d 100644 --- a/stacks-common/src/util/log.rs +++ b/stacks-common/src/util/log.rs @@ -251,6 +251,8 @@ fn inner_get_loglevel() -> slog::Level { slog::Level::Debug } else if env::var("BLOCKSTACK_DEBUG") == Ok("1".into()) { slog::Level::Debug + } else if env::var("STACKS_LOG_CRITONLY") == Ok("1".into()) { + slog::Level::Critical } else { slog::Level::Info } From 15639c5da3138833508ecb041e804a095eba5efd Mon Sep 17 00:00:00 2001 From: Aaron Blankstein Date: Fri, 12 May 2023 13:48:40 -0500 Subject: [PATCH 4/4] skip blocks without microblock data or parent header info --- src/main.rs | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index d7b09ccaf..e0878d099 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1042,6 +1042,7 @@ simulating a miner. i += 1; replay_block(stacks_path, index_block_hash); } + println!("Finished!"); process::exit(0); } @@ -1615,10 +1616,18 @@ fn replay_block(stacks_path: &str, index_block_hash_hex: &str) { .unwrap() .unwrap_or(vec![]); - let next_microblocks = - StacksChainState::find_parent_microblock_stream(&chainstate_tx.tx, &next_staging_block) - .unwrap() - .unwrap(); + let next_microblocks = match StacksChainState::find_parent_microblock_stream( + &chainstate_tx.tx, + &next_staging_block, + ) + .unwrap() + { + Some(x) => x, + None => { + println!("No microblock stream found for {}", index_block_hash_hex); + return; + } + }; let (burn_header_hash, burn_header_height, burn_header_timestamp, _winning_block_txid) = match SortitionDB::get_block_snapshot_consensus( @@ -1656,7 +1665,13 @@ fn replay_block(stacks_path: &str, index_block_hash_hex: &str) { .unwrap() { Some(hinfo) => hinfo, - None => panic!("Failed to load parent head info for block"), + None => { + println!( + "Failed to load parent head info for block: {}", + index_block_hash_hex + ); + return; + } }; let block = StacksChainState::extract_stacks_block(&next_staging_block).unwrap();