computer: snapshot

This commit is contained in:
nym21
2026-01-09 22:02:34 +01:00
parent 426d7797a3
commit 3a3f6b8593
43 changed files with 3879 additions and 4097 deletions

View File

@@ -225,6 +225,7 @@ impl AddressTypeToAddrCountVecs {
#[derive(Clone, Traversable)]
pub struct AddrCountVecs {
pub all: ComputedBlockLast<StoredU64>,
#[traversable(flatten)]
pub by_addresstype: AddressTypeToAddrCountVecs,
}

View File

@@ -8,10 +8,7 @@ use rayon::prelude::*;
use vecdb::{AnyStoredVec, AnyVec, Database, Exit, GenericStoredVec, IterableVec};
use crate::{
ComputeIndexes,
distribution::state::AddressCohortState,
indexes,
internal::ComputedBlockLast,
ComputeIndexes, distribution::state::AddressCohortState, indexes, internal::ComputedBlockLast,
price,
};
@@ -155,7 +152,7 @@ impl DynCohortVecs for AddressCohortVecs {
state.inner.supply.value = self
.metrics
.supply
.supply
.total
.sats
.height
.read_once(prev_height)?;

View File

@@ -7,7 +7,7 @@ use brk_types::{DateIndex, Dollars, Height, Version};
use rayon::prelude::*;
use vecdb::{AnyStoredVec, Database, Exit, IterableVec};
use crate::{ComputeIndexes, indexes, price, distribution::state::UTXOCohortState};
use crate::{ComputeIndexes, distribution::state::UTXOCohortState, indexes, price};
use crate::distribution::metrics::{CohortMetrics, ImportConfig, RealizedMetrics, SupplyMetrics};
@@ -149,7 +149,7 @@ impl DynCohortVecs for UTXOCohortVecs {
state.supply.value = self
.metrics
.supply
.supply
.total
.sats
.height
.read_once(prev_height)?;

View File

@@ -92,7 +92,11 @@ impl CohortMetrics {
/// Get minimum length across height-indexed vectors written in block loop.
pub fn min_stateful_height_len(&self) -> usize {
let mut min = self.supply.min_len().min(self.outputs.min_len()).min(self.activity.min_len());
let mut min = self
.supply
.min_len()
.min(self.outputs.min_len())
.min(self.activity.min_len());
if let Some(realized) = &self.realized {
min = min.min(realized.min_stateful_height_len());
@@ -124,7 +128,8 @@ impl CohortMetrics {
/// Push state values to height-indexed vectors.
pub fn truncate_push(&mut self, height: Height, state: &CohortState) -> Result<()> {
self.supply.truncate_push(height, state.supply.value)?;
self.outputs.truncate_push(height, state.supply.utxo_count)?;
self.outputs
.truncate_push(height, state.supply.utxo_count)?;
self.activity.truncate_push(
height,
state.sent,
@@ -309,8 +314,7 @@ impl CohortMetrics {
) -> Result<()> {
self.supply
.compute_rest_part1(indexes, price, starting_indexes, exit)?;
self.outputs
.compute_rest(indexes, starting_indexes, exit)?;
self.outputs.compute_rest(indexes, starting_indexes, exit)?;
self.activity
.compute_rest_part1(indexes, starting_indexes, exit)?;
@@ -345,7 +349,7 @@ impl CohortMetrics {
indexes,
price,
starting_indexes,
&self.supply.supply.bitcoin.height,
&self.supply.total.bitcoin.height,
height_to_market_cap,
dateindex_to_market_cap,
exit,

View File

@@ -77,14 +77,14 @@ impl RelativeMetrics {
let compute_rel_to_all = cfg.compute_rel_to_all();
// Global sources from "all" cohort
let global_supply_sats_height = all_supply.map(|s| &s.supply.sats.height);
let global_supply_sats_difficultyepoch = all_supply.map(|s| &s.supply.sats.difficultyepoch);
let global_supply_sats_dates = all_supply.map(|s| &s.supply.sats.rest.dates);
let global_supply_sats_dateindex = all_supply.map(|s| &s.supply.sats.rest.dateindex);
let global_market_cap = all_supply.and_then(|s| s.supply.dollars.as_ref());
let global_supply_sats_height = all_supply.map(|s| &s.total.sats.height);
let global_supply_sats_difficultyepoch = all_supply.map(|s| &s.total.sats.difficultyepoch);
let global_supply_sats_dates = all_supply.map(|s| &s.total.sats.rest.dates);
let global_supply_sats_dateindex = all_supply.map(|s| &s.total.sats.rest.dateindex);
let global_market_cap = all_supply.and_then(|s| s.total.dollars.as_ref());
// Own market cap source
let own_market_cap = supply.supply.dollars.as_ref();
let own_market_cap = supply.total.dollars.as_ref();
Ok(Self {
// === Supply Relative to Circulating Supply (lazy from global supply) ===
@@ -94,8 +94,8 @@ impl RelativeMetrics {
LazyBinaryDateLast::from_both_derived_last::<PercentageSatsF64>(
&cfg.name("supply_rel_to_circulating_supply"),
cfg.version + v1,
supply.supply.sats.rest.dateindex.boxed_clone(),
&supply.supply.sats.rest.dates,
supply.total.sats.rest.dateindex.boxed_clone(),
&supply.total.sats.rest.dates,
global_supply_sats_dateindex.unwrap().boxed_clone(),
global_supply_sats_dates.unwrap(),
)
@@ -107,34 +107,34 @@ impl RelativeMetrics {
&cfg.name("supply_in_profit_rel_to_own_supply"),
cfg.version + v1,
unrealized.supply_in_profit.height.boxed_clone(),
supply.supply.sats.height.boxed_clone(),
unrealized.supply_in_profit.difficultyepoch.boxed_clone(),
supply.supply.sats.difficultyepoch.boxed_clone(),
supply.total.sats.height.boxed_clone(),
unrealized.supply_in_profit.difficultyepoch.sats.boxed_clone(),
supply.total.sats.difficultyepoch.boxed_clone(),
unrealized
.supply_in_profit
.indexes
.sats_dateindex
.boxed_clone(),
&unrealized.supply_in_profit.indexes.sats,
supply.supply.sats.rest.dateindex.boxed_clone(),
&supply.supply.sats.rest.dates,
supply.total.sats.rest.dateindex.boxed_clone(),
&supply.total.sats.rest.dates,
),
supply_in_loss_rel_to_own_supply:
LazyBinaryBlockLast::from_height_difficultyepoch_dates::<PercentageSatsF64>(
&cfg.name("supply_in_loss_rel_to_own_supply"),
cfg.version + v1,
unrealized.supply_in_loss.height.boxed_clone(),
supply.supply.sats.height.boxed_clone(),
unrealized.supply_in_loss.difficultyepoch.boxed_clone(),
supply.supply.sats.difficultyepoch.boxed_clone(),
supply.total.sats.height.boxed_clone(),
unrealized.supply_in_loss.difficultyepoch.sats.boxed_clone(),
supply.total.sats.difficultyepoch.boxed_clone(),
unrealized
.supply_in_loss
.indexes
.sats_dateindex
.boxed_clone(),
&unrealized.supply_in_loss.indexes.sats,
supply.supply.sats.rest.dateindex.boxed_clone(),
&supply.supply.sats.rest.dates,
supply.total.sats.rest.dateindex.boxed_clone(),
&supply.total.sats.rest.dates,
),
// === Supply in Profit/Loss Relative to Circulating Supply (lazy from global supply) ===
@@ -146,7 +146,7 @@ impl RelativeMetrics {
cfg.version + v1,
unrealized.supply_in_profit.height.boxed_clone(),
global_supply_sats_height.unwrap().boxed_clone(),
unrealized.supply_in_profit.difficultyepoch.boxed_clone(),
unrealized.supply_in_profit.difficultyepoch.sats.boxed_clone(),
global_supply_sats_difficultyepoch.unwrap().boxed_clone(),
unrealized
.supply_in_profit
@@ -166,7 +166,7 @@ impl RelativeMetrics {
cfg.version + v1,
unrealized.supply_in_loss.height.boxed_clone(),
global_supply_sats_height.unwrap().boxed_clone(),
unrealized.supply_in_loss.difficultyepoch.boxed_clone(),
unrealized.supply_in_loss.difficultyepoch.sats.boxed_clone(),
global_supply_sats_difficultyepoch.unwrap().boxed_clone(),
unrealized
.supply_in_loss

View File

@@ -4,13 +4,13 @@ use brk_types::{Height, Sats, Version};
use crate::ComputeIndexes;
use rayon::prelude::*;
use vecdb::{AnyStoredVec, AnyVec, Exit, GenericStoredVec, IterableCloneableVec};
use vecdb::{AnyStoredVec, AnyVec, Exit, GenericStoredVec};
use crate::{
indexes,
internal::{
HalfClosePriceTimesSats, HalveDollars, HalveSats, HalveSatsToBitcoin, LazyBlockValue,
LazyValueDateLast, ValueBlockLast,
HalfClosePriceTimesSats, HalveDollars, HalveSats, HalveSatsToBitcoin, LazyBinaryLastBlockValue,
ValueBlockLast,
},
price,
};
@@ -20,9 +20,8 @@ use super::ImportConfig;
/// Supply metrics for a cohort.
#[derive(Clone, Traversable)]
pub struct SupplyMetrics {
pub supply: ValueBlockLast,
pub supply_half_value: LazyBlockValue,
pub supply_half: LazyValueDateLast,
pub total: ValueBlockLast,
pub halved: LazyBinaryLastBlockValue,
}
impl SupplyMetrics {
@@ -38,52 +37,39 @@ impl SupplyMetrics {
compute_dollars,
)?;
let price_source = cfg
.price
.map(|p| p.usd.split.close.height.boxed_clone());
// Create lazy supply_half from supply sources
let supply_half_value =
LazyBlockValue::from_sources::<HalveSats, HalveSatsToBitcoin, HalfClosePriceTimesSats>(
&cfg.name("supply_half"),
supply.sats.height.boxed_clone(),
price_source,
cfg.version,
);
let supply_half = LazyValueDateLast::from_block_source::<
let supply_half = LazyBinaryLastBlockValue::from_block_source::<
HalveSats,
HalveSatsToBitcoin,
HalfClosePriceTimesSats,
HalveDollars,
>(&cfg.name("supply_half"), &supply, cfg.version);
>(&cfg.name("supply_half"), &supply, cfg.price, cfg.version);
Ok(Self {
supply,
supply_half_value,
supply_half,
total: supply,
halved: supply_half,
})
}
/// Get minimum length across height-indexed vectors.
pub fn min_len(&self) -> usize {
self.supply.sats.height.len()
self.total.sats.height.len()
}
/// Push supply state values to height-indexed vectors.
pub fn truncate_push(&mut self, height: Height, supply: Sats) -> Result<()> {
self.supply.sats.height.truncate_push(height, supply)?;
self.total.sats.height.truncate_push(height, supply)?;
Ok(())
}
/// Write height-indexed vectors to disk.
pub fn write(&mut self) -> Result<()> {
self.supply.sats.height.write()?;
self.total.sats.height.write()?;
Ok(())
}
/// Returns a parallel iterator over all vecs for parallel writing.
pub fn par_iter_mut(&mut self) -> impl ParallelIterator<Item = &mut dyn AnyStoredVec> {
vec![&mut self.supply.sats.height as &mut dyn AnyStoredVec].into_par_iter()
vec![&mut self.total.sats.height as &mut dyn AnyStoredVec].into_par_iter()
}
/// Validate computed versions against base version.
@@ -99,11 +85,11 @@ impl SupplyMetrics {
others: &[&Self],
exit: &Exit,
) -> Result<()> {
self.supply.sats.height.compute_sum_of_others(
self.total.sats.height.compute_sum_of_others(
starting_indexes.height,
&others
.iter()
.map(|v| &v.supply.sats.height)
.map(|v| &v.total.sats.height)
.collect::<Vec<_>>(),
exit,
)?;
@@ -118,7 +104,7 @@ impl SupplyMetrics {
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
self.supply
self.total
.compute_rest(indexes, price, starting_indexes, exit)
}
}

View File

@@ -297,13 +297,13 @@ impl Vecs {
let supply_metrics = &self.utxo_cohorts.all.metrics.supply;
let height_to_market_cap = supply_metrics
.supply
.total
.dollars
.as_ref()
.map(|d| d.height.clone());
let dateindex_to_market_cap = supply_metrics
.supply
.total
.dollars
.as_ref()
.map(|d| d.dateindex.0.clone());
@@ -373,16 +373,10 @@ fn adjust_for_dateindex_gap(
}
// Get the dateindex at the height we want to resume at
let required_dateindex: usize = indexes
.height
.dateindex
.read_once(height_based_min)?
.into();
let required_dateindex: usize = indexes.height.dateindex.read_once(height_based_min)?.into();
// If dateindex vecs are behind, restart from first height of the missing day
if dateindex_min < required_dateindex
&& dateindex_min < indexes.dateindex.first_height.len()
{
if dateindex_min < required_dateindex && dateindex_min < indexes.dateindex.first_height.len() {
Ok(indexes
.dateindex
.first_height