Files
brk/crates/brk_computer/src/vecs/stateful/mod.rs
2025-06-01 14:37:19 +02:00

1508 lines
63 KiB
Rust

use std::{cmp::Ordering, collections::BTreeMap, mem, path::Path, thread};
use brk_core::{DateIndex, Height, InputIndex, OutputIndex, OutputType, Result, Sats, Version};
use brk_exit::Exit;
use brk_indexer::Indexer;
use brk_vec::{
AnyCollectableVec, AnyVec, BaseVecIterator, CollectableVec, Compressed, Computation, EagerVec,
GenericStoredVec, StoredIndex, StoredVec, UnsafeSlice, VecIterator,
};
use fjall::TransactionalKeyspace;
use log::info;
use outputs::OutputCohorts;
use rayon::prelude::*;
use brk_state::{
BlockState, OutputFilter, Outputs, OutputsByEpoch, OutputsByFrom, OutputsByRange,
OutputsBySize, OutputsBySpendableType, OutputsByTerm, OutputsByUpTo, SupplyState, Transacted,
};
use super::{
Indexes, fetched,
grouped::{ComputedValueVecsFromHeight, StorableVecGeneatorOptions},
indexes, transactions,
};
pub mod cohort;
mod outputs;
const VERSION: Version = Version::ZERO;
const BYSIZE_VERSION: Version = Version::ONE;
#[derive(Clone)]
pub struct Vecs {
chain_state: StoredVec<Height, SupplyState>,
// cointime,...
pub height_to_unspendable_supply: EagerVec<Height, Sats>,
pub indexes_to_unspendable_supply: ComputedValueVecsFromHeight,
pub height_to_opreturn_supply: EagerVec<Height, Sats>,
pub indexes_to_opreturn_supply: ComputedValueVecsFromHeight,
utxos_vecs: Outputs<(OutputFilter, cohort::Vecs)>,
}
impl Vecs {
pub fn forced_import(
path: &Path,
version: Version,
_computation: Computation,
compressed: Compressed,
fetched: Option<&fetched::Vecs>,
keyspace: &TransactionalKeyspace,
) -> color_eyre::Result<Self> {
let compute_dollars = fetched.is_some();
let mut root_path = path.to_owned();
root_path.pop();
let states_path = root_path.join("states");
root_path.pop();
let stores_path = root_path.join("stores");
Ok(Self {
chain_state: StoredVec::forced_import(
&states_path,
"chain",
version + VERSION + Version::ZERO,
Compressed::NO,
)?,
height_to_unspendable_supply: EagerVec::forced_import(
path,
"unspendable_supply",
version + VERSION + Version::ZERO,
compressed,
)?,
indexes_to_unspendable_supply: ComputedValueVecsFromHeight::forced_import(
path,
"unspendable_supply",
false,
version + VERSION + Version::ZERO,
compressed,
StorableVecGeneatorOptions::default().add_last(),
compute_dollars,
)?,
height_to_opreturn_supply: EagerVec::forced_import(
path,
"opreturn_supply",
version + VERSION + Version::ZERO,
compressed,
)?,
indexes_to_opreturn_supply: ComputedValueVecsFromHeight::forced_import(
path,
"opreturn_supply",
false,
version + VERSION + Version::ZERO,
compressed,
StorableVecGeneatorOptions::default().add_last(),
compute_dollars,
)?,
utxos_vecs: {
Outputs::<(OutputFilter, cohort::Vecs)>::from(Outputs {
all: cohort::Vecs::forced_import(
path,
None,
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
by_term: OutputsByTerm {
short: cohort::Vecs::forced_import(
path,
Some("sth"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
long: cohort::Vecs::forced_import(
path,
Some("lth"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
},
by_up_to: OutputsByUpTo {
_1d: cohort::Vecs::forced_import(
path,
Some("up_to_1d"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_1w: cohort::Vecs::forced_import(
path,
Some("up_to_1w"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_1m: cohort::Vecs::forced_import(
path,
Some("up_to_1m"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_2m: cohort::Vecs::forced_import(
path,
Some("up_to_2m"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_3m: cohort::Vecs::forced_import(
path,
Some("up_to_3m"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_4m: cohort::Vecs::forced_import(
path,
Some("up_to_4m"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_5m: cohort::Vecs::forced_import(
path,
Some("up_to_5m"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_6m: cohort::Vecs::forced_import(
path,
Some("up_to_6m"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_1y: cohort::Vecs::forced_import(
path,
Some("up_to_1y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_2y: cohort::Vecs::forced_import(
path,
Some("up_to_2y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_3y: cohort::Vecs::forced_import(
path,
Some("up_to_3y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_4y: cohort::Vecs::forced_import(
path,
Some("up_to_4y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_5y: cohort::Vecs::forced_import(
path,
Some("up_to_5y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_6y: cohort::Vecs::forced_import(
path,
Some("up_to_6y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_7y: cohort::Vecs::forced_import(
path,
Some("up_to_7y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_8y: cohort::Vecs::forced_import(
path,
Some("up_to_8y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_10y: cohort::Vecs::forced_import(
path,
Some("up_to_10y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_15y: cohort::Vecs::forced_import(
path,
Some("up_to_15y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
},
by_from: OutputsByFrom {
_1d: cohort::Vecs::forced_import(
path,
Some("from_1d"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_1w: cohort::Vecs::forced_import(
path,
Some("from_1w"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_1m: cohort::Vecs::forced_import(
path,
Some("from_1m"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_2m: cohort::Vecs::forced_import(
path,
Some("from_2m"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_3m: cohort::Vecs::forced_import(
path,
Some("from_3m"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_4m: cohort::Vecs::forced_import(
path,
Some("from_4m"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_5m: cohort::Vecs::forced_import(
path,
Some("from_5m"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_6m: cohort::Vecs::forced_import(
path,
Some("from_6m"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_1y: cohort::Vecs::forced_import(
path,
Some("from_1y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_2y: cohort::Vecs::forced_import(
path,
Some("from_2y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_3y: cohort::Vecs::forced_import(
path,
Some("from_3y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_4y: cohort::Vecs::forced_import(
path,
Some("from_4y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_5y: cohort::Vecs::forced_import(
path,
Some("from_5y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_6y: cohort::Vecs::forced_import(
path,
Some("from_6y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_7y: cohort::Vecs::forced_import(
path,
Some("from_7y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_8y: cohort::Vecs::forced_import(
path,
Some("from_8y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_10y: cohort::Vecs::forced_import(
path,
Some("from_10y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_15y: cohort::Vecs::forced_import(
path,
Some("from_15y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
},
by_range: OutputsByRange {
_1d_to_1w: cohort::Vecs::forced_import(
path,
Some("from_1d_to_1w"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_1w_to_1m: cohort::Vecs::forced_import(
path,
Some("from_1w_to_1m"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_1m_to_3m: cohort::Vecs::forced_import(
path,
Some("from_1m_to_3m"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_3m_to_6m: cohort::Vecs::forced_import(
path,
Some("from_3m_to_6m"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_6m_to_1y: cohort::Vecs::forced_import(
path,
Some("from_6m_to_1y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_1y_to_2y: cohort::Vecs::forced_import(
path,
Some("from_1y_to_2y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_2y_to_3y: cohort::Vecs::forced_import(
path,
Some("from_2y_to_3y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_3y_to_4y: cohort::Vecs::forced_import(
path,
Some("from_3y_to_4y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_4y_to_5y: cohort::Vecs::forced_import(
path,
Some("from_4y_to_5y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_5y_to_7y: cohort::Vecs::forced_import(
path,
Some("from_5y_to_7y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_7y_to_10y: cohort::Vecs::forced_import(
path,
Some("from_7y_to_10y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_10y_to_15y: cohort::Vecs::forced_import(
path,
Some("from_10y_to_15y"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
},
by_epoch: OutputsByEpoch {
_0: cohort::Vecs::forced_import(
path,
Some("epoch_0"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_1: cohort::Vecs::forced_import(
path,
Some("epoch_1"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_2: cohort::Vecs::forced_import(
path,
Some("epoch_2"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_3: cohort::Vecs::forced_import(
path,
Some("epoch_3"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
_4: cohort::Vecs::forced_import(
path,
Some("epoch_4"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
},
by_size: OutputsBySize {
_0sat: cohort::Vecs::forced_import(
path,
Some("0sat"),
_computation,
compressed,
version + BYSIZE_VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
from_1sat_to_10sats: cohort::Vecs::forced_import(
path,
Some("from_1sat_to_10sats"),
_computation,
compressed,
version + BYSIZE_VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
from_10sats_to_100sats: cohort::Vecs::forced_import(
path,
Some("from_10sats_to_100sats"),
_computation,
compressed,
version + BYSIZE_VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
from_100sats_to_1_000sats: cohort::Vecs::forced_import(
path,
Some("from_100sats_to_1_000sats"),
_computation,
compressed,
version + BYSIZE_VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
from_1_000sats_to_10_000sats: cohort::Vecs::forced_import(
path,
Some("from_1_000sats_to_10_000sats"),
_computation,
compressed,
version + BYSIZE_VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
from_10_000sats_to_100_000sats: cohort::Vecs::forced_import(
path,
Some("from_10_000sats_to_100_000sats"),
_computation,
compressed,
version + BYSIZE_VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
from_100_000sats_to_1_000_000sats: cohort::Vecs::forced_import(
path,
Some("from_100_000sats_to_1_000_000sats"),
_computation,
compressed,
version + BYSIZE_VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
from_1_000_000sats_to_10_000_000sats: cohort::Vecs::forced_import(
path,
Some("from_1_000_000sats_to_10_000_000sats"),
_computation,
compressed,
version + BYSIZE_VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
from_10_000_000sats_to_1btc: cohort::Vecs::forced_import(
path,
Some("from_10_000_000sats_to_1btc"),
_computation,
compressed,
version + BYSIZE_VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
from_1btc_to_10btc: cohort::Vecs::forced_import(
path,
Some("from_1btc_to_10btc"),
_computation,
compressed,
version + BYSIZE_VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
from_10btc_to_100btc: cohort::Vecs::forced_import(
path,
Some("from_10btc_to_100btc"),
_computation,
compressed,
version + BYSIZE_VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
from_100btc_to_1_000btc: cohort::Vecs::forced_import(
path,
Some("from_100btc_to_1_000btc"),
_computation,
compressed,
version + BYSIZE_VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
from_1_000btc_to_10_000btc: cohort::Vecs::forced_import(
path,
Some("from_1_000btc_to_10_000btc"),
_computation,
compressed,
version + BYSIZE_VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
from_10_000btc_to_100_000btc: cohort::Vecs::forced_import(
path,
Some("from_10_000btc_to_100_000btc"),
_computation,
compressed,
version + BYSIZE_VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
from_100_000btc: cohort::Vecs::forced_import(
path,
Some("from_100_000btc"),
_computation,
compressed,
version + BYSIZE_VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
},
// by_value: OutputsByValue {
// up_to_1cent: cohort::Vecs::forced_import(
// path,
// Some("up_to_1cent"),
// _computation,
// compressed,
// fetched,
// )?,
// from_1c_to_10c: cohort::Vecs::forced_import(
// path,
// Some("from_1c_to_10c"),
// _computation,
// compressed,
// fetched,
// )?,
// from_10c_to_1d: cohort::Vecs::forced_import(
// path,
// Some("from_10c_to_1d"),
// _computation,
// compressed,
// fetched,
// )?,
// from_1d_to_10d: cohort::Vecs::forced_import(
// path,
// Some("from_1d_to_10d"),
// _computation,
// compressed,
// fetched,
// )?,
// from_10usd_to_100usd: cohort::Vecs::forced_import(
// path,
// Some("from_10usd_to_100usd"),
// _computation,
// compressed,
// fetched,
// )?,
// from_100usd_to_1_000usd: cohort::Vecs::forced_import(
// path,
// Some("from_100usd_to_1_000usd"),
// _computation,
// compressed,
// fetched,
// )?,
// from_1_000usd_to_10_000usd: cohort::Vecs::forced_import(
// path,
// Some("from_1_000usd_to_10_000usd"),
// _computation,
// compressed,
// fetched,
// )?,
// from_10_000usd_to_100_000usd: cohort::Vecs::forced_import(
// path,
// Some("from_10_000usd_to_100_000usd"),
// _computation,
// compressed,
// fetched,
// )?,
// from_100_000usd_to_1_000_000usd: cohort::Vecs::forced_import(
// path,
// Some("from_100_000usd_to_1_000_000usd"),
// _computation,
// compressed,
// fetched,
// )?,
// from_1_000_000usd_to_10_000_000usd: cohort::Vecs::forced_import(
// path,
// Some("from_1_000_000usd_to_10_000_000usd"),
// _computation,
// compressed,
// fetched,
// )?,
// from_10_000_000usd_to_100_000_000usd: cohort::Vecs::forced_import(
// path,
// Some("from_10_000_000usd_to_100_000_000usd"),
// _computation,
// compressed,
// fetched,
// )?,
// from_100_000_000usd_to_1_000_000_000usd: cohort::Vecs::forced_import(
// path,
// Some("from_100_000_000usd_to_1_000_000_000usd"),
// _computation,
// compressed,
// fetched,
// )?,
// from_1_000_000_000usd: cohort::Vecs::forced_import(
// path,
// Some("from_1_000_000_000usd"),
// _computation,
// compressed,
// fetched,
// )?,
// },
by_type: OutputsBySpendableType {
p2pk65: cohort::Vecs::forced_import(
path,
Some("p2pk65"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
p2pk33: cohort::Vecs::forced_import(
path,
Some("p2pk33"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
p2pkh: cohort::Vecs::forced_import(
path,
Some("p2pkh"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
p2ms: cohort::Vecs::forced_import(
path,
Some("p2ms"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
p2sh: cohort::Vecs::forced_import(
path,
Some("p2sh"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
// opreturn: cohort::Vecs::forced_import(
// path,
// Some("opreturn"),
// _computation,
// compressed,
// VERSION + Version::ZERO,
// fetched,
// keyspace
// )?,
p2wpkh: cohort::Vecs::forced_import(
path,
Some("p2wpkh"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
p2wsh: cohort::Vecs::forced_import(
path,
Some("p2wsh"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
p2tr: cohort::Vecs::forced_import(
path,
Some("p2tr"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
p2a: cohort::Vecs::forced_import(
path,
Some("p2a"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
empty: cohort::Vecs::forced_import(
path,
Some("empty"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
unknown: cohort::Vecs::forced_import(
path,
Some("unknown"),
_computation,
compressed,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
)?,
},
})
},
})
}
pub fn compute(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
transactions: &transactions::Vecs,
fetched: Option<&fetched::Vecs>,
starting_indexes: &Indexes,
exit: &Exit,
) -> color_eyre::Result<()> {
let indexer_vecs = indexer.vecs();
let height_to_first_outputindex = &indexer_vecs.height_to_first_outputindex;
let height_to_first_inputindex = &indexer_vecs.height_to_first_inputindex;
let height_to_output_count = transactions.indexes_to_output_count.height.unwrap_sum();
let height_to_input_count = transactions.indexes_to_input_count.height.unwrap_sum();
let inputindex_to_outputindex = &indexer_vecs.inputindex_to_outputindex;
let outputindex_to_value = &indexer_vecs.outputindex_to_value;
let txindex_to_height = &indexes.txindex_to_height;
let height_to_timestamp_fixed = &indexes.height_to_timestamp_fixed;
let outputindex_to_txindex = &indexes.outputindex_to_txindex;
let outputindex_to_outputtype = &indexer_vecs.outputindex_to_outputtype;
let height_to_unclaimed_rewards = transactions
.indexes_to_unclaimed_rewards
.sats
.height
.as_ref()
.unwrap();
let height_to_close = fetched
.as_ref()
.map(|fetched| &fetched.chainindexes_to_close.height);
let dateindex_to_close = fetched
.as_ref()
.map(|fetched| fetched.timeindexes_to_close.dateindex.as_ref().unwrap());
let height_to_date_fixed = &indexes.height_to_date_fixed;
let dateindex_to_first_height = &indexes.dateindex_to_first_height;
let dateindex_to_height_count = &indexes.dateindex_to_height_count;
let inputindex_to_outputindex_mmap = inputindex_to_outputindex.mmap().load();
let outputindex_to_value_mmap = outputindex_to_value.mmap().load();
let outputindex_to_outputtype_mmap = outputindex_to_outputtype.mmap().load();
let outputindex_to_txindex_mmap = outputindex_to_txindex.mmap().load();
let txindex_to_height_mmap = txindex_to_height.mmap().load();
let mut height_to_first_outputindex_iter = height_to_first_outputindex.into_iter();
let mut height_to_first_inputindex_iter = height_to_first_inputindex.into_iter();
let mut height_to_output_count_iter = height_to_output_count.into_iter();
let mut height_to_input_count_iter = height_to_input_count.into_iter();
// let mut outputindex_to_value_iter_2 = outputindex_to_value.into_iter();
let mut height_to_close_iter = height_to_close.as_ref().map(|v| v.into_iter());
// let mut outputindex_to_outputtype_iter_2 = outputindex_to_outputtype.into_iter();
let mut height_to_unclaimed_rewards_iter = height_to_unclaimed_rewards.into_iter();
let mut height_to_timestamp_fixed_iter = height_to_timestamp_fixed.into_iter();
let mut dateindex_to_close_iter = dateindex_to_close.as_ref().map(|v| v.into_iter());
let mut height_to_date_fixed_iter = height_to_date_fixed.into_iter();
let mut dateindex_to_first_height_iter = dateindex_to_first_height.into_iter();
let mut dateindex_to_height_count_iter = dateindex_to_height_count.into_iter();
let mut flat_vecs_ = self.utxos_vecs.as_mut_vec();
let base_version = Version::ZERO
+ height_to_first_outputindex.version()
+ height_to_first_inputindex.version()
+ height_to_timestamp_fixed.version()
+ height_to_output_count.version()
+ height_to_input_count.version()
+ inputindex_to_outputindex.version()
+ outputindex_to_value.version()
+ txindex_to_height.version()
+ outputindex_to_txindex.version()
+ outputindex_to_outputtype.version()
+ height_to_unclaimed_rewards.version()
+ height_to_close
.as_ref()
.map_or(Version::ZERO, |v| v.version())
+ dateindex_to_close
.as_ref()
.map_or(Version::ZERO, |v| v.version())
+ height_to_date_fixed.version()
+ dateindex_to_first_height.version()
+ dateindex_to_height_count.version();
flat_vecs_
.iter_mut()
.try_for_each(|(_, v)| v.validate_computed_versions(base_version))?;
self.height_to_unspendable_supply
.validate_computed_version_or_reset_file(
base_version + self.height_to_unspendable_supply.inner_version(),
)?;
self.height_to_opreturn_supply
.validate_computed_version_or_reset_file(
base_version + self.height_to_opreturn_supply.inner_version(),
)?;
let mut chain_state: Vec<BlockState>;
let mut chain_state_starting_height = Height::from(self.chain_state.len());
let stateful_starting_height = match flat_vecs_
.iter_mut()
.map(|(_, v)| v.starting_height())
.min()
.unwrap_or_default()
.min(chain_state_starting_height)
.cmp(&chain_state_starting_height)
{
Ordering::Greater => unreachable!(),
Ordering::Equal => {
chain_state = self
.chain_state
.collect_range(None, None)?
.into_iter()
.enumerate()
.map(|(height, supply)| {
let height = Height::from(height);
let timestamp = height_to_timestamp_fixed_iter.unwrap_get_inner(height);
let price = height_to_close_iter
.as_mut()
.map(|i| *i.unwrap_get_inner(height));
BlockState {
timestamp,
price,
supply,
}
})
.collect::<Vec<_>>();
chain_state_starting_height
}
Ordering::Less => {
// todo!("rollback instead");
chain_state = vec![];
chain_state_starting_height = Height::ZERO;
Height::ZERO
}
};
if stateful_starting_height.is_zero() {
info!("Starting processing utxos from the start");
flat_vecs_
.iter_mut()
.try_for_each(|(_, v)| v.state.price_to_amount.reset_partition())?;
}
let starting_height = starting_indexes
.height
.min(stateful_starting_height)
.min(Height::from(self.height_to_unspendable_supply.len()))
.min(Height::from(self.height_to_opreturn_supply.len()));
// ---
// INIT
// ---
flat_vecs_
.iter_mut()
.for_each(|(_, v)| v.init(starting_height));
let mut unspendable_supply = if let Some(prev_height) = starting_height.decremented() {
self.height_to_unspendable_supply
.into_iter()
.unwrap_get_inner(prev_height)
} else {
Sats::ZERO
};
let mut opreturn_supply = if let Some(prev_height) = starting_height.decremented() {
self.height_to_opreturn_supply
.into_iter()
.unwrap_get_inner(prev_height)
} else {
Sats::ZERO
};
let mut height = Height::ZERO;
(starting_height.unwrap_to_usize()..height_to_first_outputindex_iter.len())
.map(Height::from)
.try_for_each(|_height| -> color_eyre::Result<()> {
height = _height;
self.utxos_vecs
.as_mut_vec()
.iter_mut()
.for_each(|(_, v)| v.state.reset_single_iteration_values());
info!("Processing chain at {height}...");
let timestamp = height_to_timestamp_fixed_iter.unwrap_get_inner(height);
let price = height_to_close_iter
.as_mut()
.map(|i| *i.unwrap_get_inner(height));
let first_outputindex = height_to_first_outputindex_iter
.unwrap_get_inner(height)
.unwrap_to_usize();
let first_inputindex = height_to_first_inputindex_iter
.unwrap_get_inner(height)
.unwrap_to_usize();
let output_count = height_to_output_count_iter.unwrap_get_inner(height);
let input_count = height_to_input_count_iter.unwrap_get_inner(height);
let (mut height_to_sent, mut received) = thread::scope(|s| {
if chain_state_starting_height <= height {
s.spawn(|| {
self.utxos_vecs
.tick_tock_next_block(&chain_state, timestamp);
});
}
let sent_handle = s.spawn(|| {
// Skip coinbase
(first_inputindex + 1..first_inputindex + *input_count)
.into_par_iter()
.map(InputIndex::from)
.map(|inputindex| {
let outputindex = inputindex_to_outputindex
.get_or_read(inputindex, &inputindex_to_outputindex_mmap)
.unwrap()
.unwrap()
.into_inner();
let value = outputindex_to_value
.get_or_read(outputindex, &outputindex_to_value_mmap)
.unwrap()
.unwrap()
.into_inner();
let input_type = outputindex_to_outputtype
.get_or_read(outputindex, &outputindex_to_outputtype_mmap)
.unwrap()
.unwrap()
.into_inner();
if input_type.is_unspendable() {
unreachable!()
}
let input_txindex = outputindex_to_txindex
.get_or_read(outputindex, &outputindex_to_txindex_mmap)
.unwrap()
.unwrap()
.into_inner();
let height = txindex_to_height
.get_or_read(input_txindex, &txindex_to_height_mmap)
.unwrap()
.unwrap()
.into_inner();
(height, value, input_type)
})
.fold(
BTreeMap::<Height, Transacted>::default,
|mut tree, (height, value, input_type)| {
tree.entry(height).or_default().iterate(value, input_type);
tree
},
)
.reduce(BTreeMap::<Height, Transacted>::default, |first, second| {
let (mut source, to_consume) = if first.len() > second.len() {
(first, second)
} else {
(second, first)
};
to_consume.into_iter().for_each(|(k, v)| {
*source.entry(k).or_default() += v;
});
source
})
});
let received_handle = s.spawn(|| {
(first_outputindex..first_outputindex + *output_count)
.into_par_iter()
.map(OutputIndex::from)
.map(|outputindex| {
let value = outputindex_to_value
.get_or_read(outputindex, &outputindex_to_value_mmap)
.unwrap()
.unwrap()
.into_inner();
let output_type = outputindex_to_outputtype
.get_or_read(outputindex, &outputindex_to_outputtype_mmap)
.unwrap()
.unwrap()
.into_inner();
(value, output_type)
})
.fold(
Transacted::default,
|mut transacted, (value, output_type)| {
transacted.iterate(value, output_type);
transacted
},
)
.reduce(Transacted::default, |acc, transacted| acc + transacted)
});
(sent_handle.join().unwrap(), received_handle.join().unwrap())
});
unspendable_supply += received
.by_type
.unspendable
.as_vec()
.into_iter()
.map(|state| state.value)
.sum::<Sats>()
+ height_to_unclaimed_rewards_iter.unwrap_get_inner(height);
opreturn_supply += received.by_type.unspendable.opreturn.value;
if height == Height::new(0) {
received = Transacted::default();
unspendable_supply += Sats::FIFTY_BTC;
} else if height == Height::new(91_842) || height == Height::new(91_880) {
// Need to destroy invalid coinbases due to duplicate txids
if height == Height::new(91_842) {
height_to_sent.entry(Height::new(91_812)).or_default()
} else {
height_to_sent.entry(Height::new(91_722)).or_default()
}
.iterate(Sats::FIFTY_BTC, OutputType::P2PK65);
};
if chain_state_starting_height <= height {
// Push current block state before processing sends and receives
chain_state.push(BlockState {
supply: received.spendable_supply.clone(),
price,
timestamp,
});
self.utxos_vecs.receive(received, height, price);
let unsafe_chain_state = UnsafeSlice::new(&mut chain_state);
height_to_sent.par_iter().for_each(|(height, sent)| unsafe {
(*unsafe_chain_state.get(height.unwrap_to_usize())).supply -=
&sent.spendable_supply;
});
self.utxos_vecs.send(height_to_sent, chain_state.as_slice());
} else {
dbg!(chain_state_starting_height, height);
panic!("temp, just making sure")
}
let mut utxos_vecs = self.utxos_vecs.as_mut_vec();
utxos_vecs
.iter_mut()
.try_for_each(|(_, v)| v.forced_pushed_at(height, exit))?;
self.height_to_unspendable_supply.forced_push_at(
height,
unspendable_supply,
exit,
)?;
self.height_to_opreturn_supply
.forced_push_at(height, opreturn_supply, exit)?;
let date = height_to_date_fixed_iter.unwrap_get_inner(height);
let dateindex = DateIndex::try_from(date).unwrap();
let date_first_height = dateindex_to_first_height_iter.unwrap_get_inner(dateindex);
let date_height_count = dateindex_to_height_count_iter.unwrap_get_inner(dateindex);
let is_date_last_height = date_first_height
+ Height::from(date_height_count).decremented().unwrap()
== height;
let date_price = dateindex_to_close_iter
.as_mut()
.map(|v| is_date_last_height.then(|| *v.unwrap_get_inner(dateindex)));
utxos_vecs.par_iter_mut().try_for_each(|(_, v)| {
v.compute_then_force_push_unrealized_states(
height,
price,
is_date_last_height.then_some(dateindex),
date_price,
exit,
)
})?;
if height != Height::ZERO && height.unwrap_to_usize() % 100_000 == 0 {
info!("Flushing...");
exit.block();
self.flush_vecs(height, exit)?;
exit.release();
}
Ok(())
})?;
exit.block();
info!("Flushing...");
self.flush_vecs(height, exit)?;
// Save chain state
self.chain_state.truncate_if_needed(Height::ZERO)?;
mem::take(&mut chain_state)
.into_iter()
.for_each(|block_state| {
self.chain_state.push(block_state.supply);
});
self.chain_state.flush()?;
info!("Computing rest...");
// Compute other vecs from height vecs
self.utxos_vecs
.as_mut_vec()
.par_iter_mut()
.try_for_each(|(_, v)| {
v.compute_rest(indexer, indexes, fetched, starting_indexes, exit)
})?;
self.indexes_to_unspendable_supply.compute_rest(
indexer,
indexes,
fetched,
starting_indexes,
exit,
Some(&self.height_to_unspendable_supply),
)?;
self.indexes_to_opreturn_supply.compute_rest(
indexer,
indexes,
fetched,
starting_indexes,
exit,
Some(&self.height_to_opreturn_supply),
)?;
exit.release();
Ok(())
}
fn flush_vecs(&mut self, height: Height, exit: &Exit) -> Result<()> {
// Flush rest of values
self.utxos_vecs
.as_mut_vec()
.par_iter_mut()
.try_for_each(|(_, v)| v.safe_flush_stateful_vecs(height, exit))?;
self.height_to_unspendable_supply.safe_flush(exit)?;
self.height_to_opreturn_supply.safe_flush(exit)?;
Ok(())
}
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
[
self.utxos_vecs
.vecs()
.into_iter()
.flat_map(|v| v.vecs())
.collect::<Vec<_>>(),
self.indexes_to_unspendable_supply.vecs(),
self.indexes_to_opreturn_supply.vecs(),
vec![
&self.height_to_unspendable_supply,
&self.height_to_opreturn_supply,
],
]
.into_iter()
.flatten()
.collect::<Vec<_>>()
}
}