mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-25 07:09:59 -07:00
website: snapshot
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user