global: snapshot

This commit is contained in:
nym21
2026-03-10 11:53:46 +01:00
parent 5ede3dc416
commit 8f93a5947e
16 changed files with 2123 additions and 2015 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -100,8 +100,10 @@ impl<R: RealizedOps> CohortState<R> {
}
pub(crate) fn reset_single_iteration_values(&mut self) {
if R::TRACK_ACTIVITY {
self.sent = Sats::ZERO;
self.satdays_destroyed = Sats::ZERO;
}
self.realized.reset_single_iteration_values();
}
@@ -198,8 +200,10 @@ impl<R: RealizedOps> CohortState<R> {
pre: &SendPrecomputed,
) {
self.supply -= supply;
if R::TRACK_ACTIVITY {
self.sent += pre.sats;
self.satdays_destroyed += pre.age.satdays_destroyed(pre.sats);
}
self.realized
.send(pre.sats, pre.current_ps, pre.prev_ps, pre.ath_ps, pre.prev_investor_cap);
@@ -241,8 +245,10 @@ impl<R: RealizedOps> CohortState<R> {
self.supply -= supply;
if supply.value > Sats::ZERO {
if R::TRACK_ACTIVITY {
self.sent += supply.value;
self.satdays_destroyed += age.satdays_destroyed(supply.value);
}
let sats = supply.value;

View File

@@ -4,6 +4,7 @@ use brk_types::{Cents, CentsSats, CentsSquaredSats, Sats};
/// Trait for realized state operations, implemented by Minimal, Core, and Full variants.
pub trait RealizedOps: Default + Clone + Send + Sync + 'static {
const TRACK_ACTIVITY: bool = false;
fn cap(&self) -> Cents;
fn profit(&self) -> Cents;
fn loss(&self) -> Cents;
@@ -159,6 +160,8 @@ pub struct CoreRealizedState {
}
impl RealizedOps for CoreRealizedState {
const TRACK_ACTIVITY: bool = true;
#[inline]
fn cap(&self) -> Cents {
self.minimal.cap()
@@ -273,6 +276,8 @@ pub struct RealizedState {
}
impl RealizedOps for RealizedState {
const TRACK_ACTIVITY: bool = true;
#[inline]
fn cap(&self) -> Cents {
self.core.cap()

View File

@@ -5,7 +5,7 @@ use brk_types::{Bitcoin, Cents, Dollars, Height, Sats, Version};
use derive_more::{Deref, DerefMut};
use vecdb::UnaryTransform;
use crate::internal::{AmountPerBlock, LazyAmount, LazyAmountDerivedResolutions};
use crate::internal::{AmountPerBlock, Identity, LazyAmount, LazyAmountDerivedResolutions, SatsToBitcoin};
/// Lazy value wrapper with height + all derived last transforms from AmountPerBlock.
#[derive(Clone, Deref, DerefMut, Traversable)]
@@ -55,4 +55,10 @@ impl LazyAmountPerBlock {
resolutions: Box::new(resolutions),
}
}
pub(crate) fn identity(name: &str, source: &AmountPerBlock, version: Version) -> Self {
Self::from_block_source::<Identity<Sats>, SatsToBitcoin, Identity<Cents>, Identity<Dollars>>(
name, source, version,
)
}
}

View File

@@ -1,8 +1,8 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::Version;
use brk_types::{Height, Version};
use derive_more::{Deref, DerefMut};
use vecdb::{Database, Rw, StorageMode};
use vecdb::{BinaryTransform, Database, Exit, ReadableVec, Rw, StorageMode, VecValue};
use crate::{
indexes,
@@ -28,4 +28,30 @@ impl<B: BpsType> PercentRollingWindows<B> {
PercentPerBlock::forced_import(db, &format!("{name}_{suffix}"), version, indexes)
})?))
}
pub(crate) fn compute_binary<S1T, S2T, F, R1, R2>(
&mut self,
max_from: Height,
sources1: [&R1; 4],
sources2: [&R2; 4],
exit: &Exit,
) -> Result<()>
where
S1T: VecValue,
S2T: VecValue,
R1: ReadableVec<Height, S1T>,
R2: ReadableVec<Height, S2T>,
F: BinaryTransform<S1T, S2T, B>,
{
for ((target, s1), s2) in self
.0
.as_mut_array()
.into_iter()
.zip(sources1)
.zip(sources2)
{
target.compute_binary::<S1T, S2T, F>(max_from, s1, s2, exit)?;
}
Ok(())
}
}

View File

@@ -3,9 +3,11 @@ mod extended;
mod percentiles;
mod price_extended;
mod std_dev_bands;
mod windows;
pub use base::*;
pub use extended::*;
pub use percentiles::*;
pub use price_extended::*;
pub use std_dev_bands::*;
pub use windows::*;

View File

@@ -0,0 +1,57 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Height, Version};
use derive_more::{Deref, DerefMut};
use vecdb::{BinaryTransform, Database, Exit, ReadableVec, Rw, StorageMode, VecValue};
use crate::{
indexes,
internal::{BpsType, RatioPerBlock, Windows},
};
/// 4 rolling window vecs (24h, 1w, 1m, 1y), each storing basis points
/// with a lazy ratio float view.
#[derive(Deref, DerefMut, Traversable)]
#[traversable(transparent)]
pub struct RatioRollingWindows<B: BpsType, M: StorageMode = Rw>(
pub Windows<RatioPerBlock<B, M>>,
);
impl<B: BpsType> RatioRollingWindows<B> {
pub(crate) fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
Ok(Self(Windows::try_from_fn(|suffix| {
RatioPerBlock::forced_import_raw(db, &format!("{name}_{suffix}"), version, indexes)
})?))
}
pub(crate) fn compute_binary<S1T, S2T, F, R1, R2>(
&mut self,
max_from: Height,
sources1: [&R1; 4],
sources2: [&R2; 4],
exit: &Exit,
) -> Result<()>
where
S1T: VecValue,
S2T: VecValue,
R1: ReadableVec<Height, S1T>,
R2: ReadableVec<Height, S2T>,
F: BinaryTransform<S1T, S2T, B>,
{
for ((target, s1), s2) in self
.0
.as_mut_array()
.into_iter()
.zip(sources1)
.zip(sources2)
{
target.bps.compute_binary::<S1T, S2T, F>(max_from, s1, s2, exit)?;
}
Ok(())
}
}

