website: snapshot

This commit is contained in:
nym21
2026-02-02 18:39:42 +01:00
parent cf4bc470e4
commit b23d20ea05
44 changed files with 2637 additions and 2800 deletions
+4 -4
View File
@@ -368,7 +368,7 @@ const _I27: &[Index] = &[Index::TxIndex];
const _I28: &[Index] = &[Index::UnknownOutputIndex];
const _I29: &[Index] = &[Index::WeekIndex];
const _I30: &[Index] = &[Index::YearIndex];
const _I31: &[Index] = &[Index::LoadedAddressIndex];
const _I31: &[Index] = &[Index::FundedAddressIndex];
const _I32: &[Index] = &[Index::EmptyAddressIndex];
#[inline]
@@ -829,7 +829,7 @@ impl<T: DeserializeOwned> MetricPattern<T> for MetricPattern30<T> { fn get(&self
pub struct MetricPattern31By<T> { client: Arc<BrkClientBase>, name: Arc<str>, _marker: std::marker::PhantomData<T> }
impl<T: DeserializeOwned> MetricPattern31By<T> {
pub fn loadedaddressindex(&self) -> MetricEndpointBuilder<T> { _ep(&self.client, &self.name, Index::LoadedAddressIndex) }
pub fn loadedaddressindex(&self) -> MetricEndpointBuilder<T> { _ep(&self.client, &self.name, Index::FundedAddressIndex) }
}
pub struct MetricPattern31<T> { name: Arc<str>, pub by: MetricPattern31By<T> }
@@ -5112,7 +5112,7 @@ pub struct MetricsTree_Distribution {
pub total_addr_count: AllP2aP2pk33P2pk65P2pkhP2shP2trP2wpkhP2wshPattern,
pub new_addr_count: MetricsTree_Distribution_NewAddrCount,
pub growth_rate: MetricsTree_Distribution_GrowthRate,
pub loadedaddressindex: MetricPattern31<LoadedAddressIndex>,
pub loadedaddressindex: MetricPattern31<FundedAddressIndex>,
pub emptyaddressindex: MetricPattern32<EmptyAddressIndex>,
}
@@ -5165,7 +5165,7 @@ impl MetricsTree_Distribution_AnyAddressIndexes {
/// Metrics tree node.
pub struct MetricsTree_Distribution_AddressesData {
pub loaded: MetricPattern31<LoadedAddressData>,
pub loaded: MetricPattern31<FundedAddressData>,
pub empty: MetricPattern32<EmptyAddressData>,
}
+2 -2
View File
@@ -2,13 +2,13 @@ use brk_traversable::Traversable;
#[derive(Debug, Default, Traversable)]
pub struct ByAnyAddress<T> {
pub loaded: T,
pub funded: T,
pub empty: T,
}
impl<T> ByAnyAddress<Option<T>> {
pub fn take(&mut self) {
self.loaded.take();
self.funded.take();
self.empty.take();
}
}
+29 -9
View File
@@ -36,27 +36,47 @@ fn run() -> Result<()> {
let start = Instant::now();
let mut buf = Vec::new();
empty_data.write_json(Some(empty_data.len() - 1), Some(empty_data.len()), &mut buf)?;
println!("emptyaddressdata last item JSON: {}", String::from_utf8_lossy(&buf));
println!(
"emptyaddressdata last item JSON: {}",
String::from_utf8_lossy(&buf)
);
println!("Time for BytesVec write_json: {:?}", start.elapsed());
// Test emptyaddressindex (LazyVecFrom1 wrapper) - computed access
let empty_index = &computer.distribution.emptyaddressindex;
println!("\nemptyaddressindex (LazyVecFrom1) len: {}", empty_index.len());
println!(
"\nemptyaddressindex (LazyVecFrom1) len: {}",
empty_index.len()
);
let start = Instant::now();
let mut buf = Vec::new();
empty_index.write_json(Some(empty_index.len() - 1), Some(empty_index.len()), &mut buf)?;
println!("emptyaddressindex last item JSON: {}", String::from_utf8_lossy(&buf));
empty_index.write_json(
Some(empty_index.len() - 1),
Some(empty_index.len()),
&mut buf,
)?;
println!(
"emptyaddressindex last item JSON: {}",
String::from_utf8_lossy(&buf)
);
println!("Time for LazyVecFrom1 write_json: {:?}", start.elapsed());
// Compare with loaded versions
let loaded_data = &computer.distribution.addresses_data.loaded;
println!("\nloadedaddressdata (BytesVec) len: {}", loaded_data.len());
// Compare with funded versions
let funded_data = &computer.distribution.addresses_data.funded;
println!("\nfundedaddressdata (BytesVec) len: {}", funded_data.len());
let start = Instant::now();
let mut buf = Vec::new();
loaded_data.write_json(Some(loaded_data.len() - 1), Some(loaded_data.len()), &mut buf)?;
println!("loadedaddressdata last item JSON: {}", String::from_utf8_lossy(&buf));
funded_data.write_json(
Some(funded_data.len() - 1),
Some(funded_data.len()),
&mut buf,
)?;
println!(
"fundedaddressdata last item JSON: {}",
String::from_utf8_lossy(&buf)
);
println!("Time for BytesVec write_json: {:?}", start.elapsed());
Ok(())
@@ -1,7 +1,7 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{
EmptyAddressData, EmptyAddressIndex, Height, LoadedAddressData, LoadedAddressIndex, Version,
EmptyAddressData, EmptyAddressIndex, FundedAddressData, FundedAddressIndex, Height, Version,
};
use rayon::prelude::*;
use vecdb::{
@@ -10,10 +10,10 @@ use vecdb::{
const SAVED_STAMPED_CHANGES: u16 = 10;
/// Storage for both loaded and empty address data.
/// Storage for both funded and empty address data.
#[derive(Clone, Traversable)]
pub struct AddressesDataVecs {
pub loaded: BytesVec<LoadedAddressIndex, LoadedAddressData>,
pub funded: BytesVec<FundedAddressIndex, FundedAddressData>,
pub empty: BytesVec<EmptyAddressIndex, EmptyAddressData>,
}
@@ -21,8 +21,8 @@ impl AddressesDataVecs {
/// Import from database.
pub fn forced_import(db: &Database, version: Version) -> Result<Self> {
Ok(Self {
loaded: BytesVec::forced_import_with(
ImportOptions::new(db, "loadedaddressdata", version)
funded: BytesVec::forced_import_with(
ImportOptions::new(db, "fundedaddressdata", version)
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
)?,
empty: BytesVec::forced_import_with(
@@ -32,31 +32,31 @@ impl AddressesDataVecs {
})
}
/// Get minimum stamped height across loaded and empty data.
/// Get minimum stamped height across funded and empty data.
pub fn min_stamped_height(&self) -> Height {
Height::from(self.loaded.stamp())
Height::from(self.funded.stamp())
.incremented()
.min(Height::from(self.empty.stamp()).incremented())
}
/// Rollback both loaded and empty data to before the given stamp.
/// Rollback both funded and empty data to before the given stamp.
pub fn rollback_before(&mut self, stamp: Stamp) -> Result<[Stamp; 2]> {
Ok([
self.loaded.rollback_before(stamp)?,
self.funded.rollback_before(stamp)?,
self.empty.rollback_before(stamp)?,
])
}
/// Reset both loaded and empty data.
/// Reset both funded and empty data.
pub fn reset(&mut self) -> Result<()> {
self.loaded.reset()?;
self.funded.reset()?;
self.empty.reset()?;
Ok(())
}
/// Flush both loaded and empty data with stamp.
/// Flush both funded and empty data with stamp.
pub fn write(&mut self, stamp: Stamp, with_changes: bool) -> Result<()> {
self.loaded
self.funded
.stamped_write_maybe_with_changes(stamp, with_changes)?;
self.empty
.stamped_write_maybe_with_changes(stamp, with_changes)?;
@@ -66,7 +66,7 @@ impl AddressesDataVecs {
/// Returns a parallel iterator over all vecs for parallel writing.
pub fn par_iter_mut(&mut self) -> impl ParallelIterator<Item = &mut dyn AnyStoredVec> {
vec![
&mut self.loaded as &mut dyn AnyStoredVec,
&mut self.funded as &mut dyn AnyStoredVec,
&mut self.empty as &mut dyn AnyStoredVec,
]
.into_par_iter()
@@ -136,7 +136,7 @@ define_any_address_indexes_vecs!(
impl AnyAddressIndexesVecs {
/// Process index updates in parallel by address type.
/// Accepts two maps (e.g. from empty and loaded processing) and merges per-thread.
/// Accepts two maps (e.g. from empty and funded processing) and merges per-thread.
/// Updates existing entries and pushes new ones (sorted).
/// Returns (update_count, push_count).
pub fn par_batch_update(
+22 -22
View File
@@ -1,5 +1,5 @@
use brk_cohort::ByAddressType;
use brk_types::{AnyAddressDataIndexEnum, LoadedAddressData, OutputType, TypeIndex};
use brk_types::{AnyAddressDataIndexEnum, FundedAddressData, OutputType, TypeIndex};
use crate::distribution::{
address::{AddressTypeToTypeIndexMap, AddressesDataVecs, AnyAddressIndexesVecs},
@@ -7,7 +7,7 @@ use crate::distribution::{
};
use super::super::cohort::{
EmptyAddressDataWithSource, LoadedAddressDataWithSource, TxIndexVec, WithAddressDataSource,
EmptyAddressDataWithSource, FundedAddressDataWithSource, TxIndexVec, WithAddressDataSource,
update_tx_counts,
};
use super::lookup::AddressLookup;
@@ -15,7 +15,7 @@ use super::lookup::AddressLookup;
/// Cache for address data within a flush interval.
pub struct AddressCache {
/// Addresses with non-zero balance
loaded: AddressTypeToTypeIndexMap<LoadedAddressDataWithSource>,
funded: AddressTypeToTypeIndexMap<FundedAddressDataWithSource>,
/// Addresses that became empty (zero balance)
empty: AddressTypeToTypeIndexMap<EmptyAddressDataWithSource>,
}
@@ -29,15 +29,15 @@ impl Default for AddressCache {
impl AddressCache {
pub fn new() -> Self {
Self {
loaded: AddressTypeToTypeIndexMap::default(),
funded: AddressTypeToTypeIndexMap::default(),
empty: AddressTypeToTypeIndexMap::default(),
}
}
/// Check if address is in cache (either loaded or empty).
/// Check if address is in cache (either funded or empty).
#[inline]
pub fn contains(&self, address_type: OutputType, typeindex: TypeIndex) -> bool {
self.loaded
self.funded
.get(address_type)
.is_some_and(|m| m.contains_key(&typeindex))
|| self
@@ -46,24 +46,24 @@ impl AddressCache {
.is_some_and(|m| m.contains_key(&typeindex))
}
/// Merge address data into loaded cache.
/// Merge address data into funded cache.
#[inline]
pub fn merge_loaded(&mut self, data: AddressTypeToTypeIndexMap<LoadedAddressDataWithSource>) {
self.loaded.merge_mut(data);
pub fn merge_funded(&mut self, data: AddressTypeToTypeIndexMap<FundedAddressDataWithSource>) {
self.funded.merge_mut(data);
}
/// Create an AddressLookup view into this cache.
#[inline]
pub fn as_lookup(&mut self) -> AddressLookup<'_> {
AddressLookup {
loaded: &mut self.loaded,
funded: &mut self.funded,
empty: &mut self.empty,
}
}
/// Update transaction counts for addresses.
pub fn update_tx_counts(&mut self, txindex_vecs: AddressTypeToTypeIndexMap<TxIndexVec>) {
update_tx_counts(&mut self.loaded, &mut self.empty, txindex_vecs);
update_tx_counts(&mut self.funded, &mut self.empty, txindex_vecs);
}
/// Take the cache contents for flushing, leaving empty caches.
@@ -71,18 +71,18 @@ impl AddressCache {
&mut self,
) -> (
AddressTypeToTypeIndexMap<EmptyAddressDataWithSource>,
AddressTypeToTypeIndexMap<LoadedAddressDataWithSource>,
AddressTypeToTypeIndexMap<FundedAddressDataWithSource>,
) {
(
std::mem::take(&mut self.empty),
std::mem::take(&mut self.loaded),
std::mem::take(&mut self.funded),
)
}
}
/// Load address data from storage or create new.
///
/// Returns None if address is already in cache (loaded or empty).
/// Returns None if address is already in cache (funded or empty).
#[allow(clippy::too_many_arguments)]
pub fn load_uncached_address_data(
address_type: OutputType,
@@ -92,11 +92,11 @@ pub fn load_uncached_address_data(
vr: &VecsReaders,
any_address_indexes: &AnyAddressIndexesVecs,
addresses_data: &AddressesDataVecs,
) -> Option<LoadedAddressDataWithSource> {
) -> Option<FundedAddressDataWithSource> {
// Check if this is a new address (typeindex >= first for this height)
let first = *first_addressindexes.get(address_type).unwrap();
if first <= typeindex {
return Some(WithAddressDataSource::New(LoadedAddressData::default()));
return Some(WithAddressDataSource::New(FundedAddressData::default()));
}
// Skip if already in cache
@@ -109,13 +109,13 @@ pub fn load_uncached_address_data(
let anyaddressindex = any_address_indexes.get(address_type, typeindex, reader);
Some(match anyaddressindex.to_enum() {
AnyAddressDataIndexEnum::Loaded(loaded_index) => {
let reader = &vr.anyaddressindex_to_anyaddressdata.loaded;
AnyAddressDataIndexEnum::Funded(funded_index) => {
let reader = &vr.anyaddressindex_to_anyaddressdata.funded;
// Use get_any_or_read_unwrap to check updated layer (needed after rollback)
let loaded_data = addresses_data
.loaded
.get_any_or_read_unwrap(loaded_index, reader);
WithAddressDataSource::FromLoaded(loaded_index, loaded_data)
let funded_data = addresses_data
.funded
.get_any_or_read_unwrap(funded_index, reader);
WithAddressDataSource::FromFunded(funded_index, funded_data)
}
AnyAddressDataIndexEnum::Empty(empty_index) => {
let reader = &vr.anyaddressindex_to_anyaddressdata.empty;
+13 -13
View File
@@ -1,9 +1,9 @@
use brk_types::{LoadedAddressData, OutputType, TypeIndex};
use brk_types::{FundedAddressData, OutputType, TypeIndex};
use crate::distribution::address::AddressTypeToTypeIndexMap;
use super::super::cohort::{
EmptyAddressDataWithSource, LoadedAddressDataWithSource, WithAddressDataSource,
EmptyAddressDataWithSource, FundedAddressDataWithSource, WithAddressDataSource,
};
/// Tracking status of an address - determines cohort update strategy.
@@ -19,7 +19,7 @@ pub enum TrackingStatus {
/// Context for looking up and storing address data during block processing.
pub struct AddressLookup<'a> {
pub loaded: &'a mut AddressTypeToTypeIndexMap<LoadedAddressDataWithSource>,
pub funded: &'a mut AddressTypeToTypeIndexMap<FundedAddressDataWithSource>,
pub empty: &'a mut AddressTypeToTypeIndexMap<EmptyAddressDataWithSource>,
}
@@ -28,21 +28,21 @@ impl<'a> AddressLookup<'a> {
&mut self,
output_type: OutputType,
type_index: TypeIndex,
) -> (&mut LoadedAddressDataWithSource, TrackingStatus) {
) -> (&mut FundedAddressDataWithSource, TrackingStatus) {
use std::collections::hash_map::Entry;
let map = self.loaded.get_mut(output_type).unwrap();
let map = self.funded.get_mut(output_type).unwrap();
match map.entry(type_index) {
Entry::Occupied(entry) => {
// Address is in cache. Need to determine if it's been processed
// by process_received (added to a cohort) or just loaded this block.
// by process_received (added to a cohort) or just funded this block.
//
// - If wrapper is New AND funded_txo_count == 0: hasn't received yet,
// was just created in process_outputs this block → New
// - If wrapper is New AND funded_txo_count > 0: received in previous
// block but still in cache (no flush) → Tracked
// - If wrapper is FromLoaded: loaded from storage → Tracked
// - If wrapper is FromFunded: funded from storage → Tracked
// - If wrapper is FromEmpty AND utxo_count == 0: still empty → WasEmpty
// - If wrapper is FromEmpty AND utxo_count > 0: already received → Tracked
let status = match entry.get() {
@@ -53,7 +53,7 @@ impl<'a> AddressLookup<'a> {
TrackingStatus::Tracked
}
}
WithAddressDataSource::FromLoaded(..) => TrackingStatus::Tracked,
WithAddressDataSource::FromFunded(..) => TrackingStatus::Tracked,
WithAddressDataSource::FromEmpty(_, data) => {
if data.utxo_count() == 0 {
TrackingStatus::WasEmpty
@@ -71,7 +71,7 @@ impl<'a> AddressLookup<'a> {
return (entry.insert(empty_data.into()), TrackingStatus::WasEmpty);
}
(
entry.insert(WithAddressDataSource::New(LoadedAddressData::default())),
entry.insert(WithAddressDataSource::New(FundedAddressData::default())),
TrackingStatus::New,
)
}
@@ -83,18 +83,18 @@ impl<'a> AddressLookup<'a> {
&mut self,
output_type: OutputType,
type_index: TypeIndex,
) -> &mut LoadedAddressDataWithSource {
self.loaded
) -> &mut FundedAddressDataWithSource {
self.funded
.get_mut(output_type)
.unwrap()
.get_mut(&type_index)
.expect("Address must exist for send")
}
/// Move address from loaded to empty set.
/// Move address from funded to empty set.
pub fn move_to_empty(&mut self, output_type: OutputType, type_index: TypeIndex) {
let data = self
.loaded
.funded
.get_mut(output_type)
.unwrap()
.remove(&type_index)
@@ -1,40 +1,40 @@
use brk_error::Result;
use brk_types::{
AnyAddressIndex, EmptyAddressData, EmptyAddressIndex, LoadedAddressData, LoadedAddressIndex,
AnyAddressIndex, EmptyAddressData, EmptyAddressIndex, FundedAddressData, FundedAddressIndex,
OutputType, TypeIndex,
};
use vecdb::AnyVec;
use crate::distribution::{AddressTypeToTypeIndexMap, AddressesDataVecs};
use super::with_source::{EmptyAddressDataWithSource, LoadedAddressDataWithSource};
use super::with_source::{EmptyAddressDataWithSource, FundedAddressDataWithSource};
/// Process loaded address data updates.
/// Process funded address data updates.
///
/// Handles:
/// - New loaded address: push to loaded storage
/// - Updated loaded address (was loaded): update in place
/// - Transition empty -> loaded: delete from empty, push to loaded
pub fn process_loaded_addresses(
/// - New funded address: push to funded storage
/// - Updated funded address (was funded): update in place
/// - Transition empty -> funded: delete from empty, push to funded
pub fn process_funded_addresses(
addresses_data: &mut AddressesDataVecs,
loaded_updates: AddressTypeToTypeIndexMap<LoadedAddressDataWithSource>,
funded_updates: AddressTypeToTypeIndexMap<FundedAddressDataWithSource>,
) -> Result<AddressTypeToTypeIndexMap<AnyAddressIndex>> {
let total: usize = loaded_updates.iter().map(|(_, m)| m.len()).sum();
let total: usize = funded_updates.iter().map(|(_, m)| m.len()).sum();
let mut updates: Vec<(LoadedAddressIndex, LoadedAddressData)> = Vec::with_capacity(total);
let mut updates: Vec<(FundedAddressIndex, FundedAddressData)> = Vec::with_capacity(total);
let mut deletes: Vec<EmptyAddressIndex> = Vec::with_capacity(total);
let mut pushes: Vec<(OutputType, TypeIndex, LoadedAddressData)> = Vec::with_capacity(total);
let mut pushes: Vec<(OutputType, TypeIndex, FundedAddressData)> = Vec::with_capacity(total);
for (address_type, items) in loaded_updates.into_iter() {
for (address_type, items) in funded_updates.into_iter() {
for (typeindex, source) in items {
match source {
LoadedAddressDataWithSource::New(data) => {
FundedAddressDataWithSource::New(data) => {
pushes.push((address_type, typeindex, data));
}
LoadedAddressDataWithSource::FromLoaded(index, data) => {
FundedAddressDataWithSource::FromFunded(index, data) => {
updates.push((index, data));
}
LoadedAddressDataWithSource::FromEmpty(empty_index, data) => {
FundedAddressDataWithSource::FromEmpty(empty_index, data) => {
deletes.push(empty_index);
pushes.push((address_type, typeindex, data));
}
@@ -49,16 +49,16 @@ pub fn process_loaded_addresses(
// Phase 2: Updates (in-place)
for (index, data) in updates {
addresses_data.loaded.update(index, data)?;
addresses_data.funded.update(index, data)?;
}
// Phase 3: Pushes (fill holes first, then pure pushes)
let mut result = AddressTypeToTypeIndexMap::with_capacity(pushes.len() / 4);
let holes_count = addresses_data.loaded.holes().len();
let holes_count = addresses_data.funded.holes().len();
let mut pushes_iter = pushes.into_iter();
for (address_type, typeindex, data) in pushes_iter.by_ref().take(holes_count) {
let index = addresses_data.loaded.fill_first_hole_or_push(data)?;
let index = addresses_data.funded.fill_first_hole_or_push(data)?;
result
.get_mut(address_type)
.unwrap()
@@ -66,14 +66,14 @@ pub fn process_loaded_addresses(
}
// Pure pushes - no holes remain
addresses_data.loaded.reserve_pushed(pushes_iter.len());
let mut next_index = addresses_data.loaded.len();
addresses_data.funded.reserve_pushed(pushes_iter.len());
let mut next_index = addresses_data.funded.len();
for (address_type, typeindex, data) in pushes_iter {
addresses_data.loaded.push(data);
result
.get_mut(address_type)
.unwrap()
.insert(typeindex, AnyAddressIndex::from(LoadedAddressIndex::from(next_index)));
addresses_data.funded.push(data);
result.get_mut(address_type).unwrap().insert(
typeindex,
AnyAddressIndex::from(FundedAddressIndex::from(next_index)),
);
next_index += 1;
}
@@ -85,7 +85,7 @@ pub fn process_loaded_addresses(
/// Handles:
/// - New empty address: push to empty storage
/// - Updated empty address (was empty): update in place
/// - Transition loaded -> empty: delete from loaded, push to empty
/// - Transition funded -> empty: delete from funded, push to empty
pub fn process_empty_addresses(
addresses_data: &mut AddressesDataVecs,
empty_updates: AddressTypeToTypeIndexMap<EmptyAddressDataWithSource>,
@@ -93,7 +93,7 @@ pub fn process_empty_addresses(
let total: usize = empty_updates.iter().map(|(_, m)| m.len()).sum();
let mut updates: Vec<(EmptyAddressIndex, EmptyAddressData)> = Vec::with_capacity(total);
let mut deletes: Vec<LoadedAddressIndex> = Vec::with_capacity(total);
let mut deletes: Vec<FundedAddressIndex> = Vec::with_capacity(total);
let mut pushes: Vec<(OutputType, TypeIndex, EmptyAddressData)> = Vec::with_capacity(total);
for (address_type, items) in empty_updates.into_iter() {
@@ -105,8 +105,8 @@ pub fn process_empty_addresses(
EmptyAddressDataWithSource::FromEmpty(index, data) => {
updates.push((index, data));
}
EmptyAddressDataWithSource::FromLoaded(loaded_index, data) => {
deletes.push(loaded_index);
EmptyAddressDataWithSource::FromFunded(funded_index, data) => {
deletes.push(funded_index);
pushes.push((address_type, typeindex, data));
}
}
@@ -114,8 +114,8 @@ pub fn process_empty_addresses(
}
// Phase 1: Deletes (creates holes)
for loaded_index in deletes {
addresses_data.loaded.delete(loaded_index);
for funded_index in deletes {
addresses_data.funded.delete(funded_index);
}
// Phase 2: Updates (in-place)
@@ -141,10 +141,10 @@ pub fn process_empty_addresses(
let mut next_index = addresses_data.empty.len();
for (address_type, typeindex, data) in pushes_iter {
addresses_data.empty.push(data);
result
.get_mut(address_type)
.unwrap()
.insert(typeindex, AnyAddressIndex::from(EmptyAddressIndex::from(next_index)));
result.get_mut(address_type).unwrap().insert(
typeindex,
AnyAddressIndex::from(EmptyAddressIndex::from(next_index)),
);
next_index += 1;
}
@@ -2,7 +2,7 @@ use brk_cohort::{AmountBucket, ByAddressType};
use brk_error::Result;
use brk_types::{Age, CentsUnsigned, CheckedSub, Height, Sats, Timestamp, TypeIndex};
use rustc_hash::FxHashSet;
use vecdb::{unlikely, VecIndex};
use vecdb::{VecIndex, unlikely};
use crate::distribution::{
address::{AddressTypeToActivityCounts, HeightToAddressTypeToVec},
@@ -131,7 +131,7 @@ pub fn process_sent(
*type_addr_count -= 1;
*type_empty_count += 1;
// Move from loaded to empty
// Move from funded to empty
lookup.move_to_empty(output_type, type_index);
} else {
// Add to new cohort
@@ -151,7 +151,14 @@ pub fn process_sent(
.state
.as_mut()
.unwrap()
.send(addr_data, value, current_price.unwrap(), prev_price.unwrap(), peak_price.unwrap(), age)?;
.send(
addr_data,
value,
current_price.unwrap(),
prev_price.unwrap(),
peak_price.unwrap(),
age,
)?;
}
}
}
@@ -1,6 +1,6 @@
use crate::distribution::address::AddressTypeToTypeIndexMap;
use super::with_source::{EmptyAddressDataWithSource, LoadedAddressDataWithSource, TxIndexVec};
use super::with_source::{EmptyAddressDataWithSource, FundedAddressDataWithSource, TxIndexVec};
/// Update tx_count for addresses based on unique transactions they participated in.
///
@@ -8,10 +8,10 @@ use super::with_source::{EmptyAddressDataWithSource, LoadedAddressDataWithSource
/// 1. Deduplicate transaction indexes (an address may appear in multiple inputs/outputs of same tx)
/// 2. Add the unique count to the address's tx_count field
///
/// Addresses are looked up in loaded_cache first, then empty_cache.
/// NOTE: This should be called AFTER merging parallel-fetched address data into loaded_cache.
/// Addresses are looked up in funded_cache first, then empty_cache.
/// NOTE: This should be called AFTER merging parallel-fetched address data into funded_cache.
pub fn update_tx_counts(
loaded_cache: &mut AddressTypeToTypeIndexMap<LoadedAddressDataWithSource>,
funded_cache: &mut AddressTypeToTypeIndexMap<FundedAddressDataWithSource>,
empty_cache: &mut AddressTypeToTypeIndexMap<EmptyAddressDataWithSource>,
mut txindex_vecs: AddressTypeToTypeIndexMap<TxIndexVec>,
) {
@@ -32,7 +32,7 @@ pub fn update_tx_counts(
{
let tx_count = txindex_vec.len() as u32;
if let Some(addr_data) = loaded_cache
if let Some(addr_data) = funded_cache
.get_mut(address_type)
.unwrap()
.get_mut(&typeindex)
@@ -1,8 +1,10 @@
use brk_types::{EmptyAddressData, EmptyAddressIndex, LoadedAddressData, LoadedAddressIndex, TxIndex};
use brk_types::{
EmptyAddressData, EmptyAddressIndex, FundedAddressData, FundedAddressIndex, TxIndex,
};
use smallvec::SmallVec;
/// Loaded address data with source tracking for flush operations.
pub type LoadedAddressDataWithSource = WithAddressDataSource<LoadedAddressData>;
/// Funded address data with source tracking for flush operations.
pub type FundedAddressDataWithSource = WithAddressDataSource<FundedAddressData>;
/// Empty address data with source tracking for flush operations.
pub type EmptyAddressDataWithSource = WithAddressDataSource<EmptyAddressData>;
@@ -18,9 +20,9 @@ pub type TxIndexVec = SmallVec<[TxIndex; 4]>;
pub enum WithAddressDataSource<T> {
/// Brand new address (never seen before)
New(T),
/// Loaded from loaded address storage (with original index)
FromLoaded(LoadedAddressIndex, T),
/// Loaded from empty address storage (with original index)
/// Funded from funded address storage (with original index)
FromFunded(FundedAddressIndex, T),
/// Funded from empty address storage (with original index)
FromEmpty(EmptyAddressIndex, T),
}
@@ -29,7 +31,7 @@ impl<T> std::ops::Deref for WithAddressDataSource<T> {
fn deref(&self) -> &Self::Target {
match self {
Self::New(v) | Self::FromLoaded(_, v) | Self::FromEmpty(_, v) => v,
Self::New(v) | Self::FromFunded(_, v) | Self::FromEmpty(_, v) => v,
}
}
}
@@ -37,28 +39,28 @@ impl<T> std::ops::Deref for WithAddressDataSource<T> {
impl<T> std::ops::DerefMut for WithAddressDataSource<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
match self {
Self::New(v) | Self::FromLoaded(_, v) | Self::FromEmpty(_, v) => v,
Self::New(v) | Self::FromFunded(_, v) | Self::FromEmpty(_, v) => v,
}
}
}
impl From<WithAddressDataSource<EmptyAddressData>> for WithAddressDataSource<LoadedAddressData> {
impl From<WithAddressDataSource<EmptyAddressData>> for WithAddressDataSource<FundedAddressData> {
#[inline]
fn from(value: WithAddressDataSource<EmptyAddressData>) -> Self {
match value {
WithAddressDataSource::New(v) => Self::New(v.into()),
WithAddressDataSource::FromLoaded(i, v) => Self::FromLoaded(i, v.into()),
WithAddressDataSource::FromFunded(i, v) => Self::FromFunded(i, v.into()),
WithAddressDataSource::FromEmpty(i, v) => Self::FromEmpty(i, v.into()),
}
}
}
impl From<WithAddressDataSource<LoadedAddressData>> for WithAddressDataSource<EmptyAddressData> {
impl From<WithAddressDataSource<FundedAddressData>> for WithAddressDataSource<EmptyAddressData> {
#[inline]
fn from(value: WithAddressDataSource<LoadedAddressData>) -> Self {
fn from(value: WithAddressDataSource<FundedAddressData>) -> Self {
match value {
WithAddressDataSource::New(v) => Self::New(v.into()),
WithAddressDataSource::FromLoaded(i, v) => Self::FromLoaded(i, v.into()),
WithAddressDataSource::FromFunded(i, v) => Self::FromFunded(i, v.into()),
WithAddressDataSource::FromEmpty(i, v) => Self::FromEmpty(i, v.into()),
}
}
@@ -13,7 +13,7 @@ use crate::distribution::address::HeightToAddressTypeToVec;
use super::super::{
cache::{AddressCache, load_uncached_address_data},
cohort::{LoadedAddressDataWithSource, TxIndexVec},
cohort::{FundedAddressDataWithSource, TxIndexVec},
};
/// Result of processing inputs for a block.
@@ -23,7 +23,7 @@ pub struct InputsResult {
/// Per-height, per-address-type sent data: (typeindex, value) for each address.
pub sent_data: HeightToAddressTypeToVec<(TypeIndex, Sats)>,
/// Address data looked up during processing, keyed by (address_type, typeindex).
pub address_data: AddressTypeToTypeIndexMap<LoadedAddressDataWithSource>,
pub address_data: AddressTypeToTypeIndexMap<FundedAddressDataWithSource>,
/// Transaction indexes per address for tx_count tracking.
pub txindex_vecs: AddressTypeToTypeIndexMap<TxIndexVec>,
}
@@ -100,7 +100,7 @@ pub fn process_inputs(
);
let mut sent_data = HeightToAddressTypeToVec::with_capacity(estimated_unique_heights);
let mut address_data =
AddressTypeToTypeIndexMap::<LoadedAddressDataWithSource>::with_capacity(estimated_per_type);
AddressTypeToTypeIndexMap::<FundedAddressDataWithSource>::with_capacity(estimated_per_type);
let mut txindex_vecs =
AddressTypeToTypeIndexMap::<TxIndexVec>::with_capacity(estimated_per_type);
@@ -11,7 +11,7 @@ use crate::distribution::{
use super::super::{
cache::{AddressCache, load_uncached_address_data},
cohort::{LoadedAddressDataWithSource, TxIndexVec},
cohort::{FundedAddressDataWithSource, TxIndexVec},
};
/// Result of processing outputs for a block.
@@ -21,7 +21,7 @@ pub struct OutputsResult {
/// Per-address-type received data: (typeindex, value) for each address.
pub received_data: AddressTypeToVec<(TypeIndex, Sats)>,
/// Address data looked up during processing, keyed by (address_type, typeindex).
pub address_data: AddressTypeToTypeIndexMap<LoadedAddressDataWithSource>,
pub address_data: AddressTypeToTypeIndexMap<FundedAddressDataWithSource>,
/// Transaction indexes per address for tx_count tracking.
pub txindex_vecs: AddressTypeToTypeIndexMap<TxIndexVec>,
}
@@ -50,7 +50,7 @@ pub fn process_outputs(
let mut transacted = Transacted::default();
let mut received_data = AddressTypeToVec::with_capacity(estimated_per_type);
let mut address_data =
AddressTypeToTypeIndexMap::<LoadedAddressDataWithSource>::with_capacity(estimated_per_type);
AddressTypeToTypeIndexMap::<FundedAddressDataWithSource>::with_capacity(estimated_per_type);
let mut txindex_vecs =
AddressTypeToTypeIndexMap::<TxIndexVec>::with_capacity(estimated_per_type);
@@ -263,8 +263,8 @@ pub fn process_blocks(
});
// Merge new address data into current cache
cache.merge_loaded(outputs_result.address_data);
cache.merge_loaded(inputs_result.address_data);
cache.merge_funded(outputs_result.address_data);
cache.merge_funded(inputs_result.address_data);
// Combine txindex_vecs from outputs and inputs, then update tx_count
let combined_txindex_vecs = outputs_result
@@ -425,14 +425,14 @@ pub fn process_blocks(
// Drop readers to release mmap handles
drop(vr);
let (empty_updates, loaded_updates) = cache.take();
let (empty_updates, funded_updates) = cache.take();
// Process address updates (mutations)
process_address_updates(
&mut vecs.addresses_data,
&mut vecs.any_address_indexes,
empty_updates,
loaded_updates,
funded_updates,
)?;
let _lock = exit.lock();
@@ -451,14 +451,14 @@ pub fn process_blocks(
let _lock = exit.lock();
drop(vr);
let (empty_updates, loaded_updates) = cache.take();
let (empty_updates, funded_updates) = cache.take();
// Process address updates (mutations)
process_address_updates(
&mut vecs.addresses_data,
&mut vecs.any_address_indexes,
empty_updates,
loaded_updates,
funded_updates,
)?;
// Write to disk (pure I/O) - save changes for rollback
@@ -140,7 +140,7 @@ impl VecsReaders {
p2wsh: any_address_indexes.p2wsh.create_reader(),
},
anyaddressindex_to_anyaddressdata: ByAnyAddress {
loaded: addresses_data.loaded.create_reader(),
funded: addresses_data.funded.create_reader(),
empty: addresses_data.empty.create_reader(),
},
}
@@ -9,8 +9,8 @@ use vecdb::{AnyStoredVec, GenericStoredVec, Stamp};
use crate::distribution::{
Vecs,
block::{
EmptyAddressDataWithSource, LoadedAddressDataWithSource, process_empty_addresses,
process_loaded_addresses,
EmptyAddressDataWithSource, FundedAddressDataWithSource, process_empty_addresses,
process_funded_addresses,
},
state::BlockState,
};
@@ -21,7 +21,7 @@ use super::super::address::{AddressTypeToTypeIndexMap, AddressesDataVecs, AnyAdd
///
/// Applies all accumulated address changes to storage structures:
/// - Processes empty address transitions
/// - Processes loaded address transitions
/// - Processes funded address transitions
/// - Updates address indexes
///
/// Call this before `flush()` to prepare data for writing.
@@ -29,14 +29,14 @@ pub fn process_address_updates(
addresses_data: &mut AddressesDataVecs,
address_indexes: &mut AnyAddressIndexesVecs,
empty_updates: AddressTypeToTypeIndexMap<EmptyAddressDataWithSource>,
loaded_updates: AddressTypeToTypeIndexMap<LoadedAddressDataWithSource>,
funded_updates: AddressTypeToTypeIndexMap<FundedAddressDataWithSource>,
) -> Result<()> {
info!("Processing address updates...");
let i = Instant::now();
let empty_result = process_empty_addresses(addresses_data, empty_updates)?;
let loaded_result = process_loaded_addresses(addresses_data, loaded_updates)?;
address_indexes.par_batch_update(empty_result, loaded_result)?;
let funded_result = process_funded_addresses(addresses_data, funded_updates)?;
address_indexes.par_batch_update(empty_result, funded_result)?;
info!("Processed address updates in {:?}", i.elapsed());
@@ -1,7 +1,7 @@
use std::path::Path;
use brk_error::Result;
use brk_types::{Age, CentsUnsigned, Height, LoadedAddressData, Sats, SupplyState};
use brk_types::{Age, CentsUnsigned, FundedAddressData, Height, Sats, SupplyState};
use vecdb::unlikely;
use super::{super::cost_basis::RealizedState, base::CohortState};
@@ -42,7 +42,7 @@ impl AddressCohortState {
pub fn send(
&mut self,
addressdata: &mut LoadedAddressData,
addressdata: &mut FundedAddressData,
value: Sats,
current_price: CentsUnsigned,
prev_price: CentsUnsigned,
@@ -54,7 +54,10 @@ impl AddressCohortState {
let current = addressdata.cost_basis_snapshot();
self.inner.send_address(
&SupplyState { utxo_count: 1, value },
&SupplyState {
utxo_count: 1,
value,
},
current_price,
prev_price,
ath,
@@ -68,7 +71,7 @@ impl AddressCohortState {
pub fn receive(
&mut self,
address_data: &mut LoadedAddressData,
address_data: &mut FundedAddressData,
value: Sats,
price: CentsUnsigned,
) {
@@ -77,7 +80,7 @@ impl AddressCohortState {
pub fn receive_outputs(
&mut self,
address_data: &mut LoadedAddressData,
address_data: &mut FundedAddressData,
value: Sats,
price: CentsUnsigned,
output_count: u32,
@@ -87,19 +90,23 @@ impl AddressCohortState {
let current = address_data.cost_basis_snapshot();
self.inner.receive_address(
&SupplyState { utxo_count: output_count as u64, value },
&SupplyState {
utxo_count: output_count as u64,
value,
},
price,
&current,
&prev,
);
}
pub fn add(&mut self, addressdata: &LoadedAddressData) {
pub fn add(&mut self, addressdata: &FundedAddressData) {
self.addr_count += 1;
self.inner.increment_snapshot(&addressdata.cost_basis_snapshot());
self.inner
.increment_snapshot(&addressdata.cost_basis_snapshot());
}
pub fn subtract(&mut self, addressdata: &LoadedAddressData) {
pub fn subtract(&mut self, addressdata: &FundedAddressData) {
let snapshot = addressdata.cost_basis_snapshot();
// Check for potential underflow before it happens
@@ -111,7 +118,11 @@ impl AddressCohortState {
Address supply: {}\n\
Realized price: {}\n\
This means the address is not properly tracked in this cohort.",
self.addr_count, self.inner.supply, addressdata, snapshot.supply_state, snapshot.realized_price
self.addr_count,
self.inner.supply,
addressdata,
snapshot.supply_state,
snapshot.realized_price
);
}
if unlikely(self.inner.supply.value < snapshot.supply_state.value) {
@@ -122,7 +133,11 @@ impl AddressCohortState {
Address supply: {}\n\
Realized price: {}\n\
This means the address is not properly tracked in this cohort.",
self.addr_count, self.inner.supply, addressdata, snapshot.supply_state, snapshot.realized_price
self.addr_count,
self.inner.supply,
addressdata,
snapshot.supply_state,
snapshot.realized_price
);
}
+10 -10
View File
@@ -4,7 +4,7 @@ use brk_error::Result;
use brk_indexer::Indexer;
use brk_traversable::Traversable;
use brk_types::{
DateIndex, EmptyAddressData, EmptyAddressIndex, Height, LoadedAddressData, LoadedAddressIndex,
DateIndex, EmptyAddressData, EmptyAddressIndex, FundedAddressData, FundedAddressIndex, Height,
SupplyState, Version,
};
use tracing::{debug, info};
@@ -55,8 +55,8 @@ pub struct Vecs {
/// Growth rate (new / addr_count) - lazy ratio with distribution stats, global + per-type
pub growth_rate: GrowthRateVecs,
pub loadedaddressindex:
LazyVecFrom1<LoadedAddressIndex, LoadedAddressIndex, LoadedAddressIndex, LoadedAddressData>,
pub fundedaddressindex:
LazyVecFrom1<FundedAddressIndex, FundedAddressIndex, FundedAddressIndex, FundedAddressData>,
pub emptyaddressindex:
LazyVecFrom1<EmptyAddressIndex, EmptyAddressIndex, EmptyAddressIndex, EmptyAddressData>,
}
@@ -92,8 +92,8 @@ impl Vecs {
)?;
// Create address data BytesVecs first so we can also use them for identity mappings
let loadedaddressindex_to_loadedaddressdata = BytesVec::forced_import_with(
vecdb::ImportOptions::new(&db, "loadedaddressdata", version)
let fundedaddressindex_to_fundedaddressdata = BytesVec::forced_import_with(
vecdb::ImportOptions::new(&db, "fundedaddressdata", version)
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
)?;
let emptyaddressindex_to_emptyaddressdata = BytesVec::forced_import_with(
@@ -102,10 +102,10 @@ impl Vecs {
)?;
// Identity mappings for traversable
let loadedaddressindex = LazyVecFrom1::init(
"loadedaddressindex",
let fundedaddressindex = LazyVecFrom1::init(
"fundedaddressindex",
version,
loadedaddressindex_to_loadedaddressdata.boxed_clone(),
fundedaddressindex_to_fundedaddressdata.boxed_clone(),
|index, _| Some(index),
);
let emptyaddressindex = LazyVecFrom1::init(
@@ -156,10 +156,10 @@ impl Vecs {
any_address_indexes: AnyAddressIndexesVecs::forced_import(&db, version)?,
addresses_data: AddressesDataVecs {
loaded: loadedaddressindex_to_loadedaddressdata,
funded: fundedaddressindex_to_fundedaddressdata,
empty: emptyaddressindex_to_emptyaddressdata,
},
loadedaddressindex,
fundedaddressindex,
emptyaddressindex,
db,
@@ -30,7 +30,7 @@ fn main() -> Result<()> {
println!("Loading indexer from: {}", outputs_dir.display());
let indexer = Indexer::forced_import(&outputs_dir)?;
println!("✅ Indexer loaded\n");
println!("✅ Indexer funded\n");
// Warmup run
println!("🔥 Warmup run...");
+2 -2
View File
@@ -58,10 +58,10 @@ impl Query {
.get_once(outputtype, type_index)?;
let address_data = match any_address_index.to_enum() {
AnyAddressDataIndexEnum::Loaded(index) => computer
AnyAddressDataIndexEnum::Funded(index) => computer
.distribution
.addresses_data
.loaded
.funded
.iter()?
.get_unwrap(index),
AnyAddressDataIndexEnum::Empty(index) => computer
+7 -7
View File
@@ -4,11 +4,11 @@ use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use vecdb::{Bytes, Formattable};
use crate::{EmptyAddressIndex, LoadedAddressIndex, TypeIndex};
use crate::{EmptyAddressIndex, FundedAddressIndex, TypeIndex};
const MIN_EMPTY_INDEX: u32 = u32::MAX - 4_000_000_000;
/// Unified index for any address type (loaded or empty)
/// Unified index for any address type (funded or empty)
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Bytes, JsonSchema)]
pub struct AnyAddressIndex(TypeIndex);
@@ -18,9 +18,9 @@ impl AnyAddressIndex {
}
}
impl From<LoadedAddressIndex> for AnyAddressIndex {
impl From<FundedAddressIndex> for AnyAddressIndex {
#[inline]
fn from(value: LoadedAddressIndex) -> Self {
fn from(value: FundedAddressIndex) -> Self {
if u32::from(value) >= MIN_EMPTY_INDEX {
panic!("{value} is higher than MIN_EMPTY_INDEX ({MIN_EMPTY_INDEX})")
}
@@ -70,7 +70,7 @@ impl Formattable for AnyAddressIndex {
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum AnyAddressDataIndexEnum {
Loaded(LoadedAddressIndex),
Funded(FundedAddressIndex),
Empty(EmptyAddressIndex),
}
@@ -81,7 +81,7 @@ impl From<AnyAddressIndex> for AnyAddressDataIndexEnum {
if uvalue >= MIN_EMPTY_INDEX {
Self::Empty(EmptyAddressIndex::from(uvalue - MIN_EMPTY_INDEX))
} else {
Self::Loaded(LoadedAddressIndex::from(value.0))
Self::Funded(FundedAddressIndex::from(value.0))
}
}
}
@@ -90,7 +90,7 @@ impl From<AnyAddressDataIndexEnum> for AnyAddressIndex {
#[inline]
fn from(value: AnyAddressDataIndexEnum) -> Self {
match value {
AnyAddressDataIndexEnum::Loaded(idx) => Self::from(idx),
AnyAddressDataIndexEnum::Funded(idx) => Self::from(idx),
AnyAddressDataIndexEnum::Empty(idx) => Self::from(idx),
}
}
+5 -5
View File
@@ -2,7 +2,7 @@ use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use vecdb::{Bytes, Formattable};
use crate::{LoadedAddressData, Sats};
use crate::{FundedAddressData, Sats};
/// Data of an empty address
#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]
@@ -16,16 +16,16 @@ pub struct EmptyAddressData {
pub transfered: Sats,
}
impl From<LoadedAddressData> for EmptyAddressData {
impl From<FundedAddressData> for EmptyAddressData {
#[inline]
fn from(value: LoadedAddressData) -> Self {
fn from(value: FundedAddressData) -> Self {
Self::from(&value)
}
}
impl From<&LoadedAddressData> for EmptyAddressData {
impl From<&FundedAddressData> for EmptyAddressData {
#[inline]
fn from(value: &LoadedAddressData) -> Self {
fn from(value: &FundedAddressData) -> Self {
if value.sent != value.received {
dbg!(&value);
panic!("Trying to convert not empty wallet to empty !");
@@ -31,10 +31,10 @@ impl CostBasisSnapshot {
}
}
/// Data for a loaded (non-empty) address with current balance
/// Data for a funded (non-empty) address with current balance
#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]
#[repr(C)]
pub struct LoadedAddressData {
pub struct FundedAddressData {
/// Total transaction count
pub tx_count: u32,
/// Number of transaction outputs funded to this address
@@ -53,7 +53,7 @@ pub struct LoadedAddressData {
pub investor_cap_raw: CentsSquaredSats,
}
impl LoadedAddressData {
impl FundedAddressData {
pub fn balance(&self) -> Sats {
(u64::from(self.received) - u64::from(self.sent)).into()
}
@@ -87,7 +87,7 @@ impl LoadedAddressData {
.checked_sub(self.spent_txo_count)
.unwrap_or_else(|| {
panic!(
"LoadedAddressData corruption: spent_txo_count ({}) > funded_txo_count ({}). \
"FundedAddressData corruption: spent_txo_count ({}) > funded_txo_count ({}). \
Address data: {:?}",
self.spent_txo_count, self.funded_txo_count, self
)
@@ -138,14 +138,14 @@ impl LoadedAddressData {
}
}
impl From<EmptyAddressData> for LoadedAddressData {
impl From<EmptyAddressData> for FundedAddressData {
#[inline]
fn from(value: EmptyAddressData) -> Self {
Self::from(&value)
}
}
impl From<&EmptyAddressData> for LoadedAddressData {
impl From<&EmptyAddressData> for FundedAddressData {
#[inline]
fn from(value: &EmptyAddressData) -> Self {
Self {
@@ -161,7 +161,7 @@ impl From<&EmptyAddressData> for LoadedAddressData {
}
}
impl std::fmt::Display for LoadedAddressData {
impl std::fmt::Display for FundedAddressData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
@@ -177,14 +177,14 @@ impl std::fmt::Display for LoadedAddressData {
}
}
impl Formattable for LoadedAddressData {
impl Formattable for FundedAddressData {
#[inline(always)]
fn may_need_escaping() -> bool {
true
}
}
impl Bytes for LoadedAddressData {
impl Bytes for FundedAddressData {
type Array = [u8; size_of::<Self>()];
fn to_bytes(&self) -> Self::Array {
@@ -22,61 +22,61 @@ use crate::TypeIndex;
Pco,
JsonSchema,
)]
pub struct LoadedAddressIndex(TypeIndex);
pub struct FundedAddressIndex(TypeIndex);
impl From<TypeIndex> for LoadedAddressIndex {
impl From<TypeIndex> for FundedAddressIndex {
#[inline]
fn from(value: TypeIndex) -> Self {
Self(value)
}
}
impl From<usize> for LoadedAddressIndex {
impl From<usize> for FundedAddressIndex {
#[inline]
fn from(value: usize) -> Self {
Self(TypeIndex::from(value))
}
}
impl From<LoadedAddressIndex> for usize {
impl From<FundedAddressIndex> for usize {
#[inline]
fn from(value: LoadedAddressIndex) -> Self {
fn from(value: FundedAddressIndex) -> Self {
usize::from(value.0)
}
}
impl From<LoadedAddressIndex> for u32 {
impl From<FundedAddressIndex> for u32 {
#[inline]
fn from(value: LoadedAddressIndex) -> Self {
fn from(value: FundedAddressIndex) -> Self {
u32::from(value.0)
}
}
impl Add<usize> for LoadedAddressIndex {
impl Add<usize> for FundedAddressIndex {
type Output = Self;
fn add(self, rhs: usize) -> Self::Output {
Self(self.0 + rhs)
}
}
impl CheckedSub<LoadedAddressIndex> for LoadedAddressIndex {
impl CheckedSub<FundedAddressIndex> for FundedAddressIndex {
fn checked_sub(self, rhs: Self) -> Option<Self> {
self.0.checked_sub(rhs.0).map(Self)
}
}
impl PrintableIndex for LoadedAddressIndex {
impl PrintableIndex for FundedAddressIndex {
fn to_string() -> &'static str {
"loadedaddressindex"
"fundedaddressindex"
}
fn to_possible_strings() -> &'static [&'static str] {
&["loadedaddr", "loadedaddressindex"]
&["fundedaddr", "fundedaddressindex"]
}
}
impl std::fmt::Display for LoadedAddressIndex {
impl std::fmt::Display for FundedAddressIndex {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
impl Formattable for LoadedAddressIndex {
impl Formattable for FundedAddressIndex {
#[inline(always)]
fn may_need_escaping() -> bool {
false
+6 -6
View File
@@ -9,7 +9,7 @@ use crate::PairOutputIndex;
use super::{
Date, DateIndex, DecadeIndex, DifficultyEpoch, EmptyAddressIndex, EmptyOutputIndex, HalvingEpoch,
Height, LoadedAddressIndex, MonthIndex, OpReturnIndex, P2AAddressIndex, P2MSOutputIndex,
Height, FundedAddressIndex, MonthIndex, OpReturnIndex, P2AAddressIndex, P2MSOutputIndex,
P2PK33AddressIndex, P2PK65AddressIndex, P2PKHAddressIndex, P2SHAddressIndex, P2TRAddressIndex,
P2WPKHAddressIndex, P2WSHAddressIndex, QuarterIndex, SemesterIndex, TxInIndex, TxIndex,
TxOutIndex, UnknownOutputIndex, WeekIndex, YearIndex,
@@ -46,7 +46,7 @@ pub enum Index {
UnknownOutputIndex,
WeekIndex,
YearIndex,
LoadedAddressIndex,
FundedAddressIndex,
EmptyAddressIndex,
PairOutputIndex,
}
@@ -79,7 +79,7 @@ impl Index {
Self::UnknownOutputIndex,
Self::WeekIndex,
Self::YearIndex,
Self::LoadedAddressIndex,
Self::FundedAddressIndex,
Self::EmptyAddressIndex,
Self::PairOutputIndex,
]
@@ -112,7 +112,7 @@ impl Index {
Self::UnknownOutputIndex => UnknownOutputIndex::to_possible_strings(),
Self::WeekIndex => WeekIndex::to_possible_strings(),
Self::YearIndex => YearIndex::to_possible_strings(),
Self::LoadedAddressIndex => LoadedAddressIndex::to_possible_strings(),
Self::FundedAddressIndex => FundedAddressIndex::to_possible_strings(),
Self::EmptyAddressIndex => EmptyAddressIndex::to_possible_strings(),
Self::PairOutputIndex => PairOutputIndex::to_possible_strings(),
}
@@ -216,8 +216,8 @@ impl TryFrom<&str> for Index {
v if (Self::UnknownOutputIndex).possible_values().contains(&v) => {
Self::UnknownOutputIndex
}
v if (Self::LoadedAddressIndex).possible_values().contains(&v) => {
Self::LoadedAddressIndex
v if (Self::FundedAddressIndex).possible_values().contains(&v) => {
Self::FundedAddressIndex
}
v if (Self::EmptyAddressIndex).possible_values().contains(&v) => {
Self::EmptyAddressIndex
+8 -8
View File
@@ -35,11 +35,11 @@ mod blockstatus;
mod blocktimestamp;
mod blockweightentry;
mod bytes;
mod cents_sats;
mod cents_signed;
mod cents_squared_sats;
mod cents_unsigned;
mod cents_unsigned_compact;
mod cents_sats;
mod cents_squared_sats;
mod datarange;
mod datarangeformat;
mod date;
@@ -60,6 +60,8 @@ mod feerate;
mod feeratepercentiles;
mod format;
mod formatresponse;
mod fundedaddressdata;
mod fundedaddressindex;
mod halvingepoch;
mod hashrateentry;
mod hashratesummary;
@@ -72,8 +74,6 @@ mod indexes;
mod indexinfo;
mod limit;
mod limitparam;
mod loadedaddressdata;
mod loadedaddressindex;
mod mempoolblock;
mod mempoolentryinfo;
mod mempoolinfo;
@@ -211,11 +211,11 @@ pub use blockstatus::*;
pub use blocktimestamp::*;
pub use blockweightentry::*;
pub use bytes::*;
pub use cents_sats::*;
pub use cents_signed::*;
pub use cents_squared_sats::*;
pub use cents_unsigned::*;
pub use cents_unsigned_compact::*;
pub use cents_sats::*;
pub use cents_squared_sats::*;
pub use datarange::*;
pub use datarangeformat::*;
pub use date::*;
@@ -236,6 +236,8 @@ pub use feerate::*;
pub use feeratepercentiles::*;
pub use format::*;
pub use formatresponse::*;
pub use fundedaddressdata::*;
pub use fundedaddressindex::*;
pub use halvingepoch::*;
pub use hashrateentry::*;
pub use hashratesummary::*;
@@ -248,8 +250,6 @@ pub use indexes::*;
pub use indexinfo::*;
pub use limit::*;
pub use limitparam::*;
pub use loadedaddressdata::*;
pub use loadedaddressindex::*;
pub use mempoolblock::*;
pub use mempoolentryinfo::*;
pub use mempoolinfo::*;
+3 -3
View File
@@ -7,7 +7,7 @@ use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use vecdb::{Bytes, Formattable};
use crate::{CheckedSub, LoadedAddressData, Sats};
use crate::{CheckedSub, FundedAddressData, Sats};
/// Current supply state tracking UTXO count and total value
#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]
@@ -65,9 +65,9 @@ impl SubAssign<&SupplyState> for SupplyState {
}
}
impl From<&LoadedAddressData> for SupplyState {
impl From<&FundedAddressData> for SupplyState {
#[inline]
fn from(value: &LoadedAddressData) -> Self {
fn from(value: &FundedAddressData) -> Self {
Self {
utxo_count: value.utxo_count() as u64,
value: value.balance(),