use brk_error::Result;
use brk_indexer::Indexer;
use brk_types::{Height, OutputType, Sats, TxOutIndex};
use vecdb::{AnyStoredVec, AnyVec, Exit, ReadableVec, VecIndex, WritableVec};
use super::Vecs;
use crate::price;
impl Vecs {
pub(crate) fn compute(
&mut self,
indexer: &Indexer,
prices: &price::Vecs,
exit: &Exit,
) -> Result<()> {
let starting_lengths = indexer.safe_lengths();
let height_vec = &mut self.op_return.cumulative.sats.height;
let dep_version = indexer.vecs.outputs.first_txout_index.version()
+ indexer.vecs.outputs.output_type.version()
+ indexer.vecs.outputs.value.version();
height_vec.validate_computed_version_or_reset(dep_version)?;
let target_len = indexer.vecs.outputs.first_txout_index.len();
if target_len == 0 {
self.op_return
.compute_cents(starting_lengths.height, prices, exit)?;
return Ok(());
}
let target_height = Height::from(target_len - 1);
let current_len = height_vec.len();
let starting_height = Height::from(current_len.min(starting_lengths.height.to_usize()));
if starting_height <= target_height {
let first_txout_indexes: Vec<TxOutIndex> =
indexer.vecs.outputs.first_txout_index.collect_range_at(
starting_height.to_usize(),
target_height.to_usize() + 2.min(indexer.vecs.outputs.first_txout_index.len()),
);
let mut output_types_buf: Vec<OutputType> = Vec::new();
let mut values_buf: Vec<Sats> = Vec::new();
let mut cumulative = starting_height
.decremented()
.and_then(|height| height_vec.collect_one(height))
.unwrap_or_default();
height_vec.truncate_if_needed(starting_height)?;
for h in starting_height.to_usize()..=target_height.to_usize() {
let local_idx = h - starting_height.to_usize();
let first_txout_index = first_txout_indexes[local_idx];
let next_first_txout_index =
if let Some(&next) = first_txout_indexes.get(local_idx + 1) {
next
} else {
TxOutIndex::from(indexer.vecs.outputs.value.len())
};
let out_start = first_txout_index.to_usize();
let out_end = next_first_txout_index.to_usize();
indexer.vecs.outputs.output_type.collect_range_into_at(
out_start,
out_end,
&mut output_types_buf,
);
indexer.vecs.outputs.value.collect_range_into_at(
out_start,
out_end,
&mut values_buf,
);
let mut op_return_value = Sats::ZERO;
for (ot, val) in output_types_buf.iter().zip(values_buf.iter()) {
if *ot == OutputType::OpReturn {
op_return_value += *val;
}
}
cumulative += op_return_value;
height_vec.push(cumulative);
}
height_vec.write()?;
}
self.op_return
.compute_cents(starting_lengths.height, prices, exit)?;
Ok(())
}
}