View File

@@ -215,6 +215,7 @@ impl Computer {
VERSION,
&indexes,
&distribution,
&cointime,
)?))
})?;

View File

@@ -1,10 +1,10 @@
use brk_error::Result;
use brk_indexer::Indexer;
use brk_types::{BasisPoints16, CheckedSub, Halving, Indexes, Sats};
use brk_types::{BasisPoints16, CheckedSub, Dollars, Halving, Indexes, Sats};
use vecdb::{Exit, ReadableVec, VecIndex};
use super::Vecs;
use crate::{blocks, indexes, internal::RatioSatsBp16, prices, transactions};
use crate::{blocks, indexes, internal::{RatioDollarsBp32, RatioSatsBp16}, prices, transactions};
impl Vecs {
#[allow(clippy::too_many_arguments)]
@@ -122,20 +122,13 @@ impl Vecs {
)?;
// Rolling fee dominance = sum(fees) / sum(coinbase)
for ((fee_dom, fees_w), coinbase_w) in self
.fee_dominance_rolling
.as_mut_array()
.into_iter()
.zip(self.fees.rolling.as_array())
.zip(self.coinbase.sum.as_array())
{
fee_dom.compute_binary::<Sats, Sats, RatioSatsBp16>(
self.fee_dominance_rolling
.compute_binary::<Sats, Sats, RatioSatsBp16, _, _>(
starting_indexes.height,
&fees_w.sum.sats.height,
&coinbase_w.sats.height,
self.fees.rolling.as_array().map(|w| &w.sum.sats.height),
self.coinbase.sum.as_array().map(|w| &w.sats.height),
exit,
)?;
}
// All-time cumulative subsidy dominance
self.subsidy_dominance
@@ -168,6 +161,15 @@ impl Vecs {
exit,
)?;
// Fee Ratio Multiple: sum(coinbase) / sum(fees) per rolling window
self.fee_ratio_multiple
.compute_binary::<Dollars, Dollars, RatioDollarsBp32, _, _>(
starting_indexes.height,
self.coinbase.sum.as_array().map(|w| &w.usd.height),
self.fees.rolling.as_array().map(|w| &w.sum.usd.height),
exit,
)?;
Ok(())
}
}

View File

