global: MASSIVE snapshot

This commit is contained in:
nym21
2026-02-23 17:22:12 +01:00
parent be0d749f9c
commit 3b7aa8242a
703 changed files with 29130 additions and 30779 deletions

View File

@@ -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(())

View File

@@ -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(())
})
}
}

View File

@@ -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,
)?,

View File

@@ -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"),
}
}
}

View File

@@ -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(())

View File

@@ -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",

View File

@@ -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>,
}

View File

@@ -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(())
}

View File

@@ -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",

View File

@@ -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>,
}

View File

@@ -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,
};

View File

@@ -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(())
}
}

View File

@@ -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 })

View File

@@ -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>,
}

View File

@@ -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(())
}
}

View File

@@ -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,
)?,
})
}
}

View File

@@ -1,5 +0,0 @@
mod compute;
mod import;
mod vecs;
pub use vecs::Vecs;

View File

@@ -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>,
}

View File

@@ -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>,
}

View File

@@ -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(())
}
}

View File

@@ -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()?,
})
}
}

View File

@@ -1,5 +0,0 @@
mod compute;
mod import;
mod vecs;
pub use vecs::Vecs;

View File

@@ -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>>,
}

View File

@@ -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(())
}

View File

@@ -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,
)?,

View File

@@ -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>,
}

View File

@@ -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(())
}
}

View File

@@ -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,
)?,
),
})
}
}

View File

@@ -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>,
}

View File

@@ -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(())
}

View File

@@ -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,
);

View File

@@ -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>,
}