From 9a4e998b4e6a0cea3e2d4c008efa98c09e948093 Mon Sep 17 00:00:00 2001 From: rustaceanrob Date: Tue, 9 Sep 2025 10:57:34 +0100 Subject: [PATCH] node: Add `bench` binary to assess accumulators When comparing different accumulator types we have to remove network stochasticity. Read all blocks from the disk and update an accumulator with no particular logic. --- node/Cargo.toml | 3 +++ node/src/bin/bench.rs | 55 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 node/src/bin/bench.rs diff --git a/node/Cargo.toml b/node/Cargo.toml index 0f2639d..9cb6d73 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -23,3 +23,6 @@ spec = "config_spec.toml" [[bin]] name = "ibd" + +[[bin]] +name = "bench" diff --git a/node/src/bin/bench.rs b/node/src/bin/bench.rs new file mode 100644 index 0000000..992df1f --- /dev/null +++ b/node/src/bin/bench.rs @@ -0,0 +1,55 @@ +// This binary is used to assess the impact of accumulator designs + +use std::{path::PathBuf, str::FromStr, time::Instant}; + +use bitcoin::{consensus, OutPoint}; +use kernel::{ChainType, ChainstateManager, ChainstateManagerOptions, ContextBuilder}; +use node::elapsed_time; + +fn main() { + let subscriber = tracing_subscriber::FmtSubscriber::new(); + tracing::subscriber::set_global_default(subscriber).unwrap(); + let home = std::env::var("HOME").unwrap(); + let path_buf = PathBuf::from_str(&home).unwrap(); + let bitcoin_dir = path_buf.join(".bitcoin"); + let blocks_dir = bitcoin_dir.join("blocks"); + let ctx = ContextBuilder::new() + .chain_type(ChainType::MAINNET) + .build() + .unwrap(); + let opts = ChainstateManagerOptions::new( + &ctx, + bitcoin_dir.to_str().unwrap(), + blocks_dir.to_str().unwrap(), + ) + .unwrap(); + let chainman = ChainstateManager::new(opts).unwrap(); + chainman.import_blocks().unwrap(); + let mut acc = accumulator::Accumulator::new(); + let mut tip = chainman.block_index_tip(); + tracing::info!("Starting accumulator bench"); + let start = Instant::now(); + while let Ok(next) = tip.prev() { + tracing::info!("process block {}", next.height()); + let block = chainman.read_block_data(&next).unwrap(); + let (_, transactions) = consensus::deserialize::(&block.to_bytes()) + .unwrap() + .into_parts(); + for tx in transactions { + let txid = tx.compute_txid(); + for input in tx.inputs { + let outpoint = input.previous_output; + acc.spend(outpoint); + } + for vout in 0..tx.outputs.len() { + let outpoint = OutPoint { + txid, + vout: vout as u32, + }; + acc.add(outpoint); + } + } + tip = next; + } + elapsed_time(start); +}