Skip to content

Commit

Permalink
Merge pull request #798 from Chia-Network/validate-blockchain
Browse files Browse the repository at this point in the history
Validate blockchain
  • Loading branch information
arvidn authored Nov 25, 2024
2 parents 96b0c0a + 8ac8bbd commit f89bc11
Showing 1 changed file with 34 additions and 5 deletions.
39 changes: 34 additions & 5 deletions crates/chia-tools/src/bin/validate-blockchain-db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ struct Args {
#[arg(short, long, default_value_t = 0)]
start: u32,

/// Validate blockchain against a height-to-hash file
#[arg(long)]
height_to_hash: Option<String>,

/// Don't validate block signatures (saves time)
#[arg(long, default_value_t = false)]
skip_signature_validation: bool,
Expand Down Expand Up @@ -66,7 +70,7 @@ const TESTNET11_CONSTANTS: ConsensusConstants = ConsensusConstants {
agg_sig_parent_puzzle_additional_data: Bytes32::new(hex!(
"54c3ed8017f77354acca4000b40424396a369740e5a504467784f392b961ab37"
)),
difficulty_constant_factor: 10052721566054,
difficulty_constant_factor: 10_052_721_566_054,
difficulty_starting: 30,
epoch_blocks: 768,
genesis_challenge: Bytes32::new(hex!(
Expand All @@ -80,12 +84,12 @@ const TESTNET11_CONSTANTS: ConsensusConstants = ConsensusConstants {
)),
mempool_block_buffer: 10,
min_plot_size: 18,
sub_slot_iters_starting: 67108864,
sub_slot_iters_starting: 67_108_864,
// forks activated from the beginning on testnet11
hard_fork_height: 0,
plot_filter_128_height: 6029568,
plot_filter_64_height: 11075328,
plot_filter_32_height: 16121088,
plot_filter_128_height: 6_029_568,
plot_filter_64_height: 11_075_328,
plot_filter_32_height: 16_121_088,
..MAINNET_CONSTANTS
};

Expand Down Expand Up @@ -129,10 +133,29 @@ features that are validated:
"SELECT coin_name, coinbase, puzzle_hash, coin_parent, amount FROM coin_record WHERE confirmed_index == ?;",
)
.expect("failed to prepare SQL statement finding created coins");
let mut select_peak = connection
.prepare("SELECT hash FROM current_peak WHERE key == 0;")
.expect("failed to prepare SQL statement finding peak");

let mut peak_row = select_peak.query([]).expect("failed to query current peak");
let peak_hash = peak_row
.next()
.expect("missing peak")
.expect("missing peak")
.get::<_, [u8; 32]>(0)
.expect("missing peak");

let mut prev_hash = constants.genesis_challenge;
let mut prev_height: i64 = args.start as i64 - 1;

let height_to_hash: Option<Vec<Bytes32>> = args.height_to_hash.map(|hth| {
std::fs::read(hth)
.expect("failed to read height-to-hash")
.chunks(32)
.map(|v| -> Bytes32 { v.try_into().unwrap() })
.collect()
});

println!("iterating over blocks starting at height {}", args.start);
iterate_blocks(&args.file, args.start, None, |height, block, block_refs| {
// If we don't start validation from height 0, we need to initialize the
Expand All @@ -159,6 +182,11 @@ features that are validated:
"at height {height} the the block height did not increment by 1, from previous block (at height {prev_height})");
prev_hash = block.header_hash();
prev_height = height as i64;
if let Some(hth) = &height_to_hash {
if hth.len() > height as usize {
assert_eq!(hth[height as usize], prev_hash, "at height {height} the block hash ({prev_hash}) does not match the height-to-hash file ({})", hth[height as usize]);
}
}
let mut removals = HashSet::<[u8; 32]>::new();
// height 0 is not a transaction block so unspent coins have a
// spent_index of 0 to indicate that they have not been spent.
Expand Down Expand Up @@ -319,5 +347,6 @@ features that are validated:
pool.join();
assert_eq!(pool.panic_count(), 0);

assert_eq!(peak_hash, prev_hash.as_slice());
println!("\nALL DONE, success!");
}

0 comments on commit f89bc11

Please sign in to comment.