mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-05-19 22:34:46 -07:00
84 lines
2.5 KiB
Rust
84 lines
2.5 KiB
Rust
//! Shared per-block-per-type cursor walker used by `outputs/by_type/` and
|
|
//! `inputs/by_type/`. The walker iterates blocks and aggregates the
|
|
//! per-tx output-type counts; pushing into a particular wrapper is left
|
|
//! to the caller.
|
|
|
|
use brk_error::Result;
|
|
use brk_types::TxIndex;
|
|
use vecdb::VecIndex;
|
|
|
|
/// Aggregated per-block counters produced by [`walk_blocks`].
|
|
pub(crate) struct BlockAggregate {
|
|
pub entries_all: u64,
|
|
pub entries_per_type: [u64; 12],
|
|
pub txs_all: u64,
|
|
pub txs_per_type: [u64; 12],
|
|
}
|
|
|
|
/// Whether to include the coinbase tx (first tx in each block) in the walk.
|
|
#[derive(Clone, Copy)]
|
|
pub(crate) enum CoinbasePolicy {
|
|
Include,
|
|
Skip,
|
|
}
|
|
|
|
/// Walk every block in `fi_batch`, calling `scan_tx` once per tx (which
|
|
/// fills a `[u32; 12]` with the per-output-type count for that tx),
|
|
/// aggregating into a [`BlockAggregate`] and handing it to `store`.
|
|
///
|
|
/// `entries_all` and `txs_all` aggregate over the 12 output types
|
|
/// indistinguishably; downstream consumers can cap to the 11 spendable
|
|
/// types if op_return is non-applicable.
|
|
#[inline]
|
|
pub(crate) fn walk_blocks(
|
|
fi_batch: &[TxIndex],
|
|
txid_len: usize,
|
|
coinbase: CoinbasePolicy,
|
|
mut scan_tx: impl FnMut(usize, &mut [u32; 12]) -> Result<()>,
|
|
mut store: impl FnMut(BlockAggregate) -> Result<()>,
|
|
) -> Result<()> {
|
|
for (j, first_tx) in fi_batch.iter().enumerate() {
|
|
let fi = first_tx.to_usize();
|
|
let next_fi = fi_batch
|
|
.get(j + 1)
|
|
.map(|v| v.to_usize())
|
|
.unwrap_or(txid_len);
|
|
|
|
let start_tx = match coinbase {
|
|
CoinbasePolicy::Include => fi,
|
|
CoinbasePolicy::Skip => fi + 1,
|
|
};
|
|
|
|
let mut entries_per_type = [0u64; 12];
|
|
let mut txs_per_type = [0u64; 12];
|
|
let mut entries_all = 0u64;
|
|
let mut txs_all = 0u64;
|
|
|
|
for tx_pos in start_tx..next_fi {
|
|
let mut per_tx = [0u32; 12];
|
|
scan_tx(tx_pos, &mut per_tx)?;
|
|
let mut tx_has_any = false;
|
|
for (i, &n) in per_tx.iter().enumerate() {
|
|
if n > 0 {
|
|
entries_per_type[i] += u64::from(n);
|
|
txs_per_type[i] += 1;
|
|
entries_all += u64::from(n);
|
|
tx_has_any = true;
|
|
}
|
|
}
|
|
if tx_has_any {
|
|
txs_all += 1;
|
|
}
|
|
}
|
|
|
|
store(BlockAggregate {
|
|
entries_all,
|
|
entries_per_type,
|
|
txs_all,
|
|
txs_per_type,
|
|
})?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|