computer: snapshot

This commit is contained in:
nym21
2026-02-26 23:01:51 +01:00
parent cccaf6b206
commit 78fc5ffcf7
69 changed files with 1578 additions and 2205 deletions

View File

@@ -60,13 +60,21 @@ impl Vecs {
)?;
// Skip coinbase (first tx per block) since it has no fee
self.fee.compute_with_skip(
let window_starts = blocks.count.window_starts();
self.fee.compute(
starting_indexes.height,
&self.fee_txindex,
&indexer.vecs.transactions.first_txindex,
&indexes.height.txindex_count,
&window_starts,
exit,
1,
|full| {
full.compute_with_skip(
starting_indexes.height,
&self.fee_txindex,
&indexer.vecs.transactions.first_txindex,
&indexes.height.txindex_count,
exit,
1,
)
},
)?;
// Skip coinbase (first tx per block) since it has no feerate
@@ -82,21 +90,12 @@ impl Vecs {
// Compute fee USD sum per block: price * Bitcoin::from(sats)
self.fee_usd_sum.compute_transform2(
starting_indexes.height,
self.fee.sum_cumulative.sum.inner(),
self.fee.height.sum_cumulative.sum.inner(),
&prices.usd.price,
|(h, sats, price, ..)| (h, price * Bitcoin::from(sats)),
exit,
)?;
// Rolling fee stats (from per-block sum)
let window_starts = blocks.count.window_starts();
self.fee_rolling.compute(
starting_indexes.height,
&window_starts,
self.fee.sum_cumulative.sum.inner(),
exit,
)?;
// Rolling fee rate distribution (from per-block average)
self.fee_rate_rolling.compute_distribution(
starting_indexes.height,

View File

@@ -5,7 +5,7 @@ use vecdb::{Database, EagerVec, ImportableVec};
use super::Vecs;
use crate::{
indexes,
internal::{Distribution, Full, RollingDistribution, RollingFull},
internal::{ComputedFromHeightFull, Distribution, RollingDistribution},
};
/// Bump this when fee/feerate aggregation logic changes (e.g., skip coinbase).
@@ -22,9 +22,8 @@ impl Vecs {
input_value: EagerVec::forced_import(db, "input_value", version)?,
output_value: EagerVec::forced_import(db, "output_value", version)?,
fee_txindex: EagerVec::forced_import(db, "fee", v)?,
fee: Full::forced_import(db, "fee", v)?,
fee: ComputedFromHeightFull::forced_import(db, "fee", v, indexes)?,
fee_usd_sum: EagerVec::forced_import(db, "fee_usd_sum", v)?,
fee_rolling: RollingFull::forced_import(db, "fee", v, indexes)?,
fee_rate_txindex: EagerVec::forced_import(db, "fee_rate", v)?,
fee_rate: Distribution::forced_import(db, "fee_rate", v)?,
fee_rate_rolling: RollingDistribution::forced_import(db, "fee_rate", v, indexes)?,

View File

@@ -2,16 +2,15 @@ use brk_traversable::Traversable;
use brk_types::{Dollars, FeeRate, Height, Sats, TxIndex};
use vecdb::{EagerVec, PcoVec, Rw, StorageMode};
use crate::internal::{Distribution, Full, RollingDistribution, RollingFull};
use crate::internal::{ComputedFromHeightFull, Distribution, RollingDistribution};
#[derive(Traversable)]
pub struct Vecs<M: StorageMode = Rw> {
pub input_value: M::Stored<EagerVec<PcoVec<TxIndex, Sats>>>,
pub output_value: M::Stored<EagerVec<PcoVec<TxIndex, Sats>>>,
pub fee_txindex: M::Stored<EagerVec<PcoVec<TxIndex, Sats>>>,
pub fee: Full<Height, Sats, M>,
pub fee: ComputedFromHeightFull<Sats, M>,
pub fee_usd_sum: M::Stored<EagerVec<PcoVec<Height, Dollars>>>,
pub fee_rolling: RollingFull<Sats, M>,
pub fee_rate_txindex: M::Stored<EagerVec<PcoVec<TxIndex, FeeRate>>>,
pub fee_rate: Distribution<Height, FeeRate, M>,
pub fee_rate_rolling: RollingDistribution<FeeRate, M>,

View File

@@ -22,61 +22,56 @@ impl Vecs {
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
self.sent_sum.sats.height.compute_filtered_sum_from_indexes(
let window_starts = blocks.count.window_starts();
self.sent_sum.compute(
starting_indexes.height,
&indexer.vecs.transactions.first_txindex,
&indexes.height.txindex_count,
&fees_vecs.input_value,
|sats| !sats.is_max(),
&window_starts,
prices,
exit,
|sats_vec| {
Ok(sats_vec.compute_filtered_sum_from_indexes(
starting_indexes.height,
&indexer.vecs.transactions.first_txindex,
&indexes.height.txindex_count,
&fees_vecs.input_value,
|sats| !sats.is_max(),
exit,
)?)
},
)?;
self.received_sum.sats.height.compute_sum_from_indexes(
self.received_sum.compute(
starting_indexes.height,
&indexer.vecs.transactions.first_txindex,
&indexes.height.txindex_count,
&fees_vecs.output_value,
&window_starts,
prices,
exit,
|sats_vec| {
Ok(sats_vec.compute_sum_from_indexes(
starting_indexes.height,
&indexer.vecs.transactions.first_txindex,
&indexes.height.txindex_count,
&fees_vecs.output_value,
exit,
)?)
},
)?;
// Compute USD from sats × price
self.sent_sum
.compute(prices, starting_indexes.height, exit)?;
self.received_sum
.compute(prices, starting_indexes.height, exit)?;
// Annualized volume: rolling 1y sum of per-block sent volume
self.annualized_volume.sats.height.compute_rolling_sum(
starting_indexes.height,
&blocks.count.height_1y_ago,
&self.sent_sum.sats.height,
&self.sent_sum.sats,
exit,
)?;
self.annualized_volume
.compute(prices, starting_indexes.height, exit)?;
// Rolling sums for sent and received
let window_starts = blocks.count.window_starts();
self.sent_sum_rolling.compute_rolling_sum(
starting_indexes.height,
&window_starts,
&self.sent_sum.sats.height,
&self.sent_sum.usd.height,
exit,
)?;
self.received_sum_rolling.compute_rolling_sum(
starting_indexes.height,
&window_starts,
&self.received_sum.sats.height,
&self.received_sum.usd.height,
exit,
)?;
// tx_per_sec: per-block tx count / block interval
self.tx_per_sec.height.compute_transform2(
starting_indexes.height,
&count_vecs.tx_count.height,
&blocks.interval.interval.height,
&blocks.interval.height,
|(h, tx_count, interval, ..)| {
let interval_f64 = f64::from(*interval);
let per_sec = if interval_f64 > 0.0 {
@@ -93,7 +88,7 @@ impl Vecs {
self.inputs_per_sec.height.compute_transform2(
starting_indexes.height,
&inputs_count.height.sum_cumulative.sum.0,
&blocks.interval.interval.height,
&blocks.interval.height,
|(h, input_count, interval, ..)| {
let interval_f64 = f64::from(*interval);
let per_sec = if interval_f64 > 0.0 {
@@ -109,8 +104,8 @@ impl Vecs {
// outputs_per_sec: per-block output count / block interval
self.outputs_per_sec.height.compute_transform2(
starting_indexes.height,
&outputs_count.total_count.sum_cumulative.sum.0,
&blocks.interval.interval.height,
&outputs_count.total_count.height.sum_cumulative.sum.0,
&blocks.interval.height,
|(h, output_count, interval, ..)| {
let interval_f64 = f64::from(*interval);
let per_sec = if interval_f64 > 0.0 {

View File

@@ -5,7 +5,7 @@ use vecdb::Database;
use super::Vecs;
use crate::{
indexes,
internal::{ComputedFromHeightLast, StoredValueRollingWindows, ValueFromHeightLast},
internal::{ComputedFromHeightLast, ValueFromHeightLast, ValueFromHeightLastRolling},
};
impl Vecs {
@@ -16,16 +16,10 @@ impl Vecs {
) -> Result<Self> {
let v2 = Version::TWO;
Ok(Self {
sent_sum: ValueFromHeightLast::forced_import(
sent_sum: ValueFromHeightLastRolling::forced_import(
db, "sent_sum", version, indexes,
)?,
sent_sum_rolling: StoredValueRollingWindows::forced_import(
db, "sent_sum", version, indexes,
)?,
received_sum: ValueFromHeightLast::forced_import(
db, "received_sum", version, indexes,
)?,
received_sum_rolling: StoredValueRollingWindows::forced_import(
received_sum: ValueFromHeightLastRolling::forced_import(
db, "received_sum", version, indexes,
)?,
annualized_volume: ValueFromHeightLast::forced_import(

View File

@@ -3,18 +3,16 @@ use brk_types::StoredF32;
use vecdb::{Rw, StorageMode};
use crate::internal::{
ComputedFromHeightLast, StoredValueRollingWindows, ValueFromHeightLast,
ComputedFromHeightLast, ValueFromHeightLast, ValueFromHeightLastRolling,
};
/// Volume metrics
#[derive(Traversable)]
pub struct Vecs<M: StorageMode = Rw> {
#[traversable(flatten)]
pub sent_sum: ValueFromHeightLast<M>,
pub sent_sum_rolling: StoredValueRollingWindows<M>,
pub sent_sum: ValueFromHeightLastRolling<M>,
#[traversable(flatten)]
pub received_sum: ValueFromHeightLast<M>,
pub received_sum_rolling: StoredValueRollingWindows<M>,
pub received_sum: ValueFromHeightLastRolling<M>,
#[traversable(flatten)]
pub annualized_volume: ValueFromHeightLast<M>,
pub tx_per_sec: ComputedFromHeightLast<StoredF32, M>,