From 7d13a331377fc52b065467f59aa3aa1043ccfbb6 Mon Sep 17 00:00:00 2001 From: Randall Naar Date: Mon, 23 Feb 2026 16:11:37 -0500 Subject: [PATCH] Added txids to 'BlockEntry' and optimized block parsing thread usage. --- src/new_index/fetch.rs | 34 +++++++++++++++++++++------------- src/new_index/schema.rs | 16 +++++++++------- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/new_index/fetch.rs b/src/new_index/fetch.rs index 7906fb206..7ead772e3 100644 --- a/src/new_index/fetch.rs +++ b/src/new_index/fetch.rs @@ -16,7 +16,7 @@ use std::thread; use electrs_macros::trace; -use crate::chain::{Block, BlockHash}; +use crate::chain::{Block, BlockHash, Txid}; use crate::daemon::Daemon; use crate::errors::*; use crate::util::{spawn_thread, HeaderEntry, SyncChannel}; @@ -45,6 +45,7 @@ pub struct BlockEntry { pub block: Block, pub entry: HeaderEntry, pub size: u32, + pub txids: Vec, } type SizedBlock = (Block, u32); @@ -106,10 +107,14 @@ fn bitcoind_fetcher( let block_entries: Vec = blocks .into_iter() .zip(entries) - .map(|(block, entry)| BlockEntry { - entry: entry.clone(), // TODO: remove this clone() - size: block.total_size() as u32, - block, + .map(|(block, entry)| { + let txids = block.txdata.iter().map(|tx| tx.compute_txid()).collect(); + BlockEntry { + entry: entry.clone(), // TODO: remove this clone() + size: block.total_size() as u32, + txids, + block, + } }) .collect(); assert_eq!(block_entries.len(), entries.len()); @@ -156,7 +161,10 @@ fn blkfiles_fetcher( let blockhash = block.block_hash(); entry_map .remove(&blockhash) - .map(|entry| BlockEntry { block, entry, size }) + .map(|entry| { + let txids = block.txdata.iter().map(|tx| tx.compute_txid()).collect(); + BlockEntry { block, entry, size, txids } + }) .or_else(|| { trace!("skipping block {}", blockhash); None @@ -224,9 +232,14 @@ fn blkfiles_parser(blobs: Fetcher>, magic: u32) -> Fetcher>, magic: u32) -> Fetcher, magic: u32) -> Result> { +fn parse_blocks(pool: &rayon::ThreadPool, blob: Vec, magic: u32) -> Result> { let mut cursor = Cursor::new(&blob); let mut slices = vec![]; let max_pos = blob.len() as u64; @@ -273,11 +286,6 @@ fn parse_blocks(blob: Vec, magic: u32) -> Result> { cursor.set_position(end as u64); } - let pool = rayon::ThreadPoolBuilder::new() - .num_threads(0) // CPU-bound - .thread_name(|i| format!("parse-blocks-{}", i)) - .build() - .unwrap(); Ok(pool.install(|| { slices .into_par_iter() diff --git a/src/new_index/schema.rs b/src/new_index/schema.rs index 22e3fe5b6..35300922e 100644 --- a/src/new_index/schema.rs +++ b/src/new_index/schema.rs @@ -1174,13 +1174,12 @@ fn add_blocks(block_entries: &[BlockEntry], iconfig: &IndexerConfig) -> Vec = b.block.txdata.iter().map(|tx| tx.compute_txid()).collect(); - for (tx, txid) in b.block.txdata.iter().zip(txids.iter()) { + for (tx, txid) in b.block.txdata.iter().zip(b.txids.iter()) { add_transaction(*txid, tx, &mut rows, iconfig); } if !iconfig.light_mode { - rows.push(BlockRow::new_txids(blockhash, &txids).into_row()); + rows.push(BlockRow::new_txids(blockhash, &b.txids).into_row()); rows.push(BlockRow::new_meta(blockhash, &BlockMeta::from(b)).into_row()); } @@ -1271,9 +1270,10 @@ fn index_blocks( .par_iter() // serialization is CPU-intensive .map(|b| { let mut rows = vec![]; - for tx in &b.block.txdata { - let height = b.entry.height() as u32; - index_transaction(tx, height, previous_txos_map, &mut rows, iconfig); + let height = b.entry.height() as u32; + for (tx, txid) in b.block.txdata.iter().zip(b.txids.iter()) { + let txid = full_hash(&txid[..]); + index_transaction(tx, txid, height, previous_txos_map, &mut rows, iconfig); } rows.push(BlockRow::new_done(full_hash(&b.entry.hash()[..])).into_row()); // mark block as "indexed" rows @@ -1285,12 +1285,12 @@ fn index_blocks( // TODO: return an iterator? fn index_transaction( tx: &Transaction, + txid: FullHash, confirmed_height: u32, previous_txos_map: &HashMap, rows: &mut Vec, iconfig: &IndexerConfig, ) { - let txid = full_hash(&tx.compute_txid()[..]); // persist tx confirmation row: // C{txid} → "{block_height}" @@ -1892,7 +1892,9 @@ pub mod bench { let height = 702861; let hash = block.block_hash(); let header = block.header.clone(); + let txids = block.txdata.iter().map(|tx| tx.compute_txid()).collect(); let block_entry = BlockEntry { + txids, block, entry: HeaderEntry::new(height, hash, header), size: 0u32, // wrong but not needed for benching