mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-27 08:09:58 -07:00
crates: snapshot
This commit is contained in:
451
crates/brk_computer/src/grouped/computed/from_txindex.rs
Normal file
451
crates/brk_computer/src/grouped/computed/from_txindex.rs
Normal file
@@ -0,0 +1,451 @@
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
Bitcoin, DateIndex, DecadeIndex, DifficultyEpoch, Dollars, Height, MonthIndex, QuarterIndex,
|
||||
Sats, SemesterIndex, TxIndex, Version, WeekIndex, YearIndex,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{
|
||||
AnyExportableVec, AnyVec, CollectableVec, Database, EagerVec, Exit, GenericStoredVec,
|
||||
ImportableVec, IterableCloneableVec, PcoVec, TypedVecIterator, VecIndex,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
Indexes,
|
||||
grouped::{LazyVecsBuilder, Source},
|
||||
indexes, price,
|
||||
utils::OptionExt,
|
||||
};
|
||||
|
||||
use crate::grouped::{ComputedVecValue, EagerVecsBuilder, VecBuilderOptions};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ComputedVecsFromTxindex<T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub txindex: Option<Box<EagerVec<PcoVec<TxIndex, T>>>>,
|
||||
pub height: EagerVecsBuilder<Height, T>,
|
||||
pub dateindex: EagerVecsBuilder<DateIndex, T>,
|
||||
pub weekindex: LazyVecsBuilder<WeekIndex, T, DateIndex, WeekIndex>,
|
||||
pub difficultyepoch: LazyVecsBuilder<DifficultyEpoch, T, Height, DifficultyEpoch>,
|
||||
pub monthindex: LazyVecsBuilder<MonthIndex, T, DateIndex, MonthIndex>,
|
||||
pub quarterindex: LazyVecsBuilder<QuarterIndex, T, DateIndex, QuarterIndex>,
|
||||
pub semesterindex: LazyVecsBuilder<SemesterIndex, T, DateIndex, SemesterIndex>,
|
||||
pub yearindex: LazyVecsBuilder<YearIndex, T, DateIndex, YearIndex>,
|
||||
// TODO: pub halvingepoch: StorableVecGeneator<Halvingepoch, T>,
|
||||
pub decadeindex: LazyVecsBuilder<DecadeIndex, T, DateIndex, DecadeIndex>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedVecsFromTxindex<T>
|
||||
where
|
||||
T: ComputedVecValue + Ord + From<f64> + JsonSchema + 'static,
|
||||
f64: From<T>,
|
||||
{
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
source: Source<TxIndex, T>,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
options: VecBuilderOptions,
|
||||
) -> Result<Self> {
|
||||
let txindex = source.is_compute().then(|| {
|
||||
Box::new(EagerVec::forced_import(db, name, version + VERSION + Version::ZERO).unwrap())
|
||||
});
|
||||
|
||||
let height =
|
||||
EagerVecsBuilder::forced_import(db, name, version + VERSION + Version::ZERO, options)?;
|
||||
|
||||
let options = options.remove_percentiles();
|
||||
|
||||
let dateindex =
|
||||
EagerVecsBuilder::forced_import(db, name, version + VERSION + Version::ZERO, options)?;
|
||||
|
||||
Ok(Self {
|
||||
weekindex: LazyVecsBuilder::forced_import(
|
||||
name,
|
||||
version + VERSION + Version::ZERO,
|
||||
None,
|
||||
&dateindex,
|
||||
indexes.time.weekindex_to_weekindex.boxed_clone(),
|
||||
options.into(),
|
||||
),
|
||||
difficultyepoch: LazyVecsBuilder::forced_import(
|
||||
name,
|
||||
version + VERSION + Version::ZERO,
|
||||
None,
|
||||
&height,
|
||||
indexes.block.difficultyepoch_to_difficultyepoch.boxed_clone(),
|
||||
options.into(),
|
||||
),
|
||||
monthindex: LazyVecsBuilder::forced_import(
|
||||
name,
|
||||
version + VERSION + Version::ZERO,
|
||||
None,
|
||||
&dateindex,
|
||||
indexes.time.monthindex_to_monthindex.boxed_clone(),
|
||||
options.into(),
|
||||
),
|
||||
quarterindex: LazyVecsBuilder::forced_import(
|
||||
name,
|
||||
version + VERSION + Version::ZERO,
|
||||
None,
|
||||
&dateindex,
|
||||
indexes.time.quarterindex_to_quarterindex.boxed_clone(),
|
||||
options.into(),
|
||||
),
|
||||
semesterindex: LazyVecsBuilder::forced_import(
|
||||
name,
|
||||
version + VERSION + Version::ZERO,
|
||||
None,
|
||||
&dateindex,
|
||||
indexes.time.semesterindex_to_semesterindex.boxed_clone(),
|
||||
options.into(),
|
||||
),
|
||||
yearindex: LazyVecsBuilder::forced_import(
|
||||
name,
|
||||
version + VERSION + Version::ZERO,
|
||||
None,
|
||||
&dateindex,
|
||||
indexes.time.yearindex_to_yearindex.boxed_clone(),
|
||||
options.into(),
|
||||
),
|
||||
decadeindex: LazyVecsBuilder::forced_import(
|
||||
name,
|
||||
version + VERSION + Version::ZERO,
|
||||
None,
|
||||
&dateindex,
|
||||
indexes.time.decadeindex_to_decadeindex.boxed_clone(),
|
||||
options.into(),
|
||||
),
|
||||
|
||||
txindex,
|
||||
height,
|
||||
dateindex,
|
||||
// halvingepoch: StorableVecGeneator::forced_import(db, name, version + VERSION + Version::ZERO, format, options)?,
|
||||
})
|
||||
}
|
||||
|
||||
// pub fn compute_all<F>(
|
||||
// &mut self,
|
||||
// indexer: &Indexer,
|
||||
// indexes: &indexes::Vecs,
|
||||
// starting_indexes: &Indexes,
|
||||
// exit: &Exit,
|
||||
// mut compute: F,
|
||||
// ) -> Result<()>
|
||||
// where
|
||||
// F: FnMut(
|
||||
// &mut EagerVec<PcoVec<TxIndex, T>>,
|
||||
// &Indexer,
|
||||
// &indexes::Vecs,
|
||||
// &Indexes,
|
||||
// &Exit,
|
||||
// ) -> Result<()>,
|
||||
// {
|
||||
// compute(
|
||||
// self.txindex.um(),
|
||||
// indexer,
|
||||
// indexes,
|
||||
// starting_indexes,
|
||||
// exit,
|
||||
// )?;
|
||||
|
||||
// let txindex: Option<&StoredVec<TxIndex, T>> = None;
|
||||
// self.compute_rest(indexer, indexes, starting_indexes, exit, txindex)?;
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
pub fn compute_rest(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
txindex: Option<&impl CollectableVec<TxIndex, T>>,
|
||||
) -> Result<()> {
|
||||
if let Some(txindex) = txindex {
|
||||
self.height.compute(
|
||||
starting_indexes.height,
|
||||
txindex,
|
||||
&indexer.vecs.tx.height_to_first_txindex,
|
||||
&indexes.block.height_to_txindex_count,
|
||||
exit,
|
||||
)?;
|
||||
} else {
|
||||
let txindex = self.txindex.u().as_ref();
|
||||
|
||||
self.height.compute(
|
||||
starting_indexes.height,
|
||||
txindex,
|
||||
&indexer.vecs.tx.height_to_first_txindex,
|
||||
&indexes.block.height_to_txindex_count,
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
|
||||
self.compute_after_height(indexes, starting_indexes, exit)
|
||||
}
|
||||
|
||||
fn compute_after_height(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.dateindex.from_aligned(
|
||||
starting_indexes.dateindex,
|
||||
&self.height,
|
||||
&indexes.time.dateindex_to_first_height,
|
||||
&indexes.time.dateindex_to_height_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputedVecsFromTxindex<Bitcoin> {
|
||||
pub fn compute_rest_from_sats(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
sats: &ComputedVecsFromTxindex<Sats>,
|
||||
txindex: Option<&impl CollectableVec<TxIndex, Bitcoin>>,
|
||||
) -> Result<()> {
|
||||
let txindex_version = if let Some(txindex) = txindex {
|
||||
txindex.version()
|
||||
} else {
|
||||
self.txindex.u().as_ref().version()
|
||||
};
|
||||
|
||||
self.height
|
||||
.validate_computed_version_or_reset(txindex_version)?;
|
||||
|
||||
let starting_index = self.height.starting_index(starting_indexes.height);
|
||||
|
||||
// Create iterators once before the loop to avoid repeated iterator creation
|
||||
let mut first_iter = sats.height.first.as_ref().map(|v| v.into_iter());
|
||||
let mut average_iter = sats.height.average.as_ref().map(|v| v.into_iter());
|
||||
let mut sum_iter = sats.height.sum.as_ref().map(|v| v.into_iter());
|
||||
let mut max_iter = sats.height.max.as_ref().map(|v| v.into_iter());
|
||||
let mut pct90_iter = sats.height.pct90.as_ref().map(|v| v.into_iter());
|
||||
let mut pct75_iter = sats.height.pct75.as_ref().map(|v| v.into_iter());
|
||||
let mut median_iter = sats.height.median.as_ref().map(|v| v.into_iter());
|
||||
let mut pct25_iter = sats.height.pct25.as_ref().map(|v| v.into_iter());
|
||||
let mut pct10_iter = sats.height.pct10.as_ref().map(|v| v.into_iter());
|
||||
let mut min_iter = sats.height.min.as_ref().map(|v| v.into_iter());
|
||||
let mut last_iter = sats.height.last.as_ref().map(|v| v.into_iter());
|
||||
let mut cumulative_iter = sats.height.cumulative.as_ref().map(|v| v.into_iter());
|
||||
|
||||
(starting_index.to_usize()..indexer.vecs.block.height_to_weight.len())
|
||||
.map(Height::from)
|
||||
.try_for_each(|height| -> Result<()> {
|
||||
if let Some(first) = self.height.first.as_mut() {
|
||||
first
|
||||
.truncate_push(height, Bitcoin::from(first_iter.um().get_unwrap(height)))?;
|
||||
}
|
||||
if let Some(average) = self.height.average.as_mut() {
|
||||
average.truncate_push(
|
||||
height,
|
||||
Bitcoin::from(average_iter.um().get_unwrap(height)),
|
||||
)?;
|
||||
}
|
||||
if let Some(sum) = self.height.sum.as_mut() {
|
||||
sum.truncate_push(height, Bitcoin::from(sum_iter.um().get_unwrap(height)))?;
|
||||
}
|
||||
if let Some(max) = self.height.max.as_mut() {
|
||||
max.truncate_push(height, Bitcoin::from(max_iter.um().get_unwrap(height)))?;
|
||||
}
|
||||
if let Some(pct90) = self.height.pct90.as_mut() {
|
||||
pct90
|
||||
.truncate_push(height, Bitcoin::from(pct90_iter.um().get_unwrap(height)))?;
|
||||
}
|
||||
if let Some(pct75) = self.height.pct75.as_mut() {
|
||||
pct75
|
||||
.truncate_push(height, Bitcoin::from(pct75_iter.um().get_unwrap(height)))?;
|
||||
}
|
||||
if let Some(median) = self.height.median.as_mut() {
|
||||
median.truncate_push(
|
||||
height,
|
||||
Bitcoin::from(median_iter.um().get_unwrap(height)),
|
||||
)?;
|
||||
}
|
||||
if let Some(pct25) = self.height.pct25.as_mut() {
|
||||
pct25
|
||||
.truncate_push(height, Bitcoin::from(pct25_iter.um().get_unwrap(height)))?;
|
||||
}
|
||||
if let Some(pct10) = self.height.pct10.as_mut() {
|
||||
pct10
|
||||
.truncate_push(height, Bitcoin::from(pct10_iter.um().get_unwrap(height)))?;
|
||||
}
|
||||
if let Some(min) = self.height.min.as_mut() {
|
||||
min.truncate_push(height, Bitcoin::from(min_iter.um().get_unwrap(height)))?;
|
||||
}
|
||||
if let Some(last) = self.height.last.as_mut() {
|
||||
last.truncate_push(height, Bitcoin::from(last_iter.um().get_unwrap(height)))?;
|
||||
}
|
||||
if let Some(cumulative) = self.height.cumulative.as_mut() {
|
||||
cumulative.truncate_push(
|
||||
height,
|
||||
Bitcoin::from(cumulative_iter.um().get_unwrap(height)),
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.height.safe_write(exit)?;
|
||||
|
||||
self.compute_after_height(indexes, starting_indexes, exit)
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputedVecsFromTxindex<Dollars> {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn compute_rest_from_bitcoin(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
bitcoin: &ComputedVecsFromTxindex<Bitcoin>,
|
||||
txindex: Option<&impl CollectableVec<TxIndex, Dollars>>,
|
||||
price: &price::Vecs,
|
||||
) -> Result<()> {
|
||||
let txindex_version = if let Some(txindex) = txindex {
|
||||
txindex.version()
|
||||
} else {
|
||||
self.txindex.u().as_ref().version()
|
||||
};
|
||||
|
||||
self.height
|
||||
.validate_computed_version_or_reset(txindex_version)?;
|
||||
|
||||
let starting_index = self.height.starting_index(starting_indexes.height);
|
||||
|
||||
let mut close_iter = price.chainindexes_to_price_close.height.into_iter();
|
||||
|
||||
// Create iterators once before the loop to avoid repeated iterator creation
|
||||
let mut first_iter = bitcoin.height.first.as_ref().map(|v| v.into_iter());
|
||||
let mut average_iter = bitcoin.height.average.as_ref().map(|v| v.into_iter());
|
||||
let mut sum_iter = bitcoin.height.sum.as_ref().map(|v| v.into_iter());
|
||||
let mut max_iter = bitcoin.height.max.as_ref().map(|v| v.into_iter());
|
||||
let mut pct90_iter = bitcoin.height.pct90.as_ref().map(|v| v.into_iter());
|
||||
let mut pct75_iter = bitcoin.height.pct75.as_ref().map(|v| v.into_iter());
|
||||
let mut median_iter = bitcoin.height.median.as_ref().map(|v| v.into_iter());
|
||||
let mut pct25_iter = bitcoin.height.pct25.as_ref().map(|v| v.into_iter());
|
||||
let mut pct10_iter = bitcoin.height.pct10.as_ref().map(|v| v.into_iter());
|
||||
let mut min_iter = bitcoin.height.min.as_ref().map(|v| v.into_iter());
|
||||
let mut last_iter = bitcoin.height.last.as_ref().map(|v| v.into_iter());
|
||||
let mut cumulative_iter = bitcoin.height.cumulative.as_ref().map(|v| v.into_iter());
|
||||
|
||||
(starting_index.to_usize()..indexer.vecs.block.height_to_weight.len())
|
||||
.map(Height::from)
|
||||
.try_for_each(|height| -> Result<()> {
|
||||
let price = *close_iter.get_unwrap(height);
|
||||
|
||||
if let Some(first) = self.height.first.as_mut() {
|
||||
first.truncate_push(height, price * first_iter.um().get_unwrap(height))?;
|
||||
}
|
||||
if let Some(average) = self.height.average.as_mut() {
|
||||
average.truncate_push(height, price * average_iter.um().get_unwrap(height))?;
|
||||
}
|
||||
if let Some(sum) = self.height.sum.as_mut() {
|
||||
sum.truncate_push(height, price * sum_iter.um().get_unwrap(height))?;
|
||||
}
|
||||
if let Some(max) = self.height.max.as_mut() {
|
||||
max.truncate_push(height, price * max_iter.um().get_unwrap(height))?;
|
||||
}
|
||||
if let Some(pct90) = self.height.pct90.as_mut() {
|
||||
pct90.truncate_push(height, price * pct90_iter.um().get_unwrap(height))?;
|
||||
}
|
||||
if let Some(pct75) = self.height.pct75.as_mut() {
|
||||
pct75.truncate_push(height, price * pct75_iter.um().get_unwrap(height))?;
|
||||
}
|
||||
if let Some(median) = self.height.median.as_mut() {
|
||||
median.truncate_push(height, price * median_iter.um().get_unwrap(height))?;
|
||||
}
|
||||
if let Some(pct25) = self.height.pct25.as_mut() {
|
||||
pct25.truncate_push(height, price * pct25_iter.um().get_unwrap(height))?;
|
||||
}
|
||||
if let Some(pct10) = self.height.pct10.as_mut() {
|
||||
pct10.truncate_push(height, price * pct10_iter.um().get_unwrap(height))?;
|
||||
}
|
||||
if let Some(min) = self.height.min.as_mut() {
|
||||
min.truncate_push(height, price * min_iter.um().get_unwrap(height))?;
|
||||
}
|
||||
if let Some(last) = self.height.last.as_mut() {
|
||||
last.truncate_push(height, price * last_iter.um().get_unwrap(height))?;
|
||||
}
|
||||
if let Some(cumulative) = self.height.cumulative.as_mut() {
|
||||
cumulative
|
||||
.truncate_push(height, price * cumulative_iter.um().get_unwrap(height))?;
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.height.safe_write(exit)?;
|
||||
|
||||
self.compute_after_height(indexes, starting_indexes, exit)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Traversable for ComputedVecsFromTxindex<T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
fn to_tree_node(&self) -> brk_traversable::TreeNode {
|
||||
brk_traversable::TreeNode::Branch(
|
||||
[
|
||||
self.txindex
|
||||
.as_ref()
|
||||
.map(|nested| ("txindex".to_string(), nested.to_tree_node())),
|
||||
Some(("height".to_string(), self.height.to_tree_node())),
|
||||
Some(("dateindex".to_string(), self.dateindex.to_tree_node())),
|
||||
Some(("weekindex".to_string(), self.weekindex.to_tree_node())),
|
||||
Some((
|
||||
"difficultyepoch".to_string(),
|
||||
self.difficultyepoch.to_tree_node(),
|
||||
)),
|
||||
Some(("monthindex".to_string(), self.monthindex.to_tree_node())),
|
||||
Some(("quarterindex".to_string(), self.quarterindex.to_tree_node())),
|
||||
Some((
|
||||
"semesterindex".to_string(),
|
||||
self.semesterindex.to_tree_node(),
|
||||
)),
|
||||
Some(("yearindex".to_string(), self.yearindex.to_tree_node())),
|
||||
Some(("decadeindex".to_string(), self.decadeindex.to_tree_node())),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect(),
|
||||
)
|
||||
.merge_branches()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn iter_any_exportable(&self) -> impl Iterator<Item = &dyn AnyExportableVec> {
|
||||
let mut regular_iter: Box<dyn Iterator<Item = &dyn AnyExportableVec>> =
|
||||
Box::new(self.height.iter_any_exportable());
|
||||
regular_iter = Box::new(regular_iter.chain(self.dateindex.iter_any_exportable()));
|
||||
regular_iter = Box::new(regular_iter.chain(self.weekindex.iter_any_exportable()));
|
||||
regular_iter = Box::new(regular_iter.chain(self.difficultyepoch.iter_any_exportable()));
|
||||
regular_iter = Box::new(regular_iter.chain(self.monthindex.iter_any_exportable()));
|
||||
regular_iter = Box::new(regular_iter.chain(self.quarterindex.iter_any_exportable()));
|
||||
regular_iter = Box::new(regular_iter.chain(self.semesterindex.iter_any_exportable()));
|
||||
regular_iter = Box::new(regular_iter.chain(self.yearindex.iter_any_exportable()));
|
||||
regular_iter = Box::new(regular_iter.chain(self.decadeindex.iter_any_exportable()));
|
||||
if let Some(ref x) = self.txindex {
|
||||
regular_iter = Box::new(regular_iter.chain(x.iter_any_exportable()));
|
||||
}
|
||||
regular_iter
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user