mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-28 16:49:58 -07:00
global: MASSIVE snapshot
This commit is contained in:
@@ -2,56 +2,27 @@ use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use vecdb::Exit;
|
||||
|
||||
use crate::{ComputeIndexes, indexes, transactions};
|
||||
use crate::{ComputeIndexes, indexes};
|
||||
|
||||
use super::Vecs;
|
||||
|
||||
impl Vecs {
|
||||
pub fn compute(
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
transactions: &transactions::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
// Core block metrics
|
||||
self.interval.compute(indexer, starting_indexes, exit)?;
|
||||
self.count
|
||||
.compute(indexer, indexes, &self.time, starting_indexes, exit)?;
|
||||
self.interval.compute(indexes, starting_indexes, exit)?;
|
||||
self.size
|
||||
.compute(indexer, indexes, starting_indexes, exit)?;
|
||||
self.weight
|
||||
.compute(indexer, indexes, starting_indexes, exit)?;
|
||||
|
||||
// Time metrics (timestamps)
|
||||
self.time.compute(indexes, starting_indexes, exit)?;
|
||||
|
||||
// Epoch metrics
|
||||
.compute(indexer, &self.time, starting_indexes, exit)?;
|
||||
self.size.compute(indexer, starting_indexes, exit)?;
|
||||
self.weight.compute(indexer, starting_indexes, exit)?;
|
||||
self.difficulty
|
||||
.compute(indexer, indexes, starting_indexes, exit)?;
|
||||
self.halving.compute(indexes, starting_indexes, exit)?;
|
||||
|
||||
// Rewards depends on count and transactions fees
|
||||
self.rewards.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
&self.count,
|
||||
&transactions.fees,
|
||||
starting_indexes,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Mining depends on count, difficulty, and rewards
|
||||
self.mining.compute(
|
||||
indexes,
|
||||
&self.count,
|
||||
&self.difficulty,
|
||||
&self.rewards,
|
||||
starting_indexes,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
let _lock = exit.lock();
|
||||
self.db.compact()?;
|
||||
Ok(())
|
||||
|
||||
@@ -1,66 +1,186 @@
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_types::{Height, StoredU32};
|
||||
use vecdb::{EagerVec, Exit, PcoVec, TypedVecIterator};
|
||||
use brk_types::{Height, StoredU32, Timestamp};
|
||||
use vecdb::{EagerVec, Exit, PcoVec, ReadableVec, VecIndex};
|
||||
|
||||
use super::super::time;
|
||||
use super::Vecs;
|
||||
use crate::{ComputeIndexes, indexes, internal::ComputedFromHeightLast};
|
||||
use crate::ComputeIndexes;
|
||||
|
||||
use super::{super::time, Vecs};
|
||||
|
||||
impl Vecs {
|
||||
pub fn compute(
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
time: &time::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.block_count.height.compute_range(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs.blocks.weight,
|
||||
|h| (h, StoredU32::from(1_u32)),
|
||||
exit,
|
||||
)?;
|
||||
self.block_count
|
||||
.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_range(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs.blocks.weight,
|
||||
|h| (h, StoredU32::from(1_u32)),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
.compute_cumulative(starting_indexes, exit)?;
|
||||
|
||||
// Compute rolling window starts
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 1, |s| &mut s._24h_start)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 7, |s| &mut s._1w_start)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 30, |s| &mut s._1m_start)?;
|
||||
self.compute_rolling_start(time, starting_indexes, exit, 365, |s| &mut s._1y_start)?;
|
||||
// Compute rolling window starts (collect monotonic data once for all windows)
|
||||
let monotonic_data: Vec<Timestamp> = time.timestamp_monotonic.collect();
|
||||
self.compute_rolling_start(&monotonic_data, time, starting_indexes, exit, 1, |s| {
|
||||
&mut s.height_24h_ago
|
||||
})?;
|
||||
self.compute_rolling_start(&monotonic_data, time, starting_indexes, exit, 3, |s| {
|
||||
&mut s.height_3d_ago
|
||||
})?;
|
||||
self.compute_rolling_start(&monotonic_data, time, starting_indexes, exit, 7, |s| {
|
||||
&mut s.height_1w_ago
|
||||
})?;
|
||||
self.compute_rolling_start(&monotonic_data, time, starting_indexes, exit, 8, |s| {
|
||||
&mut s.height_8d_ago
|
||||
})?;
|
||||
self.compute_rolling_start(&monotonic_data, time, starting_indexes, exit, 9, |s| {
|
||||
&mut s.height_9d_ago
|
||||
})?;
|
||||
self.compute_rolling_start(&monotonic_data, time, starting_indexes, exit, 12, |s| {
|
||||
&mut s.height_12d_ago
|
||||
})?;
|
||||
self.compute_rolling_start(&monotonic_data, time, starting_indexes, exit, 13, |s| {
|
||||
&mut s.height_13d_ago
|
||||
})?;
|
||||
self.compute_rolling_start(&monotonic_data, time, starting_indexes, exit, 14, |s| {
|
||||
&mut s.height_2w_ago
|
||||
})?;
|
||||
self.compute_rolling_start(&monotonic_data, time, starting_indexes, exit, 21, |s| {
|
||||
&mut s.height_21d_ago
|
||||
})?;
|
||||
self.compute_rolling_start(&monotonic_data, time, starting_indexes, exit, 26, |s| {
|
||||
&mut s.height_26d_ago
|
||||
})?;
|
||||
self.compute_rolling_start(&monotonic_data, time, starting_indexes, exit, 30, |s| {
|
||||
&mut s.height_1m_ago
|
||||
})?;
|
||||
self.compute_rolling_start(&monotonic_data, time, starting_indexes, exit, 34, |s| {
|
||||
&mut s.height_34d_ago
|
||||
})?;
|
||||
self.compute_rolling_start(&monotonic_data, time, starting_indexes, exit, 55, |s| {
|
||||
&mut s.height_55d_ago
|
||||
})?;
|
||||
self.compute_rolling_start(&monotonic_data, time, starting_indexes, exit, 2 * 30, |s| {
|
||||
&mut s.height_2m_ago
|
||||
})?;
|
||||
self.compute_rolling_start(&monotonic_data, time, starting_indexes, exit, 89, |s| {
|
||||
&mut s.height_89d_ago
|
||||
})?;
|
||||
self.compute_rolling_start(&monotonic_data, time, starting_indexes, exit, 3 * 30, |s| {
|
||||
&mut s.height_3m_ago
|
||||
})?;
|
||||
self.compute_rolling_start(&monotonic_data, time, starting_indexes, exit, 111, |s| {
|
||||
&mut s.height_111d_ago
|
||||
})?;
|
||||
self.compute_rolling_start(&monotonic_data, time, starting_indexes, exit, 144, |s| {
|
||||
&mut s.height_144d_ago
|
||||
})?;
|
||||
self.compute_rolling_start(&monotonic_data, time, starting_indexes, exit, 6 * 30, |s| {
|
||||
&mut s.height_6m_ago
|
||||
})?;
|
||||
self.compute_rolling_start(&monotonic_data, time, starting_indexes, exit, 200, |s| {
|
||||
&mut s.height_200d_ago
|
||||
})?;
|
||||
self.compute_rolling_start(&monotonic_data, time, starting_indexes, exit, 350, |s| {
|
||||
&mut s.height_350d_ago
|
||||
})?;
|
||||
self.compute_rolling_start(&monotonic_data, time, starting_indexes, exit, 365, |s| {
|
||||
&mut s.height_1y_ago
|
||||
})?;
|
||||
self.compute_rolling_start(
|
||||
&monotonic_data,
|
||||
time,
|
||||
starting_indexes,
|
||||
exit,
|
||||
2 * 365,
|
||||
|s| &mut s.height_2y_ago,
|
||||
)?;
|
||||
self.compute_rolling_start(
|
||||
&monotonic_data,
|
||||
time,
|
||||
starting_indexes,
|
||||
exit,
|
||||
200 * 7,
|
||||
|s| &mut s.height_200w_ago,
|
||||
)?;
|
||||
self.compute_rolling_start(
|
||||
&monotonic_data,
|
||||
time,
|
||||
starting_indexes,
|
||||
exit,
|
||||
3 * 365,
|
||||
|s| &mut s.height_3y_ago,
|
||||
)?;
|
||||
self.compute_rolling_start(
|
||||
&monotonic_data,
|
||||
time,
|
||||
starting_indexes,
|
||||
exit,
|
||||
4 * 365,
|
||||
|s| &mut s.height_4y_ago,
|
||||
)?;
|
||||
self.compute_rolling_start(
|
||||
&monotonic_data,
|
||||
time,
|
||||
starting_indexes,
|
||||
exit,
|
||||
5 * 365,
|
||||
|s| &mut s.height_5y_ago,
|
||||
)?;
|
||||
self.compute_rolling_start(
|
||||
&monotonic_data,
|
||||
time,
|
||||
starting_indexes,
|
||||
exit,
|
||||
6 * 365,
|
||||
|s| &mut s.height_6y_ago,
|
||||
)?;
|
||||
self.compute_rolling_start(
|
||||
&monotonic_data,
|
||||
time,
|
||||
starting_indexes,
|
||||
exit,
|
||||
8 * 365,
|
||||
|s| &mut s.height_8y_ago,
|
||||
)?;
|
||||
self.compute_rolling_start(
|
||||
&monotonic_data,
|
||||
time,
|
||||
starting_indexes,
|
||||
exit,
|
||||
10 * 365,
|
||||
|s| &mut s.height_10y_ago,
|
||||
)?;
|
||||
|
||||
// Compute rolling window block counts
|
||||
self.compute_rolling_block_count(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
self.block_count_24h_sum.height.compute_transform(
|
||||
starting_indexes.height,
|
||||
&self.height_24h_ago,
|
||||
|(h, start, ..)| (h, StoredU32::from(*h + 1 - *start)),
|
||||
exit,
|
||||
&self._24h_start.clone(),
|
||||
|s| &mut s._24h_block_count,
|
||||
)?;
|
||||
self.compute_rolling_block_count(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
self.block_count_1w_sum.height.compute_transform(
|
||||
starting_indexes.height,
|
||||
&self.height_1w_ago,
|
||||
|(h, start, ..)| (h, StoredU32::from(*h + 1 - *start)),
|
||||
exit,
|
||||
&self._1w_start.clone(),
|
||||
|s| &mut s._1w_block_count,
|
||||
)?;
|
||||
self.compute_rolling_block_count(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
self.block_count_1m_sum.height.compute_transform(
|
||||
starting_indexes.height,
|
||||
&self.height_1m_ago,
|
||||
|(h, start, ..)| (h, StoredU32::from(*h + 1 - *start)),
|
||||
exit,
|
||||
&self._1m_start.clone(),
|
||||
|s| &mut s._1m_block_count,
|
||||
)?;
|
||||
self.compute_rolling_block_count(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
self.block_count_1y_sum.height.compute_transform(
|
||||
starting_indexes.height,
|
||||
&self.height_1y_ago,
|
||||
|(h, start, ..)| (h, StoredU32::from(*h + 1 - *start)),
|
||||
exit,
|
||||
&self._1y_start.clone(),
|
||||
|s| &mut s._1y_block_count,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
@@ -68,6 +188,7 @@ impl Vecs {
|
||||
|
||||
fn compute_rolling_start<F>(
|
||||
&mut self,
|
||||
monotonic_data: &[Timestamp],
|
||||
time: &time::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
@@ -77,13 +198,12 @@ impl Vecs {
|
||||
where
|
||||
F: FnOnce(&mut Self) -> &mut EagerVec<PcoVec<Height, Height>>,
|
||||
{
|
||||
let mut iter = time.timestamp_monotonic.into_iter();
|
||||
let mut prev = Height::ZERO;
|
||||
Ok(get_field(self).compute_transform(
|
||||
starting_indexes.height,
|
||||
&time.timestamp_monotonic,
|
||||
|(h, t, ..)| {
|
||||
while t.difference_in_days_between(iter.get_unwrap(prev)) >= days {
|
||||
while t.difference_in_days_between(monotonic_data[prev.to_usize()]) >= days {
|
||||
prev.increment();
|
||||
if prev > h {
|
||||
unreachable!()
|
||||
@@ -94,26 +214,4 @@ impl Vecs {
|
||||
exit,
|
||||
)?)
|
||||
}
|
||||
|
||||
fn compute_rolling_block_count<F>(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
start_height: &EagerVec<PcoVec<Height, Height>>,
|
||||
get_field: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnOnce(&mut Self) -> &mut ComputedFromHeightLast<StoredU32>,
|
||||
{
|
||||
get_field(self).compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_transform(
|
||||
starting_indexes.height,
|
||||
start_height,
|
||||
|(h, start, ..)| (h, StoredU32::from(*h + 1 - *start)),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,59 +1,78 @@
|
||||
use brk_error::Result;
|
||||
use brk_types::{StoredU64, Version};
|
||||
use brk_types::Version;
|
||||
use vecdb::{Database, ImportableVec};
|
||||
|
||||
use super::Vecs;
|
||||
use crate::{
|
||||
blocks::{
|
||||
TARGET_BLOCKS_PER_DAY, TARGET_BLOCKS_PER_DECADE, TARGET_BLOCKS_PER_MONTH,
|
||||
TARGET_BLOCKS_PER_QUARTER, TARGET_BLOCKS_PER_SEMESTER, TARGET_BLOCKS_PER_WEEK,
|
||||
TARGET_BLOCKS_PER_YEAR,
|
||||
},
|
||||
indexes,
|
||||
internal::{ComputedFromHeightLast, ComputedFromHeightSumCum, LazyFromDate},
|
||||
internal::{BlockCountTarget, ComputedFromHeightLast, ComputedFromHeightSumCum, ConstantVecs},
|
||||
};
|
||||
|
||||
impl Vecs {
|
||||
pub fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
|
||||
pub(crate) fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
|
||||
Ok(Self {
|
||||
block_count_target: LazyFromDate::new(
|
||||
block_count_target: ConstantVecs::new::<BlockCountTarget>(
|
||||
"block_count_target",
|
||||
version,
|
||||
indexes,
|
||||
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_DAY)),
|
||||
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_WEEK)),
|
||||
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_MONTH)),
|
||||
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_QUARTER)),
|
||||
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_SEMESTER)),
|
||||
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_YEAR)),
|
||||
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_DECADE)),
|
||||
),
|
||||
block_count: ComputedFromHeightSumCum::forced_import(db, "block_count", version, indexes)?,
|
||||
_24h_start: ImportableVec::forced_import(db, "24h_start", version)?,
|
||||
_1w_start: ImportableVec::forced_import(db, "1w_start", version)?,
|
||||
_1m_start: ImportableVec::forced_import(db, "1m_start", version)?,
|
||||
_1y_start: ImportableVec::forced_import(db, "1y_start", version)?,
|
||||
_24h_block_count: ComputedFromHeightLast::forced_import(
|
||||
block_count: ComputedFromHeightSumCum::forced_import(
|
||||
db,
|
||||
"24h_block_count",
|
||||
"block_count",
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
_1w_block_count: ComputedFromHeightLast::forced_import(
|
||||
height_24h_ago: ImportableVec::forced_import(db, "height_24h_ago", version)?,
|
||||
height_3d_ago: ImportableVec::forced_import(db, "height_3d_ago", version)?,
|
||||
height_1w_ago: ImportableVec::forced_import(db, "height_1w_ago", version)?,
|
||||
height_8d_ago: ImportableVec::forced_import(db, "height_8d_ago", version)?,
|
||||
height_9d_ago: ImportableVec::forced_import(db, "height_9d_ago", version)?,
|
||||
height_12d_ago: ImportableVec::forced_import(db, "height_12d_ago", version)?,
|
||||
height_13d_ago: ImportableVec::forced_import(db, "height_13d_ago", version)?,
|
||||
height_2w_ago: ImportableVec::forced_import(db, "height_2w_ago", version)?,
|
||||
height_21d_ago: ImportableVec::forced_import(db, "height_21d_ago", version)?,
|
||||
height_26d_ago: ImportableVec::forced_import(db, "height_26d_ago", version)?,
|
||||
height_1m_ago: ImportableVec::forced_import(db, "height_1m_ago", version)?,
|
||||
height_34d_ago: ImportableVec::forced_import(db, "height_34d_ago", version)?,
|
||||
height_55d_ago: ImportableVec::forced_import(db, "height_55d_ago", version)?,
|
||||
height_2m_ago: ImportableVec::forced_import(db, "height_2m_ago", version)?,
|
||||
height_89d_ago: ImportableVec::forced_import(db, "height_89d_ago", version)?,
|
||||
height_111d_ago: ImportableVec::forced_import(db, "height_111d_ago", version)?,
|
||||
height_144d_ago: ImportableVec::forced_import(db, "height_144d_ago", version)?,
|
||||
height_3m_ago: ImportableVec::forced_import(db, "height_3m_ago", version)?,
|
||||
height_6m_ago: ImportableVec::forced_import(db, "height_6m_ago", version)?,
|
||||
height_200d_ago: ImportableVec::forced_import(db, "height_200d_ago", version)?,
|
||||
height_350d_ago: ImportableVec::forced_import(db, "height_350d_ago", version)?,
|
||||
height_1y_ago: ImportableVec::forced_import(db, "height_1y_ago", version)?,
|
||||
height_2y_ago: ImportableVec::forced_import(db, "height_2y_ago", version)?,
|
||||
height_200w_ago: ImportableVec::forced_import(db, "height_200w_ago", version)?,
|
||||
height_3y_ago: ImportableVec::forced_import(db, "height_3y_ago", version)?,
|
||||
height_4y_ago: ImportableVec::forced_import(db, "height_4y_ago", version)?,
|
||||
height_5y_ago: ImportableVec::forced_import(db, "height_5y_ago", version)?,
|
||||
height_6y_ago: ImportableVec::forced_import(db, "height_6y_ago", version)?,
|
||||
height_8y_ago: ImportableVec::forced_import(db, "height_8y_ago", version)?,
|
||||
height_10y_ago: ImportableVec::forced_import(db, "height_10y_ago", version)?,
|
||||
block_count_24h_sum: ComputedFromHeightLast::forced_import(
|
||||
db,
|
||||
"1w_block_count",
|
||||
"block_count_24h_sum",
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
_1m_block_count: ComputedFromHeightLast::forced_import(
|
||||
block_count_1w_sum: ComputedFromHeightLast::forced_import(
|
||||
db,
|
||||
"1m_block_count",
|
||||
"block_count_1w_sum",
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
_1y_block_count: ComputedFromHeightLast::forced_import(
|
||||
block_count_1m_sum: ComputedFromHeightLast::forced_import(
|
||||
db,
|
||||
"1y_block_count",
|
||||
"block_count_1m_sum",
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
block_count_1y_sum: ComputedFromHeightLast::forced_import(
|
||||
db,
|
||||
"block_count_1y_sum",
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
|
||||
@@ -1,21 +1,85 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, StoredU32, StoredU64};
|
||||
use vecdb::{EagerVec, PcoVec};
|
||||
use vecdb::{EagerVec, PcoVec, Rw, StorageMode};
|
||||
|
||||
use crate::internal::{ComputedFromHeightLast, ComputedFromHeightSumCum, LazyFromDate};
|
||||
use crate::internal::{ComputedFromHeightLast, ComputedFromHeightSumCum, ConstantVecs};
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct Vecs {
|
||||
pub block_count_target: LazyFromDate<StoredU64>,
|
||||
pub block_count: ComputedFromHeightSumCum<StoredU32>,
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
pub block_count_target: ConstantVecs<StoredU64>,
|
||||
pub block_count: ComputedFromHeightSumCum<StoredU32, M>,
|
||||
// Rolling window starts (height-indexed only, no date aggregation needed)
|
||||
pub _24h_start: EagerVec<PcoVec<Height, Height>>,
|
||||
pub _1w_start: EagerVec<PcoVec<Height, Height>>,
|
||||
pub _1m_start: EagerVec<PcoVec<Height, Height>>,
|
||||
pub _1y_start: EagerVec<PcoVec<Height, Height>>,
|
||||
pub height_24h_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_3d_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_1w_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_8d_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_9d_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_12d_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_13d_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_2w_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_21d_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_26d_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_1m_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_34d_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_55d_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_2m_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_89d_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_111d_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_144d_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_3m_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_6m_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_200d_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_350d_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_1y_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_2y_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_200w_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_3y_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_4y_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_5y_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_6y_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_8y_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
pub height_10y_ago: M::Stored<EagerVec<PcoVec<Height, Height>>>,
|
||||
// Rolling window block counts
|
||||
pub _24h_block_count: ComputedFromHeightLast<StoredU32>,
|
||||
pub _1w_block_count: ComputedFromHeightLast<StoredU32>,
|
||||
pub _1m_block_count: ComputedFromHeightLast<StoredU32>,
|
||||
pub _1y_block_count: ComputedFromHeightLast<StoredU32>,
|
||||
pub block_count_24h_sum: ComputedFromHeightLast<StoredU32, M>,
|
||||
pub block_count_1w_sum: ComputedFromHeightLast<StoredU32, M>,
|
||||
pub block_count_1m_sum: ComputedFromHeightLast<StoredU32, M>,
|
||||
pub block_count_1y_sum: ComputedFromHeightLast<StoredU32, M>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
pub fn start_vec(&self, days: usize) -> &EagerVec<PcoVec<Height, Height>> {
|
||||
match days {
|
||||
1 => &self.height_24h_ago,
|
||||
3 => &self.height_3d_ago,
|
||||
7 => &self.height_1w_ago,
|
||||
8 => &self.height_8d_ago,
|
||||
9 => &self.height_9d_ago,
|
||||
12 => &self.height_12d_ago,
|
||||
13 => &self.height_13d_ago,
|
||||
14 => &self.height_2w_ago,
|
||||
21 => &self.height_21d_ago,
|
||||
26 => &self.height_26d_ago,
|
||||
30 => &self.height_1m_ago,
|
||||
34 => &self.height_34d_ago,
|
||||
55 => &self.height_55d_ago,
|
||||
60 => &self.height_2m_ago,
|
||||
89 => &self.height_89d_ago,
|
||||
90 => &self.height_3m_ago,
|
||||
111 => &self.height_111d_ago,
|
||||
144 => &self.height_144d_ago,
|
||||
180 => &self.height_6m_ago,
|
||||
200 => &self.height_200d_ago,
|
||||
350 => &self.height_350d_ago,
|
||||
365 => &self.height_1y_ago,
|
||||
730 => &self.height_2y_ago,
|
||||
1095 => &self.height_3y_ago,
|
||||
1400 => &self.height_200w_ago,
|
||||
1460 => &self.height_4y_ago,
|
||||
1825 => &self.height_5y_ago,
|
||||
2190 => &self.height_6y_ago,
|
||||
2920 => &self.height_8y_ago,
|
||||
3650 => &self.height_10y_ago,
|
||||
_ => panic!("No start vec for {days} days"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,102 +1,61 @@
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_types::{StoredF32, StoredU32};
|
||||
use vecdb::{Exit, TypedVecIterator};
|
||||
use vecdb::Exit;
|
||||
|
||||
use super::super::TARGET_BLOCKS_PER_DAY_F32;
|
||||
use super::Vecs;
|
||||
use crate::{ComputeIndexes, indexes};
|
||||
|
||||
impl Vecs {
|
||||
pub fn compute(
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
// Derive dateindex/period stats from raw difficulty
|
||||
self.raw.derive_from(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
// raw is fully lazy from indexer height source — no compute needed
|
||||
|
||||
// Compute difficulty as hash rate equivalent
|
||||
let multiplier = 2.0_f64.powi(32) / 600.0;
|
||||
self.as_hash.height.compute_transform(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs.blocks.difficulty,
|
||||
|(i, v, ..)| (i, StoredF32::from(*v * multiplier)),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Compute difficulty as hash rate equivalent
|
||||
self.as_hash
|
||||
.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
let multiplier = 2.0_f64.powi(32) / 600.0;
|
||||
v.compute_transform(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs.blocks.difficulty,
|
||||
|(i, v, ..)| (i, StoredF32::from(*v * multiplier)),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// Compute difficulty adjustment percentage
|
||||
self.adjustment
|
||||
.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_percentage_change(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs.blocks.difficulty,
|
||||
1,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
self.adjustment.height.compute_percentage_change(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs.blocks.difficulty,
|
||||
1,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Compute epoch by dateindex
|
||||
let mut height_to_difficultyepoch_iter = indexes.height.difficultyepoch.into_iter();
|
||||
self.epoch.compute_all(starting_indexes, exit, |vec| {
|
||||
let mut height_count_iter = indexes.dateindex.height_count.into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
&indexes.dateindex.first_height,
|
||||
|(di, height, ..)| {
|
||||
(
|
||||
di,
|
||||
height_to_difficultyepoch_iter
|
||||
.get_unwrap(height + (*height_count_iter.get_unwrap(di) - 1)),
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
// Compute epoch by height
|
||||
self.epoch.height.compute_transform(
|
||||
starting_indexes.height,
|
||||
&indexes.height.difficultyepoch,
|
||||
|(h, epoch, ..)| (h, epoch),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Compute blocks before next adjustment
|
||||
self.blocks_before_next_adjustment.compute_all(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
self.blocks_before_next_adjustment.height.compute_transform(
|
||||
starting_indexes.height,
|
||||
&indexes.height.identity,
|
||||
|(h, ..)| (h, StoredU32::from(h.left_before_next_diff_adj())),
|
||||
exit,
|
||||
|v| {
|
||||
v.compute_transform(
|
||||
starting_indexes.height,
|
||||
&indexes.height.identity,
|
||||
|(h, ..)| (h, StoredU32::from(h.left_before_next_diff_adj())),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
// Compute days before next adjustment
|
||||
self.days_before_next_adjustment.compute_all(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
self.days_before_next_adjustment.height.compute_transform(
|
||||
starting_indexes.height,
|
||||
&self.blocks_before_next_adjustment.height,
|
||||
|(h, blocks, ..)| (h, (*blocks as f32 / TARGET_BLOCKS_PER_DAY_F32).into()),
|
||||
exit,
|
||||
|v| {
|
||||
v.compute_transform(
|
||||
starting_indexes.height,
|
||||
&self.blocks_before_next_adjustment.height,
|
||||
|(h, blocks, ..)| (h, (*blocks as f32 / TARGET_BLOCKS_PER_DAY_F32).into()),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_types::Version;
|
||||
use vecdb::{Database, IterableCloneableVec};
|
||||
use vecdb::{Database, ReadableCloneableVec};
|
||||
|
||||
use super::Vecs;
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{
|
||||
ComputedFromHeightLast, ComputedFromHeightSum, ComputedFromDateLast,
|
||||
ComputedHeightDerivedLast,
|
||||
},
|
||||
internal::{ComputedFromHeightLast, ComputedFromHeightSum, ComputedHeightDerivedLast},
|
||||
};
|
||||
|
||||
impl Vecs {
|
||||
pub fn forced_import(
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
version: Version,
|
||||
indexer: &Indexer,
|
||||
@@ -23,15 +20,14 @@ impl Vecs {
|
||||
|
||||
Ok(Self {
|
||||
raw: ComputedHeightDerivedLast::forced_import(
|
||||
db,
|
||||
"difficulty",
|
||||
indexer.vecs.blocks.difficulty.boxed_clone(),
|
||||
indexer.vecs.blocks.difficulty.read_only_boxed_clone(),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
),
|
||||
as_hash: ComputedFromHeightLast::forced_import(db, "difficulty_as_hash", version, indexes)?,
|
||||
adjustment: ComputedFromHeightSum::forced_import(db, "difficulty_adjustment", version, indexes)?,
|
||||
epoch: ComputedFromDateLast::forced_import(db, "difficultyepoch", version, indexes)?,
|
||||
epoch: ComputedFromHeightLast::forced_import(db, "difficulty_epoch", version, indexes)?,
|
||||
blocks_before_next_adjustment: ComputedFromHeightLast::forced_import(
|
||||
db,
|
||||
"blocks_before_next_difficulty_adjustment",
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DifficultyEpoch, StoredF32, StoredF64, StoredU32};
|
||||
use vecdb::{Rw, StorageMode};
|
||||
|
||||
use crate::internal::{
|
||||
ComputedFromHeightLast, ComputedFromHeightSum, ComputedFromDateLast, ComputedHeightDerivedLast,
|
||||
};
|
||||
use crate::internal::{ComputedFromHeightLast, ComputedFromHeightSum, ComputedHeightDerivedLast};
|
||||
|
||||
/// Difficulty metrics: raw difficulty, derived stats, adjustment, and countdown
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct Vecs {
|
||||
/// Raw difficulty with dateindex/period stats - merges with indexer's raw
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
/// Raw difficulty with day1/period stats - merges with indexer's raw
|
||||
pub raw: ComputedHeightDerivedLast<StoredF64>,
|
||||
pub as_hash: ComputedFromHeightLast<StoredF32>,
|
||||
pub adjustment: ComputedFromHeightSum<StoredF32>,
|
||||
pub epoch: ComputedFromDateLast<DifficultyEpoch>,
|
||||
pub blocks_before_next_adjustment: ComputedFromHeightLast<StoredU32>,
|
||||
pub days_before_next_adjustment: ComputedFromHeightLast<StoredF32>,
|
||||
pub as_hash: ComputedFromHeightLast<StoredF32, M>,
|
||||
pub adjustment: ComputedFromHeightSum<StoredF32, M>,
|
||||
pub epoch: ComputedFromHeightLast<DifficultyEpoch, M>,
|
||||
pub blocks_before_next_adjustment: ComputedFromHeightLast<StoredU32, M>,
|
||||
pub days_before_next_adjustment: ComputedFromHeightLast<StoredF32, M>,
|
||||
}
|
||||
|
||||
@@ -1,57 +1,38 @@
|
||||
use brk_error::Result;
|
||||
use brk_types::StoredU32;
|
||||
use vecdb::{Exit, TypedVecIterator};
|
||||
use vecdb::Exit;
|
||||
|
||||
use super::super::TARGET_BLOCKS_PER_DAY_F32;
|
||||
use super::Vecs;
|
||||
use crate::{ComputeIndexes, indexes};
|
||||
|
||||
impl Vecs {
|
||||
pub fn compute(
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let mut height_to_halvingepoch_iter = indexes.height.halvingepoch.into_iter();
|
||||
self.epoch.compute_all(starting_indexes, exit, |vec| {
|
||||
let mut height_count_iter = indexes.dateindex.height_count.into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
&indexes.dateindex.first_height,
|
||||
|(di, height, ..)| {
|
||||
(
|
||||
di,
|
||||
height_to_halvingepoch_iter
|
||||
.get_unwrap(height + (*height_count_iter.get_unwrap(di) - 1)),
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
self.epoch.height.compute_transform(
|
||||
starting_indexes.height,
|
||||
&indexes.height.halvingepoch,
|
||||
|(h, epoch, ..)| (h, epoch),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.blocks_before_next_halving
|
||||
.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_transform(
|
||||
starting_indexes.height,
|
||||
&indexes.height.identity,
|
||||
|(h, ..)| (h, StoredU32::from(h.left_before_next_halving())),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
self.blocks_before_next_halving.height.compute_transform(
|
||||
starting_indexes.height,
|
||||
&indexes.height.identity,
|
||||
|(h, ..)| (h, StoredU32::from(h.left_before_next_halving())),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.days_before_next_halving
|
||||
.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_transform(
|
||||
starting_indexes.height,
|
||||
&self.blocks_before_next_halving.height,
|
||||
|(h, blocks, ..)| (h, (*blocks as f32 / TARGET_BLOCKS_PER_DAY_F32).into()),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
self.days_before_next_halving.height.compute_transform(
|
||||
starting_indexes.height,
|
||||
&self.blocks_before_next_halving.height,
|
||||
|(h, blocks, ..)| (h, (*blocks as f32 / TARGET_BLOCKS_PER_DAY_F32).into()),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -3,17 +3,18 @@ use brk_types::Version;
|
||||
use vecdb::Database;
|
||||
|
||||
use super::Vecs;
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{ComputedFromHeightLast, ComputedFromDateLast},
|
||||
};
|
||||
use crate::{indexes, internal::ComputedFromHeightLast};
|
||||
|
||||
impl Vecs {
|
||||
pub fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let v2 = Version::TWO;
|
||||
|
||||
Ok(Self {
|
||||
epoch: ComputedFromDateLast::forced_import(db, "halvingepoch", version, indexes)?,
|
||||
epoch: ComputedFromHeightLast::forced_import(db, "halving_epoch", version, indexes)?,
|
||||
blocks_before_next_halving: ComputedFromHeightLast::forced_import(
|
||||
db,
|
||||
"blocks_before_next_halving",
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{HalvingEpoch, StoredF32, StoredU32};
|
||||
use vecdb::{Rw, StorageMode};
|
||||
|
||||
use crate::internal::{ComputedFromHeightLast, ComputedFromDateLast};
|
||||
use crate::internal::ComputedFromHeightLast;
|
||||
|
||||
/// Halving epoch metrics and countdown
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct Vecs {
|
||||
pub epoch: ComputedFromDateLast<HalvingEpoch>,
|
||||
pub blocks_before_next_halving: ComputedFromHeightLast<StoredU32>,
|
||||
pub days_before_next_halving: ComputedFromHeightLast<StoredF32>,
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
pub epoch: ComputedFromHeightLast<HalvingEpoch, M>,
|
||||
pub blocks_before_next_halving: ComputedFromHeightLast<StoredU32, M>,
|
||||
pub days_before_next_halving: ComputedFromHeightLast<StoredF32, M>,
|
||||
}
|
||||
|
||||
@@ -6,20 +6,19 @@ use brk_traversable::Traversable;
|
||||
use brk_types::Version;
|
||||
use vecdb::{Database, PAGE_SIZE};
|
||||
|
||||
use crate::{indexes, price};
|
||||
use crate::indexes;
|
||||
|
||||
use super::{
|
||||
CountVecs, DifficultyVecs, HalvingVecs, IntervalVecs, MiningVecs, RewardsVecs, SizeVecs,
|
||||
CountVecs, DifficultyVecs, HalvingVecs, IntervalVecs, SizeVecs,
|
||||
TimeVecs, Vecs, WeightVecs,
|
||||
};
|
||||
|
||||
impl Vecs {
|
||||
pub fn forced_import(
|
||||
pub(crate) fn forced_import(
|
||||
parent_path: &Path,
|
||||
parent_version: Version,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
) -> Result<Self> {
|
||||
let db = Database::open(&parent_path.join(super::DB_NAME))?;
|
||||
db.set_min_len(PAGE_SIZE * 50_000_000)?;
|
||||
@@ -27,12 +26,10 @@ impl Vecs {
|
||||
let version = parent_version;
|
||||
|
||||
let count = CountVecs::forced_import(&db, version, indexes)?;
|
||||
let interval = IntervalVecs::forced_import(&db, version, indexer, indexes)?;
|
||||
let interval = IntervalVecs::forced_import(&db, version, indexes)?;
|
||||
let size = SizeVecs::forced_import(&db, version, indexer, indexes)?;
|
||||
let weight = WeightVecs::forced_import(&db, version, indexer, indexes)?;
|
||||
let time = TimeVecs::forced_import(&db, version, indexer, indexes)?;
|
||||
let mining = MiningVecs::forced_import(&db, version, indexes)?;
|
||||
let rewards = RewardsVecs::forced_import(&db, version, indexes, price)?;
|
||||
let difficulty = DifficultyVecs::forced_import(&db, version, indexer, indexes)?;
|
||||
let halving = HalvingVecs::forced_import(&db, version, indexes)?;
|
||||
|
||||
@@ -43,8 +40,6 @@ impl Vecs {
|
||||
size,
|
||||
weight,
|
||||
time,
|
||||
mining,
|
||||
rewards,
|
||||
difficulty,
|
||||
halving,
|
||||
};
|
||||
|
||||
@@ -1,18 +1,36 @@
|
||||
use brk_error::Result;
|
||||
use vecdb::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_types::{CheckedSub, Timestamp};
|
||||
use vecdb::{Exit, ReadableVec};
|
||||
|
||||
use super::Vecs;
|
||||
use crate::{ComputeIndexes, indexes};
|
||||
use crate::ComputeIndexes;
|
||||
|
||||
impl Vecs {
|
||||
pub fn compute(
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
indexer: &Indexer,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.interval.derive_from(indexes, starting_indexes, exit)?;
|
||||
|
||||
let mut prev_timestamp = None;
|
||||
self.interval.height.compute_transform(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs.blocks.timestamp,
|
||||
|(h, timestamp, ..)| {
|
||||
let interval = if let Some(prev_h) = h.decremented() {
|
||||
let prev = prev_timestamp.unwrap_or_else(|| {
|
||||
indexer.vecs.blocks.timestamp.collect_one(prev_h).unwrap()
|
||||
});
|
||||
timestamp.checked_sub(prev).unwrap_or(Timestamp::ZERO)
|
||||
} else {
|
||||
Timestamp::ZERO
|
||||
};
|
||||
prev_timestamp = Some(timestamp);
|
||||
(h, interval)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,21 @@
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_types::{CheckedSub, Height, Timestamp, Version};
|
||||
use vecdb::{Database, VecIndex};
|
||||
use brk_types::Version;
|
||||
use vecdb::Database;
|
||||
|
||||
use super::Vecs;
|
||||
use crate::{indexes, internal::LazyFromHeightDistribution};
|
||||
use crate::{indexes, internal::ComputedFromHeightDistribution};
|
||||
|
||||
impl Vecs {
|
||||
pub fn forced_import(
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
version: Version,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let interval = LazyFromHeightDistribution::forced_import_with_init(
|
||||
let interval = ComputedFromHeightDistribution::forced_import(
|
||||
db,
|
||||
"block_interval",
|
||||
version,
|
||||
indexer.vecs.blocks.timestamp.clone(),
|
||||
indexes,
|
||||
|height: Height, timestamp_iter| {
|
||||
let timestamp = timestamp_iter.get_at(height.to_usize())?;
|
||||
let interval = height.decremented().map_or(Timestamp::ZERO, |prev_h| {
|
||||
timestamp_iter
|
||||
.get_at(prev_h.to_usize())
|
||||
.map_or(Timestamp::ZERO, |prev_t| {
|
||||
timestamp.checked_sub(prev_t).unwrap_or(Timestamp::ZERO)
|
||||
})
|
||||
});
|
||||
Some(interval)
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(Self { interval })
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::Timestamp;
|
||||
use vecdb::{Rw, StorageMode};
|
||||
|
||||
use crate::internal::LazyFromHeightDistribution;
|
||||
use crate::internal::ComputedFromHeightDistribution;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct Vecs {
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
#[traversable(flatten)]
|
||||
pub interval: LazyFromHeightDistribution<Timestamp>,
|
||||
pub interval: ComputedFromHeightDistribution<Timestamp, M>,
|
||||
}
|
||||
|
||||
@@ -1,234 +0,0 @@
|
||||
use brk_error::Result;
|
||||
use brk_types::{StoredF32, StoredF64};
|
||||
use vecdb::Exit;
|
||||
|
||||
use super::super::{ONE_TERA_HASH, TARGET_BLOCKS_PER_DAY_F64, count, difficulty, rewards};
|
||||
use super::Vecs;
|
||||
use crate::{ComputeIndexes, indexes, traits::ComputeDrawdown};
|
||||
|
||||
impl Vecs {
|
||||
pub fn compute(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
count_vecs: &count::Vecs,
|
||||
difficulty_vecs: &difficulty::Vecs,
|
||||
rewards_vecs: &rewards::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.hash_rate
|
||||
.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_transform2(
|
||||
starting_indexes.height,
|
||||
&count_vecs._24h_block_count.height,
|
||||
&difficulty_vecs.as_hash.height,
|
||||
|(i, block_count_sum, difficulty_as_hash, ..)| {
|
||||
(
|
||||
i,
|
||||
StoredF64::from(
|
||||
(f64::from(block_count_sum) / TARGET_BLOCKS_PER_DAY_F64)
|
||||
* f64::from(difficulty_as_hash),
|
||||
),
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.hash_rate_1w_sma
|
||||
.compute_all(starting_indexes, exit, |v| {
|
||||
v.compute_sma(
|
||||
starting_indexes.dateindex,
|
||||
self.hash_rate.dateindex.inner(),
|
||||
7,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.hash_rate_1m_sma
|
||||
.compute_all(starting_indexes, exit, |v| {
|
||||
v.compute_sma(
|
||||
starting_indexes.dateindex,
|
||||
self.hash_rate.dateindex.inner(),
|
||||
30,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.hash_rate_2m_sma
|
||||
.compute_all(starting_indexes, exit, |v| {
|
||||
v.compute_sma(
|
||||
starting_indexes.dateindex,
|
||||
self.hash_rate.dateindex.inner(),
|
||||
2 * 30,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.hash_rate_1y_sma
|
||||
.compute_all(starting_indexes, exit, |v| {
|
||||
v.compute_sma(
|
||||
starting_indexes.dateindex,
|
||||
self.hash_rate.dateindex.inner(),
|
||||
365,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.hash_rate_ath
|
||||
.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_all_time_high(
|
||||
starting_indexes.height,
|
||||
&self.hash_rate.height,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.hash_rate_drawdown
|
||||
.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_drawdown(
|
||||
starting_indexes.height,
|
||||
&self.hash_rate.height,
|
||||
&self.hash_rate_ath.height,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.hash_price_ths
|
||||
.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_transform2(
|
||||
starting_indexes.height,
|
||||
rewards_vecs._24h_coinbase_sum.dollars.as_ref().unwrap(),
|
||||
&self.hash_rate.height,
|
||||
|(i, coinbase_sum, hashrate, ..)| {
|
||||
let hashrate_ths = *hashrate / ONE_TERA_HASH;
|
||||
let price = if hashrate_ths == 0.0 {
|
||||
StoredF32::NAN
|
||||
} else {
|
||||
(*coinbase_sum / hashrate_ths).into()
|
||||
};
|
||||
(i, price)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.hash_price_phs
|
||||
.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_transform(
|
||||
starting_indexes.height,
|
||||
&self.hash_price_ths.height,
|
||||
|(i, price, ..)| (i, (*price * 1000.0).into()),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.hash_value_ths
|
||||
.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_transform2(
|
||||
starting_indexes.height,
|
||||
&rewards_vecs._24h_coinbase_sum.sats,
|
||||
&self.hash_rate.height,
|
||||
|(i, coinbase_sum, hashrate, ..)| {
|
||||
let hashrate_ths = *hashrate / ONE_TERA_HASH;
|
||||
let value = if hashrate_ths == 0.0 {
|
||||
StoredF32::NAN
|
||||
} else {
|
||||
StoredF32::from(*coinbase_sum as f64 / hashrate_ths)
|
||||
};
|
||||
(i, value)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.hash_value_phs
|
||||
.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_transform(
|
||||
starting_indexes.height,
|
||||
&self.hash_value_ths.height,
|
||||
|(i, value, ..)| (i, (*value * 1000.0).into()),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.hash_price_ths_min
|
||||
.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_all_time_low_(
|
||||
starting_indexes.height,
|
||||
&self.hash_price_ths.height,
|
||||
exit,
|
||||
true,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.hash_price_phs_min
|
||||
.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_all_time_low_(
|
||||
starting_indexes.height,
|
||||
&self.hash_price_phs.height,
|
||||
exit,
|
||||
true,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.hash_value_ths_min
|
||||
.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_all_time_low_(
|
||||
starting_indexes.height,
|
||||
&self.hash_value_ths.height,
|
||||
exit,
|
||||
true,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.hash_value_phs_min
|
||||
.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_all_time_low_(
|
||||
starting_indexes.height,
|
||||
&self.hash_value_phs.height,
|
||||
exit,
|
||||
true,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.hash_price_rebound
|
||||
.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_percentage_difference(
|
||||
starting_indexes.height,
|
||||
&self.hash_price_phs.height,
|
||||
&self.hash_price_phs_min.height,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.hash_value_rebound
|
||||
.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_percentage_difference(
|
||||
starting_indexes.height,
|
||||
&self.hash_value_phs.height,
|
||||
&self.hash_value_phs_min.height,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
use brk_error::Result;
|
||||
use brk_types::Version;
|
||||
use vecdb::Database;
|
||||
|
||||
use super::Vecs;
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{ComputedFromHeightLast, ComputedFromDateLast},
|
||||
};
|
||||
|
||||
impl Vecs {
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let v4 = Version::new(4);
|
||||
let v5 = Version::new(5);
|
||||
|
||||
Ok(Self {
|
||||
hash_rate: ComputedFromHeightLast::forced_import(db, "hash_rate", version + v5, indexes)?,
|
||||
hash_rate_1w_sma: ComputedFromDateLast::forced_import(
|
||||
db,
|
||||
"hash_rate_1w_sma",
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
hash_rate_1m_sma: ComputedFromDateLast::forced_import(
|
||||
db,
|
||||
"hash_rate_1m_sma",
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
hash_rate_2m_sma: ComputedFromDateLast::forced_import(
|
||||
db,
|
||||
"hash_rate_2m_sma",
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
hash_rate_1y_sma: ComputedFromDateLast::forced_import(
|
||||
db,
|
||||
"hash_rate_1y_sma",
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
hash_rate_ath: ComputedFromHeightLast::forced_import(
|
||||
db,
|
||||
"hash_rate_ath",
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
hash_rate_drawdown: ComputedFromHeightLast::forced_import(
|
||||
db,
|
||||
"hash_rate_drawdown",
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
hash_price_ths: ComputedFromHeightLast::forced_import(
|
||||
db,
|
||||
"hash_price_ths",
|
||||
version + v4,
|
||||
indexes,
|
||||
)?,
|
||||
hash_price_ths_min: ComputedFromHeightLast::forced_import(
|
||||
db,
|
||||
"hash_price_ths_min",
|
||||
version + v4,
|
||||
indexes,
|
||||
)?,
|
||||
hash_price_phs: ComputedFromHeightLast::forced_import(
|
||||
db,
|
||||
"hash_price_phs",
|
||||
version + v4,
|
||||
indexes,
|
||||
)?,
|
||||
hash_price_phs_min: ComputedFromHeightLast::forced_import(
|
||||
db,
|
||||
"hash_price_phs_min",
|
||||
version + v4,
|
||||
indexes,
|
||||
)?,
|
||||
hash_price_rebound: ComputedFromHeightLast::forced_import(
|
||||
db,
|
||||
"hash_price_rebound",
|
||||
version + v4,
|
||||
indexes,
|
||||
)?,
|
||||
hash_value_ths: ComputedFromHeightLast::forced_import(
|
||||
db,
|
||||
"hash_value_ths",
|
||||
version + v4,
|
||||
indexes,
|
||||
)?,
|
||||
hash_value_ths_min: ComputedFromHeightLast::forced_import(
|
||||
db,
|
||||
"hash_value_ths_min",
|
||||
version + v4,
|
||||
indexes,
|
||||
)?,
|
||||
hash_value_phs: ComputedFromHeightLast::forced_import(
|
||||
db,
|
||||
"hash_value_phs",
|
||||
version + v4,
|
||||
indexes,
|
||||
)?,
|
||||
hash_value_phs_min: ComputedFromHeightLast::forced_import(
|
||||
db,
|
||||
"hash_value_phs_min",
|
||||
version + v4,
|
||||
indexes,
|
||||
)?,
|
||||
hash_value_rebound: ComputedFromHeightLast::forced_import(
|
||||
db,
|
||||
"hash_value_rebound",
|
||||
version + v4,
|
||||
indexes,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
mod compute;
|
||||
mod import;
|
||||
mod vecs;
|
||||
|
||||
pub use vecs::Vecs;
|
||||
@@ -1,26 +0,0 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{StoredF32, StoredF64};
|
||||
|
||||
use crate::internal::{ComputedFromHeightLast, ComputedFromDateLast};
|
||||
|
||||
/// Mining-related metrics: hash rate, hash price, hash value
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct Vecs {
|
||||
pub hash_rate: ComputedFromHeightLast<StoredF64>,
|
||||
pub hash_rate_1w_sma: ComputedFromDateLast<StoredF64>,
|
||||
pub hash_rate_1m_sma: ComputedFromDateLast<StoredF32>,
|
||||
pub hash_rate_2m_sma: ComputedFromDateLast<StoredF32>,
|
||||
pub hash_rate_1y_sma: ComputedFromDateLast<StoredF32>,
|
||||
pub hash_rate_ath: ComputedFromHeightLast<StoredF64>,
|
||||
pub hash_rate_drawdown: ComputedFromHeightLast<StoredF32>,
|
||||
pub hash_price_ths: ComputedFromHeightLast<StoredF32>,
|
||||
pub hash_price_ths_min: ComputedFromHeightLast<StoredF32>,
|
||||
pub hash_price_phs: ComputedFromHeightLast<StoredF32>,
|
||||
pub hash_price_phs_min: ComputedFromHeightLast<StoredF32>,
|
||||
pub hash_price_rebound: ComputedFromHeightLast<StoredF32>,
|
||||
pub hash_value_ths: ComputedFromHeightLast<StoredF32>,
|
||||
pub hash_value_ths_min: ComputedFromHeightLast<StoredF32>,
|
||||
pub hash_value_phs: ComputedFromHeightLast<StoredF32>,
|
||||
pub hash_value_phs_min: ComputedFromHeightLast<StoredF32>,
|
||||
pub hash_value_rebound: ComputedFromHeightLast<StoredF32>,
|
||||
}
|
||||
@@ -2,8 +2,6 @@ pub mod count;
|
||||
pub mod difficulty;
|
||||
pub mod halving;
|
||||
pub mod interval;
|
||||
pub mod mining;
|
||||
pub mod rewards;
|
||||
pub mod size;
|
||||
pub mod time;
|
||||
pub mod weight;
|
||||
@@ -12,14 +10,12 @@ mod compute;
|
||||
mod import;
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use vecdb::Database;
|
||||
use vecdb::{Database, Rw, StorageMode};
|
||||
|
||||
pub use count::Vecs as CountVecs;
|
||||
pub use difficulty::Vecs as DifficultyVecs;
|
||||
pub use halving::Vecs as HalvingVecs;
|
||||
pub use interval::Vecs as IntervalVecs;
|
||||
pub use mining::Vecs as MiningVecs;
|
||||
pub use rewards::Vecs as RewardsVecs;
|
||||
pub use size::Vecs as SizeVecs;
|
||||
pub use time::Vecs as TimeVecs;
|
||||
pub use weight::Vecs as WeightVecs;
|
||||
@@ -28,29 +24,36 @@ pub const DB_NAME: &str = "blocks";
|
||||
|
||||
pub(crate) const TARGET_BLOCKS_PER_DAY_F64: f64 = 144.0;
|
||||
pub(crate) const TARGET_BLOCKS_PER_DAY_F32: f32 = 144.0;
|
||||
pub(crate) const TARGET_BLOCKS_PER_MINUTE1: u64 = 0;
|
||||
pub(crate) const TARGET_BLOCKS_PER_MINUTE5: u64 = 0;
|
||||
pub(crate) const TARGET_BLOCKS_PER_MINUTE10: u64 = 1;
|
||||
pub(crate) const TARGET_BLOCKS_PER_MINUTE30: u64 = 3;
|
||||
pub(crate) const TARGET_BLOCKS_PER_HOUR1: u64 = 6;
|
||||
pub(crate) const TARGET_BLOCKS_PER_HOUR4: u64 = 24;
|
||||
pub(crate) const TARGET_BLOCKS_PER_HOUR12: u64 = 72;
|
||||
pub(crate) const TARGET_BLOCKS_PER_DAY: u64 = 144;
|
||||
pub(crate) const TARGET_BLOCKS_PER_DAY3: u64 = 3 * TARGET_BLOCKS_PER_DAY;
|
||||
pub(crate) const TARGET_BLOCKS_PER_WEEK: u64 = 7 * TARGET_BLOCKS_PER_DAY;
|
||||
pub(crate) const TARGET_BLOCKS_PER_MONTH: u64 = 30 * TARGET_BLOCKS_PER_DAY;
|
||||
pub(crate) const TARGET_BLOCKS_PER_QUARTER: u64 = 3 * TARGET_BLOCKS_PER_MONTH;
|
||||
pub(crate) const TARGET_BLOCKS_PER_SEMESTER: u64 = 2 * TARGET_BLOCKS_PER_QUARTER;
|
||||
pub(crate) const TARGET_BLOCKS_PER_YEAR: u64 = 2 * TARGET_BLOCKS_PER_SEMESTER;
|
||||
pub(crate) const TARGET_BLOCKS_PER_DECADE: u64 = 10 * TARGET_BLOCKS_PER_YEAR;
|
||||
pub(crate) const TARGET_BLOCKS_PER_HALVING: u64 = 210_000;
|
||||
pub(crate) const ONE_TERA_HASH: f64 = 1_000_000_000_000.0;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct Vecs {
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
#[traversable(skip)]
|
||||
pub(crate) db: Database,
|
||||
|
||||
pub count: CountVecs,
|
||||
pub interval: IntervalVecs,
|
||||
pub count: CountVecs<M>,
|
||||
pub interval: IntervalVecs<M>,
|
||||
#[traversable(flatten)]
|
||||
pub size: SizeVecs,
|
||||
pub size: SizeVecs<M>,
|
||||
#[traversable(flatten)]
|
||||
pub weight: WeightVecs,
|
||||
pub time: TimeVecs,
|
||||
pub mining: MiningVecs,
|
||||
pub rewards: RewardsVecs,
|
||||
pub difficulty: DifficultyVecs,
|
||||
pub halving: HalvingVecs,
|
||||
pub weight: WeightVecs<M>,
|
||||
pub time: TimeVecs<M>,
|
||||
pub difficulty: DifficultyVecs<M>,
|
||||
pub halving: HalvingVecs<M>,
|
||||
}
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_types::{CheckedSub, Dollars, HalvingEpoch, Height, Sats, StoredF32, TxOutIndex};
|
||||
use vecdb::{Exit, IterableVec, TypedVecIterator, VecIndex};
|
||||
|
||||
use super::super::count;
|
||||
use super::Vecs;
|
||||
use crate::{ComputeIndexes, indexes, transactions};
|
||||
|
||||
impl Vecs {
|
||||
pub fn compute(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
count_vecs: &count::Vecs,
|
||||
transactions_fees: &transactions::FeesVecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.coinbase
|
||||
.compute_all(indexes, starting_indexes, exit, |vec| {
|
||||
let mut txindex_to_first_txoutindex_iter =
|
||||
indexer.vecs.transactions.first_txoutindex.iter()?;
|
||||
let mut txindex_to_output_count_iter =
|
||||
indexes.txindex.output_count.iter();
|
||||
let mut txoutindex_to_value_iter = indexer.vecs.outputs.value.iter()?;
|
||||
vec.compute_transform(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs.transactions.first_txindex,
|
||||
|(height, txindex, ..)| {
|
||||
let first_txoutindex = txindex_to_first_txoutindex_iter
|
||||
.get_unwrap(txindex)
|
||||
.to_usize();
|
||||
let output_count = txindex_to_output_count_iter.get_unwrap(txindex);
|
||||
let mut sats = Sats::ZERO;
|
||||
(first_txoutindex..first_txoutindex + usize::from(output_count)).for_each(
|
||||
|txoutindex| {
|
||||
sats += txoutindex_to_value_iter
|
||||
.get_unwrap(TxOutIndex::from(txoutindex));
|
||||
},
|
||||
);
|
||||
(height, sats)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let mut height_to_coinbase_iter = self.coinbase.sats.height.into_iter();
|
||||
self._24h_coinbase_sum.sats.compute_transform(
|
||||
starting_indexes.height,
|
||||
&count_vecs._24h_block_count.height,
|
||||
|(h, count, ..)| {
|
||||
let range = *h - (*count - 1)..=*h;
|
||||
let sum = range
|
||||
.map(Height::from)
|
||||
.map(|h| height_to_coinbase_iter.get_unwrap(h))
|
||||
.sum::<Sats>();
|
||||
(h, sum)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
drop(height_to_coinbase_iter);
|
||||
|
||||
if let (Some(dollars_out), Some(dollars_in)) =
|
||||
(&mut self._24h_coinbase_sum.dollars, &self.coinbase.dollars)
|
||||
{
|
||||
let mut height_to_coinbase_iter = dollars_in.height.into_iter();
|
||||
dollars_out.compute_transform(
|
||||
starting_indexes.height,
|
||||
&count_vecs._24h_block_count.height,
|
||||
|(h, count, ..)| {
|
||||
let range = *h - (*count - 1)..=*h;
|
||||
let sum = range
|
||||
.map(Height::from)
|
||||
.map(|h| height_to_coinbase_iter.get_unwrap(h))
|
||||
.sum::<Dollars>();
|
||||
(h, sum)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
|
||||
self.subsidy
|
||||
.compute_all(indexes, starting_indexes, exit, |vec| {
|
||||
vec.compute_transform2(
|
||||
starting_indexes.height,
|
||||
&self.coinbase.sats.height,
|
||||
&transactions_fees.fee.sats.height.sum_cum.sum.0,
|
||||
|(height, coinbase, fees, ..)| {
|
||||
(
|
||||
height,
|
||||
coinbase.checked_sub(fees).unwrap_or_else(|| {
|
||||
dbg!(height, coinbase, fees);
|
||||
panic!()
|
||||
}),
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.unclaimed_rewards
|
||||
.compute_all(indexes, starting_indexes, exit, |vec| {
|
||||
vec.compute_transform(
|
||||
starting_indexes.height,
|
||||
&self.subsidy.sats.height,
|
||||
|(height, subsidy, ..)| {
|
||||
let halving = HalvingEpoch::from(height);
|
||||
let expected = Sats::FIFTY_BTC / 2_usize.pow(halving.to_usize() as u32);
|
||||
(height, expected.checked_sub(subsidy).unwrap())
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.fee_dominance.compute_transform2(
|
||||
starting_indexes.dateindex,
|
||||
&transactions_fees.fee.sats.dateindex.sum_cum.sum.0,
|
||||
&self.coinbase.sats.dateindex.sum_cum.sum.0,
|
||||
|(i, fee, coinbase, ..)| {
|
||||
let coinbase_f64 = u64::from(coinbase) as f64;
|
||||
let dominance = if coinbase_f64 == 0.0 {
|
||||
StoredF32::NAN
|
||||
} else {
|
||||
StoredF32::from(u64::from(fee) as f64 / coinbase_f64 * 100.0)
|
||||
};
|
||||
(i, dominance)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.subsidy_dominance.compute_transform2(
|
||||
starting_indexes.dateindex,
|
||||
&self.subsidy.sats.dateindex.sum_cum.sum.0,
|
||||
&self.coinbase.sats.dateindex.sum_cum.sum.0,
|
||||
|(i, subsidy, coinbase, ..)| {
|
||||
let coinbase_f64 = u64::from(coinbase) as f64;
|
||||
let dominance = if coinbase_f64 == 0.0 {
|
||||
StoredF32::NAN
|
||||
} else {
|
||||
StoredF32::from(u64::from(subsidy) as f64 / coinbase_f64 * 100.0)
|
||||
};
|
||||
(i, dominance)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
|
||||
if let Some(sma) = self.subsidy_usd_1y_sma.as_mut() {
|
||||
let date_to_coinbase_usd_sum = &self
|
||||
.coinbase
|
||||
.dollars
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.sum_cum
|
||||
.sum
|
||||
.0;
|
||||
|
||||
sma.compute_all(starting_indexes, exit, |v| {
|
||||
v.compute_sma(
|
||||
starting_indexes.dateindex,
|
||||
date_to_coinbase_usd_sum,
|
||||
365,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
use brk_error::Result;
|
||||
use brk_types::Version;
|
||||
use vecdb::{Database, EagerVec, ImportableVec};
|
||||
|
||||
use super::Vecs;
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{ComputedFromDateLast, ValueFromHeightFull, ValueHeight, ValueFromHeightSumCum},
|
||||
price,
|
||||
};
|
||||
|
||||
impl Vecs {
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
) -> Result<Self> {
|
||||
let compute_dollars = price.is_some();
|
||||
|
||||
Ok(Self {
|
||||
_24h_coinbase_sum: ValueHeight::forced_import(
|
||||
db,
|
||||
"24h_coinbase_sum",
|
||||
version,
|
||||
compute_dollars,
|
||||
)?,
|
||||
coinbase: ValueFromHeightFull::forced_import(db, "coinbase", version, indexes, price)?,
|
||||
subsidy: ValueFromHeightFull::forced_import(db, "subsidy", version, indexes, price)?,
|
||||
unclaimed_rewards: ValueFromHeightSumCum::forced_import(
|
||||
db,
|
||||
"unclaimed_rewards",
|
||||
version,
|
||||
indexes,
|
||||
price,
|
||||
)?,
|
||||
fee_dominance: EagerVec::forced_import(db, "fee_dominance", version)?,
|
||||
subsidy_dominance: EagerVec::forced_import(db, "subsidy_dominance", version)?,
|
||||
subsidy_usd_1y_sma: compute_dollars
|
||||
.then(|| {
|
||||
ComputedFromDateLast::forced_import(db, "subsidy_usd_1y_sma", version, indexes)
|
||||
})
|
||||
.transpose()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
mod compute;
|
||||
mod import;
|
||||
mod vecs;
|
||||
|
||||
pub use vecs::Vecs;
|
||||
@@ -1,17 +0,0 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{DateIndex, Dollars, StoredF32};
|
||||
use vecdb::{EagerVec, PcoVec};
|
||||
|
||||
use crate::internal::{ComputedFromDateLast, ValueFromHeightFull, ValueHeight, ValueFromHeightSumCum};
|
||||
|
||||
/// Coinbase/subsidy/rewards metrics
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct Vecs {
|
||||
pub _24h_coinbase_sum: ValueHeight,
|
||||
pub coinbase: ValueFromHeightFull,
|
||||
pub subsidy: ValueFromHeightFull,
|
||||
pub unclaimed_rewards: ValueFromHeightSumCum,
|
||||
pub fee_dominance: EagerVec<PcoVec<DateIndex, StoredF32>>,
|
||||
pub subsidy_dominance: EagerVec<PcoVec<DateIndex, StoredF32>>,
|
||||
pub subsidy_usd_1y_sma: Option<ComputedFromDateLast<Dollars>>,
|
||||
}
|
||||
@@ -3,24 +3,19 @@ use brk_indexer::Indexer;
|
||||
use vecdb::Exit;
|
||||
|
||||
use super::Vecs;
|
||||
use crate::{ComputeIndexes, indexes};
|
||||
use crate::ComputeIndexes;
|
||||
|
||||
impl Vecs {
|
||||
pub fn compute(
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.size.derive_from(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
&indexer.vecs.blocks.total_size,
|
||||
exit,
|
||||
)?;
|
||||
self.size
|
||||
.compute_cumulative(starting_indexes, &indexer.vecs.blocks.total_size, exit)?;
|
||||
|
||||
self.vbytes.derive_from(indexes, starting_indexes, exit)?;
|
||||
self.vbytes.compute_cumulative(starting_indexes, exit)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,35 +1,30 @@
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_types::{Height, StoredU64, Version};
|
||||
use vecdb::{Database, IterableCloneableVec, VecIndex};
|
||||
use brk_types::Version;
|
||||
use vecdb::{Database, ReadableCloneableVec};
|
||||
|
||||
use super::Vecs;
|
||||
use crate::{indexes, internal::{ComputedHeightDerivedFull, LazyComputedFromHeightFull}};
|
||||
use crate::{indexes, internal::{ComputedHeightDerivedFull, LazyComputedFromHeightFull, WeightToVbytes}};
|
||||
|
||||
impl Vecs {
|
||||
pub fn forced_import(
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
version: Version,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
vbytes: LazyComputedFromHeightFull::forced_import_with_init(
|
||||
vbytes: LazyComputedFromHeightFull::forced_import::<WeightToVbytes>(
|
||||
db,
|
||||
"block_vbytes",
|
||||
version,
|
||||
indexer.vecs.blocks.weight.clone(),
|
||||
&indexer.vecs.blocks.weight,
|
||||
indexes,
|
||||
|height: Height, weight_iter| {
|
||||
weight_iter
|
||||
.get_at(height.to_usize())
|
||||
.map(|w| StoredU64::from(w.to_vbytes_floor()))
|
||||
},
|
||||
)?,
|
||||
size: ComputedHeightDerivedFull::forced_import(
|
||||
db,
|
||||
"block_size",
|
||||
indexer.vecs.blocks.total_size.boxed_clone(),
|
||||
indexer.vecs.blocks.total_size.read_only_boxed_clone(),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{StoredU64, Weight};
|
||||
use vecdb::{Rw, StorageMode};
|
||||
|
||||
use crate::internal::{ComputedHeightDerivedFull, LazyComputedFromHeightFull};
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct Vecs {
|
||||
pub vbytes: LazyComputedFromHeightFull<StoredU64, Weight>,
|
||||
pub size: ComputedHeightDerivedFull<StoredU64>,
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
pub vbytes: LazyComputedFromHeightFull<StoredU64, Weight, M>,
|
||||
pub size: ComputedHeightDerivedFull<StoredU64, M>,
|
||||
}
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_types::Timestamp;
|
||||
use vecdb::{Exit, TypedVecIterator};
|
||||
use vecdb::{Exit, ReadableVec};
|
||||
|
||||
use super::Vecs;
|
||||
use crate::{ComputeIndexes, indexes};
|
||||
|
||||
impl Vecs {
|
||||
/// Compute height-to-time fields early, before indexes are computed.
|
||||
/// These are needed by indexes::block to compute height_to_dateindex.
|
||||
pub fn compute_early(
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
starting_height: brk_types::Height,
|
||||
@@ -19,15 +15,11 @@ impl Vecs {
|
||||
self.timestamp_monotonic.compute_transform(
|
||||
starting_height,
|
||||
&indexer.vecs.blocks.timestamp,
|
||||
|(h, timestamp, height_to_timestamp_monotonic_iter)| {
|
||||
|(h, timestamp, this)| {
|
||||
if prev_timestamp_monotonic.is_none()
|
||||
&& let Some(prev_h) = h.decremented()
|
||||
{
|
||||
prev_timestamp_monotonic.replace(
|
||||
height_to_timestamp_monotonic_iter
|
||||
.into_iter()
|
||||
.get_unwrap(prev_h),
|
||||
);
|
||||
prev_timestamp_monotonic.replace(this.collect_one(prev_h).unwrap());
|
||||
}
|
||||
let timestamp_monotonic =
|
||||
prev_timestamp_monotonic.map_or(timestamp, |prev_d| prev_d.max(timestamp));
|
||||
@@ -39,23 +31,4 @@ impl Vecs {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn compute(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.timestamp.compute_all(|vec| {
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
&indexes.dateindex.date,
|
||||
|(di, d, ..)| (di, Timestamp::from(d)),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_types::{Date, Height, Version};
|
||||
use vecdb::{Database, EagerVec, ImportableVec, IterableCloneableVec, LazyVecFrom1};
|
||||
use vecdb::{Database, EagerVec, ImportableVec, ReadableCloneableVec, LazyVecFrom1};
|
||||
|
||||
use super::Vecs;
|
||||
use crate::{indexes, internal::ComputedHeightDerivedFirst};
|
||||
|
||||
impl Vecs {
|
||||
pub fn forced_import(
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
version: Version,
|
||||
indexer: &Indexer,
|
||||
@@ -20,17 +20,16 @@ impl Vecs {
|
||||
date: LazyVecFrom1::init(
|
||||
"date",
|
||||
version,
|
||||
timestamp_monotonic.boxed_clone(),
|
||||
|height: Height, timestamp_iter| timestamp_iter.get(height).map(Date::from),
|
||||
timestamp_monotonic.read_only_boxed_clone(),
|
||||
|_height: Height, timestamp| Date::from(timestamp),
|
||||
),
|
||||
timestamp_monotonic,
|
||||
timestamp: ComputedHeightDerivedFirst::forced_import(
|
||||
db,
|
||||
"timestamp",
|
||||
indexer.vecs.blocks.timestamp.boxed_clone(),
|
||||
indexer.vecs.blocks.timestamp.read_only_boxed_clone(),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Date, Height, Timestamp};
|
||||
use vecdb::{EagerVec, LazyVecFrom1, PcoVec};
|
||||
use vecdb::{EagerVec, LazyVecFrom1, PcoVec, Rw, StorageMode};
|
||||
|
||||
use crate::internal::ComputedHeightDerivedFirst;
|
||||
|
||||
/// Timestamp and date metrics for blocks
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct Vecs {
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
pub date: LazyVecFrom1<Height, Date, Height, Timestamp>,
|
||||
pub timestamp_monotonic: EagerVec<PcoVec<Height, Timestamp>>,
|
||||
pub timestamp_monotonic: M::Stored<EagerVec<PcoVec<Height, Timestamp>>>,
|
||||
pub timestamp: ComputedHeightDerivedFirst<Timestamp>,
|
||||
}
|
||||
|
||||
@@ -3,18 +3,17 @@ use brk_indexer::Indexer;
|
||||
use vecdb::Exit;
|
||||
|
||||
use super::Vecs;
|
||||
use crate::{ComputeIndexes, indexes};
|
||||
use crate::ComputeIndexes;
|
||||
|
||||
impl Vecs {
|
||||
pub fn compute(
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.weight
|
||||
.derive_from(indexes, starting_indexes, &indexer.vecs.blocks.weight, exit)?;
|
||||
.compute_cumulative(starting_indexes, &indexer.vecs.blocks.weight, exit)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_types::Version;
|
||||
use vecdb::{Database, IterableCloneableVec};
|
||||
use vecdb::{Database, ReadableCloneableVec};
|
||||
|
||||
use super::Vecs;
|
||||
use crate::{
|
||||
@@ -10,7 +10,7 @@ use crate::{
|
||||
};
|
||||
|
||||
impl Vecs {
|
||||
pub fn forced_import(
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
version: Version,
|
||||
indexer: &Indexer,
|
||||
@@ -19,7 +19,7 @@ impl Vecs {
|
||||
let weight = ComputedHeightDerivedFull::forced_import(
|
||||
db,
|
||||
"block_weight",
|
||||
indexer.vecs.blocks.weight.boxed_clone(),
|
||||
indexer.vecs.blocks.weight.read_only_boxed_clone(),
|
||||
version,
|
||||
indexes,
|
||||
)?;
|
||||
@@ -27,7 +27,7 @@ impl Vecs {
|
||||
let fullness = LazyFromHeightTransformDistribution::from_derived::<WeightToFullness>(
|
||||
"block_fullness",
|
||||
version,
|
||||
indexer.vecs.blocks.weight.boxed_clone(),
|
||||
indexer.vecs.blocks.weight.read_only_boxed_clone(),
|
||||
&weight,
|
||||
);
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{StoredF32, Weight};
|
||||
use vecdb::{Rw, StorageMode};
|
||||
|
||||
use crate::internal::{ComputedHeightDerivedFull, LazyFromHeightTransformDistribution};
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct Vecs {
|
||||
pub weight: ComputedHeightDerivedFull<Weight>,
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
pub weight: ComputedHeightDerivedFull<Weight, M>,
|
||||
pub fullness: LazyFromHeightTransformDistribution<StoredF32, Weight>,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user