use brk_error::Result; use brk_indexer::Indexer; use brk_types::{CheckedSub, Dollars, Halving, Sats}; use vecdb::{Exit, ReadableVec, VecIndex}; use super::Vecs; use crate::{ blocks, indexes, internal::{RatioDollarsBp32, RatioSatsBp16}, price, transactions, }; impl Vecs { #[allow(clippy::too_many_arguments)] pub(crate) fn compute( &mut self, indexer: &Indexer, indexes: &indexes::Vecs, lookback: &blocks::LookbackVecs, transactions: &transactions::Vecs, prices: &price::Vecs, exit: &Exit, ) -> Result<()> { let starting_height = indexer.safe_lengths().height; // coinbase and fees are independent — parallelize let window_starts = lookback.window_starts(); let (r_coinbase, r_fees) = rayon::join( || { self.coinbase.compute(starting_height, prices, exit, |vec| { let mut txout_cursor = indexer.vecs.transactions.first_txout_index.cursor(); let mut count_cursor = indexes.tx_index.output_count.cursor(); vec.compute_transform( starting_height, &indexer.vecs.transactions.first_tx_index, |(height, tx_index, ..)| { let ti = tx_index.to_usize(); txout_cursor.advance(ti - txout_cursor.position()); let first_txout_index = txout_cursor.next().unwrap().to_usize(); count_cursor.advance(ti - count_cursor.position()); let output_count: usize = count_cursor.next().unwrap().into(); let sats = indexer.vecs.outputs.value.fold_range_at( first_txout_index, first_txout_index + output_count, Sats::ZERO, |acc, v| acc + v, ); (height, sats) }, exit, )?; Ok(()) }) }, || { self.fees .compute(starting_height, &window_starts, prices, exit, |vec| { vec.compute_sum_from_indexes( starting_height, &indexer.vecs.transactions.first_tx_index, &indexes.height.tx_index_count, &transactions.fees.fee.tx_index, exit, )?; Ok(()) }) }, ); r_coinbase?; r_fees?; self.subsidy.block.sats.compute_transform2( starting_height, &self.coinbase.block.sats, &self.fees.block.sats, |(height, coinbase, fees, ..)| { ( height, coinbase.checked_sub(fees).unwrap_or_else(|| { panic!("coinbase {coinbase:?} < fees {fees:?} at {height:?}") }), ) }, exit, )?; self.subsidy.compute_rest(starting_height, prices, exit)?; self.output_volume.compute_subtract( starting_height, &transactions.volume.transfer_volume.block.sats, &self.fees.block.sats, exit, )?; self.unclaimed.block.sats.compute_transform( starting_height, &self.subsidy.block.sats, |(height, subsidy, ..)| { let halving = Halving::from(height); let expected = Sats::FIFTY_BTC / 2_usize.pow(halving.to_usize() as u32); (height, expected.checked_sub(subsidy).unwrap()) }, exit, )?; self.unclaimed.compute(prices, starting_height, exit)?; self.fee_dominance .compute_binary::( starting_height, &self.fees.cumulative.sats.height, &self.coinbase.cumulative.sats.height, self.fees.sum.as_array().map(|w| &w.sats.height), self.coinbase.sum.as_array().map(|w| &w.sats.height), exit, )?; self.fee_to_subsidy_ratio .compute_binary::( starting_height, self.coinbase.sum.as_array().map(|w| &w.usd.height), self.fees.sum.as_array().map(|w| &w.usd.height), exit, )?; Ok(()) } }