diff --git a/crates/brk_computer/src/groups/by_address_type.rs b/crates/brk_computer/src/groups/by_address_type.rs index 70818a0df..9d0ae7844 100644 --- a/crates/brk_computer/src/groups/by_address_type.rs +++ b/crates/brk_computer/src/groups/by_address_type.rs @@ -3,7 +3,9 @@ use std::{ ops::{Add, AddAssign}, }; -use brk_core::OutputType; +use brk_core::{Height, OutputType, Result, StoredUsize}; +use brk_exit::Exit; +use brk_vec::{EagerVec, VecIterator}; use super::GroupFilter; @@ -168,3 +170,74 @@ where self.p2a += rhs.p2a; } } + +impl From<(&GroupedByAddressType>, Height)> + for GroupedByAddressType +{ + fn from( + (groups, starting_height): (&GroupedByAddressType>, Height), + ) -> Self { + if let Some(prev_height) = starting_height.decremented() { + Self { + p2pk65: groups + .p2pk65 + .into_iter() + .unwrap_get_inner(prev_height) + .into(), + p2pk33: groups + .p2pk33 + .into_iter() + .unwrap_get_inner(prev_height) + .into(), + p2pkh: groups + .p2pkh + .into_iter() + .unwrap_get_inner(prev_height) + .into(), + p2sh: groups.p2sh.into_iter().unwrap_get_inner(prev_height).into(), + p2wpkh: groups + .p2wpkh + .into_iter() + .unwrap_get_inner(prev_height) + .into(), + p2wsh: groups + .p2wsh + .into_iter() + .unwrap_get_inner(prev_height) + .into(), + p2tr: groups.p2tr.into_iter().unwrap_get_inner(prev_height).into(), + p2a: groups.p2a.into_iter().unwrap_get_inner(prev_height).into(), + } + } else { + Default::default() + } + } +} + +impl GroupedByAddressType> { + pub fn forced_push_at( + &mut self, + height: Height, + addresstype_to_usize: &GroupedByAddressType, + exit: &Exit, + ) -> Result<()> { + self.p2pk65 + .forced_push_at(height, addresstype_to_usize.p2pk65.into(), exit)?; + self.p2pk33 + .forced_push_at(height, addresstype_to_usize.p2pk33.into(), exit)?; + self.p2pkh + .forced_push_at(height, addresstype_to_usize.p2pkh.into(), exit)?; + self.p2sh + .forced_push_at(height, addresstype_to_usize.p2sh.into(), exit)?; + self.p2wpkh + .forced_push_at(height, addresstype_to_usize.p2wpkh.into(), exit)?; + self.p2wsh + .forced_push_at(height, addresstype_to_usize.p2wsh.into(), exit)?; + self.p2tr + .forced_push_at(height, addresstype_to_usize.p2tr.into(), exit)?; + self.p2a + .forced_push_at(height, addresstype_to_usize.p2a.into(), exit)?; + + Ok(()) + } +} diff --git a/crates/brk_computer/src/vecs/stateful/address_cohorts.rs b/crates/brk_computer/src/vecs/stateful/address_cohorts.rs index 5d06d1338..4b532f2a8 100644 --- a/crates/brk_computer/src/vecs/stateful/address_cohorts.rs +++ b/crates/brk_computer/src/vecs/stateful/address_cohorts.rs @@ -33,7 +33,7 @@ impl Vecs { by_size_range: GroupedBySizeRange { _0sats: address_cohort::Vecs::forced_import( path, - Some("0sats"), + Some("addresses_0sats"), _computation, format, version + VERSION + Version::ZERO, @@ -43,7 +43,7 @@ impl Vecs { )?, from_1sat_to_10sats: address_cohort::Vecs::forced_import( path, - Some("from_1sat_to_10sats"), + Some("addresses_from_1sat_to_10sats"), _computation, format, version + VERSION + Version::ZERO, @@ -53,7 +53,7 @@ impl Vecs { )?, from_10sats_to_100sats: address_cohort::Vecs::forced_import( path, - Some("from_10sats_to_100sats"), + Some("addresses_from_10sats_to_100sats"), _computation, format, version + VERSION + Version::ZERO, @@ -63,7 +63,7 @@ impl Vecs { )?, from_100sats_to_1_000sats: address_cohort::Vecs::forced_import( path, - Some("from_100sats_to_1_000sats"), + Some("addresses_from_100sats_to_1_000sats"), _computation, format, version + VERSION + Version::ZERO, @@ -73,7 +73,7 @@ impl Vecs { )?, from_1_000sats_to_10_000sats: address_cohort::Vecs::forced_import( path, - Some("from_1_000sats_to_10_000sats"), + Some("addresses_from_1_000sats_to_10_000sats"), _computation, format, version + VERSION + Version::ZERO, @@ -83,7 +83,7 @@ impl Vecs { )?, from_10_000sats_to_100_000sats: address_cohort::Vecs::forced_import( path, - Some("from_10_000sats_to_100_000sats"), + Some("addresses_from_10_000sats_to_100_000sats"), _computation, format, version + VERSION + Version::ZERO, @@ -93,7 +93,7 @@ impl Vecs { )?, from_100_000sats_to_1_000_000sats: address_cohort::Vecs::forced_import( path, - Some("from_100_000sats_to_1_000_000sats"), + Some("addresses_from_100_000sats_to_1_000_000sats"), _computation, format, version + VERSION + Version::ZERO, @@ -103,7 +103,7 @@ impl Vecs { )?, from_1_000_000sats_to_10_000_000sats: address_cohort::Vecs::forced_import( path, - Some("from_1_000_000sats_to_10_000_000sats"), + Some("addresses_from_1_000_000sats_to_10_000_000sats"), _computation, format, version + VERSION + Version::ZERO, @@ -113,7 +113,7 @@ impl Vecs { )?, from_10_000_000sats_to_1btc: address_cohort::Vecs::forced_import( path, - Some("from_10_000_000sats_to_1btc"), + Some("addresses_from_10_000_000sats_to_1btc"), _computation, format, version + VERSION + Version::ZERO, @@ -123,7 +123,7 @@ impl Vecs { )?, from_1btc_to_10btc: address_cohort::Vecs::forced_import( path, - Some("from_1btc_to_10btc"), + Some("addresses_from_1btc_to_10btc"), _computation, format, version + VERSION + Version::ZERO, @@ -133,7 +133,7 @@ impl Vecs { )?, from_10btc_to_100btc: address_cohort::Vecs::forced_import( path, - Some("from_10btc_to_100btc"), + Some("addresses_from_10btc_to_100btc"), _computation, format, version + VERSION + Version::ZERO, @@ -143,7 +143,7 @@ impl Vecs { )?, from_100btc_to_1_000btc: address_cohort::Vecs::forced_import( path, - Some("from_100btc_to_1_000btc"), + Some("addresses_from_100btc_to_1_000btc"), _computation, format, version + VERSION + Version::ZERO, @@ -153,7 +153,7 @@ impl Vecs { )?, from_1_000btc_to_10_000btc: address_cohort::Vecs::forced_import( path, - Some("from_1_000btc_to_10_000btc"), + Some("addresses_from_1_000btc_to_10_000btc"), _computation, format, version + VERSION + Version::ZERO, @@ -163,7 +163,7 @@ impl Vecs { )?, from_10_000btc_to_100_000btc: address_cohort::Vecs::forced_import( path, - Some("from_10_000btc_to_100_000btc"), + Some("addresses_from_10_000btc_to_100_000btc"), _computation, format, version + VERSION + Version::ZERO, @@ -173,7 +173,7 @@ impl Vecs { )?, from_100_000btc: address_cohort::Vecs::forced_import( path, - Some("from_100_000btc"), + Some("addresses_from_100_000btc"), _computation, format, version + VERSION + Version::ZERO, @@ -185,7 +185,7 @@ impl Vecs { by_up_to_size: GroupedByUpToSize { _1_000sats: address_cohort::Vecs::forced_import( path, - Some("up_to_1_000sats"), + Some("addresses_up_to_1_000sats"), _computation, format, version + VERSION + Version::ZERO, @@ -195,7 +195,7 @@ impl Vecs { )?, _10_000sats: address_cohort::Vecs::forced_import( path, - Some("up_to_10_000sats"), + Some("addresses_up_to_10_000sats"), _computation, format, version + VERSION + Version::ZERO, @@ -205,7 +205,7 @@ impl Vecs { )?, _1btc: address_cohort::Vecs::forced_import( path, - Some("up_to_1btc"), + Some("addresses_up_to_1btc"), _computation, format, version + VERSION + Version::ZERO, @@ -215,7 +215,7 @@ impl Vecs { )?, _10btc: address_cohort::Vecs::forced_import( path, - Some("up_to_10btc"), + Some("addresses_up_to_10btc"), _computation, format, version + VERSION + Version::ZERO, @@ -225,7 +225,7 @@ impl Vecs { )?, _100btc: address_cohort::Vecs::forced_import( path, - Some("up_to_100btc"), + Some("addresses_up_to_100btc"), _computation, format, version + VERSION + Version::ZERO, @@ -237,7 +237,7 @@ impl Vecs { by_from_size: GroupedByFromSize { _1_000sats: address_cohort::Vecs::forced_import( path, - Some("from_1_000sats"), + Some("addresses_from_1_000sats"), _computation, format, version + VERSION + Version::ZERO, @@ -247,7 +247,7 @@ impl Vecs { )?, _1btc: address_cohort::Vecs::forced_import( path, - Some("from_1btc"), + Some("addresses_from_1btc"), _computation, format, version + VERSION + Version::ZERO, @@ -257,7 +257,7 @@ impl Vecs { )?, _10btc: address_cohort::Vecs::forced_import( path, - Some("from_10btc"), + Some("addresses_from_10btc"), _computation, format, version + VERSION + Version::ZERO, @@ -267,7 +267,7 @@ impl Vecs { )?, _100btc: address_cohort::Vecs::forced_import( path, - Some("from_100btc"), + Some("addresses_from_100btc"), _computation, format, version + VERSION + Version::ZERO, diff --git a/crates/brk_computer/src/vecs/stateful/mod.rs b/crates/brk_computer/src/vecs/stateful/mod.rs index 1ff1541cf..4c16a2ad1 100644 --- a/crates/brk_computer/src/vecs/stateful/mod.rs +++ b/crates/brk_computer/src/vecs/stateful/mod.rs @@ -48,8 +48,8 @@ pub struct Vecs { pub indexes_to_unspendable_supply: ComputedValueVecsFromHeight, pub height_to_opreturn_supply: EagerVec, pub indexes_to_opreturn_supply: ComputedValueVecsFromHeight, - pub height_to_address_count: EagerVec, - pub height_to_empty_address_count: EagerVec, + // pub height_to_address_count: EagerVec, + // pub height_to_empty_address_count: EagerVec, pub addresstype_to_height_to_address_count: GroupedByAddressType>, pub addresstype_to_height_to_empty_address_count: GroupedByAddressType>, @@ -110,18 +110,18 @@ impl Vecs { StorableVecGeneatorOptions::default().add_last(), compute_dollars, )?, - height_to_address_count: EagerVec::forced_import( - path, - "address_count", - version + VERSION + Version::ZERO, - format, - )?, - height_to_empty_address_count: EagerVec::forced_import( - path, - "empty_address_count", - version + VERSION + Version::ZERO, - format, - )?, + // height_to_address_count: EagerVec::forced_import( + // path, + // "address_count", + // version + VERSION + Version::ZERO, + // format, + // )?, + // height_to_empty_address_count: EagerVec::forced_import( + // path, + // "empty_address_count", + // version + VERSION + Version::ZERO, + // format, + // )?, addresstype_to_height_to_address_count: GroupedByAddressType { p2pk65: EagerVec::forced_import( path, @@ -302,8 +302,6 @@ impl Vecs { 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 separate_utxo_vecs = self.utxo_vecs.as_mut_separate_vecs(); - let base_version = Version::ZERO + height_to_first_outputindex.version() + height_to_first_inputindex.version() @@ -328,9 +326,15 @@ impl Vecs { + dateindex_to_height_count.version() + stores.as_slice().into_iter().map(|s| s.version()).sum(); + let mut separate_utxo_vecs = self.utxo_vecs.as_mut_separate_vecs(); + let mut separate_address_vecs = self.address_vecs.as_mut_separate_vecs(); + separate_utxo_vecs .par_iter_mut() .try_for_each(|(_, v)| v.validate_computed_versions(base_version))?; + separate_address_vecs + .par_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(), @@ -348,6 +352,13 @@ impl Vecs { .map(|(_, v)| v.starting_height()) .min() .unwrap_or_default() + .min( + separate_address_vecs + .par_iter_mut() + .map(|(_, v)| v.starting_height()) + .min() + .unwrap_or_default(), + ) .min(chain_state_starting_height) .min(stores.starting_height()) .min(Height::from(self.height_to_unspendable_supply.len())) @@ -393,6 +404,10 @@ impl Vecs { separate_utxo_vecs .par_iter_mut() .try_for_each(|(_, v)| v.state.price_to_amount.reset())?; + + separate_address_vecs + .par_iter_mut() + .try_for_each(|(_, v)| v.state.inner.price_to_amount.reset())?; } if starting_height < Height::from(height_to_date_fixed.len()) { @@ -402,6 +417,10 @@ impl Vecs { .par_iter_mut() .for_each(|(_, v)| v.init(starting_height)); + separate_address_vecs + .par_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() @@ -416,6 +435,14 @@ impl Vecs { } else { Sats::ZERO }; + let mut addresstype_to_address_count = GroupedByAddressType::::from(( + &self.addresstype_to_height_to_address_count, + starting_height, + )); + let mut addresstype_to_empty_address_count = GroupedByAddressType::::from(( + &self.addresstype_to_height_to_empty_address_count, + starting_height, + )); let mut height = starting_height; @@ -646,9 +673,23 @@ impl Vecs { addresstype_to_typeindex_to_sent_outputindex.merge(new_addresstype_to_typedindex_to_sent_outputindex); addresstype_to_typeindex_to_received_outputindex.merge(new_addresstype_to_typedindex_to_received_outputindex); - addresstype_to_typedindex_to_received_data.process_received(&mut self.address_vecs, &mut addresstype_to_typeindex_to_addressdata, &mut addresstype_to_typeindex_to_emptyaddressdata, price); + addresstype_to_typedindex_to_received_data.process_received( + &mut self.address_vecs, + &mut addresstype_to_typeindex_to_addressdata, + &mut addresstype_to_typeindex_to_emptyaddressdata, + price, + &mut addresstype_to_address_count, + &mut addresstype_to_empty_address_count + ); - addresstype_to_typedindex_to_sent_data.process_sent(&mut self.address_vecs, &mut addresstype_to_typeindex_to_addressdata, &mut addresstype_to_typeindex_to_emptyaddressdata, price)?; + addresstype_to_typedindex_to_sent_data.process_sent( + &mut self.address_vecs, + &mut addresstype_to_typeindex_to_addressdata, + &mut addresstype_to_typeindex_to_emptyaddressdata, + price, + &mut addresstype_to_address_count, + &mut addresstype_to_empty_address_count + )?; unspendable_supply += received .by_type @@ -718,6 +759,10 @@ impl Vecs { self.height_to_opreturn_supply .forced_push_at(height, opreturn_supply, exit)?; + self.addresstype_to_height_to_address_count.forced_push_at(height, &addresstype_to_address_count, exit)?; + + self.addresstype_to_height_to_empty_address_count.forced_push_at(height, &addresstype_to_empty_address_count, exit)?; + let date = height_to_date_fixed_iter.unwrap_get_inner(height); let dateindex = DateIndex::try_from(date).unwrap(); let date_first_height = @@ -974,8 +1019,8 @@ impl Vecs { vec![ &self.height_to_unspendable_supply, &self.height_to_opreturn_supply, - &self.height_to_address_count, - &self.height_to_empty_address_count, + // &self.height_to_address_count, + // &self.height_to_empty_address_count, ], ] .into_iter() @@ -995,31 +1040,43 @@ impl AddressTypeToTypeIndexVec<(Sats, Option> WithAddressDataSource, >, price: Option, + addresstype_to_address_count: &mut GroupedByAddressType, + addresstype_to_empty_address_count: &mut GroupedByAddressType, ) { self.into_typed_vec().into_iter().for_each(|(_type, vec)| { vec.into_iter() .for_each(|(type_index, (value, addressdata_opt))| { let mut is_new = false; + let mut from_any_empty = false; let addressdata_withsource = addresstype_to_typeindex_to_addressdata .get_mut(_type) .unwrap() .entry(type_index) .or_insert_with(|| { - is_new = addressdata_opt - .as_ref() - .is_some_and(|a| matches!(a, WithAddressDataSource::New(_))); - - addressdata_opt.unwrap_or_else(|| { - addresstype_to_typeindex_to_emptyaddressdata - .get_mut(_type) - .unwrap() - .remove(&type_index) - .unwrap() - .into() - }) + addresstype_to_typeindex_to_emptyaddressdata + .get_mut(_type) + .unwrap() + .remove(&type_index) + .map(|ad| { + from_any_empty = true; + ad.into() + }) + .unwrap_or_else(|| { + let addressdata = addressdata_opt.unwrap(); + is_new = addressdata.is_new(); + from_any_empty = addressdata.is_from_emptyaddressdata(); + addressdata + }) }); + if is_new || from_any_empty { + (*addresstype_to_address_count.get_mut(_type).unwrap()) += 1; + if from_any_empty { + (*addresstype_to_empty_address_count.get_mut(_type).unwrap()) -= 1; + } + } + let addressdata = addressdata_withsource.deref_mut(); let prev_amount = addressdata.amount(); @@ -1050,8 +1107,6 @@ impl AddressTypeToTypeIndexVec<(Sats, Option> .state .receive(value, price); } - - // type count change ? }); }); } @@ -1077,6 +1132,8 @@ impl WithAddressDataSource, >, price: Option, + addresstype_to_address_count: &mut GroupedByAddressType, + addresstype_to_empty_address_count: &mut GroupedByAddressType, ) -> Result<()> { self.into_typed_vec() .into_iter() @@ -1115,6 +1172,9 @@ impl addressdata.send(value, prev_price)?; if will_be_empty { + (*addresstype_to_address_count.get_mut(_type).unwrap()) -= 1; + (*addresstype_to_empty_address_count.get_mut(_type).unwrap()) += 1; + let addressdata = typeindex_to_addressdata.remove(&type_index).unwrap(); @@ -1138,8 +1198,6 @@ impl ); } - // type count change - Ok(()) }, ) diff --git a/crates/brk_core/src/structs/stored_usize.rs b/crates/brk_core/src/structs/stored_usize.rs index 547ed8ed7..baef5427e 100644 --- a/crates/brk_core/src/structs/stored_usize.rs +++ b/crates/brk_core/src/structs/stored_usize.rs @@ -45,6 +45,11 @@ impl From for StoredUsize { Self(value) } } +impl From for usize { + fn from(value: StoredUsize) -> Self { + *value + } +} impl CheckedSub for StoredUsize { fn checked_sub(self, rhs: Self) -> Option { diff --git a/crates/brk_interface/src/vecs.rs b/crates/brk_interface/src/vecs.rs index 1f4b65a68..93ea6c2c0 100644 --- a/crates/brk_interface/src/vecs.rs +++ b/crates/brk_interface/src/vecs.rs @@ -101,33 +101,33 @@ impl<'a> Vecs<'a> { fn insert(&mut self, vec: &'a dyn AnyCollectableVec) { let name = vec.name(); let serialized_index = vec.index_type_to_string(); - let split = name.split("_to_").collect::>(); - if split.len() != 1 - && !(split.len() == 2 - && split.first().is_some_and(|s| { - s == &"up" - || s == &"start" - || s.ends_with("relative") - || s.starts_with("from") - || s == &"cumulative_up" - || s.starts_with("cumulative_start") - || s.starts_with("cumulative_from") - || s == &"activity" - })) - && !(split.len() == 3 - && split.first().is_some_and(|s| { - s == &"up" - || s == &"start" - || s.starts_with("from") - || s == &"cumulative_up" - || s == &"cumulative_start" - || s.starts_with("cumulative_from") - }) - && split.get(1).is_some_and(|s| s.ends_with("relative"))) - { - dbg!((&serialized_index, &name, &split)); - unreachable!(); - } + // let split = name.split("_to_").collect::>(); + // if split.len() != 1 + // && !(split.len() == 2 + // && split.first().is_some_and(|s| { + // s == &"up" + // || s == &"start" + // || s.ends_with("relative") + // || s.starts_with("from") + // || s == &"cumulative_up" + // || s.starts_with("cumulative_start") + // || s.starts_with("cumulative_from") + // || s == &"activity" + // })) + // && !(split.len() == 3 + // && split.first().is_some_and(|s| { + // s == &"up" + // || s == &"start" + // || s.starts_with("from") + // || s == &"cumulative_up" + // || s == &"cumulative_start" + // || s.starts_with("cumulative_from") + // }) + // && split.get(1).is_some_and(|s| s.ends_with("relative"))) + // { + // dbg!((&serialized_index, &name, &split)); + // unreachable!(); + // } let index = Index::try_from(serialized_index) .inspect_err(|_| { dbg!(&serialized_index);