website: snapshot

This commit is contained in:
nym21
2026-01-24 19:22:03 +01:00
parent 9b706dfaee
commit 7cdf47a9e4
33 changed files with 3031 additions and 2132 deletions

View File

@@ -38,8 +38,8 @@ impl UTXOCohorts {
) -> Result<Self> {
let v = version + VERSION;
// Phase 1: Import base cohorts that don't need adjusted (age_range, amount_range, etc.)
// These are the source cohorts for overlapping computations.
// Phase 1: Import base cohorts for overlapping computations (age_range, amount_range).
// These are the source cohorts and must be imported before "all" to provide up_to_1h.
let base = |f: Filter, name: &'static str| {
UTXOCohortVecs::forced_import(
db,
@@ -57,9 +57,6 @@ impl UTXOCohorts {
let age_range = ByAgeRange::try_new(&base)?;
let amount_range = ByAmountRange::try_new(&base)?;
let epoch = ByEpoch::try_new(&base)?;
let year = ByYear::try_new(&base)?;
let type_ = BySpendableType::try_new(&base)?;
// Get up_to_1h realized for adjusted computation (cohort - up_to_1h)
let up_to_1h_realized = age_range.up_to_1h.metrics.realized.as_ref();
@@ -80,7 +77,27 @@ impl UTXOCohorts {
let all_supply = Some(&all.metrics.supply);
// Phase 3: Import cohorts that need adjusted and/or all_supply
// Phase 3: Import cohorts that need all_supply but not adjusted (epoch, year, type)
let base_with_all_supply = |f: Filter, name: &'static str| {
UTXOCohortVecs::forced_import(
db,
f,
name,
v,
indexes,
price,
states_path,
StateLevel::Full,
all_supply,
None,
)
};
let epoch = ByEpoch::try_new(&base_with_all_supply)?;
let year = ByYear::try_new(&base_with_all_supply)?;
let type_ = BySpendableType::try_new(&base_with_all_supply)?;
// Phase 4: Import cohorts that need all_supply and up_to_1h for adjusted
let price_only_adjusted = |f: Filter, name: &'static str| {
UTXOCohortVecs::forced_import(
db,
@@ -115,7 +132,17 @@ impl UTXOCohorts {
let max_age = ByMaxAge::try_new(&none_adjusted)?;
// Phase 4: Import remaining cohorts (no adjusted needed)
// Phase 5: Add rel_to_circulating metrics to base cohorts now that up_to_1h_realized is no longer borrowed
let mut age_range = age_range;
let mut amount_range = amount_range;
for (vecs, name) in age_range.iter_mut().zip(ByAgeRange::names().iter()) {
vecs.add_rel_to_circulating(name.id, v, all_supply.unwrap());
}
for (vecs, name) in amount_range.iter_mut().zip(ByAmountRange::names().iter()) {
vecs.add_rel_to_circulating(name.id, v, all_supply.unwrap());
}
// Phase 6: Import remaining cohorts (no adjusted needed)
let none = |f: Filter, name: &'static str| {
UTXOCohortVecs::forced_import(
db,

View File

@@ -80,6 +80,19 @@ impl UTXOCohortVecs {
})
}
/// Add relative-to-circulating-supply metrics in a second step.
/// Called after the "all" cohort is available.
pub fn add_rel_to_circulating(
&mut self,
name: &str,
version: Version,
all_supply: &SupplyMetrics,
) {
let full_name = CohortContext::Utxo.full_name(self.filter(), name);
self.metrics
.add_rel_to_circulating(&full_name, version, all_supply);
}
/// Get the starting height when state was imported.
pub fn state_starting_height(&self) -> Option<Height> {
self.state_starting_height

View File

@@ -333,6 +333,28 @@ impl CohortMetrics {
Ok(())
}
/// Add relative-to-circulating-supply metrics in a second step.
/// Called after the "all" cohort is available.
pub fn add_rel_to_circulating(
&mut self,
full_name: &str,
version: Version,
all_supply: &SupplyMetrics,
) {
if let (Some(relative), Some(unrealized)) =
(self.relative.as_mut(), self.unrealized.as_ref())
{
relative.add_rel_to_circulating(
&self.filter,
full_name,
version,
unrealized,
&self.supply,
all_supply,
);
}
}
/// Second phase of computed metrics (ratios, relative values).
#[allow(clippy::too_many_arguments)]
pub fn compute_rest_part2(

View File

@@ -1,3 +1,4 @@
use brk_cohort::Filter;
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Dollars, Sats, StoredF32, StoredF64, Version};
@@ -352,4 +353,95 @@ impl RelativeMetrics {
}),
})
}
/// Add relative-to-circulating-supply metrics in a second step.
/// Called after the "all" cohort is available to provide global supply sources.
pub fn add_rel_to_circulating(
&mut self,
filter: &Filter,
full_name: &str,
version: Version,
unrealized: &UnrealizedMetrics,
supply: &SupplyMetrics,
all_supply: &SupplyMetrics,
) {
let v1 = Version::ONE;
// Skip if this is the "all" cohort itself
if !filter.compute_rel_to_all() {
return;
}
let name = |suffix: &str| {
if full_name.is_empty() {
suffix.to_string()
} else {
format!("{full_name}_{suffix}")
}
};
// Global sources from "all" cohort
let global_supply_sats_height = &all_supply.total.sats.height;
let global_supply_sats_difficultyepoch = &all_supply.total.sats.difficultyepoch;
let global_supply_sats_dates = &all_supply.total.sats.rest.dates;
let global_supply_sats_dateindex = &all_supply.total.sats.rest.dateindex;
// Fill in supply_rel_to_circulating_supply if not already set
if self.supply_rel_to_circulating_supply.is_none() {
self.supply_rel_to_circulating_supply = Some(
LazyBinaryFromDateLast::from_both_derived_last::<PercentageSatsF64>(
&name("supply_rel_to_circulating_supply"),
version + v1,
supply.total.sats.rest.dateindex.boxed_clone(),
&supply.total.sats.rest.dates,
global_supply_sats_dateindex.boxed_clone(),
global_supply_sats_dates,
),
);
}
// Fill in supply_in_profit_rel_to_circulating_supply if not already set
if self.supply_in_profit_rel_to_circulating_supply.is_none() {
self.supply_in_profit_rel_to_circulating_supply = Some(
LazyBinaryFromHeightLast::from_height_difficultyepoch_dates::<PercentageSatsF64>(
&name("supply_in_profit_rel_to_circulating_supply"),
version + v1,
unrealized.supply_in_profit.height.boxed_clone(),
global_supply_sats_height.boxed_clone(),
unrealized.supply_in_profit.difficultyepoch.sats.boxed_clone(),
global_supply_sats_difficultyepoch.boxed_clone(),
unrealized
.supply_in_profit
.indexes
.sats_dateindex
.boxed_clone(),
&unrealized.supply_in_profit.indexes.sats,
global_supply_sats_dateindex.boxed_clone(),
global_supply_sats_dates,
),
);
}
// Fill in supply_in_loss_rel_to_circulating_supply if not already set
if self.supply_in_loss_rel_to_circulating_supply.is_none() {
self.supply_in_loss_rel_to_circulating_supply = Some(
LazyBinaryFromHeightLast::from_height_difficultyepoch_dates::<PercentageSatsF64>(
&name("supply_in_loss_rel_to_circulating_supply"),
version + v1,
unrealized.supply_in_loss.height.boxed_clone(),
global_supply_sats_height.boxed_clone(),
unrealized.supply_in_loss.difficultyepoch.sats.boxed_clone(),
global_supply_sats_difficultyepoch.boxed_clone(),
unrealized
.supply_in_loss
.indexes
.sats_dateindex
.boxed_clone(),
&unrealized.supply_in_loss.indexes.sats,
global_supply_sats_dateindex.boxed_clone(),
global_supply_sats_dates,
),
);
}
}
}