@@ -7,7 +7,7 @@ use crate::{
indexes,
internal::{
AmountPerBlockCumulative, AmountPerBlockCumulativeSum, AmountPerBlockFull,
FiatPerBlock, PercentPerBlock, PercentRollingWindows,
FiatPerBlock, PercentPerBlock, PercentRollingWindows, RatioRollingWindows,
},
};
@@ -49,6 +49,12 @@ impl Vecs {
indexes,
)?,
subsidy_sma_1y: FiatPerBlock::forced_import(db, "subsidy_sma_1y", version, indexes)?,
fee_ratio_multiple: RatioRollingWindows::forced_import(
db,
"fee_ratio_multiple",
version,
indexes,
)?,
})
}
}

View File

@@ -1,10 +1,10 @@
use brk_traversable::Traversable;
use brk_types::{BasisPoints16, Cents};
use brk_types::{BasisPoints16, BasisPoints32, Cents};
use vecdb::{Rw, StorageMode};
use crate::internal::{
AmountPerBlockCumulative, AmountPerBlockCumulativeSum, AmountPerBlockFull,
FiatPerBlock, PercentPerBlock, PercentRollingWindows,
FiatPerBlock, PercentPerBlock, PercentRollingWindows, RatioRollingWindows,
};
#[derive(Traversable)]
@@ -20,4 +20,5 @@ pub struct Vecs<M: StorageMode = Rw> {
#[traversable(rename = "subsidy_dominance")]
pub subsidy_dominance_rolling: PercentRollingWindows<BasisPoints16, M>,
pub subsidy_sma_1y: FiatPerBlock<Cents, M>,
pub fee_ratio_multiple: RatioRollingWindows<BasisPoints32, M>,
}

View File

@@ -1,13 +1,13 @@
use std::path::Path;
use brk_error::Result;
use brk_types::{Cents, Dollars, Sats, Version};
use brk_types::Version;
use crate::{
distribution, indexes,
cointime, distribution, indexes,
internal::{
FiatRollingDelta, Identity, LazyFiatPerBlock, LazyAmountPerBlock, PercentPerBlock,
RollingWindows, SatsToBitcoin, finalize_db, open_db,
FiatRollingDelta, LazyFiatPerBlock, LazyAmountPerBlock, PercentPerBlock,
RollingWindows, finalize_db, open_db,
},
};
@@ -21,6 +21,7 @@ impl Vecs {
parent_version: Version,
indexes: &indexes::Vecs,
distribution: &distribution::Vecs,
cointime: &cointime::Vecs,
) -> Result<Self> {
let db = open_db(parent, super::DB_NAME, 10_000_000)?;
@@ -28,12 +29,8 @@ impl Vecs {
let supply_metrics = &distribution.utxo_cohorts.all.metrics.supply;
// Circulating supply - lazy refs to distribution
let circulating = LazyAmountPerBlock::from_block_source::<
Identity<Sats>,
SatsToBitcoin,
Identity<Cents>,
Identity<Dollars>,
>("circulating_supply", &supply_metrics.total, version);
let circulating =
LazyAmountPerBlock::identity("circulating_supply", &supply_metrics.total, version);
// Burned/unspendable supply - computed from scripts
let burned = super::burned::Vecs::forced_import(&db, version, indexes)?;
@@ -64,6 +61,12 @@ impl Vecs {
indexes,
)?;
let hodled_or_lost_coins = LazyAmountPerBlock::identity(
"hodled_or_lost_coins",
&cointime.supply.vaulted_supply,
version,
);
let this = Self {
db,
circulating,
@@ -73,6 +76,7 @@ impl Vecs {
market_cap,
market_cap_delta,
market_minus_realized_cap_growth_rate,
hodled_or_lost_coins,
};
finalize_db(&this.db, &this)?;
Ok(this)

View File

@@ -19,4 +19,5 @@ pub struct Vecs<M: StorageMode = Rw> {
pub market_cap: LazyFiatPerBlock<Cents>,
pub market_cap_delta: FiatRollingDelta<Cents, CentsSigned, M>,
pub market_minus_realized_cap_growth_rate: RollingWindows<BasisPointsSigned32, M>,
pub hodled_or_lost_coins: LazyAmountPerBlock,
}

View File

@@ -14,7 +14,7 @@ impl Query {
let coinbase_vec = &computer.mining.rewards.coinbase.base.sats.height;
let fee_vec = &computer.mining.rewards.fees.base.sats.height;
let tx_count_vec = &computer.transactions.count.tx_count.height;
let tx_count_vec = &computer.transactions.count.tx_count.raw.height;
let start = start_block.to_usize();
let end = end_block.to_usize() + 1;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff