| Crates.io | brk_indexer |
| lib.rs | brk_indexer |
| version | 0.0.109 |
| created_at | 2025-02-23 23:30:40.558838+00 |
| updated_at | 2025-09-20 17:21:50.012588+00 |
| description | A Bitcoin indexer built on top of brk_parser |
| homepage | https://bitcoinresearchkit.org |
| repository | https://github.com/bitcoinresearchkit/brk |
| max_upload_size | |
| id | 1566725 |
| size | 159,249 |
High-performance Bitcoin blockchain indexer with parallel processing and dual storage architecture.
This crate provides a comprehensive Bitcoin blockchain indexer built on top of brk_parser. It processes raw Bitcoin blocks in parallel, extracting and indexing transactions, addresses, inputs, outputs, and metadata into optimized storage structures. The indexer maintains two complementary storage systems: columnar vectors for analytics and key-value stores for fast lookups.
Key Features:
Target Use Cases:
cargo add brk_indexer
use brk_indexer::Indexer;
use brk_parser::Parser;
use bitcoincore_rpc::{Client, Auth};
use vecdb::Exit;
use std::path::Path;
// Initialize Bitcoin Core RPC client
let rpc = Client::new("http://localhost:8332", Auth::None)?;
let rpc = Box::leak(Box::new(rpc));
// Create parser for raw block data
let blocks_dir = Path::new("/path/to/bitcoin/blocks");
let parser = Parser::new(blocks_dir, None, rpc);
// Initialize indexer with output directory
let outputs_dir = Path::new("./indexed_data");
let mut indexer = Indexer::forced_import(outputs_dir)?;
// Index blockchain data
let exit = Exit::default();
let starting_indexes = indexer.index(&parser, rpc, &exit, true)?;
println!("Indexed up to height: {}", starting_indexes.height);
Indexer: Main coordinator managing vectors and storesVecs: Columnar storage for blockchain data analyticsStores: Key-value storage for fast hash-based lookupsIndexes: Current indexing state tracking progress across data typesIndexer::forced_import(outputs_dir: &Path) -> Result<Self>
Creates or opens indexer instance with automatic version management.
index(&mut self, parser: &Parser, rpc: &'static Client, exit: &Exit, check_collisions: bool) -> Result<Indexes>
Main indexing function processing blocks from parser with collision detection.
Columnar Vectors (Vecs):
height_to_*: Block-level data (hash, timestamp, difficulty, size, weight)txindex_to_*: Transaction data (ID, version, locktime, size, RBF flag)outputindex_to_*: Output data (value, type, address mapping)inputindex_to_outputindex: Input-to-output relationship mappingKey-Value Stores:
addressbyteshash_to_typeindex: Address hash to internal index mappingblockhashprefix_to_height: Block hash prefix to height lookuptxidprefix_to_txindex: Transaction ID prefix to internal indexaddresstype_to_typeindex_with_outputindex: Address type to output mappingsComplete coverage of Bitcoin script types:
use brk_indexer::Indexer;
use brk_parser::Parser;
use std::path::Path;
// Initialize components
let outputs_dir = Path::new("./blockchain_index");
let mut indexer = Indexer::forced_import(outputs_dir)?;
let blocks_dir = Path::new("/Users/satoshi/.bitcoin/blocks");
let parser = Parser::new(blocks_dir, None, rpc);
// Index with collision checking enabled
let exit = vecdb::Exit::default();
let final_indexes = indexer.index(&parser, rpc, &exit, true)?;
println!("Final height: {}", final_indexes.height);
println!("Total transactions: {}", final_indexes.txindex);
println!("Total addresses: {}", final_indexes.total_address_count());
use brk_indexer::Indexer;
use brk_structs::{Height, TxidPrefix, AddressBytesHash};
let indexer = Indexer::forced_import("./blockchain_index")?;
// Look up block hash by height
let height = Height::new(750000);
if let Some(block_hash) = indexer.vecs.height_to_blockhash.get(height)? {
println!("Block 750000 hash: {}", block_hash);
}
// Look up transaction by ID prefix
let txid_prefix = TxidPrefix::from_str("abcdef123456")?;
if let Some(tx_index) = indexer.stores.txidprefix_to_txindex.get(&txid_prefix)? {
println!("Transaction index: {}", tx_index);
}
// Query address information
let address_hash = AddressBytesHash::from(/* address bytes */);
if let Some(type_index) = indexer.stores.addressbyteshash_to_typeindex.get(&address_hash)? {
println!("Address type index: {}", type_index);
}
use brk_indexer::Indexer;
// Indexer automatically resumes from last processed height
let mut indexer = Indexer::forced_import("./blockchain_index")?;
let current_indexes = indexer.vecs.current_indexes(&indexer.stores, rpc)?;
println!("Resuming from height: {}", current_indexes.height);
// Process new blocks incrementally
let exit = vecdb::Exit::default();
let updated_indexes = indexer.index(&parser, rpc, &exit, true)?;
println!("Processed {} new blocks",
updated_indexes.height.as_u32() - current_indexes.height.as_u32());
use brk_indexer::Indexer;
use brk_structs::OutputType;
let indexer = Indexer::forced_import("./blockchain_index")?;
// Analyze address distribution by type
for output_type in OutputType::as_vec() {
let count = indexer.vecs.outputindex_to_outputtype
.iter()
.filter(|&ot| ot == output_type)
.count();
println!("{:?}: {} outputs", output_type, count);
}
// Query specific address type data
let p2pkh_store = &indexer.stores.addresstype_to_typeindex_with_outputindex
.p2pkh;
println!("P2PKH addresses: {}", p2pkh_store.len());
The indexer uses sophisticated parallel processing:
rayonColumnar Storage (vecdb):
Key-Value Storage (Fjall):
Main Structure: Indexer coordinating Vecs (columnar analytics) and Stores (key-value lookups)
Processing Pipeline: Multi-threaded block analysis with parallel transaction/address processing
Storage Architecture: Dual system using vecdb for analytics and Fjall for lookups
Address Indexing: Complete Bitcoin script type coverage with collision detection
Synchronization: Height-based coordination with Bitcoin Core RPC validation
Parallel Processing: rayon-based parallelism for transaction analysis and address resolution
Architecture: High-performance blockchain indexer with ACID guarantees and incremental processing
This README was generated by Claude Code