View File

@@ -34,6 +34,7 @@ pub struct Vecs {
pub _1w_dominance: LazyBinaryFromHeightLast<StoredF32, StoredU32, StoredU32>,
pub _1m_dominance: LazyBinaryFromHeightLast<StoredF32, StoredU32, StoredU32>,
pub _1y_dominance: LazyBinaryFromHeightLast<StoredF32, StoredU32, StoredU32>,
pub blocks_since_block: ComputedFromHeightLast<StoredU32>,
pub days_since_block: ComputedFromDateLast<StoredU16>,
}
@@ -128,6 +129,12 @@ impl Vecs {
>(&suffix("coinbase"), version, &subsidy, &fee),
subsidy,
fee,
blocks_since_block: ComputedFromHeightLast::forced_import(
db,
&suffix("blocks_since_block"),
version,
indexes,
)?,
days_since_block: ComputedFromDateLast::forced_import(
db,
&suffix("days_since_block"),
@@ -211,6 +218,26 @@ impl Vecs {
self.fee.derive_from(indexes, starting_indexes, exit)?;
self.blocks_since_block
.compute_all(indexes, starting_indexes, exit, |v| {
let mut prev = StoredU32::ZERO;
v.compute_transform(
starting_indexes.height,
blocks_mined_height,
|(h, mined, ..)| {
let blocks = if mined.is_zero() {
prev + StoredU32::ONE
} else {
StoredU32::ZERO
};
prev = blocks;
(h, blocks)
},
exit,
)?;
Ok(())
})?;
self.days_since_block
.compute_all(starting_indexes, exit, |v| {
let mut prev = None;