From c1745793b8ffae9f286c3175b9fe9df26b99b5f0 Mon Sep 17 00:00:00 2001 From: nym21 Date: Wed, 29 Jul 2026 23:40:11 +0200 Subject: [PATCH] brk: metric trimming part X + 1 --- .../src/distribution/cohorts/utxo/groups.rs | 8 +- .../src/distribution/metrics/activity/core.rs | 26 +- .../distribution/metrics/activity/minimal.rs | 30 +- .../distribution/metrics/cohort/minimal.rs | 1 - .../src/distribution/metrics/cohort/type.rs | 1 - .../src/distribution/metrics/realized/core.rs | 21 +- .../src/distribution/metrics/realized/full.rs | 29 +- .../distribution/metrics/realized/minimal.rs | 34 +-- .../src/internal/per_block/fiat/block.rs | 25 -- .../internal/per_block/fiat/cumulative_sum.rs | 93 +++++- .../src/internal/per_block/fiat/lazy_block.rs | 30 ++ .../src/internal/per_block/fiat/mod.rs | 4 +- .../src/internal/per_block/value/block.rs | 58 ---- .../internal/per_block/value/cumulative.rs | 288 ++++++++++++++++-- .../per_block/value/cumulative_rolling.rs | 17 +- .../src/internal/per_block/value/full.rs | 35 ++- .../internal/per_block/value/lazy_block.rs | 47 +++ .../src/internal/per_block/value/mod.rs | 4 +- .../src/mining/rewards/compute.rs | 88 +++--- .../brk_computer/src/outputs/value/compute.rs | 131 ++++---- crates/brk_computer/src/pools/major.rs | 18 +- .../brk_computer/src/supply/burned/compute.rs | 33 +- .../src/transactions/volume/compute.rs | 21 +- 23 files changed, 656 insertions(+), 386 deletions(-) delete mode 100644 crates/brk_computer/src/internal/per_block/fiat/block.rs create mode 100644 crates/brk_computer/src/internal/per_block/fiat/lazy_block.rs delete mode 100644 crates/brk_computer/src/internal/per_block/value/block.rs create mode 100644 crates/brk_computer/src/internal/per_block/value/lazy_block.rs diff --git a/crates/brk_computer/src/distribution/cohorts/utxo/groups.rs b/crates/brk_computer/src/distribution/cohorts/utxo/groups.rs index 5ede5f635..cf179d1ae 100644 --- a/crates/brk_computer/src/distribution/cohorts/utxo/groups.rs +++ b/crates/brk_computer/src/distribution/cohorts/utxo/groups.rs @@ -394,7 +394,7 @@ impl UTXOCohorts { #[inline(always)] pub(crate) fn push_maturation(&mut self, matured: &AgeRange) { for (v, &sats) in self.matured.iter_mut().zip(matured.iter()) { - v.block.sats.push(sats); + v.push_block_sats(sats); } } @@ -605,7 +605,7 @@ impl UTXOCohorts { .transfer_volume .block .cents - .read_only_clone(); + .clone(); let under_1h_value_destroyed = self .age_range .under_1h @@ -801,8 +801,6 @@ impl UTXOCohorts { vecs.extend(self.profitability.collect_all_vecs_mut()); for v in self.matured.iter_mut() { let inner = &mut v.inner; - vecs.push(&mut inner.block.sats); - vecs.push(&mut inner.block.cents); vecs.push(&mut inner.cumulative.sats.height); vecs.push(&mut inner.cumulative.cents.height); } @@ -821,7 +819,7 @@ impl UTXOCohorts { .chain( self.matured .iter() - .map(|v| Height::from(v.block.sats.len())), + .map(|v| Height::from(v.cumulative.sats.height.len())), ) .min() .unwrap_or_default() diff --git a/crates/brk_computer/src/distribution/metrics/activity/core.rs b/crates/brk_computer/src/distribution/metrics/activity/core.rs index d8c58aaa9..cea0e3dcf 100644 --- a/crates/brk_computer/src/distribution/metrics/activity/core.rs +++ b/crates/brk_computer/src/distribution/metrics/activity/core.rs @@ -3,7 +3,7 @@ use brk_indexer::Lengths; use brk_traversable::Traversable; use brk_types::{Bitcoin, StoredF64, Version}; use derive_more::{Deref, DerefMut}; -use vecdb::{AnyStoredVec, AnyVec, Exit, Rw, StorageMode, WritableVec}; +use vecdb::{AnyStoredVec, AnyVec, Exit, Rw, StorageMode}; use crate::{ distribution::{ @@ -45,8 +45,8 @@ impl ActivityCore { self.minimal .min_len() .min(self.coindays_destroyed.block.len()) - .min(self.transfer_volume_in_profit.block.sats.len()) - .min(self.transfer_volume_in_loss.block.sats.len()) + .min(self.transfer_volume_in_profit.cumulative.sats.height.len()) + .min(self.transfer_volume_in_loss.cumulative.sats.height.len()) } #[inline(always)] @@ -55,22 +55,18 @@ impl ActivityCore { self.coindays_destroyed .push_block(StoredF64::from(Bitcoin::from(state.satdays_destroyed))); self.transfer_volume_in_profit - .block - .sats - .push(state.realized.sent_in_profit()); + .push_block_sats(state.realized.sent_in_profit()); self.transfer_volume_in_loss - .block - .sats - .push(state.realized.sent_in_loss()); + .push_block_sats(state.realized.sent_in_loss()); } pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> { let mut vecs = self.minimal.collect_vecs_mut(); vecs.push(self.coindays_destroyed.stored_mut()); - vecs.push(&mut self.transfer_volume_in_profit.inner.block.sats); - vecs.push(&mut self.transfer_volume_in_profit.inner.block.cents); - vecs.push(&mut self.transfer_volume_in_loss.inner.block.sats); - vecs.push(&mut self.transfer_volume_in_loss.inner.block.cents); + vecs.push(&mut self.transfer_volume_in_profit.inner.cumulative.sats.height); + vecs.push(&mut self.transfer_volume_in_profit.inner.cumulative.cents.height); + vecs.push(&mut self.transfer_volume_in_loss.inner.cumulative.sats.height); + vecs.push(&mut self.transfer_volume_in_loss.inner.cumulative.cents.height); vecs } @@ -89,8 +85,8 @@ impl ActivityCore { .compute_from_stateful(starting_lengths, &minimal_refs, exit)?; sum_others!(self, starting_lengths, others, exit; coindays_destroyed.cumulative.height); - sum_others!(self, starting_lengths, others, exit; transfer_volume_in_profit.block.sats); - sum_others!(self, starting_lengths, others, exit; transfer_volume_in_loss.block.sats); + sum_others!(self, starting_lengths, others, exit; transfer_volume_in_profit.cumulative.sats.height); + sum_others!(self, starting_lengths, others, exit; transfer_volume_in_loss.cumulative.sats.height); Ok(()) } diff --git a/crates/brk_computer/src/distribution/metrics/activity/minimal.rs b/crates/brk_computer/src/distribution/metrics/activity/minimal.rs index 9398a510d..ee02f4dc4 100644 --- a/crates/brk_computer/src/distribution/metrics/activity/minimal.rs +++ b/crates/brk_computer/src/distribution/metrics/activity/minimal.rs @@ -2,7 +2,7 @@ use brk_error::Result; use brk_indexer::Lengths; use brk_traversable::Traversable; use brk_types::Version; -use vecdb::{AnyStoredVec, AnyVec, Exit, Rw, StorageMode, WritableVec}; +use vecdb::{AnyStoredVec, AnyVec, Exit, Rw, StorageMode}; use crate::{ distribution::{ @@ -27,19 +27,19 @@ impl ActivityMinimal { } pub(crate) fn min_len(&self) -> usize { - self.transfer_volume.block.sats.len() + self.transfer_volume.cumulative.sats.height.len() } #[inline(always)] pub(crate) fn push_state(&mut self, state: &CohortState) { - self.transfer_volume.block.sats.push(state.sent); + self.transfer_volume.push_block_sats(state.sent); } pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> { let inner = &mut self.transfer_volume.inner; vec![ - &mut inner.block.sats as &mut dyn AnyStoredVec, - &mut inner.block.cents, + &mut inner.cumulative.sats.height as &mut dyn AnyStoredVec, + &mut inner.cumulative.cents.height, ] } @@ -49,14 +49,18 @@ impl ActivityMinimal { others: &[&Self], exit: &Exit, ) -> Result<()> { - self.transfer_volume.block.sats.compute_sum_of_others( - starting_lengths.height, - &others - .iter() - .map(|v| &v.transfer_volume.block.sats) - .collect::>(), - exit, - )?; + self.transfer_volume + .cumulative + .sats + .height + .compute_sum_of_others( + starting_lengths.height, + &others + .iter() + .map(|v| &v.transfer_volume.cumulative.sats.height) + .collect::>(), + exit, + )?; Ok(()) } diff --git a/crates/brk_computer/src/distribution/metrics/cohort/minimal.rs b/crates/brk_computer/src/distribution/metrics/cohort/minimal.rs index eb52dd23c..c5d0b6eef 100644 --- a/crates/brk_computer/src/distribution/metrics/cohort/minimal.rs +++ b/crates/brk_computer/src/distribution/metrics/cohort/minimal.rs @@ -105,7 +105,6 @@ impl MinimalCohortMetrics { self.outputs.compute_rest(starting_lengths.height, exit)?; self.activity .compute_rest_part1(prices, starting_lengths, exit)?; - self.realized.compute_rest_part1(starting_lengths, exit)?; Ok(()) } diff --git a/crates/brk_computer/src/distribution/metrics/cohort/type.rs b/crates/brk_computer/src/distribution/metrics/cohort/type.rs index 4ff2127bb..e2b16b149 100644 --- a/crates/brk_computer/src/distribution/metrics/cohort/type.rs +++ b/crates/brk_computer/src/distribution/metrics/cohort/type.rs @@ -67,7 +67,6 @@ impl TypeCohortMetrics { self.outputs.compute_rest(starting_lengths.height, exit)?; self.activity .compute_rest_part1(prices, starting_lengths, exit)?; - self.realized.compute_rest_part1(starting_lengths, exit)?; Ok(()) } diff --git a/crates/brk_computer/src/distribution/metrics/realized/core.rs b/crates/brk_computer/src/distribution/metrics/realized/core.rs index fdfb6a4fc..7addefc82 100644 --- a/crates/brk_computer/src/distribution/metrics/realized/core.rs +++ b/crates/brk_computer/src/distribution/metrics/realized/core.rs @@ -142,22 +142,13 @@ impl RealizedCore { starting_lengths: &Lengths, exit: &Exit, ) -> Result<()> { - self.minimal.compute_rest_part1(starting_lengths, exit)?; - - self.net_pnl.block.cents.compute_transform2( + self.net_pnl.compute_from_cumulative_pair( starting_lengths.height, - &self.minimal.profit.block.cents, - &self.minimal.loss.block.cents, - |(i, profit, loss, ..)| { - ( - i, - CentsSigned::new(profit.inner() as i64 - loss.inner() as i64), - ) - }, + &self.minimal.profit.cumulative.cents.height, + &self.minimal.loss.cumulative.cents.height, + |_, profit, loss| CentsSigned::new(profit.inner() as i64 - loss.inner() as i64), exit, - )?; - - Ok(()) + ) } pub(crate) fn compute_rest_part2( @@ -171,8 +162,6 @@ impl RealizedCore { self.minimal .compute_rest_part2(prices, starting_lengths, height_to_supply, exit)?; - self.net_pnl.compute_rest(starting_lengths.height, exit)?; - self.sopr .ratio ._24h diff --git a/crates/brk_computer/src/distribution/metrics/realized/full.rs b/crates/brk_computer/src/distribution/metrics/realized/full.rs index b51d6babd..276835c7d 100644 --- a/crates/brk_computer/src/distribution/metrics/realized/full.rs +++ b/crates/brk_computer/src/distribution/metrics/realized/full.rs @@ -128,7 +128,7 @@ impl RealizedFull { .len() .min(self.cap_raw.len()) .min(self.capitalized.cap_raw.len()) - .min(self.peak_regret.value.block.cents.len()) + .min(self.peak_regret.value.cumulative.cents.height.len()) } #[inline(always)] @@ -148,9 +148,7 @@ impl RealizedFull { .push(state.realized.capitalized_cap_raw()); self.peak_regret .value - .block - .cents - .push(state.realized.peak_regret()); + .push_block(state.realized.peak_regret()); } pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> { @@ -158,7 +156,7 @@ impl RealizedFull { vecs.push(&mut self.capitalized.price.cents.height); vecs.push(&mut self.cap_raw as &mut dyn AnyStoredVec); vecs.push(&mut self.capitalized.cap_raw as &mut dyn AnyStoredVec); - vecs.push(&mut self.peak_regret.value.block.cents); + vecs.push(self.peak_regret.value.stored_mut()); vecs } @@ -169,9 +167,7 @@ impl RealizedFull { exit: &Exit, ) -> Result<()> { self.core - .compute_from_stateful(starting_lengths, others, exit)?; - - Ok(()) + .compute_from_stateful(starting_lengths, others, exit) } #[inline(always)] @@ -189,7 +185,7 @@ impl RealizedFull { }; self.capitalized.price.cents.height.push(capitalized_price); - self.peak_regret.value.block.cents.push(accum.peak_regret()); + self.peak_regret.value.push_block(accum.peak_regret()); capitalized_price } @@ -199,12 +195,7 @@ impl RealizedFull { starting_lengths: &Lengths, exit: &Exit, ) -> Result<()> { - self.core.compute_rest_part1(starting_lengths, exit)?; - - self.peak_regret - .value - .compute_rest(starting_lengths.height, exit)?; - Ok(()) + self.core.compute_rest_part1(starting_lengths, exit) } #[allow(clippy::too_many_arguments)] @@ -243,13 +234,13 @@ impl RealizedFull { } // Gross PnL - self.gross_pnl.block.cents.compute_add( + self.gross_pnl.compute_from_cumulative_pair( starting_lengths.height, - &self.core.minimal.profit.block.cents, - &self.core.minimal.loss.block.cents, + &self.core.minimal.profit.cumulative.cents.height, + &self.core.minimal.loss.cumulative.cents.height, + |_, profit, loss| profit + loss, exit, )?; - self.gross_pnl.compute_rest(starting_lengths.height, exit)?; // Net PnL 1m change relative to rcap and mcap self.net_pnl diff --git a/crates/brk_computer/src/distribution/metrics/realized/minimal.rs b/crates/brk_computer/src/distribution/metrics/realized/minimal.rs index 156acb2c4..c736b0ce6 100644 --- a/crates/brk_computer/src/distribution/metrics/realized/minimal.rs +++ b/crates/brk_computer/src/distribution/metrics/realized/minimal.rs @@ -61,22 +61,22 @@ impl RealizedMinimal { .cents .height .len() - .min(self.profit.block.cents.len()) - .min(self.loss.block.cents.len()) + .min(self.profit.cumulative.cents.height.len()) + .min(self.loss.cumulative.cents.height.len()) } #[inline(always)] pub(crate) fn push_state(&mut self, state: &CohortState) { self.cap.cents.height.push(state.realized.cap()); - self.profit.block.cents.push(state.realized.profit()); - self.loss.block.cents.push(state.realized.loss()); + self.profit.push_block(state.realized.profit()); + self.loss.push_block(state.realized.loss()); } pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> { vec![ &mut self.cap.cents.height as &mut dyn AnyStoredVec, - &mut self.profit.block.cents, - &mut self.loss.block.cents, + self.profit.stored_mut(), + self.loss.stored_mut(), ] } @@ -87,18 +87,16 @@ impl RealizedMinimal { exit: &Exit, ) -> Result<()> { sum_others!(self, starting_lengths, others, exit; cap.cents.height); - sum_others!(self, starting_lengths, others, exit; profit.block.cents); - sum_others!(self, starting_lengths, others, exit; loss.block.cents); - Ok(()) - } - - pub(crate) fn compute_rest_part1( - &mut self, - starting_lengths: &Lengths, - exit: &Exit, - ) -> Result<()> { - self.profit.compute_rest(starting_lengths.height, exit)?; - self.loss.compute_rest(starting_lengths.height, exit)?; + self.profit.compute_sum_of_others( + starting_lengths.height, + &others.iter().map(|v| &v.profit).collect::>(), + exit, + )?; + self.loss.compute_sum_of_others( + starting_lengths.height, + &others.iter().map(|v| &v.loss).collect::>(), + exit, + )?; Ok(()) } diff --git a/crates/brk_computer/src/internal/per_block/fiat/block.rs b/crates/brk_computer/src/internal/per_block/fiat/block.rs deleted file mode 100644 index d43a935e8..000000000 --- a/crates/brk_computer/src/internal/per_block/fiat/block.rs +++ /dev/null @@ -1,25 +0,0 @@ -use brk_error::Result; -use brk_traversable::Traversable; -use brk_types::{Dollars, Height, Version}; -use vecdb::{ - Database, EagerVec, ImportableVec, LazyVecFrom1, PcoVec, ReadableCloneableVec, Rw, StorageMode, -}; - -use super::FiatType; - -/// Raw per-block fiat data: cents (stored) + usd (lazy), no resolutions. -#[derive(Traversable)] -pub struct FiatBlock { - pub usd: LazyVecFrom1, - pub cents: M::Stored>>, -} - -impl FiatBlock { - pub(crate) fn forced_import(db: &Database, name: &str, version: Version) -> Result { - let cents: EagerVec> = - EagerVec::forced_import(db, &format!("{name}_cents"), version)?; - let usd = - LazyVecFrom1::transformed::(name, version, cents.read_only_boxed_clone()); - Ok(Self { usd, cents }) - } -} diff --git a/crates/brk_computer/src/internal/per_block/fiat/cumulative_sum.rs b/crates/brk_computer/src/internal/per_block/fiat/cumulative_sum.rs index b66c60dd5..85885416c 100644 --- a/crates/brk_computer/src/internal/per_block/fiat/cumulative_sum.rs +++ b/crates/brk_computer/src/internal/per_block/fiat/cumulative_sum.rs @@ -1,22 +1,29 @@ use brk_error::Result; use brk_traversable::Traversable; use brk_types::{Height, Version}; -use vecdb::{Database, Exit, Rw, StorageMode}; +use vecdb::{ + AnyStoredVec, AnyVec, Database, Exit, ReadableVec, Rw, StorageMode, VecValue, WritableVec, +}; use crate::{ indexes, internal::{ - FiatBlock, FiatPerBlock, FiatType, LazyRollingSumsFiatFromHeight, WindowStartVec, Windows, + FiatPerBlock, FiatType, LazyFiatBlock, LazyRollingSumsFiatFromHeight, WindowStartVec, + Windows, }, }; #[derive(Traversable)] pub struct FiatPerBlockCumulativeWithSums { - pub block: FiatBlock, + pub block: LazyFiatBlock, pub cumulative: FiatPerBlock, pub sum: LazyRollingSumsFiatFromHeight, + #[traversable(skip)] + last_cumulative: Option<(usize, C)>, } +const VERSION: Version = Version::ONE; + impl FiatPerBlockCumulativeWithSums { pub(crate) fn forced_import( db: &Database, @@ -25,12 +32,18 @@ impl FiatPerBlockCumulativeWithSums { indexes: &indexes::Vecs, cached_starts: &Windows<&WindowStartVec>, ) -> Result { - let block = FiatBlock::forced_import(db, name, version)?; + let v = version + VERSION; let cumulative = - FiatPerBlock::forced_import(db, &format!("{name}_cumulative"), version, indexes)?; + FiatPerBlock::forced_import(db, &format!("{name}_cumulative"), v, indexes)?; + let last_cumulative = cumulative + .cents + .height + .collect_last() + .map(|value| (cumulative.cents.height.len(), value)); + let block = LazyFiatBlock::from_cumulative(name, v, &cumulative); let sum = LazyRollingSumsFiatFromHeight::new( &format!("{name}_sum"), - version, + v, &cumulative.cents.height, cached_starts, indexes, @@ -39,17 +52,73 @@ impl FiatPerBlockCumulativeWithSums { block, cumulative, sum, + last_cumulative, }) } - pub(crate) fn compute_rest(&mut self, max_from: Height, exit: &Exit) -> Result<()> + #[inline(always)] + pub(crate) fn push_block(&mut self, value: C) where - C: Default, + C: Copy, { - self.cumulative - .cents - .height - .compute_cumulative(max_from, &self.block.cents, exit)?; + let len = self.cumulative.cents.height.len(); + let mut cumulative = match self.last_cumulative { + Some((cached_len, value)) if cached_len == len => value, + _ => self + .cumulative + .cents + .height + .collect_last() + .unwrap_or_default(), + }; + cumulative += value; + self.cumulative.cents.height.push(cumulative); + self.last_cumulative = Some((len + 1, cumulative)); + } + + pub(crate) fn compute_from_cumulative_pair( + &mut self, + max_from: Height, + source1: &impl ReadableVec, + source2: &impl ReadableVec, + mut transform: impl FnMut(Height, S1, S2) -> C, + exit: &Exit, + ) -> Result<()> + where + S1: VecValue, + S2: VecValue, + { + self.cumulative.cents.height.compute_transform2( + max_from, + source1, + source2, + |(height, value1, value2, ..)| (height, transform(height, value1, value2)), + exit, + )?; + self.last_cumulative = None; Ok(()) } + + pub(crate) fn compute_sum_of_others( + &mut self, + max_from: Height, + others: &[&Self], + exit: &Exit, + ) -> Result<()> { + self.cumulative.cents.height.compute_sum_of_others( + max_from, + &others + .iter() + .map(|v| &v.cumulative.cents.height) + .collect::>(), + exit, + )?; + self.last_cumulative = None; + Ok(()) + } + + pub(crate) fn stored_mut(&mut self) -> &mut dyn AnyStoredVec { + self.last_cumulative = None; + &mut self.cumulative.cents.height + } } diff --git a/crates/brk_computer/src/internal/per_block/fiat/lazy_block.rs b/crates/brk_computer/src/internal/per_block/fiat/lazy_block.rs new file mode 100644 index 000000000..19364c3ef --- /dev/null +++ b/crates/brk_computer/src/internal/per_block/fiat/lazy_block.rs @@ -0,0 +1,30 @@ +use brk_traversable::Traversable; +use brk_types::{Dollars, Height, Version}; +use vecdb::{LazyVecFrom1, ReadableCloneableVec}; + +use crate::internal::{FiatPerBlock, FiatType, LazyPreviousDeltaVec}; + +/// Per-block fiat data derived from stored cumulative cents. +#[derive(Clone, Traversable)] +pub struct LazyFiatBlock { + pub usd: LazyVecFrom1, + pub cents: LazyPreviousDeltaVec, +} + +impl LazyFiatBlock { + pub(crate) fn from_cumulative( + name: &str, + version: Version, + cumulative: &FiatPerBlock, + ) -> Self { + let cents = LazyPreviousDeltaVec::new( + &format!("{name}_cents"), + version, + cumulative.cents.height.read_only_boxed_clone(), + ); + let usd = + LazyVecFrom1::transformed::(name, version, cents.read_only_boxed_clone()); + + Self { usd, cents } + } +} diff --git a/crates/brk_computer/src/internal/per_block/fiat/mod.rs b/crates/brk_computer/src/internal/per_block/fiat/mod.rs index bc02d6c60..0c69d1a01 100644 --- a/crates/brk_computer/src/internal/per_block/fiat/mod.rs +++ b/crates/brk_computer/src/internal/per_block/fiat/mod.rs @@ -1,14 +1,14 @@ mod base; -mod block; mod cumulative_sum; mod cumulative_sum_with_deltas; mod lazy; +mod lazy_block; mod lazy_rolling_sum; mod with_deltas; pub use base::*; -pub use block::*; pub use cumulative_sum::*; pub use cumulative_sum_with_deltas::*; pub use lazy::*; +pub use lazy_block::*; pub use lazy_rolling_sum::*; pub use with_deltas::*; diff --git a/crates/brk_computer/src/internal/per_block/value/block.rs b/crates/brk_computer/src/internal/per_block/value/block.rs deleted file mode 100644 index f619c10fe..000000000 --- a/crates/brk_computer/src/internal/per_block/value/block.rs +++ /dev/null @@ -1,58 +0,0 @@ -use brk_error::Result; -use brk_traversable::Traversable; -use brk_types::{Bitcoin, Cents, Dollars, Height, Sats, Version}; -use vecdb::{ - Database, EagerVec, Exit, ImportableVec, LazyVecFrom1, PcoVec, ReadableCloneableVec, Rw, - StorageMode, -}; - -use crate::{ - internal::{CentsUnsignedToDollars, SatsToBitcoin, SatsToCents}, - price, -}; - -/// Raw per-block amount data: sats + cents (stored), btc + usd (lazy), no resolutions. -#[derive(Traversable)] -pub struct ValueBlock { - pub btc: LazyVecFrom1, - pub sats: M::Stored>>, - pub usd: LazyVecFrom1, - pub cents: M::Stored>>, -} - -impl ValueBlock { - pub(crate) fn forced_import(db: &Database, name: &str, version: Version) -> Result { - let sats: EagerVec> = - EagerVec::forced_import(db, &format!("{name}_sats"), version)?; - let btc = - LazyVecFrom1::transformed::(name, version, sats.read_only_boxed_clone()); - let cents: EagerVec> = - EagerVec::forced_import(db, &format!("{name}_cents"), version)?; - let usd = LazyVecFrom1::transformed::( - &format!("{name}_usd"), - version, - cents.read_only_boxed_clone(), - ); - Ok(Self { - btc, - sats, - usd, - cents, - }) - } - - pub(crate) fn compute_cents( - &mut self, - max_from: Height, - prices: &price::Vecs, - exit: &Exit, - ) -> Result<()> { - self.cents.compute_binary::( - max_from, - &self.sats, - &prices.spot.cents.height, - exit, - )?; - Ok(()) - } -} diff --git a/crates/brk_computer/src/internal/per_block/value/cumulative.rs b/crates/brk_computer/src/internal/per_block/value/cumulative.rs index 23c51cf00..37142a0f3 100644 --- a/crates/brk_computer/src/internal/per_block/value/cumulative.rs +++ b/crates/brk_computer/src/internal/per_block/value/cumulative.rs @@ -1,18 +1,23 @@ use brk_error::Result; use brk_traversable::Traversable; use brk_types::{Height, Sats, Version}; -use vecdb::{Database, EagerVec, Exit, PcoVec, Rw, StorageMode}; +use vecdb::{ + AnyVec, BinaryTransform, Database, Exit, ReadableVec, Rw, StorageMode, VecIndex, VecValue, + WritableVec, +}; use crate::{ indexes, - internal::{ValueBlock, ValuePerBlock}, + internal::{LazyValueBlock, SatsToCents, ValuePerBlock}, price, }; #[derive(Traversable)] pub struct ValuePerBlockCumulative { - pub block: ValueBlock, + pub block: LazyValueBlock, pub cumulative: ValuePerBlock, + #[traversable(skip)] + last_cumulative_sats: Option<(usize, Sats)>, } const VERSION: Version = Version::ONE; @@ -25,47 +30,278 @@ impl ValuePerBlockCumulative { indexes: &indexes::Vecs, ) -> Result { let v = version + VERSION; + let cumulative = + ValuePerBlock::forced_import(db, &format!("{name}_cumulative"), v, indexes)?; + let last_cumulative_sats = cumulative + .sats + .height + .collect_last() + .map(|value| (cumulative.sats.height.len(), value)); + let block = LazyValueBlock::from_cumulative(name, v, &cumulative); Ok(Self { - block: ValueBlock::forced_import(db, name, v)?, - cumulative: ValuePerBlock::forced_import( - db, - &format!("{name}_cumulative"), - v, - indexes, - )?, + block, + cumulative, + last_cumulative_sats, }) } - pub(crate) fn compute( + #[inline(always)] + pub(crate) fn push_block_sats(&mut self, value: Sats) { + let len = self.cumulative.sats.height.len(); + let mut cumulative = match self.last_cumulative_sats { + Some((cached_len, value)) if cached_len == len => value, + _ => self + .cumulative + .sats + .height + .collect_last() + .unwrap_or_default(), + }; + cumulative += value; + self.cumulative.sats.height.push(cumulative); + self.last_cumulative_sats = Some((len + 1, cumulative)); + } + + pub(crate) fn compute_from( &mut self, - prices: &price::Vecs, max_from: Height, + prices: &price::Vecs, + source: &impl ReadableVec, + transform: impl FnMut(Height, S) -> Sats, exit: &Exit, - ) -> Result<()> { - self.cumulative - .sats - .height - .compute_cumulative(max_from, &self.block.sats, exit)?; + ) -> Result<()> + where + S: VecValue, + { + self.compute_sats_from(max_from, source, transform, exit)?; + self.compute_cents(max_from, prices, exit) + } - self.block.compute_cents(max_from, prices, exit)?; + pub(crate) fn compute_from_pair( + &mut self, + max_from: Height, + prices: &price::Vecs, + source1: &impl ReadableVec, + source2: &impl ReadableVec, + transform: impl FnMut(Height, S1, S2) -> Sats, + exit: &Exit, + ) -> Result<()> + where + S1: VecValue, + S2: VecValue, + { + self.compute_sats_from_pair(max_from, source1, source2, transform, exit)?; + self.compute_cents(max_from, prices, exit) + } - self.cumulative - .cents - .height - .compute_cumulative(max_from, &self.block.cents, exit)?; + #[allow(clippy::too_many_arguments)] + pub(crate) fn compute_from_indexes( + &mut self, + max_from: Height, + prices: &price::Vecs, + first_indexes: &impl ReadableVec, + indexes_count: &impl ReadableVec, + source: &impl ReadableVec, + exit: &Exit, + ) -> Result<()> + where + A: VecIndex + VecValue, + B: VecValue, + usize: From, + { + self.compute_sats_from_indexes( + max_from, + first_indexes, + indexes_count, + source, + |_| true, + exit, + )?; + self.compute_cents(max_from, prices, exit) + } + #[allow(clippy::too_many_arguments)] + pub(crate) fn compute_filtered_from_indexes( + &mut self, + max_from: Height, + prices: &price::Vecs, + first_indexes: &impl ReadableVec, + indexes_count: &impl ReadableVec, + source: &impl ReadableVec, + filter: impl FnMut(&Sats) -> bool, + exit: &Exit, + ) -> Result<()> + where + A: VecIndex + VecValue, + B: VecValue, + usize: From, + { + self.compute_sats_from_indexes( + max_from, + first_indexes, + indexes_count, + source, + filter, + exit, + )?; + self.compute_cents(max_from, prices, exit) + } + + fn compute_sats_from( + &mut self, + max_from: Height, + source: &impl ReadableVec, + mut transform: impl FnMut(Height, S) -> Sats, + exit: &Exit, + ) -> Result<()> + where + S: VecValue, + { + let mut cumulative = None; + self.cumulative.sats.height.compute_transform( + max_from, + source, + |(height, value, this)| { + let cumulative = cumulative.get_or_insert_with(|| { + height + .decremented() + .and_then(|height| this.collect_one(height)) + .unwrap_or_default() + }); + *cumulative += transform(height, value); + (height, *cumulative) + }, + exit, + )?; + self.last_cumulative_sats = None; Ok(()) } - pub(crate) fn compute_with( + fn compute_sats_from_pair( + &mut self, + max_from: Height, + source1: &impl ReadableVec, + source2: &impl ReadableVec, + mut transform: impl FnMut(Height, S1, S2) -> Sats, + exit: &Exit, + ) -> Result<()> + where + S1: VecValue, + S2: VecValue, + { + let mut cumulative = None; + self.cumulative.sats.height.compute_transform2( + max_from, + source1, + source2, + |(height, value1, value2, this)| { + let cumulative = cumulative.get_or_insert_with(|| { + height + .decremented() + .and_then(|height| this.collect_one(height)) + .unwrap_or_default() + }); + *cumulative += transform(height, value1, value2); + (height, *cumulative) + }, + exit, + )?; + self.last_cumulative_sats = None; + Ok(()) + } + + #[allow(clippy::too_many_arguments)] + fn compute_sats_from_indexes( + &mut self, + max_from: Height, + first_indexes: &impl ReadableVec, + indexes_count: &impl ReadableVec, + source: &impl ReadableVec, + mut filter: impl FnMut(&Sats) -> bool, + exit: &Exit, + ) -> Result<()> + where + A: VecIndex + VecValue, + B: VecValue, + usize: From, + { + let target = &mut self.cumulative.sats.height; + target.validate_computed_version_or_reset( + first_indexes.version() + indexes_count.version() + source.version(), + )?; + target.truncate_if_needed(max_from)?; + target.repeat_until_complete(exit, |target| { + let skip = target.len(); + let end = target.batch_end(indexes_count.len()); + if skip >= end || skip >= first_indexes.len() { + return Ok(()); + } + + let source_start = first_indexes.collect_one_at(skip).unwrap().to_usize(); + let counts: Vec = indexes_count + .collect_range_at(skip, end) + .into_iter() + .map(usize::from) + .collect(); + let source_end = source_start + counts.iter().sum::(); + let mut cumulative = skip + .checked_sub(1) + .and_then(|index| target.collect_one_at(index)) + .unwrap_or_default(); + let mut group_index = 0; + + while group_index < counts.len() && counts[group_index] == 0 { + target.push(cumulative); + group_index += 1; + } + + if group_index < counts.len() { + let mut remaining = counts[group_index]; + source.fold_range_at(source_start, source_end, Sats::ZERO, |sum, value| { + let sum = if filter(&value) { sum + value } else { sum }; + remaining -= 1; + if remaining == 0 { + cumulative += sum; + target.push(cumulative); + group_index += 1; + while group_index < counts.len() && counts[group_index] == 0 { + target.push(cumulative); + group_index += 1; + } + if group_index < counts.len() { + remaining = counts[group_index]; + } + Sats::ZERO + } else { + sum + } + }); + } + + Ok(()) + })?; + self.last_cumulative_sats = None; + Ok(()) + } + + pub(crate) fn compute_cents( &mut self, max_from: Height, prices: &price::Vecs, exit: &Exit, - compute_sats: impl FnOnce(&mut EagerVec>) -> Result<()>, ) -> Result<()> { - compute_sats(&mut self.block.sats)?; - self.compute(prices, max_from, exit) + self.cumulative + .cents + .height + .compute_cumulative_transformed_binary( + max_from, + &self.block.sats, + &prices.spot.cents.height, + SatsToCents::apply, + exit, + )?; + + Ok(()) } } diff --git a/crates/brk_computer/src/internal/per_block/value/cumulative_rolling.rs b/crates/brk_computer/src/internal/per_block/value/cumulative_rolling.rs index 51d7fed15..f85aca223 100644 --- a/crates/brk_computer/src/internal/per_block/value/cumulative_rolling.rs +++ b/crates/brk_computer/src/internal/per_block/value/cumulative_rolling.rs @@ -1,8 +1,8 @@ use brk_error::Result; use brk_traversable::Traversable; -use brk_types::{Height, Sats, Version}; +use brk_types::{Height, Version}; use derive_more::{Deref, DerefMut}; -use vecdb::{Database, EagerVec, Exit, PcoVec, Rw, StorageMode}; +use vecdb::{Database, Exit, Rw, StorageMode}; use crate::{ indexes, @@ -60,23 +60,12 @@ impl ValuePerBlockCumulativeRolling { }) } - pub(crate) fn compute( - &mut self, - max_from: Height, - prices: &price::Vecs, - exit: &Exit, - compute_sats: impl FnOnce(&mut EagerVec>) -> Result<()>, - ) -> Result<()> { - compute_sats(&mut self.block.sats)?; - self.compute_rest(max_from, prices, exit) - } - pub(crate) fn compute_rest( &mut self, max_from: Height, prices: &price::Vecs, exit: &Exit, ) -> Result<()> { - self.inner.compute(prices, max_from, exit) + self.inner.compute_cents(max_from, prices, exit) } } diff --git a/crates/brk_computer/src/internal/per_block/value/full.rs b/crates/brk_computer/src/internal/per_block/value/full.rs index c92a0ad7a..00f77a2a3 100644 --- a/crates/brk_computer/src/internal/per_block/value/full.rs +++ b/crates/brk_computer/src/internal/per_block/value/full.rs @@ -2,7 +2,7 @@ use brk_error::Result; use brk_traversable::Traversable; use brk_types::{Height, Sats, Version}; use derive_more::{Deref, DerefMut}; -use vecdb::{Database, EagerVec, Exit, PcoVec, Rw, StorageMode}; +use vecdb::{Database, Exit, ReadableVec, Rw, StorageMode, VecIndex, VecValue}; use crate::{ indexes, @@ -45,18 +45,39 @@ impl ValuePerBlockFull { }) } - pub(crate) fn compute( + #[allow(clippy::too_many_arguments)] + pub(crate) fn compute_from_indexes( &mut self, max_from: Height, windows: &WindowStarts<'_>, prices: &price::Vecs, + first_indexes: &impl ReadableVec, + indexes_count: &impl ReadableVec, + source: &impl ReadableVec, + exit: &Exit, + ) -> Result<()> + where + A: VecIndex + VecValue, + B: VecValue, + usize: From, + { + self.inner.compute_from_indexes( + max_from, + prices, + first_indexes, + indexes_count, + source, + exit, + )?; + self.compute_distribution(max_from, windows, exit) + } + + fn compute_distribution( + &mut self, + max_from: Height, + windows: &WindowStarts<'_>, exit: &Exit, - compute_sats: impl FnOnce(&mut EagerVec>) -> Result<()>, ) -> Result<()> { - compute_sats(&mut self.inner.block.sats)?; - - self.inner.compute_rest(max_from, prices, exit)?; - self.distribution.compute( max_from, windows, diff --git a/crates/brk_computer/src/internal/per_block/value/lazy_block.rs b/crates/brk_computer/src/internal/per_block/value/lazy_block.rs new file mode 100644 index 000000000..a45dbd701 --- /dev/null +++ b/crates/brk_computer/src/internal/per_block/value/lazy_block.rs @@ -0,0 +1,47 @@ +use brk_traversable::Traversable; +use brk_types::{Bitcoin, Cents, Dollars, Height, Sats, Version}; +use vecdb::{LazyVecFrom1, ReadableCloneableVec}; + +use crate::internal::{CentsUnsignedToDollars, LazyPreviousDeltaVec, SatsToBitcoin, ValuePerBlock}; + +/// Per-block amount data derived from stored cumulative sats and cents. +#[derive(Clone, Traversable)] +pub struct LazyValueBlock { + pub btc: LazyVecFrom1, + pub sats: LazyPreviousDeltaVec, + pub usd: LazyVecFrom1, + pub cents: LazyPreviousDeltaVec, +} + +impl LazyValueBlock { + pub(crate) fn from_cumulative( + name: &str, + version: Version, + cumulative: &ValuePerBlock, + ) -> Self { + let sats = LazyPreviousDeltaVec::new( + &format!("{name}_sats"), + version, + cumulative.sats.height.read_only_boxed_clone(), + ); + let btc = + LazyVecFrom1::transformed::(name, version, sats.read_only_boxed_clone()); + let cents = LazyPreviousDeltaVec::new( + &format!("{name}_cents"), + version, + cumulative.cents.height.read_only_boxed_clone(), + ); + let usd = LazyVecFrom1::transformed::( + &format!("{name}_usd"), + version, + cents.read_only_boxed_clone(), + ); + + Self { + btc, + sats, + usd, + cents, + } + } +} diff --git a/crates/brk_computer/src/internal/per_block/value/mod.rs b/crates/brk_computer/src/internal/per_block/value/mod.rs index 4866ebd1e..15813efb7 100644 --- a/crates/brk_computer/src/internal/per_block/value/mod.rs +++ b/crates/brk_computer/src/internal/per_block/value/mod.rs @@ -1,9 +1,9 @@ mod base; -mod block; mod cumulative; mod cumulative_rolling; mod full; mod lazy; +mod lazy_block; mod lazy_derived_resolutions; mod lazy_rolling_avg; mod lazy_rolling_sum; @@ -11,11 +11,11 @@ mod rolling_distribution; mod with_deltas; pub use base::*; -pub use block::*; pub use cumulative::*; pub use cumulative_rolling::*; pub use full::*; pub use lazy::*; +pub use lazy_block::*; pub use lazy_derived_resolutions::*; pub use lazy_rolling_avg::*; pub use lazy_rolling_sum::*; diff --git a/crates/brk_computer/src/mining/rewards/compute.rs b/crates/brk_computer/src/mining/rewards/compute.rs index b3ecb3749..35487a976 100644 --- a/crates/brk_computer/src/mining/rewards/compute.rs +++ b/crates/brk_computer/src/mining/rewards/compute.rs @@ -27,67 +27,59 @@ impl Vecs { let window_starts = lookback.window_starts(); let (r_coinbase, r_fees) = rayon::join( || { - self.coinbase.compute(starting_height, prices, exit, |vec| { - let mut txout_cursor = indexer.vecs.transactions.first_txout_index.cursor(); - let mut count_cursor = indexes.tx_index.output_count.cursor(); + self.coinbase.compute_from( + starting_height, + prices, + &indexer.vecs.transactions.first_tx_index, + |_, tx_index| { + let mut txout_cursor = indexer.vecs.transactions.first_txout_index.cursor(); + let mut count_cursor = indexes.tx_index.output_count.cursor(); - vec.compute_transform( - starting_height, - &indexer.vecs.transactions.first_tx_index, - |(height, tx_index, ..)| { - let ti = tx_index.to_usize(); + let ti = tx_index.to_usize(); - txout_cursor.advance(ti - txout_cursor.position()); - let first_txout_index = txout_cursor.next().unwrap().to_usize(); + txout_cursor.advance(ti - txout_cursor.position()); + let first_txout_index = txout_cursor.next().unwrap().to_usize(); - count_cursor.advance(ti - count_cursor.position()); - let output_count: usize = count_cursor.next().unwrap().into(); + count_cursor.advance(ti - count_cursor.position()); + let output_count: usize = count_cursor.next().unwrap().into(); - let sats = indexer.vecs.outputs.value.fold_range_at( - first_txout_index, - first_txout_index + output_count, - Sats::ZERO, - |acc, v| acc + v, - ); - (height, sats) - }, - exit, - )?; - Ok(()) - }) + indexer.vecs.outputs.value.fold_range_at( + first_txout_index, + first_txout_index + output_count, + Sats::ZERO, + |acc, v| acc + v, + ) + }, + exit, + ) }, || { - self.fees - .compute(starting_height, &window_starts, prices, exit, |vec| { - vec.compute_sum_from_indexes( - starting_height, - &indexer.vecs.transactions.first_tx_index, - &indexes.height.tx_index_count, - &transactions.fees.fee.tx_index, - exit, - )?; - Ok(()) - }) + self.fees.compute_from_indexes( + starting_height, + &window_starts, + prices, + &indexer.vecs.transactions.first_tx_index, + &indexes.height.tx_index_count, + &transactions.fees.fee.tx_index, + exit, + ) }, ); r_coinbase?; r_fees?; - self.subsidy.block.sats.compute_transform2( + self.subsidy.compute_from_pair( starting_height, + prices, &self.coinbase.block.sats, &self.fees.block.sats, - |(height, coinbase, fees, ..)| { - ( - height, - coinbase.checked_sub(fees).unwrap_or_else(|| { - panic!("coinbase {coinbase:?} < fees {fees:?} at {height:?}") - }), - ) + |height, coinbase, fees| { + coinbase.checked_sub(fees).unwrap_or_else(|| { + panic!("coinbase {coinbase:?} < fees {fees:?} at {height:?}") + }) }, exit, )?; - self.subsidy.compute_rest(starting_height, prices, exit)?; self.output_volume.compute_subtract( starting_height, @@ -96,17 +88,17 @@ impl Vecs { exit, )?; - self.unclaimed.block.sats.compute_transform( + self.unclaimed.compute_from( starting_height, + prices, &self.subsidy.block.sats, - |(height, subsidy, ..)| { + |height, subsidy| { let halving = Halving::from(height); let expected = Sats::FIFTY_BTC / 2_usize.pow(halving.to_usize() as u32); - (height, expected.checked_sub(subsidy).unwrap()) + expected.checked_sub(subsidy).unwrap() }, exit, )?; - self.unclaimed.compute(prices, starting_height, exit)?; self.fee_dominance .compute_binary::, _, _, _, _>( diff --git a/crates/brk_computer/src/outputs/value/compute.rs b/crates/brk_computer/src/outputs/value/compute.rs index 9fb9f8542..e3ff580e0 100644 --- a/crates/brk_computer/src/outputs/value/compute.rs +++ b/crates/brk_computer/src/outputs/value/compute.rs @@ -14,85 +14,88 @@ impl Vecs { exit: &Exit, ) -> Result<()> { let starting_lengths = indexer.safe_lengths(); - self.op_return - .compute_with(starting_lengths.height, prices, exit, |height_vec| { - // Validate computed versions against dependencies - let dep_version = indexer.vecs.outputs.first_txout_index.version() - + indexer.vecs.outputs.output_type.version() - + indexer.vecs.outputs.value.version(); - height_vec.validate_computed_version_or_reset(dep_version)?; + let height_vec = &mut self.op_return.cumulative.sats.height; - // Get target height - let target_len = indexer.vecs.outputs.first_txout_index.len(); - if target_len == 0 { - return Ok(()); - } - let target_height = Height::from(target_len - 1); + // Validate computed versions against dependencies + let dep_version = indexer.vecs.outputs.first_txout_index.version() + + indexer.vecs.outputs.output_type.version() + + indexer.vecs.outputs.value.version(); + height_vec.validate_computed_version_or_reset(dep_version)?; - // Find starting height for this vec - let current_len = height_vec.len(); - let starting_height = - Height::from(current_len.min(starting_lengths.height.to_usize())); + // Get target height + let target_len = indexer.vecs.outputs.first_txout_index.len(); + if target_len == 0 { + self.op_return + .compute_cents(starting_lengths.height, prices, exit)?; + return Ok(()); + } + let target_height = Height::from(target_len - 1); - if starting_height > target_height { - return Ok(()); - } + // Find starting height for this vec + let current_len = height_vec.len(); + let starting_height = Height::from(current_len.min(starting_lengths.height.to_usize())); - // Pre-collect height-indexed data - let first_txout_indexes: Vec = - indexer.vecs.outputs.first_txout_index.collect_range_at( - starting_height.to_usize(), - target_height.to_usize() - + 2.min(indexer.vecs.outputs.first_txout_index.len()), - ); + if starting_height <= target_height { + // Pre-collect height-indexed data + let first_txout_indexes: Vec = + indexer.vecs.outputs.first_txout_index.collect_range_at( + starting_height.to_usize(), + target_height.to_usize() + 2.min(indexer.vecs.outputs.first_txout_index.len()), + ); - let mut output_types_buf: Vec = Vec::new(); - let mut values_buf: Vec = Vec::new(); + let mut output_types_buf: Vec = Vec::new(); + let mut values_buf: Vec = Vec::new(); + let mut cumulative = starting_height + .decremented() + .and_then(|height| height_vec.collect_one(height)) + .unwrap_or_default(); - height_vec.truncate_if_needed(starting_height)?; + height_vec.truncate_if_needed(starting_height)?; - // Iterate blocks - for h in starting_height.to_usize()..=target_height.to_usize() { - let local_idx = h - starting_height.to_usize(); + // Iterate blocks + for h in starting_height.to_usize()..=target_height.to_usize() { + let local_idx = h - starting_height.to_usize(); - // Get output range for this block - let first_txout_index = first_txout_indexes[local_idx]; - let next_first_txout_index = - if let Some(&next) = first_txout_indexes.get(local_idx + 1) { - next - } else { - TxOutIndex::from(indexer.vecs.outputs.value.len()) - }; + // Get output range for this block + let first_txout_index = first_txout_indexes[local_idx]; + let next_first_txout_index = + if let Some(&next) = first_txout_indexes.get(local_idx + 1) { + next + } else { + TxOutIndex::from(indexer.vecs.outputs.value.len()) + }; - let out_start = first_txout_index.to_usize(); - let out_end = next_first_txout_index.to_usize(); + let out_start = first_txout_index.to_usize(); + let out_end = next_first_txout_index.to_usize(); - // Pre-collect both vecs into reusable buffers - indexer.vecs.outputs.output_type.collect_range_into_at( - out_start, - out_end, - &mut output_types_buf, - ); - indexer.vecs.outputs.value.collect_range_into_at( - out_start, - out_end, - &mut values_buf, - ); + // Pre-collect both vecs into reusable buffers + indexer.vecs.outputs.output_type.collect_range_into_at( + out_start, + out_end, + &mut output_types_buf, + ); + indexer.vecs.outputs.value.collect_range_into_at( + out_start, + out_end, + &mut values_buf, + ); - let mut op_return_value = Sats::ZERO; - for (ot, val) in output_types_buf.iter().zip(values_buf.iter()) { - if *ot == OutputType::OpReturn { - op_return_value += *val; - } + let mut op_return_value = Sats::ZERO; + for (ot, val) in output_types_buf.iter().zip(values_buf.iter()) { + if *ot == OutputType::OpReturn { + op_return_value += *val; } - - height_vec.push(op_return_value); } - height_vec.write()?; + cumulative += op_return_value; + height_vec.push(cumulative); + } - Ok(()) - })?; + height_vec.write()?; + } + + self.op_return + .compute_cents(starting_lengths.height, prices, exit)?; Ok(()) } diff --git a/crates/brk_computer/src/pools/major.rs b/crates/brk_computer/src/pools/major.rs index 777ea6635..d4a6b6ae5 100644 --- a/crates/brk_computer/src/pools/major.rs +++ b/crates/brk_computer/src/pools/major.rs @@ -87,16 +87,14 @@ impl Vecs { )?; } - self.rewards.compute(starting_height, prices, exit, |vec| { - Ok(vec.compute_transform2( - starting_height, - &self.base.blocks_mined.block, - &mining.rewards.coinbase.block.sats, - |(h, mask, val, ..)| (h, MaskSats::apply(mask, val)), - exit, - )?) - })?; - + self.rewards.compute_from_pair( + starting_height, + prices, + &self.base.blocks_mined.block, + &mining.rewards.coinbase.block.sats, + |_, mask, value| MaskSats::apply(mask, value), + exit, + )?; Ok(()) } } diff --git a/crates/brk_computer/src/supply/burned/compute.rs b/crates/brk_computer/src/supply/burned/compute.rs index 855e969ad..2a4e6ca33 100644 --- a/crates/brk_computer/src/supply/burned/compute.rs +++ b/crates/brk_computer/src/supply/burned/compute.rs @@ -17,24 +17,21 @@ impl Vecs { ) -> Result<()> { let starting_height = indexer.safe_lengths().height; - self.total - .compute_with(starting_height, prices, exit, |sats| { - Ok(sats.compute_transform2( - starting_height, - &outputs.value.op_return.block.sats, - &mining.rewards.unclaimed.block.sats, - |(h, op_return, unclaimed, ..)| { - let genesis = if h.to_usize() == 0 { - Sats::FIFTY_BTC - } else { - Sats::ZERO - }; - (h, genesis + op_return + unclaimed) - }, - exit, - )?) - })?; - + self.total.compute_from_pair( + starting_height, + prices, + &outputs.value.op_return.block.sats, + &mining.rewards.unclaimed.block.sats, + |height, op_return, unclaimed| { + let genesis = if height.to_usize() == 0 { + Sats::FIFTY_BTC + } else { + Sats::ZERO + }; + genesis + op_return + unclaimed + }, + exit, + )?; Ok(()) } } diff --git a/crates/brk_computer/src/transactions/volume/compute.rs b/crates/brk_computer/src/transactions/volume/compute.rs index a54102d6e..af6115e00 100644 --- a/crates/brk_computer/src/transactions/volume/compute.rs +++ b/crates/brk_computer/src/transactions/volume/compute.rs @@ -20,18 +20,15 @@ impl Vecs { ) -> Result<()> { let starting_height = indexer.safe_lengths().height; - self.transfer_volume - .compute(starting_height, prices, exit, |sats_vec| { - Ok(sats_vec.compute_filtered_sum_from_indexes( - starting_height, - &indexer.vecs.transactions.first_tx_index, - &indexes.height.tx_index_count, - &fees_vecs.input_value, - |sats| !sats.is_max(), - exit, - )?) - })?; - + self.transfer_volume.compute_filtered_from_indexes( + starting_height, + prices, + &indexer.vecs.transactions.first_tx_index, + &indexes.height.tx_index_count, + &fees_vecs.input_value, + |sats| !sats.is_max(), + exit, + )?; let tx_sums = count_vecs.total.rolling.sum.0.as_array(); let tx_per_sec = self.tx_per_sec.as_mut_array(); for (i, &secs) in Windows::<()>::SECS.iter().enumerate() {