global: renames part 2

This commit is contained in:
nym21
2026-03-13 22:42:43 +01:00
parent 0795c1bbf8
commit a0d378d06d
117 changed files with 3024 additions and 3189 deletions
File diff suppressed because it is too large Load Diff
@@ -14,23 +14,23 @@ pub fn main() -> Result<()> {
let computer = Computer::forced_import(&outputs_dir, &indexer)?;
// Test emptyaddressdata (underlying BytesVec) - direct access
// Test empty_address_data (underlying BytesVec) - direct access
let empty_data = &computer.distribution.addresses_data.empty;
println!("emptyaddressdata (BytesVec) len: {}", empty_data.len());
println!("empty_address_data (BytesVec) len: {}", empty_data.len());
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: {}",
"empty_address_data last item JSON: {}",
String::from_utf8_lossy(&buf)
);
println!("Time for BytesVec write_json: {:?}", start.elapsed());
// Test emptyaddressindex (LazyVecFrom1 wrapper) - computed access
// Test empty_address_index (LazyVecFrom1 wrapper) - computed access
let empty_index = &computer.distribution.addresses.empty_index;
println!(
"\nemptyaddressindex (LazyVecFrom1) len: {}",
"\nempty_address_index (LazyVecFrom1) len: {}",
empty_index.len()
);
@@ -42,14 +42,14 @@ pub fn main() -> Result<()> {
&mut buf,
)?;
println!(
"emptyaddressindex last item JSON: {}",
"empty_address_index last item JSON: {}",
String::from_utf8_lossy(&buf)
);
println!("Time for LazyVecFrom1 write_json: {:?}", start.elapsed());
// Compare with funded versions
let funded_data = &computer.distribution.addresses_data.funded;
println!("\nfundedaddressdata (BytesVec) len: {}", funded_data.len());
println!("\nfunded_address_data (BytesVec) len: {}", funded_data.len());
let start = Instant::now();
let mut buf = Vec::new();
@@ -59,7 +59,7 @@ pub fn main() -> Result<()> {
&mut buf,
)?;
println!(
"fundedaddressdata last item JSON: {}",
"funded_address_data last item JSON: {}",
String::from_utf8_lossy(&buf)
);
println!("Time for BytesVec write_json: {:?}", start.elapsed());
@@ -259,7 +259,7 @@ impl AddressTypeToActivityCountVecs {
pub struct AddressActivityVecs<M: StorageMode = Rw> {
pub all: ActivityCountVecs<M>,
#[traversable(flatten)]
pub by_addresstype: AddressTypeToActivityCountVecs<M>,
pub by_address_type: AddressTypeToActivityCountVecs<M>,
}
impl AddressActivityVecs {
@@ -272,7 +272,7 @@ impl AddressActivityVecs {
) -> Result<Self> {
Ok(Self {
all: ActivityCountVecs::forced_import(db, name, version, indexes, cached_starts)?,
by_addresstype: AddressTypeToActivityCountVecs::forced_import(
by_address_type: AddressTypeToActivityCountVecs::forced_import(
db, name, version, indexes, cached_starts,
)?,
})
@@ -281,7 +281,7 @@ impl AddressActivityVecs {
pub(crate) fn min_stateful_len(&self) -> usize {
self.all
.min_stateful_len()
.min(self.by_addresstype.min_stateful_len())
.min(self.by_address_type.min_stateful_len())
}
pub(crate) fn par_iter_height_mut(
@@ -289,12 +289,12 @@ impl AddressActivityVecs {
) -> impl ParallelIterator<Item = &mut dyn AnyStoredVec> {
self.all
.par_iter_height_mut()
.chain(self.by_addresstype.par_iter_height_mut())
.chain(self.by_address_type.par_iter_height_mut())
}
pub(crate) fn reset_height(&mut self) -> Result<()> {
self.all.reset_height()?;
self.by_addresstype.reset_height()?;
self.by_address_type.reset_height()?;
Ok(())
}
@@ -304,7 +304,7 @@ impl AddressActivityVecs {
exit: &Exit,
) -> Result<()> {
self.all.compute_rest(max_from, exit)?;
self.by_addresstype.compute_rest(max_from, exit)?;
self.by_address_type.compute_rest(max_from, exit)?;
Ok(())
}
@@ -315,7 +315,7 @@ impl AddressActivityVecs {
) -> Result<()> {
let totals = counts.totals();
self.all.truncate_push_height(height, &totals)?;
self.by_addresstype.truncate_push_height(height, counts)?;
self.by_address_type.truncate_push_height(height, counts)?;
Ok(())
}
}
@@ -165,7 +165,7 @@ impl AddressTypeToAddressCountVecs {
pub struct AddressCountsVecs<M: StorageMode = Rw> {
pub all: AddressCountVecs<M>,
#[traversable(flatten)]
pub by_addresstype: AddressTypeToAddressCountVecs<M>,
pub by_address_type: AddressTypeToAddressCountVecs<M>,
}
impl AddressCountsVecs {
@@ -177,24 +177,24 @@ impl AddressCountsVecs {
) -> Result<Self> {
Ok(Self {
all: AddressCountVecs::forced_import(db, name, version, indexes)?,
by_addresstype: AddressTypeToAddressCountVecs::forced_import(db, name, version, indexes)?,
by_address_type: AddressTypeToAddressCountVecs::forced_import(db, name, version, indexes)?,
})
}
pub(crate) fn min_stateful_len(&self) -> usize {
self.all.height.len().min(self.by_addresstype.min_stateful_len())
self.all.height.len().min(self.by_address_type.min_stateful_len())
}
pub(crate) fn par_iter_height_mut(
&mut self,
) -> impl ParallelIterator<Item = &mut dyn AnyStoredVec> {
rayon::iter::once(&mut self.all.height as &mut dyn AnyStoredVec)
.chain(self.by_addresstype.par_iter_height_mut())
.chain(self.by_address_type.par_iter_height_mut())
}
pub(crate) fn reset_height(&mut self) -> Result<()> {
self.all.height.reset()?;
self.by_addresstype.reset_height()?;
self.by_address_type.reset_height()?;
Ok(())
}
@@ -205,7 +205,7 @@ impl AddressCountsVecs {
address_counts: &AddressTypeToAddressCount,
) -> Result<()> {
self.all.height.truncate_push(height, total.into())?;
self.by_addresstype
self.by_address_type
.truncate_push_height(height, address_counts)?;
Ok(())
}
@@ -215,7 +215,7 @@ impl AddressCountsVecs {
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
let sources = self.by_addresstype.by_height();
let sources = self.by_address_type.by_height();
self.all
.height
.compute_sum_of_others(starting_indexes.height, &sources, exit)?;
@@ -1,6 +1,6 @@
use brk_cohort::ByAddressType;
use brk_traversable::Traversable;
use brk_types::{BasisPoints32, StoredI64, StoredU64, Version};
use brk_types::{BasisPointsSigned32, StoredI64, StoredU64, Version};
use crate::{
indexes,
@@ -9,13 +9,13 @@ use crate::{
use super::AddressCountsVecs;
type AddrDelta = LazyRollingDeltasFromHeight<StoredU64, StoredI64, BasisPoints32>;
type AddrDelta = LazyRollingDeltasFromHeight<StoredU64, StoredI64, BasisPointsSigned32>;
#[derive(Clone, Traversable)]
pub struct DeltaVecs {
pub all: AddrDelta,
#[traversable(flatten)]
pub by_addresstype: ByAddressType<AddrDelta>,
pub by_address_type: ByAddressType<AddrDelta>,
}
impl DeltaVecs {
@@ -35,7 +35,7 @@ impl DeltaVecs {
indexes,
);
let by_addresstype = address_count.by_addresstype.map_with_name(|name, addr| {
let by_address_type = address_count.by_address_type.map_with_name(|name, addr| {
LazyRollingDeltasFromHeight::new(
&format!("{name}_address_count"),
version,
@@ -47,7 +47,7 @@ impl DeltaVecs {
Self {
all,
by_addresstype,
by_address_type,
}
}
}
@@ -32,7 +32,7 @@ macro_rules! define_any_address_indexes_vecs {
pub(crate) fn forced_import(db: &Database, version: Version) -> Result<Self> {
Ok(Self {
$($field: BytesVec::forced_import_with(
ImportOptions::new(db, "anyaddressindex", version)
ImportOptions::new(db, "any_address_index", version)
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
)?,)*
})
@@ -57,11 +57,11 @@ macro_rules! define_any_address_indexes_vecs {
Ok(())
}
/// Get address index for a given type and typeindex.
/// Get address index for a given type and type_index.
/// Uses get_any_or_read_at to check updated layer (needed after rollback).
pub(crate) fn get(&self, address_type: OutputType, typeindex: TypeIndex, reader: &Reader) -> Result<AnyAddressIndex> {
pub(crate) fn get(&self, address_type: OutputType, type_index: TypeIndex, reader: &Reader) -> Result<AnyAddressIndex> {
match address_type {
$(OutputType::$variant => Ok(self.$field.get_any_or_read_at(typeindex.into(), reader)?.unwrap()),)*
$(OutputType::$variant => Ok(self.$field.get_any_or_read_at(type_index.into(), reader)?.unwrap()),)*
_ => unreachable!("Invalid address type: {:?}", address_type),
}
}
@@ -74,10 +74,10 @@ macro_rules! define_any_address_indexes_vecs {
impl<M: StorageMode> AnyAddressIndexesVecs<M> {
/// Get address index with single read (no caching).
pub fn get_once(&self, address_type: OutputType, typeindex: TypeIndex) -> Result<AnyAddressIndex> {
pub fn get_once(&self, address_type: OutputType, type_index: TypeIndex) -> Result<AnyAddressIndex> {
match address_type {
$(OutputType::$variant => self.$field
.collect_one(<$index>::from(usize::from(typeindex)))
.collect_one(<$index>::from(usize::from(type_index)))
.ok_or_else(|| Error::UnsupportedType(address_type.to_string())),)*
_ => Err(Error::UnsupportedType(address_type.to_string())),
}
@@ -177,18 +177,18 @@ fn process_single_type_merged<I: vecdb::VecIndex>(
let mut pushes = Vec::with_capacity(map1.len() + map2.len());
let mut update_count = 0usize;
for (typeindex, any_index) in map1.into_iter().chain(map2) {
if usize::from(typeindex) < current_len {
vec.update(I::from(usize::from(typeindex)), any_index)?;
for (type_index, any_index) in map1.into_iter().chain(map2) {
if usize::from(type_index) < current_len {
vec.update(I::from(usize::from(type_index)), any_index)?;
update_count += 1;
} else {
pushes.push((typeindex, any_index));
pushes.push((type_index, any_index));
}
}
let push_count = pushes.len();
if !pushes.is_empty() {
pushes.sort_unstable_by_key(|(typeindex, _)| *typeindex);
pushes.sort_unstable_by_key(|(type_index, _)| *type_index);
for (_, any_index) in pushes {
vec.push(any_index);
}
@@ -16,7 +16,7 @@ use super::TotalAddressCountVecs;
pub struct NewAddressCountVecs<M: StorageMode = Rw> {
pub all: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
#[traversable(flatten)]
pub by_addresstype: ByAddressType<PerBlockCumulativeWithSums<StoredU64, StoredU64, M>>,
pub by_address_type: ByAddressType<PerBlockCumulativeWithSums<StoredU64, StoredU64, M>>,
}
impl NewAddressCountVecs {
@@ -34,7 +34,7 @@ impl NewAddressCountVecs {
cached_starts,
)?;
let by_addresstype = ByAddressType::new_with_name(|name| {
let by_address_type = ByAddressType::new_with_name(|name| {
PerBlockCumulativeWithSums::forced_import(
db,
&format!("{name}_new_address_count"),
@@ -46,7 +46,7 @@ impl NewAddressCountVecs {
Ok(Self {
all,
by_addresstype,
by_address_type,
})
}
@@ -61,9 +61,9 @@ impl NewAddressCountVecs {
})?;
for ((_, new), (_, total)) in self
.by_addresstype
.by_address_type
.iter_mut()
.zip(total_address_count.by_addresstype.iter())
.zip(total_address_count.by_address_type.iter())
{
new.compute(max_from, exit, |height_vec| {
Ok(height_vec.compute_change(max_from, &total.height, 1, exit)?)
@@ -13,7 +13,7 @@ use super::AddressCountsVecs;
pub struct TotalAddressCountVecs<M: StorageMode = Rw> {
pub all: PerBlock<StoredU64, M>,
#[traversable(flatten)]
pub by_addresstype: ByAddressType<PerBlock<StoredU64, M>>,
pub by_address_type: ByAddressType<PerBlock<StoredU64, M>>,
}
impl TotalAddressCountVecs {
@@ -24,7 +24,7 @@ impl TotalAddressCountVecs {
) -> Result<Self> {
let all = PerBlock::forced_import(db, "total_address_count", version, indexes)?;
let by_addresstype: ByAddressType<PerBlock<StoredU64>> =
let by_address_type: ByAddressType<PerBlock<StoredU64>> =
ByAddressType::new_with_name(|name| {
PerBlock::forced_import(
db,
@@ -36,7 +36,7 @@ impl TotalAddressCountVecs {
Ok(Self {
all,
by_addresstype,
by_address_type,
})
}
@@ -55,11 +55,11 @@ impl TotalAddressCountVecs {
exit,
)?;
for ((_, total), ((_, addr), (_, empty))) in self.by_addresstype.iter_mut().zip(
for ((_, total), ((_, addr), (_, empty))) in self.by_address_type.iter_mut().zip(
address_count
.by_addresstype
.by_address_type
.iter()
.zip(empty_address_count.by_addresstype.iter()),
.zip(empty_address_count.by_address_type.iter()),
) {
total
.height
@@ -59,14 +59,14 @@ impl<T> AddressTypeToTypeIndexMap<T> {
Self::merge_single(&mut self.p2wsh, &mut other.p2wsh);
}
/// Insert a value for a specific address type and typeindex.
/// Insert a value for a specific address type and type_index.
pub(crate) fn insert_for_type(
&mut self,
address_type: OutputType,
typeindex: TypeIndex,
type_index: TypeIndex,
value: T,
) {
self.get_mut(address_type).unwrap().insert(typeindex, value);
self.get_mut(address_type).unwrap().insert(type_index, value);
}
/// Consume and iterate over entries by address type.
@@ -96,8 +96,8 @@ where
pub(crate) fn merge_vec(mut self, other: Self) -> Self {
for (address_type, other_map) in other.0.into_iter() {
let self_map = self.0.get_mut_unwrap(address_type);
for (typeindex, mut other_vec) in other_map {
match self_map.entry(typeindex) {
for (type_index, mut other_vec) in other_map {
match self_map.entry(type_index) {
Entry::Occupied(mut entry) => {
let self_vec = entry.get_mut();
if other_vec.len() > self_vec.len() {
+15 -15
View File
@@ -37,14 +37,14 @@ impl AddressCache {
/// Check if address is in cache (either funded or empty).
#[inline]
pub(crate) fn contains(&self, address_type: OutputType, typeindex: TypeIndex) -> bool {
pub(crate) fn contains(&self, address_type: OutputType, type_index: TypeIndex) -> bool {
self.funded
.get(address_type)
.is_some_and(|m| m.contains_key(&typeindex))
.is_some_and(|m| m.contains_key(&type_index))
|| self
.empty
.get(address_type)
.is_some_and(|m| m.contains_key(&typeindex))
.is_some_and(|m| m.contains_key(&type_index))
}
/// Merge address data into funded cache.
@@ -68,9 +68,9 @@ impl AddressCache {
/// Update transaction counts for addresses.
pub(crate) fn update_tx_counts(
&mut self,
txindex_vecs: AddressTypeToTypeIndexMap<SmallVec<[TxIndex; 4]>>,
tx_index_vecs: AddressTypeToTypeIndexMap<SmallVec<[TxIndex; 4]>>,
) {
update_tx_counts(&mut self.funded, &mut self.empty, txindex_vecs);
update_tx_counts(&mut self.funded, &mut self.empty, tx_index_vecs);
}
/// Take the cache contents for flushing, leaving empty caches.
@@ -93,33 +93,33 @@ impl AddressCache {
#[allow(clippy::too_many_arguments)]
pub(crate) fn load_uncached_address_data(
address_type: OutputType,
typeindex: TypeIndex,
first_addressindexes: &ByAddressType<TypeIndex>,
type_index: TypeIndex,
first_address_indexes: &ByAddressType<TypeIndex>,
cache: &AddressCache,
vr: &VecsReaders,
any_address_indexes: &AnyAddressIndexesVecs,
addresses_data: &AddressesDataVecs,
) -> Result<Option<WithAddressDataSource<FundedAddressData>>> {
// Check if this is a new address (typeindex >= first for this height)
let first = *first_addressindexes.get(address_type).unwrap();
if first <= typeindex {
// Check if this is a new address (type_index >= first for this height)
let first = *first_address_indexes.get(address_type).unwrap();
if first <= type_index {
return Ok(Some(WithAddressDataSource::New(
FundedAddressData::default(),
)));
}
// Skip if already in cache
if cache.contains(address_type, typeindex) {
if cache.contains(address_type, type_index) {
return Ok(None);
}
// Read from storage
let reader = vr.address_reader(address_type);
let anyaddressindex = any_address_indexes.get(address_type, typeindex, reader)?;
let any_address_index = any_address_indexes.get(address_type, type_index, reader)?;
Ok(Some(match anyaddressindex.to_enum() {
Ok(Some(match any_address_index.to_enum() {
AnyAddressDataIndexEnum::Funded(funded_index) => {
let reader = &vr.anyaddressindex_to_anyaddressdata.funded;
let reader = &vr.any_address_index_to_any_address_data.funded;
let funded_data = addresses_data
.funded
.get_any_or_read_at(funded_index.into(), reader)?
@@ -127,7 +127,7 @@ pub(crate) fn load_uncached_address_data(
WithAddressDataSource::FromFunded(funded_index, funded_data)
}
AnyAddressDataIndexEnum::Empty(empty_index) => {
let reader = &vr.anyaddressindex_to_anyaddressdata.empty;
let reader = &vr.any_address_index_to_any_address_data.empty;
let empty_data = addresses_data
.empty
.get_any_or_read_at(empty_index.into(), reader)?
@@ -26,17 +26,17 @@ pub(crate) fn process_funded_addresses(
let mut pushes: Vec<(OutputType, TypeIndex, FundedAddressData)> = Vec::with_capacity(total);
for (address_type, items) in funded_updates.into_iter() {
for (typeindex, source) in items {
for (type_index, source) in items {
match source {
WithAddressDataSource::New(data) => {
pushes.push((address_type, typeindex, data));
pushes.push((address_type, type_index, data));
}
WithAddressDataSource::FromFunded(index, data) => {
updates.push((index, data));
}
WithAddressDataSource::FromEmpty(empty_index, data) => {
deletes.push(empty_index);
pushes.push((address_type, typeindex, data));
pushes.push((address_type, type_index, data));
}
}
}
@@ -57,21 +57,21 @@ pub(crate) fn process_funded_addresses(
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) {
for (address_type, type_index, data) in pushes_iter.by_ref().take(holes_count) {
let index = addresses_data.funded.fill_first_hole_or_push(data)?;
result
.get_mut(address_type)
.unwrap()
.insert(typeindex, AnyAddressIndex::from(index));
.insert(type_index, AnyAddressIndex::from(index));
}
// Pure pushes - no holes remain
addresses_data.funded.reserve_pushed(pushes_iter.len());
let mut next_index = addresses_data.funded.len();
for (address_type, typeindex, data) in pushes_iter {
for (address_type, type_index, data) in pushes_iter {
addresses_data.funded.push(data);
result.get_mut(address_type).unwrap().insert(
typeindex,
type_index,
AnyAddressIndex::from(FundedAddressIndex::from(next_index)),
);
next_index += 1;
@@ -97,17 +97,17 @@ pub(crate) fn process_empty_addresses(
let mut pushes: Vec<(OutputType, TypeIndex, EmptyAddressData)> = Vec::with_capacity(total);
for (address_type, items) in empty_updates.into_iter() {
for (typeindex, source) in items {
for (type_index, source) in items {
match source {
WithAddressDataSource::New(data) => {
pushes.push((address_type, typeindex, data));
pushes.push((address_type, type_index, data));
}
WithAddressDataSource::FromEmpty(index, data) => {
updates.push((index, data));
}
WithAddressDataSource::FromFunded(funded_index, data) => {
deletes.push(funded_index);
pushes.push((address_type, typeindex, data));
pushes.push((address_type, type_index, data));
}
}
}
@@ -128,21 +128,21 @@ pub(crate) fn process_empty_addresses(
let holes_count = addresses_data.empty.holes().len();
let mut pushes_iter = pushes.into_iter();
for (address_type, typeindex, data) in pushes_iter.by_ref().take(holes_count) {
for (address_type, type_index, data) in pushes_iter.by_ref().take(holes_count) {
let index = addresses_data.empty.fill_first_hole_or_push(data)?;
result
.get_mut(address_type)
.unwrap()
.insert(typeindex, AnyAddressIndex::from(index));
.insert(type_index, AnyAddressIndex::from(index));
}
// Pure pushes - no holes remain
addresses_data.empty.reserve_pushed(pushes_iter.len());
let mut next_index = addresses_data.empty.len();
for (address_type, typeindex, data) in pushes_iter {
for (address_type, type_index, data) in pushes_iter {
addresses_data.empty.push(data);
result.get_mut(address_type).unwrap().insert(
typeindex,
type_index,
AnyAddressIndex::from(EmptyAddressIndex::from(next_index)),
);
next_index += 1;
@@ -16,35 +16,35 @@ use super::with_source::WithAddressDataSource;
pub(crate) fn update_tx_counts(
funded_cache: &mut AddressTypeToTypeIndexMap<WithAddressDataSource<FundedAddressData>>,
empty_cache: &mut AddressTypeToTypeIndexMap<WithAddressDataSource<EmptyAddressData>>,
mut txindex_vecs: AddressTypeToTypeIndexMap<SmallVec<[TxIndex; 4]>>,
mut tx_index_vecs: AddressTypeToTypeIndexMap<SmallVec<[TxIndex; 4]>>,
) {
// First, deduplicate txindex_vecs for addresses that appear multiple times in a block
for (_, map) in txindex_vecs.iter_mut() {
for (_, txindex_vec) in map.iter_mut() {
if txindex_vec.len() > 1 {
txindex_vec.sort_unstable();
txindex_vec.dedup();
// First, deduplicate tx_index_vecs for addresses that appear multiple times in a block
for (_, map) in tx_index_vecs.iter_mut() {
for (_, tx_index_vec) in map.iter_mut() {
if tx_index_vec.len() > 1 {
tx_index_vec.sort_unstable();
tx_index_vec.dedup();
}
}
}
// Update tx_count on address data
for (address_type, typeindex, txindex_vec) in txindex_vecs
for (address_type, type_index, tx_index_vec) in tx_index_vecs
.into_iter()
.flat_map(|(t, m)| m.into_iter().map(move |(i, v)| (t, i, v)))
{
let tx_count = txindex_vec.len() as u32;
let tx_count = tx_index_vec.len() as u32;
if let Some(addr_data) = funded_cache
.get_mut(address_type)
.unwrap()
.get_mut(&typeindex)
.get_mut(&type_index)
{
addr_data.tx_count += tx_count;
} else if let Some(addr_data) = empty_cache
.get_mut(address_type)
.unwrap()
.get_mut(&typeindex)
.get_mut(&type_index)
{
addr_data.tx_count += tx_count;
}
@@ -22,20 +22,20 @@ use super::super::{
pub struct InputsResult {
/// Map from UTXO creation height -> aggregated sent supply.
pub height_to_sent: FxHashMap<Height, Transacted>,
/// Per-height, per-address-type sent data: (typeindex, value) for each address.
/// Per-height, per-address-type sent data: (type_index, value) for each address.
pub sent_data: HeightToAddressTypeToVec<(TypeIndex, Sats)>,
/// Address data looked up during processing, keyed by (address_type, typeindex).
/// Address data looked up during processing, keyed by (address_type, type_index).
pub address_data: AddressTypeToTypeIndexMap<WithAddressDataSource<FundedAddressData>>,
/// Transaction indexes per address for tx_count tracking.
pub txindex_vecs: AddressTypeToTypeIndexMap<SmallVec<[TxIndex; 4]>>,
pub tx_index_vecs: AddressTypeToTypeIndexMap<SmallVec<[TxIndex; 4]>>,
}
/// Process inputs (spent UTXOs) for a block.
///
/// For each input:
/// 1. Use pre-collected outpoint (from reusable iterator, avoids PcoVec re-decompression)
/// 2. Resolve outpoint to txoutindex
/// 3. Get the creation height from txoutindex_to_height map
/// 2. Resolve outpoint to txout_index
/// 3. Get the creation height from txout_index_to_height map
/// 4. Read value and type from the referenced output (random access via mmap)
/// 5. Look up address data if input references an address type
/// 6. Accumulate into height_to_sent map
@@ -46,35 +46,35 @@ pub struct InputsResult {
#[allow(clippy::too_many_arguments)]
pub(crate) fn process_inputs(
input_count: usize,
txinindex_to_txindex: &[TxIndex],
txinindex_to_value: &[Sats],
txinindex_to_outputtype: &[OutputType],
txinindex_to_typeindex: &[TypeIndex],
txinindex_to_prev_height: &[Height],
first_addressindexes: &ByAddressType<TypeIndex>,
txin_index_to_tx_index: &[TxIndex],
txin_index_to_value: &[Sats],
txin_index_to_output_type: &[OutputType],
txin_index_to_type_index: &[TypeIndex],
txin_index_to_prev_height: &[Height],
first_address_indexes: &ByAddressType<TypeIndex>,
cache: &AddressCache,
vr: &VecsReaders,
any_address_indexes: &AnyAddressIndexesVecs,
addresses_data: &AddressesDataVecs,
) -> Result<InputsResult> {
let map_fn = |local_idx: usize| -> Result<_> {
let txindex = txinindex_to_txindex[local_idx];
let tx_index = txin_index_to_tx_index[local_idx];
let prev_height = txinindex_to_prev_height[local_idx];
let value = txinindex_to_value[local_idx];
let input_type = txinindex_to_outputtype[local_idx];
let prev_height = txin_index_to_prev_height[local_idx];
let value = txin_index_to_value[local_idx];
let input_type = txin_index_to_output_type[local_idx];
if input_type.is_not_address() {
return Ok((prev_height, value, input_type, None));
}
let typeindex = txinindex_to_typeindex[local_idx];
let type_index = txin_index_to_type_index[local_idx];
// Look up address data
let addr_data_opt = load_uncached_address_data(
input_type,
typeindex,
first_addressindexes,
type_index,
first_address_indexes,
cache,
vr,
any_address_indexes,
@@ -85,7 +85,7 @@ pub(crate) fn process_inputs(
prev_height,
value,
input_type,
Some((typeindex, txindex, value, addr_data_opt)),
Some((type_index, tx_index, value, addr_data_opt)),
))
};
@@ -113,7 +113,7 @@ pub(crate) fn process_inputs(
AddressTypeToTypeIndexMap::<WithAddressDataSource<FundedAddressData>>::with_capacity(
estimated_per_type,
);
let mut txindex_vecs =
let mut tx_index_vecs =
AddressTypeToTypeIndexMap::<SmallVec<[TxIndex; 4]>>::with_capacity(estimated_per_type);
for (prev_height, value, output_type, addr_info) in items {
@@ -122,24 +122,24 @@ pub(crate) fn process_inputs(
.or_default()
.iterate(value, output_type);
if let Some((typeindex, txindex, value, addr_data_opt)) = addr_info {
if let Some((type_index, tx_index, value, addr_data_opt)) = addr_info {
sent_data
.entry(prev_height)
.or_default()
.get_mut(output_type)
.unwrap()
.push((typeindex, value));
.push((type_index, value));
if let Some(addr_data) = addr_data_opt {
address_data.insert_for_type(output_type, typeindex, addr_data);
address_data.insert_for_type(output_type, type_index, addr_data);
}
txindex_vecs
tx_index_vecs
.get_mut(output_type)
.unwrap()
.entry(typeindex)
.entry(type_index)
.or_default()
.push(txindex);
.push(tx_index);
}
}
@@ -147,6 +147,6 @@ pub(crate) fn process_inputs(
height_to_sent,
sent_data,
address_data,
txindex_vecs,
tx_index_vecs,
})
}
@@ -21,50 +21,50 @@ use super::super::{
pub struct OutputsResult {
/// Aggregated supply transacted in this block.
pub transacted: Transacted,
/// Per-address-type received data: (typeindex, value) for each address.
/// Per-address-type received data: (type_index, value) for each address.
pub received_data: AddressTypeToVec<(TypeIndex, Sats)>,
/// Address data looked up during processing, keyed by (address_type, typeindex).
/// Address data looked up during processing, keyed by (address_type, type_index).
pub address_data: AddressTypeToTypeIndexMap<WithAddressDataSource<FundedAddressData>>,
/// Transaction indexes per address for tx_count tracking.
pub txindex_vecs: AddressTypeToTypeIndexMap<SmallVec<[TxIndex; 4]>>,
pub tx_index_vecs: AddressTypeToTypeIndexMap<SmallVec<[TxIndex; 4]>>,
}
/// Process outputs (new UTXOs) for a block.
///
/// For each output:
/// 1. Read pre-collected value, output type, and typeindex
/// 1. Read pre-collected value, output type, and type_index
/// 2. Accumulate into Transacted by type and amount
/// 3. Look up address data if output is an address type
/// 4. Track address-specific data for address cohort processing
#[allow(clippy::too_many_arguments)]
pub(crate) fn process_outputs(
txoutindex_to_txindex: &[TxIndex],
txoutdata_vec: &[TxOutData],
first_addressindexes: &ByAddressType<TypeIndex>,
txout_index_to_tx_index: &[TxIndex],
txout_data_vec: &[TxOutData],
first_address_indexes: &ByAddressType<TypeIndex>,
cache: &AddressCache,
vr: &VecsReaders,
any_address_indexes: &AnyAddressIndexesVecs,
addresses_data: &AddressesDataVecs,
) -> Result<OutputsResult> {
let output_count = txoutdata_vec.len();
let output_count = txout_data_vec.len();
// Phase 1: Address lookups (mmap reads) — parallel for large blocks, sequential for small
let map_fn = |local_idx: usize| -> Result<_> {
let txoutdata = &txoutdata_vec[local_idx];
let value = txoutdata.value;
let output_type = txoutdata.outputtype;
let txout_data = &txout_data_vec[local_idx];
let value = txout_data.value;
let output_type = txout_data.output_type;
if output_type.is_not_address() {
return Ok((value, output_type, None));
}
let typeindex = txoutdata.typeindex;
let txindex = txoutindex_to_txindex[local_idx];
let type_index = txout_data.type_index;
let tx_index = txout_index_to_tx_index[local_idx];
let addr_data_opt = load_uncached_address_data(
output_type,
typeindex,
first_addressindexes,
type_index,
first_address_indexes,
cache,
vr,
any_address_indexes,
@@ -74,7 +74,7 @@ pub(crate) fn process_outputs(
Ok((
value,
output_type,
Some((typeindex, txindex, value, addr_data_opt)),
Some((type_index, tx_index, value, addr_data_opt)),
))
};
@@ -97,28 +97,28 @@ pub(crate) fn process_outputs(
AddressTypeToTypeIndexMap::<WithAddressDataSource<FundedAddressData>>::with_capacity(
estimated_per_type,
);
let mut txindex_vecs =
let mut tx_index_vecs =
AddressTypeToTypeIndexMap::<SmallVec<[TxIndex; 4]>>::with_capacity(estimated_per_type);
for (value, output_type, addr_info) in items {
transacted.iterate(value, output_type);
if let Some((typeindex, txindex, value, addr_data_opt)) = addr_info {
if let Some((type_index, tx_index, value, addr_data_opt)) = addr_info {
received_data
.get_mut(output_type)
.unwrap()
.push((typeindex, value));
.push((type_index, value));
if let Some(addr_data) = addr_data_opt {
address_data.insert_for_type(output_type, typeindex, addr_data);
address_data.insert_for_type(output_type, type_index, addr_data);
}
txindex_vecs
tx_index_vecs
.get_mut(output_type)
.unwrap()
.entry(typeindex)
.entry(type_index)
.or_default()
.push(txindex);
.push(tx_index);
}
}
@@ -126,6 +126,6 @@ pub(crate) fn process_outputs(
transacted,
received_data,
address_data,
txindex_vecs,
tx_index_vecs,
})
}
@@ -45,7 +45,7 @@ pub(crate) fn process_blocks(
starting_height: Height,
last_height: Height,
chain_state: &mut Vec<BlockState>,
txindex_to_height: &mut RangeMap<TxIndex, Height>,
tx_index_to_height: &mut RangeMap<TxIndex, Height>,
cached_prices: &[Cents],
cached_timestamps: &[Timestamp],
cached_price_range_max: &PriceRangeMax,
@@ -63,14 +63,14 @@ pub(crate) fn process_blocks(
return Ok(());
}
let height_to_first_txindex = &indexer.vecs.transactions.first_txindex;
let height_to_first_txoutindex = &indexer.vecs.outputs.first_txoutindex;
let height_to_first_txinindex = &indexer.vecs.inputs.first_txinindex;
let height_to_first_tx_index = &indexer.vecs.transactions.first_tx_index;
let height_to_first_txout_index = &indexer.vecs.outputs.first_txout_index;
let height_to_first_txin_index = &indexer.vecs.inputs.first_txin_index;
let height_to_tx_count = &transactions.count.total.base.height;
let height_to_output_count = &outputs.count.total.full.sum;
let height_to_input_count = &inputs.count.full.sum;
let txindex_to_output_count = &indexes.txindex.output_count;
let txindex_to_input_count = &indexes.txindex.input_count;
let tx_index_to_output_count = &indexes.tx_index.output_count;
let tx_index_to_input_count = &indexes.tx_index.input_count;
let height_to_price_vec = cached_prices;
let height_to_timestamp_vec = cached_timestamps;
@@ -78,12 +78,12 @@ pub(crate) fn process_blocks(
let start_usize = starting_height.to_usize();
let end_usize = last_height.to_usize() + 1;
let height_to_first_txindex_vec: Vec<TxIndex> =
height_to_first_txindex.collect_range_at(start_usize, end_usize);
let height_to_first_txoutindex_vec: Vec<_> =
height_to_first_txoutindex.collect_range_at(start_usize, end_usize);
let height_to_first_txinindex_vec: Vec<_> =
height_to_first_txinindex.collect_range_at(start_usize, end_usize);
let height_to_first_tx_index_vec: Vec<TxIndex> =
height_to_first_tx_index.collect_range_at(start_usize, end_usize);
let height_to_first_txout_index_vec: Vec<_> =
height_to_first_txout_index.collect_range_at(start_usize, end_usize);
let height_to_first_txin_index_vec: Vec<_> =
height_to_first_txin_index.collect_range_at(start_usize, end_usize);
let height_to_tx_count_vec: Vec<_> =
height_to_tx_count.collect_range_at(start_usize, end_usize);
let height_to_output_count_vec: Vec<_> =
@@ -106,39 +106,39 @@ pub(crate) fn process_blocks(
let mut vr = VecsReaders::new(&vecs.any_address_indexes, &vecs.addresses_data);
debug!("VecsReaders created");
// Extend txindex_to_height RangeMap with new entries (incremental, O(new_blocks))
let target_len = indexer.vecs.transactions.first_txindex.len();
let current_len = txindex_to_height.len();
// Extend tx_index_to_height RangeMap with new entries (incremental, O(new_blocks))
let target_len = indexer.vecs.transactions.first_tx_index.len();
let current_len = tx_index_to_height.len();
if current_len < target_len {
debug!(
"extending txindex_to_height RangeMap from {} to {}",
"extending tx_index_to_height RangeMap from {} to {}",
current_len, target_len
);
let new_entries: Vec<TxIndex> = indexer
.vecs
.transactions
.first_txindex
.first_tx_index
.collect_range_at(current_len, target_len);
for first_txindex in new_entries {
txindex_to_height.push(first_txindex);
for first_tx_index in new_entries {
tx_index_to_height.push(first_tx_index);
}
} else if current_len > target_len {
debug!(
"truncating txindex_to_height RangeMap from {} to {}",
"truncating tx_index_to_height RangeMap from {} to {}",
current_len, target_len
);
txindex_to_height.truncate(target_len);
tx_index_to_height.truncate(target_len);
}
debug!(
"txindex_to_height RangeMap ready ({} entries)",
txindex_to_height.len()
"tx_index_to_height RangeMap ready ({} entries)",
tx_index_to_height.len()
);
// Create reusable iterators and buffers for per-block reads
let mut txout_iters = TxOutReaders::new(indexer);
let mut txin_iters = TxInReaders::new(indexer, inputs, txindex_to_height);
let mut txout_to_txindex_buf = IndexToTxIndexBuf::new();
let mut txin_to_txindex_buf = IndexToTxIndexBuf::new();
let mut txin_iters = TxInReaders::new(indexer, inputs, tx_index_to_height);
let mut txout_to_tx_index_buf = IndexToTxIndexBuf::new();
let mut txin_to_tx_index_buf = IndexToTxIndexBuf::new();
// Pre-collect first address indexes per type for the block range
let first_p2a_vec = indexer
@@ -186,9 +186,9 @@ pub(crate) fn process_blocks(
debug!("recovering address_counts from height {}", starting_height);
let (mut address_counts, mut empty_address_counts) = if starting_height > Height::ZERO {
let address_counts =
AddressTypeToAddressCount::from((&vecs.addresses.funded.by_addresstype, starting_height));
AddressTypeToAddressCount::from((&vecs.addresses.funded.by_address_type, starting_height));
let empty_address_counts = AddressTypeToAddressCount::from((
&vecs.addresses.empty.by_addresstype,
&vecs.addresses.empty.by_address_type,
starting_height,
));
(address_counts, empty_address_counts)
@@ -225,11 +225,11 @@ pub(crate) fn process_blocks(
// Get block metadata from pre-collected vecs
let offset = height.to_usize() - start_usize;
let first_txindex = height_to_first_txindex_vec[offset];
let first_tx_index = height_to_first_tx_index_vec[offset];
let tx_count = u64::from(height_to_tx_count_vec[offset]);
let first_txoutindex = height_to_first_txoutindex_vec[offset].to_usize();
let first_txout_index = height_to_first_txout_index_vec[offset].to_usize();
let output_count = u64::from(height_to_output_count_vec[offset]) as usize;
let first_txinindex = height_to_first_txinindex_vec[offset].to_usize();
let first_txin_index = height_to_first_txin_index_vec[offset].to_usize();
let input_count = u64::from(height_to_input_count_vec[offset]) as usize;
let timestamp = height_to_timestamp_collected[offset];
let block_price = height_to_price_collected[offset];
@@ -239,7 +239,7 @@ pub(crate) fn process_blocks(
debug_assert_eq!(ctx.price_at(height), block_price);
// Get first address indexes for this height from pre-collected vecs
let first_addressindexes = ByAddressType {
let first_address_indexes = ByAddressType {
p2a: TypeIndex::from(first_p2a_vec[offset].to_usize()),
p2pk33: TypeIndex::from(first_p2pk33_vec[offset].to_usize()),
p2pk65: TypeIndex::from(first_p2pk65_vec[offset].to_usize()),
@@ -254,7 +254,7 @@ pub(crate) fn process_blocks(
activity_counts.reset();
// Process outputs, inputs, and tick-tock in parallel via rayon::join.
// Collection (build txindex mappings + bulk mmap reads) is merged into the
// Collection (build tx_index mappings + bulk mmap reads) is merged into the
// processing closures so outputs and inputs collection overlap each other
// and tick-tock, instead of running sequentially before the join.
let (matured, oi_result) = rayon::join(
@@ -262,14 +262,14 @@ pub(crate) fn process_blocks(
|| -> Result<_> {
let (outputs_result, inputs_result) = rayon::join(
|| {
let txoutindex_to_txindex = txout_to_txindex_buf
.build(first_txindex, tx_count, txindex_to_output_count);
let txoutdata_vec =
txout_iters.collect_block_outputs(first_txoutindex, output_count);
let txout_index_to_tx_index = txout_to_tx_index_buf
.build(first_tx_index, tx_count, tx_index_to_output_count);
let txout_data_vec =
txout_iters.collect_block_outputs(first_txout_index, output_count);
process_outputs(
txoutindex_to_txindex,
txoutdata_vec,
&first_addressindexes,
txout_index_to_tx_index,
txout_data_vec,
&first_address_indexes,
&cache,
&vr,
&vecs.any_address_indexes,
@@ -278,22 +278,22 @@ pub(crate) fn process_blocks(
},
|| -> Result<_> {
if input_count > 1 {
let txinindex_to_txindex = txin_to_txindex_buf
.build(first_txindex, tx_count, txindex_to_input_count);
let (input_values, input_prev_heights, input_outputtypes, input_typeindexes) =
let txin_index_to_tx_index = txin_to_tx_index_buf
.build(first_tx_index, tx_count, tx_index_to_input_count);
let (input_values, input_prev_heights, input_output_types, input_type_indexes) =
txin_iters.collect_block_inputs(
first_txinindex + 1,
first_txin_index + 1,
input_count - 1,
height,
);
process_inputs(
input_count - 1,
&txinindex_to_txindex[1..],
&txin_index_to_tx_index[1..],
input_values,
input_outputtypes,
input_typeindexes,
input_output_types,
input_type_indexes,
input_prev_heights,
&first_addressindexes,
&first_address_indexes,
&cache,
&vr,
&vecs.any_address_indexes,
@@ -304,7 +304,7 @@ pub(crate) fn process_blocks(
height_to_sent: Default::default(),
sent_data: Default::default(),
address_data: Default::default(),
txindex_vecs: Default::default(),
tx_index_vecs: Default::default(),
})
}
},
@@ -318,11 +318,11 @@ pub(crate) fn process_blocks(
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
.txindex_vecs
.merge_vec(inputs_result.txindex_vecs);
cache.update_tx_counts(combined_txindex_vecs);
// Combine tx_index_vecs from outputs and inputs, then update tx_count
let combined_tx_index_vecs = outputs_result
.tx_index_vecs
.merge_vec(inputs_result.tx_index_vecs);
cache.update_tx_counts(combined_tx_index_vecs);
let mut transacted = outputs_result.transacted;
let mut height_to_sent = inputs_result.height_to_sent;
@@ -15,17 +15,17 @@ use crate::{
#[derive(Debug, Clone, Copy)]
pub struct TxOutData {
pub value: Sats,
pub outputtype: OutputType,
pub typeindex: TypeIndex,
pub output_type: OutputType,
pub type_index: TypeIndex,
}
/// Readers for txout vectors. Reuses internal buffers across blocks.
pub struct TxOutReaders<'a> {
indexer: &'a Indexer,
values_buf: Vec<Sats>,
outputtypes_buf: Vec<OutputType>,
typeindexes_buf: Vec<TypeIndex>,
txoutdata_buf: Vec<TxOutData>,
output_types_buf: Vec<OutputType>,
type_indexes_buf: Vec<TypeIndex>,
txout_data_buf: Vec<TxOutData>,
}
impl<'a> TxOutReaders<'a> {
@@ -33,48 +33,48 @@ impl<'a> TxOutReaders<'a> {
Self {
indexer,
values_buf: Vec::new(),
outputtypes_buf: Vec::new(),
typeindexes_buf: Vec::new(),
txoutdata_buf: Vec::new(),
output_types_buf: Vec::new(),
type_indexes_buf: Vec::new(),
txout_data_buf: Vec::new(),
}
}
/// Collect output data for a block range using bulk reads with buffer reuse.
pub(crate) fn collect_block_outputs(
&mut self,
first_txoutindex: usize,
first_txout_index: usize,
output_count: usize,
) -> &[TxOutData] {
let end = first_txoutindex + output_count;
let end = first_txout_index + output_count;
self.indexer.vecs.outputs.value.collect_range_into_at(
first_txoutindex,
first_txout_index,
end,
&mut self.values_buf,
);
self.indexer.vecs.outputs.outputtype.collect_range_into_at(
first_txoutindex,
self.indexer.vecs.outputs.output_type.collect_range_into_at(
first_txout_index,
end,
&mut self.outputtypes_buf,
&mut self.output_types_buf,
);
self.indexer.vecs.outputs.typeindex.collect_range_into_at(
first_txoutindex,
self.indexer.vecs.outputs.type_index.collect_range_into_at(
first_txout_index,
end,
&mut self.typeindexes_buf,
&mut self.type_indexes_buf,
);
self.txoutdata_buf.clear();
self.txoutdata_buf.extend(
self.txout_data_buf.clear();
self.txout_data_buf.extend(
self.values_buf
.iter()
.zip(&self.outputtypes_buf)
.zip(&self.typeindexes_buf)
.map(|((&value, &outputtype), &typeindex)| TxOutData {
.zip(&self.output_types_buf)
.zip(&self.type_indexes_buf)
.map(|((&value, &output_type), &type_index)| TxOutData {
value,
outputtype,
typeindex,
output_type,
type_index,
}),
);
&self.txoutdata_buf
&self.txout_data_buf
}
}
@@ -82,59 +82,59 @@ impl<'a> TxOutReaders<'a> {
pub struct TxInReaders<'a> {
indexer: &'a Indexer,
txins: &'a inputs::Vecs,
txindex_to_height: &'a mut RangeMap<TxIndex, Height>,
tx_index_to_height: &'a mut RangeMap<TxIndex, Height>,
outpoints_buf: Vec<OutPoint>,
values_buf: Vec<Sats>,
prev_heights_buf: Vec<Height>,
outputtypes_buf: Vec<OutputType>,
typeindexes_buf: Vec<TypeIndex>,
output_types_buf: Vec<OutputType>,
type_indexes_buf: Vec<TypeIndex>,
}
impl<'a> TxInReaders<'a> {
pub(crate) fn new(
indexer: &'a Indexer,
txins: &'a inputs::Vecs,
txindex_to_height: &'a mut RangeMap<TxIndex, Height>,
tx_index_to_height: &'a mut RangeMap<TxIndex, Height>,
) -> Self {
Self {
indexer,
txins,
txindex_to_height,
tx_index_to_height,
outpoints_buf: Vec::new(),
values_buf: Vec::new(),
prev_heights_buf: Vec::new(),
outputtypes_buf: Vec::new(),
typeindexes_buf: Vec::new(),
output_types_buf: Vec::new(),
type_indexes_buf: Vec::new(),
}
}
/// Collect input data for a block range using bulk reads with buffer reuse.
pub(crate) fn collect_block_inputs(
&mut self,
first_txinindex: usize,
first_txin_index: usize,
input_count: usize,
current_height: Height,
) -> (&[Sats], &[Height], &[OutputType], &[TypeIndex]) {
let end = first_txinindex + input_count;
let end = first_txin_index + input_count;
self.txins.spent.value.collect_range_into_at(
first_txinindex,
first_txin_index,
end,
&mut self.values_buf,
);
self.indexer.vecs.inputs.outpoint.collect_range_into_at(
first_txinindex,
first_txin_index,
end,
&mut self.outpoints_buf,
);
self.indexer.vecs.inputs.outputtype.collect_range_into_at(
first_txinindex,
self.indexer.vecs.inputs.output_type.collect_range_into_at(
first_txin_index,
end,
&mut self.outputtypes_buf,
&mut self.output_types_buf,
);
self.indexer.vecs.inputs.typeindex.collect_range_into_at(
first_txinindex,
self.indexer.vecs.inputs.type_index.collect_range_into_at(
first_txin_index,
end,
&mut self.typeindexes_buf,
&mut self.type_indexes_buf,
);
self.prev_heights_buf.clear();
@@ -143,8 +143,8 @@ impl<'a> TxInReaders<'a> {
if outpoint.is_coinbase() {
current_height
} else {
self.txindex_to_height
.get(outpoint.txindex())
self.tx_index_to_height
.get(outpoint.tx_index())
.unwrap_or(current_height)
}
}),
@@ -153,16 +153,16 @@ impl<'a> TxInReaders<'a> {
(
&self.values_buf,
&self.prev_heights_buf,
&self.outputtypes_buf,
&self.typeindexes_buf,
&self.output_types_buf,
&self.type_indexes_buf,
)
}
}
/// Cached readers for stateful vectors.
pub struct VecsReaders {
pub addresstypeindex_to_anyaddressindex: ByAddressType<Reader>,
pub anyaddressindex_to_anyaddressdata: ByAnyAddress<Reader>,
pub address_type_index_to_any_address_index: ByAddressType<Reader>,
pub any_address_index_to_any_address_data: ByAnyAddress<Reader>,
}
impl VecsReaders {
@@ -171,7 +171,7 @@ impl VecsReaders {
addresses_data: &AddressesDataVecs,
) -> Self {
Self {
addresstypeindex_to_anyaddressindex: ByAddressType {
address_type_index_to_any_address_index: ByAddressType {
p2a: any_address_indexes.p2a.create_reader(),
p2pk33: any_address_indexes.p2pk33.create_reader(),
p2pk65: any_address_indexes.p2pk65.create_reader(),
@@ -181,7 +181,7 @@ impl VecsReaders {
p2wpkh: any_address_indexes.p2wpkh.create_reader(),
p2wsh: any_address_indexes.p2wsh.create_reader(),
},
anyaddressindex_to_anyaddressdata: ByAnyAddress {
any_address_index_to_any_address_data: ByAnyAddress {
funded: addresses_data.funded.create_reader(),
empty: addresses_data.empty.create_reader(),
},
@@ -190,13 +190,13 @@ impl VecsReaders {
/// Get reader for specific address type.
pub(crate) fn address_reader(&self, address_type: OutputType) -> &Reader {
self.addresstypeindex_to_anyaddressindex
self.address_type_index_to_any_address_index
.get(address_type)
.unwrap()
}
}
/// Reusable buffers for per-block txindex mapping construction.
/// Reusable buffers for per-block tx_index mapping construction.
pub(crate) struct IndexToTxIndexBuf {
counts: Vec<StoredU64>,
result: Vec<TxIndex>,
@@ -210,15 +210,15 @@ impl IndexToTxIndexBuf {
}
}
/// Build index -> txindex mapping for a block, reusing internal buffers.
/// Build index -> tx_index mapping for a block, reusing internal buffers.
pub(crate) fn build(
&mut self,
block_first_txindex: TxIndex,
block_first_tx_index: TxIndex,
block_tx_count: u64,
txindex_to_count: &impl ReadableVec<TxIndex, StoredU64>,
tx_index_to_count: &impl ReadableVec<TxIndex, StoredU64>,
) -> &[TxIndex] {
let first = block_first_txindex.to_usize();
txindex_to_count.collect_range_into_at(
let first = block_first_tx_index.to_usize();
tx_index_to_count.collect_range_into_at(
first,
first + block_tx_count as usize,
&mut self.counts,
@@ -229,9 +229,9 @@ impl IndexToTxIndexBuf {
self.result.reserve(total as usize);
for (offset, count) in self.counts.iter().enumerate() {
let txindex = TxIndex::from(first + offset);
let tx_index = TxIndex::from(first + offset);
self.result
.extend(std::iter::repeat_n(txindex, u64::from(*count) as usize));
.extend(std::iter::repeat_n(tx_index, u64::from(*count) as usize));
}
&self.result
@@ -34,16 +34,16 @@ impl<R: RealizedOps> AddressCohortState<R> {
pub(crate) fn send(
&mut self,
addressdata: &mut FundedAddressData,
address_data: &mut FundedAddressData,
value: Sats,
current_price: Cents,
prev_price: Cents,
ath: Cents,
age: Age,
) -> Result<()> {
let prev = addressdata.cost_basis_snapshot();
addressdata.send(value, prev_price)?;
let current = addressdata.cost_basis_snapshot();
let prev = address_data.cost_basis_snapshot();
address_data.send(value, prev_price)?;
let current = address_data.cost_basis_snapshot();
self.inner.send_address(
&SupplyState {
@@ -83,14 +83,14 @@ impl<R: RealizedOps> AddressCohortState<R> {
);
}
pub(crate) fn add(&mut self, addressdata: &FundedAddressData) {
pub(crate) fn add(&mut self, address_data: &FundedAddressData) {
self.address_count += 1;
self.inner
.increment_snapshot(&addressdata.cost_basis_snapshot());
.increment_snapshot(&address_data.cost_basis_snapshot());
}
pub(crate) fn subtract(&mut self, addressdata: &FundedAddressData) {
let snapshot = addressdata.cost_basis_snapshot();
pub(crate) fn subtract(&mut self, address_data: &FundedAddressData) {
let snapshot = address_data.cost_basis_snapshot();
// Check for potential underflow before it happens
if unlikely(self.inner.supply.utxo_count < snapshot.supply_state.utxo_count) {
@@ -103,7 +103,7 @@ impl<R: RealizedOps> AddressCohortState<R> {
This means the address is not properly tracked in this cohort.",
self.address_count,
self.inner.supply,
addressdata,
address_data,
snapshot.supply_state,
snapshot.realized_price
);
@@ -118,7 +118,7 @@ impl<R: RealizedOps> AddressCohortState<R> {
This means the address is not properly tracked in this cohort.",
self.address_count,
self.inner.supply,
addressdata,
address_data,
snapshot.supply_state,
snapshot.realized_price
);
@@ -129,7 +129,7 @@ impl<R: RealizedOps> AddressCohortState<R> {
"AddressCohortState::subtract address_count underflow! address_count=0\n\
Address being subtracted: {}\n\
Realized price: {}",
addressdata, snapshot.realized_price
address_data, snapshot.realized_price
)
});
+23 -22
View File
@@ -23,7 +23,7 @@ use crate::{
state::BlockState,
},
indexes, inputs,
internal::{CachedWindowStarts, PerBlockCumulative, db_utils::{finalize_db, open_db}},
internal::{CachedWindowStarts, PerBlockCumulativeWithSums, db_utils::{finalize_db, open_db}},
outputs, prices, transactions,
};
@@ -70,16 +70,16 @@ pub struct Vecs<M: StorageMode = Rw> {
#[traversable(wrap = "cohorts", rename = "address")]
pub address_cohorts: AddressCohorts<M>,
#[traversable(wrap = "cointime")]
pub coinblocks_destroyed: PerBlockCumulative<StoredF64, M>,
pub coinblocks_destroyed: PerBlockCumulativeWithSums<StoredF64, StoredF64, M>,
pub addresses: AddressMetricsVecs<M>,
/// In-memory block state for UTXO processing. Persisted via supply_state.
/// Kept across compute() calls to avoid O(n) rebuild on resume.
#[traversable(skip)]
chain_state: Vec<BlockState>,
/// In-memory txindex→height reverse lookup. Kept across compute() calls.
/// In-memory tx_index→height reverse lookup. Kept across compute() calls.
#[traversable(skip)]
txindex_to_height: RangeMap<TxIndex, Height>,
tx_index_to_height: RangeMap<TxIndex, Height>,
/// Cached height→price mapping. Incrementally extended, O(new_blocks) on resume.
#[traversable(skip)]
@@ -114,12 +114,12 @@ impl Vecs {
let address_cohorts = AddressCohorts::forced_import(&db, version, indexes, &states_path, cached_starts)?;
// Create address data BytesVecs first so we can also use them for identity mappings
let fundedaddressindex_to_fundedaddressdata = BytesVec::forced_import_with(
vecdb::ImportOptions::new(&db, "fundedaddressdata", version)
let funded_address_index_to_funded_address_data = BytesVec::forced_import_with(
vecdb::ImportOptions::new(&db, "funded_address_data", version)
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
)?;
let emptyaddressindex_to_emptyaddressdata = BytesVec::forced_import_with(
vecdb::ImportOptions::new(&db, "emptyaddressdata", version)
let empty_address_index_to_empty_address_data = BytesVec::forced_import_with(
vecdb::ImportOptions::new(&db, "empty_address_data", version)
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
)?;
@@ -127,13 +127,13 @@ impl Vecs {
let funded_address_index = LazyVecFrom1::init(
"funded_address_index",
version,
fundedaddressindex_to_fundedaddressdata.read_only_boxed_clone(),
funded_address_index_to_funded_address_data.read_only_boxed_clone(),
|index, _| index,
);
let empty_address_index = LazyVecFrom1::init(
"empty_address_index",
version,
emptyaddressindex_to_emptyaddressdata.read_only_boxed_clone(),
empty_address_index_to_empty_address_data.read_only_boxed_clone(),
|index, _| index,
);
@@ -173,20 +173,21 @@ impl Vecs {
utxo_cohorts,
address_cohorts,
coinblocks_destroyed: PerBlockCumulative::forced_import(
coinblocks_destroyed: PerBlockCumulativeWithSums::forced_import(
&db,
"coinblocks_destroyed",
version + Version::TWO,
indexes,
cached_starts,
)?,
any_address_indexes: AnyAddressIndexesVecs::forced_import(&db, version)?,
addresses_data: AddressesDataVecs {
funded: fundedaddressindex_to_fundedaddressdata,
empty: emptyaddressindex_to_emptyaddressdata,
funded: funded_address_index_to_funded_address_data,
empty: empty_address_index_to_empty_address_data,
},
chain_state: Vec::new(),
txindex_to_height: RangeMap::default(),
tx_index_to_height: RangeMap::default(),
cached_prices: Vec::new(),
cached_timestamps: Vec::new(),
@@ -294,9 +295,9 @@ impl Vecs {
debug!("recovered_height={}", recovered_height);
// Take chain_state and txindex_to_height out of self to avoid borrow conflicts
// Take chain_state and tx_index_to_height out of self to avoid borrow conflicts
let mut chain_state = std::mem::take(&mut self.chain_state);
let mut txindex_to_height = std::mem::take(&mut self.txindex_to_height);
let mut tx_index_to_height = std::mem::take(&mut self.tx_index_to_height);
// Recover or reuse chain_state
let starting_height = if recovered_height.is_zero() {
@@ -312,7 +313,7 @@ impl Vecs {
)?;
chain_state.clear();
txindex_to_height.truncate(0);
tx_index_to_height.truncate(0);
info!("State recovery: fresh start");
Height::ZERO
@@ -341,7 +342,7 @@ impl Vecs {
debug!("chain_state rebuilt");
// Truncate RangeMap to match (entries are immutable, safe to keep)
txindex_to_height.truncate(end);
tx_index_to_height.truncate(end);
recovered_height
};
@@ -384,7 +385,7 @@ impl Vecs {
starting_height,
last_height,
&mut chain_state,
&mut txindex_to_height,
&mut tx_index_to_height,
&cached_prices,
&cached_timestamps,
&cached_price_range_max,
@@ -396,9 +397,9 @@ impl Vecs {
self.cached_price_range_max = cached_price_range_max;
}
// Put chain_state and txindex_to_height back
// Put chain_state and tx_index_to_height back
self.chain_state = chain_state;
self.txindex_to_height = txindex_to_height;
self.tx_index_to_height = tx_index_to_height;
// 5. Compute aggregates (overlapping cohorts from separate cohorts)
info!("Computing overlapping cohorts...");
@@ -426,7 +427,7 @@ impl Vecs {
r2?;
}
// 6b. Compute address count sum (by addresstype → all)
// 6b. Compute address count sum (by address_type → all)
self.addresses.funded.compute_rest(starting_indexes, exit)?;
self.addresses.empty.compute_rest(starting_indexes, exit)?;
+16 -16
View File
@@ -92,7 +92,7 @@ impl Vecs {
Self {
p2pk33: P2PK33Vecs {
identity: LazyVecFrom1::init(
"p2pk33addressindex",
"p2pk33_address_index",
version,
indexer.vecs.addresses.p2pk33.bytes.read_only_boxed_clone(),
|index, _| index,
@@ -100,7 +100,7 @@ impl Vecs {
},
p2pk65: P2PK65Vecs {
identity: LazyVecFrom1::init(
"p2pk65addressindex",
"p2pk65_address_index",
version,
indexer.vecs.addresses.p2pk65.bytes.read_only_boxed_clone(),
|index, _| index,
@@ -108,7 +108,7 @@ impl Vecs {
},
p2pkh: P2PKHVecs {
identity: LazyVecFrom1::init(
"p2pkhaddressindex",
"p2pkh_address_index",
version,
indexer.vecs.addresses.p2pkh.bytes.read_only_boxed_clone(),
|index, _| index,
@@ -116,7 +116,7 @@ impl Vecs {
},
p2sh: P2SHVecs {
identity: LazyVecFrom1::init(
"p2shaddressindex",
"p2sh_address_index",
version,
indexer.vecs.addresses.p2sh.bytes.read_only_boxed_clone(),
|index, _| index,
@@ -124,7 +124,7 @@ impl Vecs {
},
p2tr: P2TRVecs {
identity: LazyVecFrom1::init(
"p2traddressindex",
"p2tr_address_index",
version,
indexer.vecs.addresses.p2tr.bytes.read_only_boxed_clone(),
|index, _| index,
@@ -132,7 +132,7 @@ impl Vecs {
},
p2wpkh: P2WPKHVecs {
identity: LazyVecFrom1::init(
"p2wpkhaddressindex",
"p2wpkh_address_index",
version,
indexer.vecs.addresses.p2wpkh.bytes.read_only_boxed_clone(),
|index, _| index,
@@ -140,7 +140,7 @@ impl Vecs {
},
p2wsh: P2WSHVecs {
identity: LazyVecFrom1::init(
"p2wshaddressindex",
"p2wsh_address_index",
version,
indexer.vecs.addresses.p2wsh.bytes.read_only_boxed_clone(),
|index, _| index,
@@ -148,7 +148,7 @@ impl Vecs {
},
p2a: P2AVecs {
identity: LazyVecFrom1::init(
"p2aaddressindex",
"p2a_address_index",
version,
indexer.vecs.addresses.p2a.bytes.read_only_boxed_clone(),
|index, _| index,
@@ -156,44 +156,44 @@ impl Vecs {
},
p2ms: P2MSVecs {
identity: LazyVecFrom1::init(
"p2msoutputindex",
"p2ms_output_index",
version,
indexer.vecs.scripts.p2ms.to_txindex.read_only_boxed_clone(),
indexer.vecs.scripts.p2ms.to_tx_index.read_only_boxed_clone(),
|index, _| index,
),
},
empty: EmptyVecs {
identity: LazyVecFrom1::init(
"emptyoutputindex",
"empty_output_index",
version,
indexer
.vecs
.scripts
.empty.to_txindex
.empty.to_tx_index
.read_only_boxed_clone(),
|index, _| index,
),
},
unknown: UnknownVecs {
identity: LazyVecFrom1::init(
"unknownoutputindex",
"unknown_output_index",
version,
indexer
.vecs
.scripts
.unknown.to_txindex
.unknown.to_tx_index
.read_only_boxed_clone(),
|index, _| index,
),
},
opreturn: OpReturnVecs {
identity: LazyVecFrom1::init(
"opreturnindex",
"op_return_index",
version,
indexer
.vecs
.scripts
.opreturn.to_txindex
.opreturn.to_tx_index
.read_only_boxed_clone(),
|index, _| index,
),
+2 -2
View File
@@ -25,7 +25,7 @@ pub struct Vecs<M: StorageMode = Rw> {
pub month6: M::Stored<EagerVec<PcoVec<Height, Month6>>>,
pub year1: M::Stored<EagerVec<PcoVec<Height, Year1>>>,
pub year10: M::Stored<EagerVec<PcoVec<Height, Year10>>>,
pub txindex_count: M::Stored<EagerVec<PcoVec<Height, StoredU64>>>,
pub tx_index_count: M::Stored<EagerVec<PcoVec<Height, StoredU64>>>,
}
impl Vecs {
@@ -47,7 +47,7 @@ impl Vecs {
month6: EagerVec::forced_import(db, "month6", version)?,
year1: EagerVec::forced_import(db, "year1", version)?,
year10: EagerVec::forced_import(db, "year10", version)?,
txindex_count: EagerVec::forced_import(db, "txindex_count", version)?,
tx_index_count: EagerVec::forced_import(db, "tx_index_count", version)?,
})
}
}
+23 -23
View File
@@ -13,9 +13,9 @@ mod minute30;
mod month1;
mod month3;
mod month6;
mod txindex;
mod txinindex;
mod txoutindex;
mod tx_index;
mod txin_index;
mod txout_index;
mod week1;
mod year1;
mod year10;
@@ -51,9 +51,9 @@ pub use minute30::Vecs as Minute30Vecs;
pub use month1::Vecs as Month1Vecs;
pub use month3::Vecs as Month3Vecs;
pub use month6::Vecs as Month6Vecs;
pub use txindex::Vecs as TxIndexVecs;
pub use txinindex::Vecs as TxInIndexVecs;
pub use txoutindex::Vecs as TxOutIndexVecs;
pub use tx_index::Vecs as TxIndexVecs;
pub use txin_index::Vecs as TxInIndexVecs;
pub use txout_index::Vecs as TxOutIndexVecs;
pub use week1::Vecs as Week1Vecs;
pub use year1::Vecs as Year1Vecs;
pub use year10::Vecs as Year10Vecs;
@@ -82,9 +82,9 @@ pub struct Vecs<M: StorageMode = Rw> {
pub month6: Month6Vecs<M>,
pub year1: Year1Vecs<M>,
pub year10: Year10Vecs<M>,
pub txindex: TxIndexVecs<M>,
pub txinindex: TxInIndexVecs,
pub txoutindex: TxOutIndexVecs,
pub tx_index: TxIndexVecs<M>,
pub txin_index: TxInIndexVecs,
pub txout_index: TxOutIndexVecs,
}
impl Vecs {
@@ -114,9 +114,9 @@ impl Vecs {
let month6 = Month6Vecs::forced_import(&db, version)?;
let year1 = Year1Vecs::forced_import(&db, version)?;
let year10 = Year10Vecs::forced_import(&db, version)?;
let txindex = TxIndexVecs::forced_import(&db, version, indexer)?;
let txinindex = TxInIndexVecs::forced_import(version, indexer);
let txoutindex = TxOutIndexVecs::forced_import(version, indexer);
let tx_index = TxIndexVecs::forced_import(&db, version, indexer)?;
let txin_index = TxInIndexVecs::forced_import(version, indexer);
let txout_index = TxOutIndexVecs::forced_import(version, indexer);
let cached_mappings = CachedMappings {
minute10_first_height: CachedVec::new(&minute10.first_height),
@@ -155,9 +155,9 @@ impl Vecs {
month6,
year1,
year10,
txindex,
txinindex,
txoutindex,
tx_index,
txin_index,
txout_index,
db,
};
@@ -221,15 +221,15 @@ impl Vecs {
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.txindex.input_count.compute_count_from_indexes(
starting_indexes.txindex,
&indexer.vecs.transactions.first_txinindex,
self.tx_index.input_count.compute_count_from_indexes(
starting_indexes.tx_index,
&indexer.vecs.transactions.first_txin_index,
&indexer.vecs.inputs.outpoint,
exit,
)?;
self.txindex.output_count.compute_count_from_indexes(
starting_indexes.txindex,
&indexer.vecs.transactions.first_txoutindex,
self.tx_index.output_count.compute_count_from_indexes(
starting_indexes.tx_index,
&indexer.vecs.transactions.first_txout_index,
&indexer.vecs.outputs.value,
exit,
)?;
@@ -242,9 +242,9 @@ impl Vecs {
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.height.txindex_count.compute_count_from_indexes(
self.height.tx_index_count.compute_count_from_indexes(
starting_indexes.height,
&indexer.vecs.transactions.first_txindex,
&indexer.vecs.transactions.first_tx_index,
&indexer.vecs.transactions.txid,
exit,
)?;
+1 -1
View File
@@ -22,7 +22,7 @@ impl Vecs {
) -> Result<Self> {
Ok(Self {
identity: LazyVecFrom1::init(
"txindex",
"tx_index",
version,
indexer.vecs.transactions.txid.read_only_boxed_clone(),
|index, _| index,
@@ -12,7 +12,7 @@ impl Vecs {
pub(crate) fn forced_import(version: Version, indexer: &Indexer) -> Self {
Self {
identity: LazyVecFrom1::init(
"txinindex",
"txin_index",
version,
indexer.vecs.inputs.outpoint.read_only_boxed_clone(),
|index, _| index,
@@ -12,7 +12,7 @@ impl Vecs {
pub(crate) fn forced_import(version: Version, indexer: &Indexer) -> Self {
Self {
identity: LazyVecFrom1::init(
"txoutindex",
"txout_index",
version,
indexer.vecs.outputs.value.read_only_boxed_clone(),
|index, _| index,
@@ -20,9 +20,9 @@ impl Vecs {
.compute(starting_indexes.height, &window_starts, exit, |full| {
full.compute_with_skip(
starting_indexes.height,
&indexes.txindex.input_count,
&indexer.vecs.transactions.first_txindex,
&indexes.height.txindex_count,
&indexes.tx_index.input_count,
&indexer.vecs.transactions.first_tx_index,
&indexes.height.tx_index_count,
exit,
0,
)
+27 -27
View File
@@ -18,9 +18,9 @@ impl Vecs {
) -> Result<()> {
// Validate computed versions against dependencies
let dep_version = indexer.vecs.inputs.outpoint.version()
+ indexer.vecs.transactions.first_txoutindex.version()
+ indexer.vecs.transactions.first_txout_index.version()
+ indexer.vecs.outputs.value.version();
self.txoutindex
self.txout_index
.validate_computed_version_or_reset(dep_version)?;
self.value.validate_computed_version_or_reset(dep_version)?;
@@ -29,21 +29,21 @@ impl Vecs {
return Ok(());
}
let len1 = self.txoutindex.len();
let len1 = self.txout_index.len();
let len2 = self.value.len();
let starting = starting_indexes.txinindex.to_usize();
let starting = starting_indexes.txin_index.to_usize();
let min = len1.min(len2).min(starting);
if min >= target {
return Ok(());
}
let first_txoutindex_reader = indexer.vecs.transactions.first_txoutindex.reader();
let first_txout_index_reader = indexer.vecs.transactions.first_txout_index.reader();
let value_reader = indexer.vecs.outputs.value.reader();
let actual_total = target - min;
let mut entries: Vec<Entry> = Vec::with_capacity(actual_total.min(BATCH_SIZE));
// Pre-allocate output buffers for scatter-write pattern
let mut out_txoutindex: Vec<TxOutIndex> = Vec::new();
let mut out_txout_index: Vec<TxOutIndex> = Vec::new();
let mut out_value: Vec<Sats> = Vec::new();
let mut batch_start = min;
@@ -60,49 +60,49 @@ impl Vecs {
.for_each_range_at(batch_start, batch_end, |outpoint| {
entries.push(Entry {
original_idx: j,
txindex: outpoint.txindex(),
tx_index: outpoint.tx_index(),
vout: outpoint.vout(),
txoutindex: TxOutIndex::COINBASE,
txout_index: TxOutIndex::COINBASE,
value: Sats::MAX,
});
j += 1;
});
// Sort 1: by txindex (group by transaction for sequential first_txoutindex reads)
entries.sort_unstable_by_key(|e| e.txindex);
// Sort 1: by tx_index (group by transaction for sequential first_txout_index reads)
entries.sort_unstable_by_key(|e| e.tx_index);
for entry in &mut entries {
if entry.txindex.is_coinbase() {
if entry.tx_index.is_coinbase() {
break;
}
entry.txoutindex =
first_txoutindex_reader.get(entry.txindex.to_usize()) + entry.vout;
entry.txout_index =
first_txout_index_reader.get(entry.tx_index.to_usize()) + entry.vout;
}
// Sort 2: by txoutindex (sequential value reads)
entries.sort_unstable_by_key(|e| e.txoutindex);
// Sort 2: by txout_index (sequential value reads)
entries.sort_unstable_by_key(|e| e.txout_index);
for entry in &mut entries {
if entry.txoutindex.is_coinbase() {
if entry.txout_index.is_coinbase() {
break;
}
entry.value = value_reader.get(entry.txoutindex.to_usize());
entry.value = value_reader.get(entry.txout_index.to_usize());
}
// Scatter-write to output buffers using original_idx (avoids Sort 3)
out_txoutindex.clear();
out_txoutindex.resize(batch_len, TxOutIndex::COINBASE);
out_txout_index.clear();
out_txout_index.resize(batch_len, TxOutIndex::COINBASE);
out_value.clear();
out_value.resize(batch_len, Sats::MAX);
for entry in &entries {
out_txoutindex[entry.original_idx] = entry.txoutindex;
out_txout_index[entry.original_idx] = entry.txout_index;
out_value[entry.original_idx] = entry.value;
}
for i in 0..batch_len {
let txinindex = TxInIndex::from(batch_start + i);
self.txoutindex
.truncate_push(txinindex, out_txoutindex[i])?;
self.value.truncate_push(txinindex, out_value[i])?;
let txin_index = TxInIndex::from(batch_start + i);
self.txout_index
.truncate_push(txin_index, out_txout_index[i])?;
self.value.truncate_push(txin_index, out_value[i])?;
}
if batch_end < target {
@@ -110,7 +110,7 @@ impl Vecs {
}
let _lock = exit.lock();
self.txoutindex.write()?;
self.txout_index.write()?;
self.value.write()?;
db.flush()?;
@@ -123,8 +123,8 @@ impl Vecs {
struct Entry {
original_idx: usize,
txindex: TxIndex,
tx_index: TxIndex,
vout: Vout,
txoutindex: TxOutIndex,
txout_index: TxOutIndex,
value: Sats,
}
@@ -7,7 +7,7 @@ use super::Vecs;
impl Vecs {
pub(crate) fn forced_import(db: &Database, version: Version) -> Result<Self> {
Ok(Self {
txoutindex: PcoVec::forced_import(db, "txoutindex", version)?,
txout_index: PcoVec::forced_import(db, "txout_index", version)?,
value: PcoVec::forced_import(db, "value", version)?,
})
}
+1 -1
View File
@@ -4,6 +4,6 @@ use vecdb::{PcoVec, Rw, StorageMode};
#[derive(Traversable)]
pub struct Vecs<M: StorageMode = Rw> {
pub txoutindex: M::Stored<PcoVec<TxInIndex, TxOutIndex>>,
pub txout_index: M::Stored<PcoVec<TxInIndex, TxOutIndex>>,
pub value: M::Stored<PcoVec<TxInIndex, Sats>>,
}
@@ -62,14 +62,14 @@ where
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
txindex_source: &impl ReadableVec<TxIndex, T>,
tx_index_source: &impl ReadableVec<TxIndex, T>,
exit: &Exit,
) -> Result<()>
where
T: Copy + Ord + From<f64> + Default,
f64: From<T>,
{
self.derive_from_with_skip(indexer, indexes, starting_indexes, txindex_source, exit, 0)
self.derive_from_with_skip(indexer, indexes, starting_indexes, tx_index_source, exit, 0)
}
/// Derive from source, skipping first N transactions per block from per-block stats.
@@ -82,7 +82,7 @@ where
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
txindex_source: &impl ReadableVec<TxIndex, T>,
tx_index_source: &impl ReadableVec<TxIndex, T>,
exit: &Exit,
skip_count: usize,
) -> Result<()>
@@ -93,9 +93,9 @@ where
// Per-block distribution (supports skip for coinbase exclusion)
self.block.compute_with_skip(
starting_indexes.height,
txindex_source,
&indexer.vecs.transactions.first_txindex,
&indexes.height.txindex_count,
tx_index_source,
&indexer.vecs.transactions.first_tx_index,
&indexes.height.tx_index_count,
exit,
skip_count,
)?;
@@ -103,9 +103,9 @@ where
// 6-block rolling: true distribution from all txs in last 6 blocks
self.rolling._6b.compute_from_nblocks(
starting_indexes.height,
txindex_source,
&indexer.vecs.transactions.first_txindex,
&indexes.height.txindex_count,
tx_index_source,
&indexer.vecs.transactions.first_tx_index,
&indexes.height.tx_index_count,
6,
exit,
)?;
@@ -20,7 +20,7 @@ pub struct PerTxDistribution<T, M: StorageMode = Rw>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub txindex: M::Stored<EagerVec<PcoVec<TxIndex, T>>>,
pub tx_index: M::Stored<EagerVec<PcoVec<TxIndex, T>>>,
#[traversable(flatten)]
pub distribution: TxDerivedDistribution<T, M>,
}
@@ -30,10 +30,10 @@ where
T: NumericValue + JsonSchema,
{
pub(crate) fn forced_import(db: &Database, name: &str, version: Version) -> Result<Self> {
let txindex = EagerVec::forced_import(db, name, version)?;
let tx_index = EagerVec::forced_import(db, name, version)?;
let distribution = TxDerivedDistribution::forced_import(db, name, version)?;
Ok(Self {
txindex,
tx_index,
distribution,
})
}
@@ -55,7 +55,7 @@ where
indexer,
indexes,
starting_indexes,
&self.txindex,
&self.tx_index,
exit,
skip_count,
)
@@ -17,7 +17,7 @@ where
S1: ComputedVecValue,
S2: ComputedVecValue,
{
pub txindex: LazyVecFrom2<TxIndex, T, TxIndex, S1, TxIndex, S2>,
pub tx_index: LazyVecFrom2<TxIndex, T, TxIndex, S1, TxIndex, S2>,
#[traversable(flatten)]
pub distribution: TxDerivedDistribution<T, M>,
}
@@ -32,11 +32,11 @@ where
db: &Database,
name: &str,
version: Version,
txindex: LazyVecFrom2<TxIndex, T, TxIndex, S1, TxIndex, S2>,
tx_index: LazyVecFrom2<TxIndex, T, TxIndex, S1, TxIndex, S2>,
) -> Result<Self> {
let distribution = TxDerivedDistribution::forced_import(db, name, version)?;
Ok(Self {
txindex,
tx_index,
distribution,
})
}
@@ -54,6 +54,6 @@ where
LazyVecFrom2<TxIndex, T, TxIndex, S1, TxIndex, S2>: ReadableVec<TxIndex, T>,
{
self.distribution
.derive_from(indexer, indexes, starting_indexes, &self.txindex, exit)
.derive_from(indexer, indexes, starting_indexes, &self.tx_index, exit)
}
}
@@ -15,7 +15,7 @@ where
S2: ComputedVecValue,
DSource: ComputedVecValue,
{
pub txindex: LazyVecFrom2<TxIndex, T, TxIndex, S1, TxIndex, S2>,
pub tx_index: LazyVecFrom2<TxIndex, T, TxIndex, S1, TxIndex, S2>,
#[traversable(flatten)]
pub distribution: LazyTxDerivedDistribution<T, DSource>,
}
@@ -30,13 +30,13 @@ where
pub(crate) fn new<F: UnaryTransform<DSource, T>>(
name: &str,
version: Version,
txindex: LazyVecFrom2<TxIndex, T, TxIndex, S1, TxIndex, S2>,
tx_index: LazyVecFrom2<TxIndex, T, TxIndex, S1, TxIndex, S2>,
source_distribution: &TxDerivedDistribution<DSource>,
) -> Self {
let distribution =
LazyTxDerivedDistribution::from_tx_derived::<F>(name, version, source_distribution);
Self {
txindex,
tx_index,
distribution,
}
}
@@ -24,26 +24,26 @@ impl Vecs {
exit,
|vec| {
// Cursors avoid per-height PcoVec page decompression for the
// tx-indexed lookups. Coinbase txindex values are strictly
// tx-indexed lookups. Coinbase tx_index values are strictly
// increasing, so the cursors only advance forward.
let mut txout_cursor = indexer.vecs.transactions.first_txoutindex.cursor();
let mut count_cursor = indexes.txindex.output_count.cursor();
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_indexes.height,
&indexer.vecs.transactions.first_txindex,
|(height, txindex, ..)| {
let ti = txindex.to_usize();
&indexer.vecs.transactions.first_tx_index,
|(height, tx_index, ..)| {
let ti = tx_index.to_usize();
txout_cursor.advance(ti - txout_cursor.position());
let first_txoutindex = txout_cursor.next().unwrap().to_usize();
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_txoutindex,
first_txoutindex + output_count,
first_txout_index,
first_txout_index + output_count,
Sats::ZERO,
|acc, v| acc + v,
);
@@ -66,9 +66,9 @@ impl Vecs {
|vec| {
vec.compute_sum_from_indexes(
starting_indexes.height,
&indexer.vecs.transactions.first_txindex,
&indexes.height.txindex_count,
&transactions_fees.fee.txindex,
&indexer.vecs.transactions.first_tx_index,
&indexes.height.tx_index_count,
&transactions_fees.fee.tx_index,
exit,
)?;
Ok(())
@@ -23,9 +23,9 @@ impl Vecs {
.compute(starting_indexes.height, &window_starts, exit, |full| {
full.compute_with_skip(
starting_indexes.height,
&indexes.txindex.output_count,
&indexer.vecs.transactions.first_txindex,
&indexes.height.txindex_count,
&indexes.tx_index.output_count,
&indexer.vecs.transactions.first_tx_index,
&indexes.height.tx_index_count,
exit,
0,
)
@@ -25,29 +25,29 @@ impl Vecs {
let target_height = Height::from(target_height - 1);
// Find min_height from current vec length
let current_txoutindex = self.txinindex.len();
let min_txoutindex = current_txoutindex.min(starting_indexes.txoutindex.to_usize());
let current_txout_index = self.txin_index.len();
let min_txout_index = current_txout_index.min(starting_indexes.txout_index.to_usize());
let starting_stamp = Stamp::from(starting_indexes.height);
let _ = self.txinindex.rollback_before(starting_stamp);
let _ = self.txin_index.rollback_before(starting_stamp);
self.txinindex
.truncate_if_needed(TxOutIndex::from(min_txoutindex))?;
self.txin_index
.truncate_if_needed(TxOutIndex::from(min_txout_index))?;
let txinindex_to_txoutindex = &inputs.spent.txoutindex;
let txin_index_to_txout_index = &inputs.spent.txout_index;
// Find min_height via binary search (first_txoutindex is monotonically non-decreasing)
let first_txoutindex_vec = &indexer.vecs.outputs.first_txoutindex;
let min_height = if min_txoutindex == 0 {
// Find min_height via binary search (first_txout_index is monotonically non-decreasing)
let first_txout_index_vec = &indexer.vecs.outputs.first_txout_index;
let min_height = if min_txout_index == 0 {
Height::ZERO
} else if min_txoutindex >= starting_indexes.txoutindex.to_usize() {
} else if min_txout_index >= starting_indexes.txout_index.to_usize() {
starting_indexes.height
} else {
let mut lo = 0usize;
let mut hi = starting_indexes.height.to_usize() + 1;
while lo < hi {
let mid = lo + (hi - lo) / 2;
if first_txoutindex_vec.collect_one_at(mid).unwrap().to_usize() <= min_txoutindex {
if first_txout_index_vec.collect_one_at(mid).unwrap().to_usize() <= min_txout_index {
lo = mid + 1;
} else {
hi = mid;
@@ -58,12 +58,12 @@ impl Vecs {
// Only collect from min_height onward (not from 0)
let offset = min_height.to_usize();
let first_txoutindex_data =
first_txoutindex_vec.collect_range_at(offset, target_height.to_usize() + 1);
let first_txinindex_data = indexer
let first_txout_index_data =
first_txout_index_vec.collect_range_at(offset, target_height.to_usize() + 1);
let first_txin_index_data = indexer
.vecs
.inputs
.first_txinindex
.first_txin_index
.collect_range_at(offset, target_height.to_usize() + 2);
// Validate: computed height must not exceed starting height
@@ -80,47 +80,47 @@ impl Vecs {
while batch_start_height <= target_height {
let batch_end_height = (batch_start_height + HEIGHT_BATCH).min(target_height);
// Fill txoutindex up to batch_end_height + 1
let batch_txoutindex = if batch_end_height >= target_height {
// Fill txout_index up to batch_end_height + 1
let batch_txout_index = if batch_end_height >= target_height {
indexer.vecs.outputs.value.len()
} else {
first_txoutindex_data[batch_end_height.to_usize() + 1 - offset].to_usize()
first_txout_index_data[batch_end_height.to_usize() + 1 - offset].to_usize()
};
self.txinindex
.fill_to(batch_txoutindex, TxInIndex::UNSPENT)?;
self.txin_index
.fill_to(batch_txout_index, TxInIndex::UNSPENT)?;
// Get txin range for this height batch
let txin_start =
first_txinindex_data[batch_start_height.to_usize() - offset].to_usize();
first_txin_index_data[batch_start_height.to_usize() - offset].to_usize();
let txin_end = if batch_end_height >= target_height {
inputs.spent.txoutindex.len()
inputs.spent.txout_index.len()
} else {
first_txinindex_data[batch_end_height.to_usize() + 1 - offset].to_usize()
first_txin_index_data[batch_end_height.to_usize() + 1 - offset].to_usize()
};
// Stream txins directly into pairs — avoids intermediate Vec allocation
pairs.clear();
let mut j = txin_start;
txinindex_to_txoutindex.for_each_range_at(
txin_index_to_txout_index.for_each_range_at(
txin_start,
txin_end,
|txoutindex: TxOutIndex| {
if !txoutindex.is_coinbase() {
pairs.push((txoutindex, TxInIndex::from(j)));
|txout_index: TxOutIndex| {
if !txout_index.is_coinbase() {
pairs.push((txout_index, TxInIndex::from(j)));
}
j += 1;
},
);
pairs.sort_unstable_by_key(|(txoutindex, _)| *txoutindex);
pairs.sort_unstable_by_key(|(txout_index, _)| *txout_index);
for &(txoutindex, txinindex) in &pairs {
self.txinindex.update(txoutindex, txinindex)?;
for &(txout_index, txin_index) in &pairs {
self.txin_index.update(txout_index, txin_index)?;
}
if batch_end_height < target_height {
let _lock = exit.lock();
self.txinindex.write()?;
self.txin_index.write()?;
info!(
"TxOuts: {:.2}%",
batch_end_height.to_usize() as f64 / target_height.to_usize() as f64 * 100.0
@@ -132,7 +132,7 @@ impl Vecs {
}
let _lock = exit.lock();
self.txinindex
self.txin_index
.stamped_write_with_changes(Stamp::from(target_height))?;
db.flush()?;
@@ -7,7 +7,7 @@ use super::Vecs;
impl Vecs {
pub(crate) fn forced_import(db: &Database, version: Version) -> Result<Self> {
Ok(Self {
txinindex: BytesVec::forced_import(db, "txinindex", version)?,
txin_index: BytesVec::forced_import(db, "txin_index", version)?,
})
}
}
@@ -4,5 +4,5 @@ use vecdb::{BytesVec, Rw, StorageMode};
#[derive(Traversable)]
pub struct Vecs<M: StorageMode = Rw> {
pub txinindex: M::Stored<BytesVec<TxOutIndex, TxInIndex>>,
pub txin_index: M::Stored<BytesVec<TxOutIndex, TxInIndex>>,
}
+15 -15
View File
@@ -118,9 +118,9 @@ impl Vecs {
self.height_to_pool
.validate_computed_version_or_reset(indexer.stores.height_to_coinbase_tag.version())?;
let first_txoutindex = indexer.vecs.transactions.first_txoutindex.reader();
let outputtype = indexer.vecs.outputs.outputtype.reader();
let typeindex = indexer.vecs.outputs.typeindex.reader();
let first_txout_index = indexer.vecs.transactions.first_txout_index.reader();
let output_type = indexer.vecs.outputs.output_type.reader();
let type_index = indexer.vecs.outputs.type_index.reader();
let p2pk65 = indexer.vecs.addresses.p2pk65.bytes.reader();
let p2pk33 = indexer.vecs.addresses.p2pk33.bytes.reader();
let p2pkh = indexer.vecs.addresses.p2pkh.bytes.reader();
@@ -138,11 +138,11 @@ impl Vecs {
.min(self.height_to_pool.len());
// Cursors avoid per-height PcoVec page decompression.
// Heights are sequential, txindex values derived from them are monotonically
// Heights are sequential, tx_index values derived from them are monotonically
// increasing, so both cursors only advance forward.
let mut first_txindex_cursor = indexer.vecs.transactions.first_txindex.cursor();
first_txindex_cursor.advance(min);
let mut output_count_cursor = indexes.txindex.output_count.cursor();
let mut first_tx_index_cursor = indexer.vecs.transactions.first_tx_index.cursor();
first_tx_index_cursor.advance(min);
let mut output_count_cursor = indexes.tx_index.output_count.cursor();
indexer
.stores
@@ -150,18 +150,18 @@ impl Vecs {
.iter()
.skip(min)
.try_for_each(|(height, coinbase_tag)| -> Result<()> {
let txindex = first_txindex_cursor.next().unwrap();
let out_start = first_txoutindex.get(txindex.to_usize());
let tx_index = first_tx_index_cursor.next().unwrap();
let out_start = first_txout_index.get(tx_index.to_usize());
let ti = txindex.to_usize();
let ti = tx_index.to_usize();
output_count_cursor.advance(ti - output_count_cursor.position());
let outputcount = output_count_cursor.next().unwrap();
let output_count_val = output_count_cursor.next().unwrap();
let pool = (*out_start..(*out_start + *outputcount))
let pool = (*out_start..(*out_start + *output_count_val))
.map(TxOutIndex::from)
.find_map(|txoutindex| {
let ot = outputtype.get(txoutindex.to_usize());
let ti = usize::from(typeindex.get(txoutindex.to_usize()));
.find_map(|txout_index| {
let ot = output_type.get(txout_index.to_usize());
let ti = usize::from(type_index.get(txout_index.to_usize()));
match ot {
OutputType::P2PK65 => Some(AddressBytes::from(p2pk65.get(ti))),
OutputType::P2PK33 => Some(AddressBytes::from(p2pk33.get(ti))),
+9 -9
View File
@@ -83,20 +83,20 @@ impl Vecs {
self.check_xor_bytes(parser)?;
// Validate computed versions against dependencies
let dep_version = indexer.vecs.transactions.first_txindex.version()
let dep_version = indexer.vecs.transactions.first_tx_index.version()
+ indexer.vecs.transactions.height.version();
self.block
.validate_computed_version_or_reset(dep_version)?;
self.tx
.validate_computed_version_or_reset(dep_version)?;
let min_txindex = TxIndex::from(self.tx.len()).min(starting_indexes.txindex);
let min_tx_index = TxIndex::from(self.tx.len()).min(starting_indexes.tx_index);
let Some(min_height) = indexer
.vecs
.transactions
.height
.collect_one(min_txindex)
.collect_one(min_tx_index)
.map(|h: Height| h.min(starting_indexes.height))
else {
return Ok(());
@@ -104,13 +104,13 @@ impl Vecs {
// Cursor avoids per-height PcoVec page decompression.
// Heights are sequential, so the cursor only advances forward.
let mut first_txindex_cursor = indexer.vecs.transactions.first_txindex.cursor();
first_txindex_cursor.advance(min_height.to_usize());
let mut first_tx_index_cursor = indexer.vecs.transactions.first_tx_index.cursor();
first_tx_index_cursor.advance(min_height.to_usize());
parser
.read(
Some(min_height),
Some((indexer.vecs.transactions.first_txindex.len() - 1).into()),
Some((indexer.vecs.transactions.first_tx_index.len() - 1).into()),
)
.iter()
.try_for_each(|block| -> Result<()> {
@@ -119,13 +119,13 @@ impl Vecs {
self.block
.truncate_push(height, block.metadata().position())?;
let txindex = first_txindex_cursor.next().unwrap();
let tx_index = first_tx_index_cursor.next().unwrap();
block.tx_metadata().iter().enumerate().try_for_each(
|(index, metadata)| -> Result<()> {
let txindex = txindex + index;
let tx_index = tx_index + index;
self.tx
.truncate_push(txindex, metadata.position())?;
.truncate_push(tx_index, metadata.position())?;
Ok(())
},
)?;
+13 -13
View File
@@ -59,7 +59,7 @@ impl Vecs {
exit: &Exit,
) -> Result<()> {
let source_version =
indexer.vecs.outputs.value.version() + indexer.vecs.outputs.outputtype.version();
indexer.vecs.outputs.value.version() + indexer.vecs.outputs.output_type.version();
self.spot
.cents
.height
@@ -156,34 +156,34 @@ impl Vecs {
let total_outputs = indexer.vecs.outputs.value.len();
// Pre-collect height-indexed data for the range (plus one extra for next-block lookups)
let collect_end = (range.end + 1).min(indexer.vecs.transactions.first_txindex.len());
let first_txindexes: Vec<TxIndex> = indexer
let collect_end = (range.end + 1).min(indexer.vecs.transactions.first_tx_index.len());
let first_tx_indexes: Vec<TxIndex> = indexer
.vecs
.transactions
.first_txindex
.first_tx_index
.collect_range_at(range.start, collect_end);
let out_firsts: Vec<TxOutIndex> = indexer
.vecs
.outputs
.first_txoutindex
.first_txout_index
.collect_range_at(range.start, collect_end);
let mut ref_bins = Vec::with_capacity(range.len());
// Cursor avoids per-block PcoVec page decompression for
// the tx-indexed first_txoutindex lookup. The accessed
// txindex values (first_txindex + 1) are strictly increasing
// the tx-indexed first_txout_index lookup. The accessed
// tx_index values (first_tx_index + 1) are strictly increasing
// across blocks, so the cursor only advances forward.
let mut txout_cursor = indexer.vecs.transactions.first_txoutindex.cursor();
let mut txout_cursor = indexer.vecs.transactions.first_txout_index.cursor();
// Reusable buffers — avoid per-block allocation
let mut values: Vec<Sats> = Vec::new();
let mut output_types: Vec<OutputType> = Vec::new();
for (idx, _h) in range.enumerate() {
let first_txindex = first_txindexes[idx];
let next_first_txindex = first_txindexes
let first_tx_index = first_tx_indexes[idx];
let next_first_tx_index = first_tx_indexes
.get(idx + 1)
.copied()
.unwrap_or(TxIndex::from(total_txs));
@@ -193,8 +193,8 @@ impl Vecs {
.copied()
.unwrap_or(TxOutIndex::from(total_outputs))
.to_usize();
let out_start = if first_txindex.to_usize() + 1 < next_first_txindex.to_usize() {
let target = first_txindex.to_usize() + 1;
let out_start = if first_tx_index.to_usize() + 1 < next_first_tx_index.to_usize() {
let target = first_tx_index.to_usize() + 1;
txout_cursor.advance(target - txout_cursor.position());
txout_cursor.next().unwrap().to_usize()
} else {
@@ -207,7 +207,7 @@ impl Vecs {
.outputs
.value
.collect_range_into_at(out_start, out_end, &mut values);
indexer.vecs.outputs.outputtype.collect_range_into_at(
indexer.vecs.outputs.output_type.collect_range_into_at(
out_start,
out_end,
&mut output_types,
@@ -27,7 +27,7 @@ impl Vecs {
Ok(v.compute_count_from_indexes(
starting_indexes.height,
&indexer.vecs.scripts.p2ms.first_index,
&indexer.vecs.scripts.p2ms.to_txindex,
&indexer.vecs.scripts.p2ms.to_tx_index,
exit,
)?)
})?;
@@ -107,27 +107,27 @@ impl Vecs {
Ok(v.compute_count_from_indexes(
starting_indexes.height,
&indexer.vecs.scripts.opreturn.first_index,
&indexer.vecs.scripts.opreturn.to_txindex,
&indexer.vecs.scripts.opreturn.to_tx_index,
exit,
)?)
})?;
self.unknownoutput
self.unknown_output
.compute(starting_indexes.height, exit, |v| {
Ok(v.compute_count_from_indexes(
starting_indexes.height,
&indexer.vecs.scripts.unknown.first_index,
&indexer.vecs.scripts.unknown.to_txindex,
&indexer.vecs.scripts.unknown.to_tx_index,
exit,
)?)
})?;
self.emptyoutput
self.empty_output
.compute(starting_indexes.height, exit, |v| {
Ok(v.compute_count_from_indexes(
starting_indexes.height,
&indexer.vecs.scripts.empty.first_index,
&indexer.vecs.scripts.empty.to_txindex,
&indexer.vecs.scripts.empty.to_tx_index,
exit,
)?)
})?;
@@ -53,16 +53,16 @@ impl Vecs {
indexes,
cached_starts,
)?,
emptyoutput: PerBlockCumulativeWithSums::forced_import(
empty_output: PerBlockCumulativeWithSums::forced_import(
db,
"emptyoutput_count",
"empty_output_count",
version,
indexes,
cached_starts,
)?,
unknownoutput: PerBlockCumulativeWithSums::forced_import(
unknown_output: PerBlockCumulativeWithSums::forced_import(
db,
"unknownoutput_count",
"unknown_output_count",
version,
indexes,
cached_starts,
@@ -16,8 +16,8 @@ pub struct Vecs<M: StorageMode = Rw> {
pub p2wpkh: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
pub p2wsh: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
pub opreturn: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
pub emptyoutput: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
pub unknownoutput: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
pub empty_output: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
pub unknown_output: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
pub segwit: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
}
@@ -20,13 +20,13 @@ impl Vecs {
exit,
|height_vec| {
// Validate computed versions against dependencies
let dep_version = indexer.vecs.outputs.first_txoutindex.version()
+ indexer.vecs.outputs.outputtype.version()
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)?;
// Get target height
let target_len = indexer.vecs.outputs.first_txoutindex.len();
let target_len = indexer.vecs.outputs.first_txout_index.len();
if target_len == 0 {
return Ok(());
}
@@ -42,14 +42,14 @@ impl Vecs {
}
// Pre-collect height-indexed data
let first_txoutindexes: Vec<TxOutIndex> =
indexer.vecs.outputs.first_txoutindex.collect_range_at(
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_txoutindex.len()),
+ 2.min(indexer.vecs.outputs.first_txout_index.len()),
);
let mut outputtypes_buf: Vec<OutputType> = Vec::new();
let mut output_types_buf: Vec<OutputType> = Vec::new();
let mut values_buf: Vec<Sats> = Vec::new();
// Iterate blocks
@@ -58,23 +58,23 @@ impl Vecs {
let local_idx = h - starting_height.to_usize();
// Get output range for this block
let first_txoutindex = first_txoutindexes[local_idx];
let next_first_txoutindex =
if let Some(&next) = first_txoutindexes.get(local_idx + 1) {
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_txoutindex.to_usize();
let out_end = next_first_txoutindex.to_usize();
let out_start = first_txout_index.to_usize();
let out_end = next_first_txout_index.to_usize();
// Pre-collect both vecs into reusable buffers
indexer
.vecs
.outputs
.outputtype
.collect_range_into_at(out_start, out_end, &mut outputtypes_buf);
.output_type
.collect_range_into_at(out_start, out_end, &mut output_types_buf);
indexer
.vecs
.outputs
@@ -82,7 +82,7 @@ impl Vecs {
.collect_range_into_at(out_start, out_end, &mut values_buf);
let mut opreturn_value = Sats::ZERO;
for (ot, val) in outputtypes_buf.iter().zip(values_buf.iter()) {
for (ot, val) in output_types_buf.iter().zip(values_buf.iter()) {
if *ot == OutputType::OpReturn {
opreturn_value += *val;
}
@@ -19,7 +19,7 @@ impl Vecs {
.compute(starting_indexes.height, &window_starts, exit, |height| {
Ok(height.compute_count_from_indexes(
starting_indexes.height,
&indexer.vecs.transactions.first_txindex,
&indexer.vecs.transactions.first_tx_index,
&indexer.vecs.transactions.txid,
exit,
)?)
@@ -14,16 +14,16 @@ impl Vecs {
indexes: &indexes::Vecs,
cached_starts: &CachedWindowStarts,
) -> Result<Self> {
let txindex_to_is_coinbase = LazyVecFrom2::init(
let tx_index_to_is_coinbase = LazyVecFrom2::init(
"is_coinbase",
version,
indexer.vecs.transactions.height.read_only_boxed_clone(),
indexer
.vecs
.transactions
.first_txindex
.first_tx_index
.read_only_boxed_clone(),
|index: TxIndex, _height, first_txindex| StoredBool::from(index == first_txindex),
|index: TxIndex, _height, first_tx_index| StoredBool::from(index == first_tx_index),
);
Ok(Self {
@@ -34,7 +34,7 @@ impl Vecs {
indexes,
cached_starts,
)?,
is_coinbase: txindex_to_is_coinbase,
is_coinbase: tx_index_to_is_coinbase,
})
}
}
@@ -19,23 +19,23 @@ impl Vecs {
exit: &Exit,
) -> Result<()> {
self.input_value.compute_sum_from_indexes(
starting_indexes.txindex,
&indexer.vecs.transactions.first_txinindex,
&indexes.txindex.input_count,
starting_indexes.tx_index,
&indexer.vecs.transactions.first_txin_index,
&indexes.tx_index.input_count,
&txins.spent.value,
exit,
)?;
self.output_value.compute_sum_from_indexes(
starting_indexes.txindex,
&indexer.vecs.transactions.first_txoutindex,
&indexes.txindex.output_count,
starting_indexes.tx_index,
&indexer.vecs.transactions.first_txout_index,
&indexes.tx_index.output_count,
&indexer.vecs.outputs.value,
exit,
)?;
self.fee.txindex.compute_transform2(
starting_indexes.txindex,
self.fee.tx_index.compute_transform2(
starting_indexes.tx_index,
&self.input_value,
&self.output_value,
|(i, input, output, ..)| {
@@ -49,11 +49,11 @@ impl Vecs {
exit,
)?;
self.fee_rate.txindex.compute_transform2(
starting_indexes.txindex,
&self.fee.txindex,
&size_vecs.vsize.txindex,
|(txindex, fee, vsize, ..)| (txindex, FeeRate::from((fee, vsize))),
self.fee_rate.tx_index.compute_transform2(
starting_indexes.tx_index,
&self.fee.tx_index,
&size_vecs.vsize.tx_index,
|(tx_index, fee, vsize, ..)| (tx_index, FeeRate::from((fee, vsize))),
exit,
)?;
@@ -12,7 +12,7 @@ impl Vecs {
version: Version,
indexer: &Indexer,
) -> Result<Self> {
let txindex_to_vsize = LazyVecFrom2::init(
let tx_index_to_vsize = LazyVecFrom2::init(
"tx_vsize",
version,
indexer.vecs.transactions.base_size.read_only_boxed_clone(),
@@ -23,9 +23,9 @@ impl Vecs {
);
let vsize =
LazyPerTxDistribution::forced_import(db, "tx_vsize", version, txindex_to_vsize)?;
LazyPerTxDistribution::forced_import(db, "tx_vsize", version, tx_index_to_vsize)?;
let txindex_to_weight = LazyVecFrom2::init(
let tx_index_to_weight = LazyVecFrom2::init(
"tx_weight",
version,
indexer.vecs.transactions.base_size.read_only_boxed_clone(),
@@ -36,7 +36,7 @@ impl Vecs {
let weight = LazyPerTxDistributionTransformed::new::<VSizeToWeight>(
"tx_weight",
version,
txindex_to_weight,
tx_index_to_weight,
&vsize.distribution,
);
@@ -14,20 +14,20 @@ impl Vecs {
exit: &Exit,
) -> Result<()> {
let tx_vany = |tx_vany: &mut PerBlockCumulativeWithSums<StoredU64, StoredU64>,
txversion: TxVersion| {
let txversion_vec = &indexer.vecs.transactions.txversion;
tx_version: TxVersion| {
let tx_version_vec = &indexer.vecs.transactions.tx_version;
// Cursor avoids per-transaction PcoVec page decompression.
// Txindex values are sequential, so the cursor only advances forward.
let mut cursor = txversion_vec.cursor();
let mut cursor = tx_version_vec.cursor();
tx_vany.compute(starting_indexes.height, exit, |vec| {
vec.compute_filtered_count_from_indexes(
starting_indexes.height,
&indexer.vecs.transactions.first_txindex,
&indexer.vecs.transactions.first_tx_index,
&indexer.vecs.transactions.txid,
|txindex| {
let ti = txindex.to_usize();
|tx_index| {
let ti = tx_index.to_usize();
cursor.advance(ti - cursor.position());
cursor.next().unwrap() == txversion
cursor.next().unwrap() == tx_version
},
exit,
)?;
@@ -29,8 +29,8 @@ impl Vecs {
|sats_vec| {
Ok(sats_vec.compute_filtered_sum_from_indexes(
starting_indexes.height,
&indexer.vecs.transactions.first_txindex,
&indexes.height.txindex_count,
&indexer.vecs.transactions.first_tx_index,
&indexes.height.tx_index_count,
&fees_vecs.input_value,
|sats| !sats.is_max(),
exit,
@@ -45,8 +45,8 @@ impl Vecs {
|sats_vec| {
Ok(sats_vec.compute_sum_from_indexes(
starting_indexes.height,
&indexer.vecs.transactions.first_txindex,
&indexes.height.txindex_count,
&indexer.vecs.transactions.first_tx_index,
&indexes.height.tx_index_count,
&fees_vecs.output_value,
exit,
)?)
+3 -3
View File
@@ -9,7 +9,7 @@ pub const SNAPSHOT_BLOCK_RANGE: usize = 1_000;
/// Known duplicate Bitcoin transactions (BIP30)
/// https://github.com/bitcoin/bips/blob/master/bip-0030.mediawiki
/// Each entry is (txid_str, txindex) - these are coinbase txs that were duplicated.
/// Each entry is (txid_str, tx_index) - these are coinbase txs that were duplicated.
pub const DUPLICATE_TXID_STRS: [(&str, u32); 2] = [
(
"d5d27987d2a3dfc724e359870c6644b40e497bdc0589a033220fe15429d88599",
@@ -34,10 +34,10 @@ pub static DUPLICATE_TXIDS: std::sync::LazyLock<[Txid; 2]> = std::sync::LazyLock
pub static DUPLICATE_TXID_PREFIXES: std::sync::LazyLock<[(TxidPrefix, TxIndex); 2]> =
std::sync::LazyLock::new(|| {
DUPLICATE_TXID_STRS.map(|(s, txindex)| {
DUPLICATE_TXID_STRS.map(|(s, tx_index)| {
(
TxidPrefix::from(&Txid::from(bitcoin::Txid::from_str(s).unwrap())),
TxIndex::new(txindex),
TxIndex::new(tx_index),
)
})
});
+55 -55
View File
@@ -21,50 +21,50 @@ impl IndexesExt for Indexes {
fn checked_push(&self, vecs: &mut Vecs) -> Result<()> {
let height = self.height;
vecs.transactions
.first_txindex
.checked_push(height, self.txindex)?;
.first_tx_index
.checked_push(height, self.tx_index)?;
vecs.inputs
.first_txinindex
.checked_push(height, self.txinindex)?;
.first_txin_index
.checked_push(height, self.txin_index)?;
vecs.outputs
.first_txoutindex
.checked_push(height, self.txoutindex)?;
.first_txout_index
.checked_push(height, self.txout_index)?;
vecs.scripts
.empty.first_index
.checked_push(height, self.emptyoutputindex)?;
.checked_push(height, self.empty_output_index)?;
vecs.scripts
.p2ms.first_index
.checked_push(height, self.p2msoutputindex)?;
.checked_push(height, self.p2ms_output_index)?;
vecs.scripts
.opreturn.first_index
.checked_push(height, self.opreturnindex)?;
.checked_push(height, self.op_return_index)?;
vecs.addresses
.p2a.first_index
.checked_push(height, self.p2aaddressindex)?;
.checked_push(height, self.p2a_address_index)?;
vecs.scripts
.unknown.first_index
.checked_push(height, self.unknownoutputindex)?;
.checked_push(height, self.unknown_output_index)?;
vecs.addresses
.p2pk33.first_index
.checked_push(height, self.p2pk33addressindex)?;
.checked_push(height, self.p2pk33_address_index)?;
vecs.addresses
.p2pk65.first_index
.checked_push(height, self.p2pk65addressindex)?;
.checked_push(height, self.p2pk65_address_index)?;
vecs.addresses
.p2pkh.first_index
.checked_push(height, self.p2pkhaddressindex)?;
.checked_push(height, self.p2pkh_address_index)?;
vecs.addresses
.p2sh.first_index
.checked_push(height, self.p2shaddressindex)?;
.checked_push(height, self.p2sh_address_index)?;
vecs.addresses
.p2tr.first_index
.checked_push(height, self.p2traddressindex)?;
.checked_push(height, self.p2tr_address_index)?;
vecs.addresses
.p2wpkh.first_index
.checked_push(height, self.p2wpkhaddressindex)?;
.checked_push(height, self.p2wpkh_address_index)?;
vecs.addresses
.p2wsh.first_index
.checked_push(height, self.p2wshaddressindex)?;
.checked_push(height, self.p2wsh_address_index)?;
Ok(())
}
@@ -97,113 +97,113 @@ impl IndexesExt for Indexes {
local_height
};
let emptyoutputindex = starting_index(
let empty_output_index = starting_index(
&vecs.scripts.empty.first_index,
&vecs.scripts.empty.to_txindex,
&vecs.scripts.empty.to_tx_index,
starting_height,
)?;
let p2msoutputindex = starting_index(
let p2ms_output_index = starting_index(
&vecs.scripts.p2ms.first_index,
&vecs.scripts.p2ms.to_txindex,
&vecs.scripts.p2ms.to_tx_index,
starting_height,
)?;
let opreturnindex = starting_index(
let op_return_index = starting_index(
&vecs.scripts.opreturn.first_index,
&vecs.scripts.opreturn.to_txindex,
&vecs.scripts.opreturn.to_tx_index,
starting_height,
)?;
let p2pk33addressindex = starting_index(
let p2pk33_address_index = starting_index(
&vecs.addresses.p2pk33.first_index,
&vecs.addresses.p2pk33.bytes,
starting_height,
)?;
let p2pk65addressindex = starting_index(
let p2pk65_address_index = starting_index(
&vecs.addresses.p2pk65.first_index,
&vecs.addresses.p2pk65.bytes,
starting_height,
)?;
let p2pkhaddressindex = starting_index(
let p2pkh_address_index = starting_index(
&vecs.addresses.p2pkh.first_index,
&vecs.addresses.p2pkh.bytes,
starting_height,
)?;
let p2shaddressindex = starting_index(
let p2sh_address_index = starting_index(
&vecs.addresses.p2sh.first_index,
&vecs.addresses.p2sh.bytes,
starting_height,
)?;
let p2traddressindex = starting_index(
let p2tr_address_index = starting_index(
&vecs.addresses.p2tr.first_index,
&vecs.addresses.p2tr.bytes,
starting_height,
)?;
let p2wpkhaddressindex = starting_index(
let p2wpkh_address_index = starting_index(
&vecs.addresses.p2wpkh.first_index,
&vecs.addresses.p2wpkh.bytes,
starting_height,
)?;
let p2wshaddressindex = starting_index(
let p2wsh_address_index = starting_index(
&vecs.addresses.p2wsh.first_index,
&vecs.addresses.p2wsh.bytes,
starting_height,
)?;
let p2aaddressindex = starting_index(
let p2a_address_index = starting_index(
&vecs.addresses.p2a.first_index,
&vecs.addresses.p2a.bytes,
starting_height,
)?;
let txindex = starting_index(
&vecs.transactions.first_txindex,
let tx_index = starting_index(
&vecs.transactions.first_tx_index,
&vecs.transactions.txid,
starting_height,
)?;
let txinindex = starting_index(
&vecs.inputs.first_txinindex,
let txin_index = starting_index(
&vecs.inputs.first_txin_index,
&vecs.inputs.outpoint,
starting_height,
)?;
let txoutindex = starting_index(
&vecs.outputs.first_txoutindex,
let txout_index = starting_index(
&vecs.outputs.first_txout_index,
&vecs.outputs.value,
starting_height,
)?;
let unknownoutputindex = starting_index(
let unknown_output_index = starting_index(
&vecs.scripts.unknown.first_index,
&vecs.scripts.unknown.to_txindex,
&vecs.scripts.unknown.to_tx_index,
starting_height,
)?;
Some(Indexes {
emptyoutputindex,
empty_output_index,
height: starting_height,
p2msoutputindex,
opreturnindex,
p2pk33addressindex,
p2pk65addressindex,
p2pkhaddressindex,
p2shaddressindex,
p2traddressindex,
p2wpkhaddressindex,
p2wshaddressindex,
p2aaddressindex,
txindex,
txinindex,
txoutindex,
unknownoutputindex,
p2ms_output_index,
op_return_index,
p2pk33_address_index,
p2pk65_address_index,
p2pkh_address_index,
p2sh_address_index,
p2tr_address_index,
p2wpkh_address_index,
p2wsh_address_index,
p2a_address_index,
tx_index,
txin_index,
txout_index,
unknown_output_index,
})
}
}
+2 -2
View File
@@ -14,7 +14,7 @@ impl BlockProcessor<'_> {
if self
.stores
.blockhashprefix_to_height
.blockhash_prefix_to_height
.get(&blockhash_prefix)?
.is_some_and(|prev_height| *prev_height != height)
{
@@ -25,7 +25,7 @@ impl BlockProcessor<'_> {
self.indexes.checked_push(self.vecs)?;
self.stores
.blockhashprefix_to_height
.blockhash_prefix_to_height
.insert(blockhash_prefix, height);
self.stores
+14 -14
View File
@@ -27,9 +27,9 @@ pub struct BlockProcessor<'a> {
impl BlockProcessor<'_> {
/// Update global indexes after processing a block.
pub fn update_indexes(&mut self, tx_count: usize, input_count: usize, output_count: usize) {
self.indexes.txindex += TxIndex::from(tx_count);
self.indexes.txinindex += TxInIndex::from(input_count);
self.indexes.txoutindex += TxOutIndex::from(output_count);
self.indexes.tx_index += TxIndex::from(tx_count);
self.indexes.txin_index += TxInIndex::from(input_count);
self.indexes.txout_index += TxOutIndex::from(output_count);
}
/// Finalizes outputs/inputs in parallel with storing tx metadata.
@@ -46,8 +46,8 @@ impl BlockProcessor<'_> {
let height = self.height;
let indexes = &mut *self.indexes;
// Split transactions vecs: finalize needs first_txoutindex/first_txinindex, metadata needs the rest
let (first_txoutindex, first_txinindex, mut tx_metadata) =
// Split transactions vecs: finalize needs first_txout_index/first_txin_index, metadata needs the rest
let (first_txout_index, first_txin_index, mut tx_metadata) =
self.vecs.transactions.split_for_finalize();
let outputs = &mut self.vecs.outputs;
@@ -55,21 +55,21 @@ impl BlockProcessor<'_> {
let addresses = &mut self.vecs.addresses;
let scripts = &mut self.vecs.scripts;
let addr_hash_stores = &mut self.stores.addresstype_to_addresshash_to_addressindex;
let addr_txindex_stores = &mut self.stores.addresstype_to_addressindex_and_txindex;
let addr_outpoint_stores = &mut self.stores.addresstype_to_addressindex_and_unspentoutpoint;
let txidprefix_store = &mut self.stores.txidprefix_to_txindex;
let addr_hash_stores = &mut self.stores.address_type_to_address_hash_to_address_index;
let addr_tx_index_stores = &mut self.stores.address_type_to_address_index_and_tx_index;
let addr_outpoint_stores = &mut self.stores.address_type_to_address_index_and_unspent_outpoint;
let txid_prefix_store = &mut self.stores.txid_prefix_to_tx_index;
let (finalize_result, metadata_result) = rayon::join(
|| -> Result<()> {
txout::finalize_outputs(
indexes,
first_txoutindex,
first_txout_index,
outputs,
addresses,
scripts,
addr_hash_stores,
addr_txindex_stores,
addr_tx_index_stores,
addr_outpoint_stores,
txouts,
same_block_spent_outpoints,
@@ -77,15 +77,15 @@ impl BlockProcessor<'_> {
same_block_info,
)?;
txin::finalize_inputs(
first_txinindex,
first_txin_index,
inputs,
addr_txindex_stores,
addr_tx_index_stores,
addr_outpoint_stores,
txins,
same_block_info,
)
},
|| tx::store_tx_metadata(height, txs, txidprefix_store, &mut tx_metadata),
|| tx::store_tx_metadata(height, txs, txid_prefix_store, &mut tx_metadata),
);
finalize_result?;
+23 -23
View File
@@ -13,7 +13,7 @@ use super::{BlockProcessor, ComputedTx};
impl<'a> BlockProcessor<'a> {
pub fn compute_txids(&self) -> Result<Vec<ComputedTx<'a>>> {
let will_check_collisions = self.check_collisions;
let base_txindex = self.indexes.txindex;
let base_tx_index = self.indexes.tx_index;
self.block
.txdata
@@ -24,9 +24,9 @@ impl<'a> BlockProcessor<'a> {
let txid = Txid::from(btc_txid);
let txid_prefix = TxidPrefix::from(&txid);
let prev_txindex_opt = if will_check_collisions {
let prev_tx_index_opt = if will_check_collisions {
self.stores
.txidprefix_to_txindex
.txid_prefix_to_tx_index
.get(&txid_prefix)?
.map(|v| *v)
} else {
@@ -34,11 +34,11 @@ impl<'a> BlockProcessor<'a> {
};
Ok(ComputedTx {
txindex: base_txindex + TxIndex::from(index),
tx_index: base_tx_index + TxIndex::from(index),
tx,
txid,
txid_prefix,
prev_txindex_opt,
prev_tx_index_opt,
base_size,
total_size,
})
@@ -53,11 +53,11 @@ impl<'a> BlockProcessor<'a> {
}
for ct in txs.iter() {
let Some(prev_txindex) = ct.prev_txindex_opt else {
let Some(prev_tx_index) = ct.prev_tx_index_opt else {
continue;
};
if ct.txindex == prev_txindex {
if ct.tx_index == prev_tx_index {
continue;
}
@@ -66,18 +66,18 @@ impl<'a> BlockProcessor<'a> {
.vecs
.transactions
.txid
.get_pushed_or_read(prev_txindex, &self.readers.txid)
.ok_or(Error::Internal("Missing txid for txindex"))
.get_pushed_or_read(prev_tx_index, &self.readers.txid)
.ok_or(Error::Internal("Missing txid for tx_index"))
.inspect_err(|_| {
error!(txindex = ?ct.txindex, len, "Missing txid for txindex");
error!(tx_index = ?ct.tx_index, len, "Missing txid for tx_index");
})?;
let is_dup = DUPLICATE_TXIDS.contains(&prev_txid);
if !is_dup {
error!(
height = ?self.height, txindex = ?ct.txindex,
?prev_txid, ?prev_txindex,
height = ?self.height, tx_index = ?ct.tx_index,
?prev_txid, ?prev_tx_index,
"Unexpected TXID collision"
);
return Err(Error::Internal("Unexpected TXID collision"));
@@ -95,20 +95,20 @@ pub(super) fn store_tx_metadata(
md: &mut TxMetadataVecs<'_>,
) -> Result<()> {
for ct in txs {
if ct.prev_txindex_opt.is_none() {
store.insert(ct.txid_prefix, ct.txindex);
if ct.prev_tx_index_opt.is_none() {
store.insert(ct.txid_prefix, ct.tx_index);
}
md.height.checked_push(ct.txindex, height)?;
md.txversion
.checked_push(ct.txindex, ct.tx.version.into())?;
md.txid.checked_push(ct.txindex, ct.txid)?;
md.rawlocktime
.checked_push(ct.txindex, ct.tx.lock_time.into())?;
md.base_size.checked_push(ct.txindex, ct.base_size.into())?;
md.height.checked_push(ct.tx_index, height)?;
md.tx_version
.checked_push(ct.tx_index, ct.tx.version.into())?;
md.txid.checked_push(ct.tx_index, ct.txid)?;
md.raw_locktime
.checked_push(ct.tx_index, ct.tx.lock_time.into())?;
md.base_size.checked_push(ct.tx_index, ct.base_size.into())?;
md.total_size
.checked_push(ct.txindex, ct.total_size.into())?;
.checked_push(ct.tx_index, ct.total_size.into())?;
md.is_explicitly_rbf
.checked_push(ct.txindex, StoredBool::from(ct.tx.is_explicitly_rbf()))?;
.checked_push(ct.tx_index, StoredBool::from(ct.tx.is_explicitly_rbf()))?;
}
Ok(())
}
+61 -61
View File
@@ -17,13 +17,13 @@ impl<'a> BlockProcessor<'a> {
pub fn process_inputs(
&self,
txs: &[ComputedTx],
txid_prefix_to_txindex: &mut FxHashMap<TxidPrefix, TxIndex>,
txid_prefix_to_tx_index: &mut FxHashMap<TxidPrefix, TxIndex>,
) -> Result<Vec<(TxInIndex, InputSource)>> {
txid_prefix_to_txindex.clear();
txid_prefix_to_txindex.extend(txs.iter().map(|ct| (ct.txid_prefix, ct.txindex)));
txid_prefix_to_tx_index.clear();
txid_prefix_to_tx_index.extend(txs.iter().map(|ct| (ct.txid_prefix, ct.tx_index)));
let base_txindex = self.indexes.txindex;
let base_txinindex = self.indexes.txinindex;
let base_tx_index = self.indexes.tx_index;
let base_txin_index = self.indexes.txin_index;
let total_inputs: usize = self.block.txdata.iter().map(|tx| tx.input.len()).sum();
let mut items = Vec::with_capacity(total_inputs);
@@ -33,21 +33,21 @@ impl<'a> BlockProcessor<'a> {
}
}
let txid_prefix_to_txindex = &*txid_prefix_to_txindex;
let txid_prefix_to_tx_index = &*txid_prefix_to_tx_index;
let txins = items
.into_par_iter()
.enumerate()
.map(
|(block_txinindex, (block_txindex, vin, txin, tx))| -> Result<(TxInIndex, InputSource)> {
let txindex = base_txindex + block_txindex;
let txinindex = base_txinindex + TxInIndex::from(block_txinindex);
|(block_txin_index, (block_tx_index, vin, txin, tx))| -> Result<(TxInIndex, InputSource)> {
let tx_index = base_tx_index + block_tx_index;
let txin_index = base_txin_index + TxInIndex::from(block_txin_index);
if tx.is_coinbase() {
return Ok((
txinindex,
txin_index,
InputSource::SameBlock {
txindex,
tx_index,
vin,
outpoint: OutPoint::COINBASE,
},
@@ -59,13 +59,13 @@ impl<'a> BlockProcessor<'a> {
let txid_prefix = TxidPrefix::from(&txid);
let vout = Vout::from(outpoint.vout);
if let Some(&same_block_txindex) = txid_prefix_to_txindex
if let Some(&same_block_tx_index) = txid_prefix_to_tx_index
.get(&txid_prefix) {
let outpoint = OutPoint::new(same_block_txindex, vout);
let outpoint = OutPoint::new(same_block_tx_index, vout);
return Ok((
txinindex,
txin_index,
InputSource::SameBlock {
txindex,
tx_index,
vin,
outpoint,
},
@@ -74,53 +74,53 @@ impl<'a> BlockProcessor<'a> {
let store_result = self
.stores
.txidprefix_to_txindex
.txid_prefix_to_tx_index
.get(&txid_prefix)?
.map(|v| *v);
let prev_txindex = match store_result {
Some(txindex) if txindex < self.indexes.txindex => txindex,
let prev_tx_index = match store_result {
Some(tx_index) if tx_index < self.indexes.tx_index => tx_index,
_ => {
error!(
"UnknownTxid: txid={}, prefix={:?}, store_result={:?}, current_txindex={:?}",
txid, txid_prefix, store_result, self.indexes.txindex
"UnknownTxid: txid={}, prefix={:?}, store_result={:?}, current_tx_index={:?}",
txid, txid_prefix, store_result, self.indexes.tx_index
);
return Err(Error::UnknownTxid);
}
};
let txoutindex = self
let txout_index = self
.vecs
.transactions
.first_txoutindex
.get_pushed_or_read(prev_txindex, &self.readers.txindex_to_first_txoutindex)
.ok_or(Error::Internal("Missing txoutindex"))?
.first_txout_index
.get_pushed_or_read(prev_tx_index, &self.readers.tx_index_to_first_txout_index)
.ok_or(Error::Internal("Missing txout_index"))?
+ vout;
let outpoint = OutPoint::new(prev_txindex, vout);
let outpoint = OutPoint::new(prev_tx_index, vout);
let outputtype = self
let output_type = self
.vecs
.outputs
.outputtype
.get_pushed_or_read(txoutindex, &self.readers.txoutindex_to_outputtype)
.ok_or(Error::Internal("Missing outputtype"))?;
.output_type
.get_pushed_or_read(txout_index, &self.readers.txout_index_to_output_type)
.ok_or(Error::Internal("Missing output_type"))?;
let typeindex = self
let type_index = self
.vecs
.outputs
.typeindex
.get_pushed_or_read(txoutindex, &self.readers.txoutindex_to_typeindex)
.ok_or(Error::Internal("Missing typeindex"))?;
.type_index
.get_pushed_or_read(txout_index, &self.readers.txout_index_to_type_index)
.ok_or(Error::Internal("Missing type_index"))?;
Ok((
txinindex,
txin_index,
InputSource::PreviousBlock {
vin,
txindex,
tx_index,
outpoint,
outputtype,
typeindex,
output_type,
type_index,
},
))
},
@@ -149,31 +149,31 @@ impl<'a> BlockProcessor<'a> {
}
pub(super) fn finalize_inputs(
first_txinindex: &mut PcoVec<TxIndex, TxInIndex>,
first_txin_index: &mut PcoVec<TxIndex, TxInIndex>,
inputs: &mut InputsVecs,
addr_txindex_stores: &mut ByAddressType<Store<AddressIndexTxIndex, Unit>>,
addr_tx_index_stores: &mut ByAddressType<Store<AddressIndexTxIndex, Unit>>,
addr_outpoint_stores: &mut ByAddressType<Store<AddressIndexOutPoint, Unit>>,
txins: Vec<(TxInIndex, InputSource)>,
same_block_output_info: &mut FxHashMap<OutPoint, SameBlockOutputInfo>,
) -> Result<()> {
for (txinindex, input_source) in txins {
let (vin, txindex, outpoint, outputtype, typeindex) = match input_source {
for (txin_index, input_source) in txins {
let (vin, tx_index, outpoint, output_type, type_index) = match input_source {
InputSource::PreviousBlock {
vin,
txindex,
tx_index,
outpoint,
outputtype,
typeindex,
} => (vin, txindex, outpoint, outputtype, typeindex),
output_type,
type_index,
} => (vin, tx_index, outpoint, output_type, type_index),
InputSource::SameBlock {
txindex,
tx_index,
vin,
outpoint,
} => {
if outpoint.is_coinbase() {
(
vin,
txindex,
tx_index,
outpoint,
OutputType::Unknown,
TypeIndex::COINBASE,
@@ -189,33 +189,33 @@ pub(super) fn finalize_inputs(
"Same-block output not found"
);
})?;
(vin, txindex, outpoint, info.outputtype, info.typeindex)
(vin, tx_index, outpoint, info.output_type, info.type_index)
}
}
};
if vin.is_zero() {
first_txinindex.checked_push(txindex, txinindex)?;
first_txin_index.checked_push(tx_index, txin_index)?;
}
inputs.txindex.checked_push(txinindex, txindex)?;
inputs.outpoint.checked_push(txinindex, outpoint)?;
inputs.outputtype.checked_push(txinindex, outputtype)?;
inputs.typeindex.checked_push(txinindex, typeindex)?;
inputs.tx_index.checked_push(txin_index, tx_index)?;
inputs.outpoint.checked_push(txin_index, outpoint)?;
inputs.output_type.checked_push(txin_index, output_type)?;
inputs.type_index.checked_push(txin_index, type_index)?;
if !outputtype.is_address() {
if !output_type.is_address() {
continue;
}
let addresstype = outputtype;
let addressindex = typeindex;
let address_type = output_type;
let address_index = type_index;
addr_txindex_stores
.get_mut_unwrap(addresstype)
.insert(AddressIndexTxIndex::from((addressindex, txindex)), Unit);
addr_tx_index_stores
.get_mut_unwrap(address_type)
.insert(AddressIndexTxIndex::from((address_index, tx_index)), Unit);
addr_outpoint_stores
.get_mut_unwrap(addresstype)
.remove(AddressIndexOutPoint::from((addressindex, outpoint)));
.get_mut_unwrap(address_type)
.remove(AddressIndexOutPoint::from((address_index, outpoint)));
}
Ok(())
+77 -77
View File
@@ -18,8 +18,8 @@ impl<'a> BlockProcessor<'a> {
let height = self.height;
let check_collisions = self.check_collisions;
let base_txindex = self.indexes.txindex;
let base_txoutindex = self.indexes.txoutindex;
let base_tx_index = self.indexes.tx_index;
let base_txout_index = self.indexes.txout_index;
let total_outputs: usize = self.block.txdata.iter().map(|tx| tx.output.len()).sum();
let mut items = Vec::with_capacity(total_outputs);
@@ -33,56 +33,56 @@ impl<'a> BlockProcessor<'a> {
.into_par_iter()
.enumerate()
.map(
|(block_txoutindex, (block_txindex, vout, txout))| -> Result<ProcessedOutput> {
let txindex = base_txindex + block_txindex;
let txoutindex = base_txoutindex + TxOutIndex::from(block_txoutindex);
|(block_txout_index, (block_tx_index, vout, txout))| -> Result<ProcessedOutput> {
let tx_index = base_tx_index + block_tx_index;
let txout_index = base_txout_index + TxOutIndex::from(block_txout_index);
let script = &txout.script_pubkey;
let outputtype = OutputType::from(script);
let output_type = OutputType::from(script);
if outputtype.is_not_address() {
if output_type.is_not_address() {
return Ok(ProcessedOutput {
txoutindex,
txout_index,
txout,
txindex,
tx_index,
vout,
outputtype,
output_type,
address_info: None,
existing_typeindex: None,
existing_type_index: None,
});
}
let addresstype = outputtype;
let address_bytes = AddressBytes::try_from((script, addresstype)).unwrap();
let address_type = output_type;
let address_bytes = AddressBytes::try_from((script, address_type)).unwrap();
let address_hash = AddressHash::from(&address_bytes);
let existing_typeindex = self
let existing_type_index = self
.stores
.addresstype_to_addresshash_to_addressindex
.get_unwrap(addresstype)
.address_type_to_address_hash_to_address_index
.get_unwrap(address_type)
.get(&address_hash)?
.map(|v| *v)
.and_then(|typeindex_local| {
(typeindex_local < self.indexes.to_typeindex(addresstype))
.then_some(typeindex_local)
.and_then(|type_index_local| {
(type_index_local < self.indexes.to_type_index(address_type))
.then_some(type_index_local)
});
if check_collisions && let Some(typeindex) = existing_typeindex {
if check_collisions && let Some(type_index) = existing_type_index {
let prev_addressbytes = self
.vecs
.addresses
.get_bytes_by_type(addresstype, typeindex, &self.readers.addressbytes)
.get_bytes_by_type(address_type, type_index, &self.readers.addressbytes)
.ok_or(Error::Internal("Missing addressbytes"))?;
if prev_addressbytes != address_bytes {
error!(
?height,
?vout,
?block_txindex,
?addresstype,
?block_tx_index,
?address_type,
?prev_addressbytes,
?address_bytes,
?typeindex,
?type_index,
"Address hash collision"
);
return Err(Error::Internal("Address hash collision"));
@@ -90,13 +90,13 @@ impl<'a> BlockProcessor<'a> {
}
Ok(ProcessedOutput {
txoutindex,
txout_index,
txout,
txindex,
tx_index,
vout,
outputtype,
output_type,
address_info: Some((address_bytes, address_hash)),
existing_typeindex,
existing_type_index,
})
},
)
@@ -107,125 +107,125 @@ impl<'a> BlockProcessor<'a> {
#[allow(clippy::too_many_arguments)]
pub(super) fn finalize_outputs(
indexes: &mut Indexes,
first_txoutindex: &mut BytesVec<TxIndex, TxOutIndex>,
first_txout_index: &mut BytesVec<TxIndex, TxOutIndex>,
outputs: &mut OutputsVecs,
addresses: &mut AddressesVecs,
scripts: &mut ScriptsVecs,
addr_hash_stores: &mut ByAddressType<Store<AddressHash, TypeIndex>>,
addr_txindex_stores: &mut ByAddressType<Store<AddressIndexTxIndex, Unit>>,
addr_tx_index_stores: &mut ByAddressType<Store<AddressIndexTxIndex, Unit>>,
addr_outpoint_stores: &mut ByAddressType<Store<AddressIndexOutPoint, Unit>>,
txouts: Vec<ProcessedOutput>,
same_block_spent_outpoints: &FxHashSet<OutPoint>,
already_added_addresshash: &mut ByAddressType<FxHashMap<AddressHash, TypeIndex>>,
already_added_address_hash: &mut ByAddressType<FxHashMap<AddressHash, TypeIndex>>,
same_block_output_info: &mut FxHashMap<OutPoint, SameBlockOutputInfo>,
) -> Result<()> {
already_added_addresshash
already_added_address_hash
.values_mut()
.for_each(|m| m.clear());
same_block_output_info.clear();
for ProcessedOutput {
txoutindex,
txout_index,
txout,
txindex,
tx_index,
vout,
outputtype,
output_type,
address_info,
existing_typeindex,
existing_type_index,
} in txouts
{
let sats = Sats::from(txout.value);
if vout.is_zero() {
first_txoutindex.checked_push(txindex, txoutindex)?;
first_txout_index.checked_push(tx_index, txout_index)?;
}
outputs.txindex.checked_push(txoutindex, txindex)?;
outputs.tx_index.checked_push(txout_index, tx_index)?;
let typeindex = if let Some(ti) = existing_typeindex {
let type_index = if let Some(ti) = existing_type_index {
ti
} else if let Some((address_bytes, address_hash)) = address_info {
let addresstype = outputtype;
if let Some(&ti) = already_added_addresshash
.get_unwrap(addresstype)
let address_type = output_type;
if let Some(&ti) = already_added_address_hash
.get_unwrap(address_type)
.get(&address_hash)
{
ti
} else {
let ti = indexes.increment_address_index(addresstype);
let ti = indexes.increment_address_index(address_type);
already_added_addresshash
.get_mut_unwrap(addresstype)
already_added_address_hash
.get_mut_unwrap(address_type)
.insert(address_hash, ti);
addr_hash_stores
.get_mut_unwrap(addresstype)
.get_mut_unwrap(address_type)
.insert(address_hash, ti);
addresses.push_bytes_if_needed(ti, address_bytes)?;
ti
}
} else {
match outputtype {
match output_type {
OutputType::P2MS => {
scripts
.p2ms.to_txindex
.checked_push(indexes.p2msoutputindex, txindex)?;
indexes.p2msoutputindex.copy_then_increment()
.p2ms.to_tx_index
.checked_push(indexes.p2ms_output_index, tx_index)?;
indexes.p2ms_output_index.copy_then_increment()
}
OutputType::OpReturn => {
scripts
.opreturn.to_txindex
.checked_push(indexes.opreturnindex, txindex)?;
indexes.opreturnindex.copy_then_increment()
.opreturn.to_tx_index
.checked_push(indexes.op_return_index, tx_index)?;
indexes.op_return_index.copy_then_increment()
}
OutputType::Empty => {
scripts
.empty.to_txindex
.checked_push(indexes.emptyoutputindex, txindex)?;
indexes.emptyoutputindex.copy_then_increment()
.empty.to_tx_index
.checked_push(indexes.empty_output_index, tx_index)?;
indexes.empty_output_index.copy_then_increment()
}
OutputType::Unknown => {
scripts
.unknown.to_txindex
.checked_push(indexes.unknownoutputindex, txindex)?;
indexes.unknownoutputindex.copy_then_increment()
.unknown.to_tx_index
.checked_push(indexes.unknown_output_index, tx_index)?;
indexes.unknown_output_index.copy_then_increment()
}
_ => unreachable!(),
}
};
outputs.value.checked_push(txoutindex, sats)?;
outputs.outputtype.checked_push(txoutindex, outputtype)?;
outputs.typeindex.checked_push(txoutindex, typeindex)?;
outputs.value.checked_push(txout_index, sats)?;
outputs.output_type.checked_push(txout_index, output_type)?;
outputs.type_index.checked_push(txout_index, type_index)?;
if outputtype.is_unspendable() {
if output_type.is_unspendable() {
continue;
} else if outputtype.is_address() {
let addresstype = outputtype;
let addressindex = typeindex;
} else if output_type.is_address() {
let address_type = output_type;
let address_index = type_index;
addr_txindex_stores
.get_mut_unwrap(addresstype)
.insert(AddressIndexTxIndex::from((addressindex, txindex)), Unit);
addr_tx_index_stores
.get_mut_unwrap(address_type)
.insert(AddressIndexTxIndex::from((address_index, tx_index)), Unit);
}
let outpoint = OutPoint::new(txindex, vout);
let outpoint = OutPoint::new(tx_index, vout);
if same_block_spent_outpoints.contains(&outpoint) {
same_block_output_info.insert(
outpoint,
SameBlockOutputInfo {
outputtype,
typeindex,
output_type,
type_index,
},
);
} else if outputtype.is_address() {
let addresstype = outputtype;
let addressindex = typeindex;
} else if output_type.is_address() {
let address_type = output_type;
let address_index = type_index;
addr_outpoint_stores
.get_mut_unwrap(addresstype)
.insert(AddressIndexOutPoint::from((addressindex, outpoint)), Unit);
.get_mut_unwrap(address_type)
.insert(AddressIndexOutPoint::from((address_index, outpoint)), Unit);
}
}
+12 -12
View File
@@ -10,13 +10,13 @@ use rustc_hash::{FxHashMap, FxHashSet};
pub enum InputSource {
PreviousBlock {
vin: Vin,
txindex: TxIndex,
tx_index: TxIndex,
outpoint: OutPoint,
outputtype: OutputType,
typeindex: TypeIndex,
output_type: OutputType,
type_index: TypeIndex,
},
SameBlock {
txindex: TxIndex,
tx_index: TxIndex,
vin: Vin,
outpoint: OutPoint,
},
@@ -24,26 +24,26 @@ pub enum InputSource {
#[derive(Debug, Clone, Copy)]
pub struct SameBlockOutputInfo {
pub outputtype: OutputType,
pub typeindex: TypeIndex,
pub output_type: OutputType,
pub type_index: TypeIndex,
}
pub struct ProcessedOutput<'a> {
pub txoutindex: TxOutIndex,
pub txout_index: TxOutIndex,
pub txout: &'a TxOut,
pub txindex: TxIndex,
pub tx_index: TxIndex,
pub vout: Vout,
pub outputtype: OutputType,
pub output_type: OutputType,
pub address_info: Option<(AddressBytes, AddressHash)>,
pub existing_typeindex: Option<TypeIndex>,
pub existing_type_index: Option<TypeIndex>,
}
pub struct ComputedTx<'a> {
pub txindex: TxIndex,
pub tx_index: TxIndex,
pub tx: &'a Transaction,
pub txid: Txid,
pub txid_prefix: TxidPrefix,
pub prev_txindex_opt: Option<TxIndex>,
pub prev_tx_index_opt: Option<TxIndex>,
pub base_size: u32,
pub total_size: u32,
}
+9 -9
View File
@@ -21,9 +21,9 @@ pub struct AddressReaders {
}
impl AddressReaders {
pub fn script_pubkey(&self, outputtype: OutputType, typeindex: TypeIndex) -> ScriptBuf {
let idx = usize::from(typeindex);
let bytes: Option<AddressBytes> = match outputtype {
pub fn script_pubkey(&self, output_type: OutputType, type_index: TypeIndex) -> ScriptBuf {
let idx = usize::from(type_index);
let bytes: Option<AddressBytes> = match output_type {
OutputType::P2PK65 => self.p2pk65.try_get(idx).map(Into::into),
OutputType::P2PK33 => self.p2pk33.try_get(idx).map(Into::into),
OutputType::P2PKH => self.p2pkh.try_get(idx).map(Into::into),
@@ -44,9 +44,9 @@ impl AddressReaders {
/// random access without recomputing `region.start() + HEADER_OFFSET` per read.
pub struct Readers {
pub txid: VecReader<TxIndex, Txid, BytesStrategy<Txid>>,
pub txindex_to_first_txoutindex: VecReader<TxIndex, TxOutIndex, BytesStrategy<TxOutIndex>>,
pub txoutindex_to_outputtype: VecReader<TxOutIndex, OutputType, BytesStrategy<OutputType>>,
pub txoutindex_to_typeindex: VecReader<TxOutIndex, TypeIndex, BytesStrategy<TypeIndex>>,
pub tx_index_to_first_txout_index: VecReader<TxIndex, TxOutIndex, BytesStrategy<TxOutIndex>>,
pub txout_index_to_output_type: VecReader<TxOutIndex, OutputType, BytesStrategy<OutputType>>,
pub txout_index_to_type_index: VecReader<TxOutIndex, TypeIndex, BytesStrategy<TypeIndex>>,
pub addressbytes: AddressReaders,
}
@@ -54,9 +54,9 @@ impl Readers {
pub fn new(vecs: &Vecs) -> Self {
Self {
txid: vecs.transactions.txid.reader(),
txindex_to_first_txoutindex: vecs.transactions.first_txoutindex.reader(),
txoutindex_to_outputtype: vecs.outputs.outputtype.reader(),
txoutindex_to_typeindex: vecs.outputs.typeindex.reader(),
tx_index_to_first_txout_index: vecs.transactions.first_txout_index.reader(),
txout_index_to_output_type: vecs.outputs.output_type.reader(),
txout_index_to_type_index: vecs.outputs.type_index.reader(),
addressbytes: vecs.addresses.address_readers(),
}
}
+92 -92
View File
@@ -22,13 +22,13 @@ use super::Vecs;
pub struct Stores {
pub db: Database,
pub addresstype_to_addresshash_to_addressindex: ByAddressType<Store<AddressHash, TypeIndex>>,
pub addresstype_to_addressindex_and_txindex: ByAddressType<Store<AddressIndexTxIndex, Unit>>,
pub addresstype_to_addressindex_and_unspentoutpoint:
pub address_type_to_address_hash_to_address_index: ByAddressType<Store<AddressHash, TypeIndex>>,
pub address_type_to_address_index_and_tx_index: ByAddressType<Store<AddressIndexTxIndex, Unit>>,
pub address_type_to_address_index_and_unspent_outpoint:
ByAddressType<Store<AddressIndexOutPoint, Unit>>,
pub blockhashprefix_to_height: Store<BlockHashPrefix, Height>,
pub blockhash_prefix_to_height: Store<BlockHashPrefix, Height>,
pub height_to_coinbase_tag: Store<Height, StoredString>,
pub txidprefix_to_txindex: Store<TxidPrefix, TxIndex>,
pub txid_prefix_to_tx_index: Store<TxidPrefix, TxIndex>,
}
impl Stores {
@@ -53,7 +53,7 @@ impl Stores {
let database_ref = &database;
let create_addresshash_to_addressindex_store = |index| {
let create_address_hash_to_address_index_store = |index| {
Store::import(
database_ref,
path,
@@ -64,7 +64,7 @@ impl Stores {
)
};
let create_addressindex_to_txindex_store = |index| {
let create_address_index_to_tx_index_store = |index| {
Store::import(
database_ref,
path,
@@ -75,7 +75,7 @@ impl Stores {
)
};
let create_addressindex_to_unspentoutpoint_store = |index| {
let create_address_index_to_unspent_outpoint_store = |index| {
Store::import(
database_ref,
path,
@@ -97,27 +97,27 @@ impl Stores {
Mode::PushOnly,
Kind::Sequential,
)?,
addresstype_to_addresshash_to_addressindex: ByAddressType::new_with_index(
create_addresshash_to_addressindex_store,
address_type_to_address_hash_to_address_index: ByAddressType::new_with_index(
create_address_hash_to_address_index_store,
)?,
addresstype_to_addressindex_and_txindex: ByAddressType::new_with_index(
create_addressindex_to_txindex_store,
address_type_to_address_index_and_tx_index: ByAddressType::new_with_index(
create_address_index_to_tx_index_store,
)?,
addresstype_to_addressindex_and_unspentoutpoint: ByAddressType::new_with_index(
create_addressindex_to_unspentoutpoint_store,
address_type_to_address_index_and_unspent_outpoint: ByAddressType::new_with_index(
create_address_index_to_unspent_outpoint_store,
)?,
blockhashprefix_to_height: Store::import(
blockhash_prefix_to_height: Store::import(
database_ref,
path,
"blockhashprefix_to_height",
"blockhash_prefix_to_height",
version,
Mode::PushOnly,
Kind::Random,
)?,
txidprefix_to_txindex: Store::import_cached(
txid_prefix_to_tx_index: Store::import_cached(
database_ref,
path,
"txidprefix_to_txindex",
"txid_prefix_to_tx_index",
version,
Mode::PushOnly,
Kind::Recent,
@@ -135,23 +135,23 @@ impl Stores {
fn iter_any(&self) -> impl Iterator<Item = &dyn AnyStore> {
[
&self.blockhashprefix_to_height as &dyn AnyStore,
&self.blockhash_prefix_to_height as &dyn AnyStore,
&self.height_to_coinbase_tag,
&self.txidprefix_to_txindex,
&self.txid_prefix_to_tx_index,
]
.into_iter()
.chain(
self.addresstype_to_addresshash_to_addressindex
self.address_type_to_address_hash_to_address_index
.values()
.map(|s| s as &dyn AnyStore),
)
.chain(
self.addresstype_to_addressindex_and_txindex
self.address_type_to_address_index_and_tx_index
.values()
.map(|s| s as &dyn AnyStore),
)
.chain(
self.addresstype_to_addressindex_and_unspentoutpoint
self.address_type_to_address_index_and_unspent_outpoint
.values()
.map(|s| s as &dyn AnyStore),
)
@@ -159,23 +159,23 @@ impl Stores {
fn par_iter_any_mut(&mut self) -> impl ParallelIterator<Item = &mut dyn AnyStore> {
[
&mut self.blockhashprefix_to_height as &mut dyn AnyStore,
&mut self.blockhash_prefix_to_height as &mut dyn AnyStore,
&mut self.height_to_coinbase_tag,
&mut self.txidprefix_to_txindex,
&mut self.txid_prefix_to_tx_index,
]
.into_par_iter()
.chain(
self.addresstype_to_addresshash_to_addressindex
self.address_type_to_address_hash_to_address_index
.par_values_mut()
.map(|s| s as &mut dyn AnyStore),
)
.chain(
self.addresstype_to_addressindex_and_txindex
self.address_type_to_address_index_and_tx_index
.par_values_mut()
.map(|s| s as &mut dyn AnyStore),
)
.chain(
self.addresstype_to_addressindex_and_unspentoutpoint
self.address_type_to_address_index_and_unspent_outpoint
.par_values_mut()
.map(|s| s as &mut dyn AnyStore),
)
@@ -204,8 +204,8 @@ impl Stores {
}
debug_assert!(starting_indexes.height != Height::ZERO);
debug_assert!(starting_indexes.txindex != TxIndex::ZERO);
debug_assert!(starting_indexes.txoutindex != TxOutIndex::ZERO);
debug_assert!(starting_indexes.tx_index != TxIndex::ZERO);
debug_assert!(starting_indexes.txout_index != TxOutIndex::ZERO);
self.rollback_block_metadata(vecs, starting_indexes)?;
self.rollback_txids(vecs, starting_indexes);
@@ -220,19 +220,19 @@ impl Stores {
}
fn is_empty(&self) -> Result<bool> {
Ok(self.blockhashprefix_to_height.is_empty()?
&& self.txidprefix_to_txindex.is_empty()?
Ok(self.blockhash_prefix_to_height.is_empty()?
&& self.txid_prefix_to_tx_index.is_empty()?
&& self.height_to_coinbase_tag.is_empty()?
&& self
.addresstype_to_addresshash_to_addressindex
.address_type_to_address_hash_to_address_index
.values()
.try_fold(true, |acc, s| s.is_empty().map(|empty| acc && empty))?
&& self
.addresstype_to_addressindex_and_txindex
.address_type_to_address_index_and_tx_index
.values()
.try_fold(true, |acc, s| s.is_empty().map(|empty| acc && empty))?
&& self
.addresstype_to_addressindex_and_unspentoutpoint
.address_type_to_address_index_and_unspent_outpoint
.values()
.try_fold(true, |acc, s| s.is_empty().map(|empty| acc && empty))?)
}
@@ -246,7 +246,7 @@ impl Stores {
starting_indexes.height.to_usize(),
vecs.blocks.blockhash.len(),
|blockhash| {
self.blockhashprefix_to_height
self.blockhash_prefix_to_height
.remove(BlockHashPrefix::from(blockhash));
},
);
@@ -259,7 +259,7 @@ impl Stores {
for address_type in OutputType::ADDRESS_TYPES {
for hash in vecs.iter_address_hashes_from(address_type, starting_indexes.height)? {
self.addresstype_to_addresshash_to_addressindex
self.address_type_to_address_hash_to_address_index
.get_mut_unwrap(address_type)
.remove(hash);
}
@@ -269,121 +269,121 @@ impl Stores {
}
fn rollback_txids(&mut self, vecs: &mut Vecs, starting_indexes: &Indexes) {
let start = starting_indexes.txindex.to_usize();
let start = starting_indexes.tx_index.to_usize();
let end = vecs.transactions.txid.len();
let mut current_index = start;
vecs.transactions
.txid
.for_each_range_at(start, end, |txid| {
let txindex = TxIndex::from(current_index);
let txidprefix = TxidPrefix::from(&txid);
let tx_index = TxIndex::from(current_index);
let txid_prefix = TxidPrefix::from(&txid);
let is_known_dup =
DUPLICATE_TXID_PREFIXES
.iter()
.any(|(dup_prefix, dup_txindex)| {
txindex == *dup_txindex && txidprefix == *dup_prefix
.any(|(dup_prefix, dup_tx_index)| {
tx_index == *dup_tx_index && txid_prefix == *dup_prefix
});
if !is_known_dup {
self.txidprefix_to_txindex.remove(txidprefix);
self.txid_prefix_to_tx_index.remove(txid_prefix);
}
current_index += 1;
});
self.txidprefix_to_txindex.clear_caches();
self.txid_prefix_to_tx_index.clear_caches();
}
fn rollback_outputs_and_inputs(&mut self, vecs: &mut Vecs, starting_indexes: &Indexes) {
let txindex_to_first_txoutindex_reader = vecs.transactions.first_txoutindex.reader();
let txoutindex_to_outputtype_reader = vecs.outputs.outputtype.reader();
let txoutindex_to_typeindex_reader = vecs.outputs.typeindex.reader();
let tx_index_to_first_txout_index_reader = vecs.transactions.first_txout_index.reader();
let txout_index_to_output_type_reader = vecs.outputs.output_type.reader();
let txout_index_to_type_index_reader = vecs.outputs.type_index.reader();
let mut addressindex_txindex_to_remove: FxHashSet<(OutputType, TypeIndex, TxIndex)> =
let mut address_index_tx_index_to_remove: FxHashSet<(OutputType, TypeIndex, TxIndex)> =
FxHashSet::default();
let rollback_start = starting_indexes.txoutindex.to_usize();
let rollback_end = vecs.outputs.outputtype.len();
let rollback_start = starting_indexes.txout_index.to_usize();
let rollback_end = vecs.outputs.output_type.len();
let txindexes: Vec<TxIndex> = vecs
let tx_indexes: Vec<TxIndex> = vecs
.outputs
.txindex
.tx_index
.collect_range_at(rollback_start, rollback_end);
for (i, txoutindex) in (rollback_start..rollback_end).enumerate() {
let outputtype = txoutindex_to_outputtype_reader.get(txoutindex);
if !outputtype.is_address() {
for (i, txout_index) in (rollback_start..rollback_end).enumerate() {
let output_type = txout_index_to_output_type_reader.get(txout_index);
if !output_type.is_address() {
continue;
}
let addresstype = outputtype;
let addressindex = txoutindex_to_typeindex_reader.get(txoutindex);
let txindex = txindexes[i];
let address_type = output_type;
let address_index = txout_index_to_type_index_reader.get(txout_index);
let tx_index = tx_indexes[i];
addressindex_txindex_to_remove.insert((addresstype, addressindex, txindex));
address_index_tx_index_to_remove.insert((address_type, address_index, tx_index));
let vout = Vout::from(
txoutindex
- txindex_to_first_txoutindex_reader
.get(txindex.to_usize())
txout_index
- tx_index_to_first_txout_index_reader
.get(tx_index.to_usize())
.to_usize(),
);
let outpoint = OutPoint::new(txindex, vout);
let outpoint = OutPoint::new(tx_index, vout);
self.addresstype_to_addressindex_and_unspentoutpoint
.get_mut_unwrap(addresstype)
.remove(AddressIndexOutPoint::from((addressindex, outpoint)));
self.address_type_to_address_index_and_unspent_outpoint
.get_mut_unwrap(address_type)
.remove(AddressIndexOutPoint::from((address_index, outpoint)));
}
let start = starting_indexes.txinindex.to_usize();
let start = starting_indexes.txin_index.to_usize();
let end = vecs.inputs.outpoint.len();
let outpoints: Vec<OutPoint> = vecs.inputs.outpoint.collect_range_at(start, end);
let spending_txindexes: Vec<TxIndex> = vecs.inputs.txindex.collect_range_at(start, end);
let spending_tx_indexes: Vec<TxIndex> = vecs.inputs.tx_index.collect_range_at(start, end);
let outputs_to_unspend: Vec<_> = outpoints
.into_iter()
.zip(spending_txindexes)
.filter_map(|(outpoint, spending_txindex)| {
.zip(spending_tx_indexes)
.filter_map(|(outpoint, spending_tx_index)| {
if outpoint.is_coinbase() {
return None;
}
let output_txindex = outpoint.txindex();
let output_tx_index = outpoint.tx_index();
let vout = outpoint.vout();
let txoutindex =
txindex_to_first_txoutindex_reader.get(output_txindex.to_usize()) + vout;
let txout_index =
tx_index_to_first_txout_index_reader.get(output_tx_index.to_usize()) + vout;
if txoutindex < starting_indexes.txoutindex {
let outputtype = txoutindex_to_outputtype_reader.get(txoutindex.to_usize());
let typeindex = txoutindex_to_typeindex_reader.get(txoutindex.to_usize());
Some((outpoint, outputtype, typeindex, spending_txindex))
if txout_index < starting_indexes.txout_index {
let output_type = txout_index_to_output_type_reader.get(txout_index.to_usize());
let type_index = txout_index_to_type_index_reader.get(txout_index.to_usize());
Some((outpoint, output_type, type_index, spending_tx_index))
} else {
None
}
})
.collect();
for (outpoint, outputtype, typeindex, spending_txindex) in outputs_to_unspend {
if outputtype.is_address() {
let addresstype = outputtype;
let addressindex = typeindex;
for (outpoint, output_type, type_index, spending_tx_index) in outputs_to_unspend {
if output_type.is_address() {
let address_type = output_type;
let address_index = type_index;
addressindex_txindex_to_remove.insert((
addresstype,
addressindex,
spending_txindex,
address_index_tx_index_to_remove.insert((
address_type,
address_index,
spending_tx_index,
));
self.addresstype_to_addressindex_and_unspentoutpoint
.get_mut_unwrap(addresstype)
.insert(AddressIndexOutPoint::from((addressindex, outpoint)), Unit);
self.address_type_to_address_index_and_unspent_outpoint
.get_mut_unwrap(address_type)
.insert(AddressIndexOutPoint::from((address_index, outpoint)), Unit);
}
}
for (addresstype, addressindex, txindex) in addressindex_txindex_to_remove {
self.addresstype_to_addressindex_and_txindex
.get_mut_unwrap(addresstype)
.remove(AddressIndexTxIndex::from((addressindex, txindex)));
for (address_type, address_index, tx_index) in address_index_tx_index_to_remove {
self.address_type_to_address_index_and_tx_index
.get_mut_unwrap(address_type)
.remove(AddressIndexTxIndex::from((address_index, tx_index)));
}
}
+67 -67
View File
@@ -38,49 +38,49 @@ pub struct AddressesVecs<M: StorageMode = Rw> {
impl AddressesVecs {
pub fn forced_import(db: &Database, version: Version) -> Result<Self> {
let (
first_p2pk65addressindex,
first_p2pk33addressindex,
first_p2pkhaddressindex,
first_p2shaddressindex,
first_p2wpkhaddressindex,
first_p2wshaddressindex,
first_p2traddressindex,
first_p2aaddressindex,
p2pk65bytes,
p2pk33bytes,
p2pkhbytes,
p2shbytes,
p2wpkhbytes,
p2wshbytes,
p2trbytes,
p2abytes,
first_p2pk65_address_index,
first_p2pk33_address_index,
first_p2pkh_address_index,
first_p2sh_address_index,
first_p2wpkh_address_index,
first_p2wsh_address_index,
first_p2tr_address_index,
first_p2a_address_index,
p2pk65_bytes,
p2pk33_bytes,
p2pkh_bytes,
p2sh_bytes,
p2wpkh_bytes,
p2wsh_bytes,
p2tr_bytes,
p2a_bytes,
) = parallel_import! {
first_p2pk65addressindex = PcoVec::forced_import(db, "first_p2pk65addressindex", version),
first_p2pk33addressindex = PcoVec::forced_import(db, "first_p2pk33addressindex", version),
first_p2pkhaddressindex = PcoVec::forced_import(db, "first_p2pkhaddressindex", version),
first_p2shaddressindex = PcoVec::forced_import(db, "first_p2shaddressindex", version),
first_p2wpkhaddressindex = PcoVec::forced_import(db, "first_p2wpkhaddressindex", version),
first_p2wshaddressindex = PcoVec::forced_import(db, "first_p2wshaddressindex", version),
first_p2traddressindex = PcoVec::forced_import(db, "first_p2traddressindex", version),
first_p2aaddressindex = PcoVec::forced_import(db, "first_p2aaddressindex", version),
p2pk65bytes = BytesVec::forced_import(db, "p2pk65bytes", version),
p2pk33bytes = BytesVec::forced_import(db, "p2pk33bytes", version),
p2pkhbytes = BytesVec::forced_import(db, "p2pkhbytes", version),
p2shbytes = BytesVec::forced_import(db, "p2shbytes", version),
p2wpkhbytes = BytesVec::forced_import(db, "p2wpkhbytes", version),
p2wshbytes = BytesVec::forced_import(db, "p2wshbytes", version),
p2trbytes = BytesVec::forced_import(db, "p2trbytes", version),
p2abytes = BytesVec::forced_import(db, "p2abytes", version),
first_p2pk65_address_index = PcoVec::forced_import(db, "first_p2pk65_address_index", version),
first_p2pk33_address_index = PcoVec::forced_import(db, "first_p2pk33_address_index", version),
first_p2pkh_address_index = PcoVec::forced_import(db, "first_p2pkh_address_index", version),
first_p2sh_address_index = PcoVec::forced_import(db, "first_p2sh_address_index", version),
first_p2wpkh_address_index = PcoVec::forced_import(db, "first_p2wpkh_address_index", version),
first_p2wsh_address_index = PcoVec::forced_import(db, "first_p2wsh_address_index", version),
first_p2tr_address_index = PcoVec::forced_import(db, "first_p2tr_address_index", version),
first_p2a_address_index = PcoVec::forced_import(db, "first_p2a_address_index", version),
p2pk65_bytes = BytesVec::forced_import(db, "p2pk65_bytes", version),
p2pk33_bytes = BytesVec::forced_import(db, "p2pk33_bytes", version),
p2pkh_bytes = BytesVec::forced_import(db, "p2pkh_bytes", version),
p2sh_bytes = BytesVec::forced_import(db, "p2sh_bytes", version),
p2wpkh_bytes = BytesVec::forced_import(db, "p2wpkh_bytes", version),
p2wsh_bytes = BytesVec::forced_import(db, "p2wsh_bytes", version),
p2tr_bytes = BytesVec::forced_import(db, "p2tr_bytes", version),
p2a_bytes = BytesVec::forced_import(db, "p2a_bytes", version),
};
Ok(Self {
p2pk65: AddressTypeVecs { first_index: first_p2pk65addressindex, bytes: p2pk65bytes },
p2pk33: AddressTypeVecs { first_index: first_p2pk33addressindex, bytes: p2pk33bytes },
p2pkh: AddressTypeVecs { first_index: first_p2pkhaddressindex, bytes: p2pkhbytes },
p2sh: AddressTypeVecs { first_index: first_p2shaddressindex, bytes: p2shbytes },
p2wpkh: AddressTypeVecs { first_index: first_p2wpkhaddressindex, bytes: p2wpkhbytes },
p2wsh: AddressTypeVecs { first_index: first_p2wshaddressindex, bytes: p2wshbytes },
p2tr: AddressTypeVecs { first_index: first_p2traddressindex, bytes: p2trbytes },
p2a: AddressTypeVecs { first_index: first_p2aaddressindex, bytes: p2abytes },
p2pk65: AddressTypeVecs { first_index: first_p2pk65_address_index, bytes: p2pk65_bytes },
p2pk33: AddressTypeVecs { first_index: first_p2pk33_address_index, bytes: p2pk33_bytes },
p2pkh: AddressTypeVecs { first_index: first_p2pkh_address_index, bytes: p2pkh_bytes },
p2sh: AddressTypeVecs { first_index: first_p2sh_address_index, bytes: p2sh_bytes },
p2wpkh: AddressTypeVecs { first_index: first_p2wpkh_address_index, bytes: p2wpkh_bytes },
p2wsh: AddressTypeVecs { first_index: first_p2wsh_address_index, bytes: p2wsh_bytes },
p2tr: AddressTypeVecs { first_index: first_p2tr_address_index, bytes: p2tr_bytes },
p2a: AddressTypeVecs { first_index: first_p2a_address_index, bytes: p2a_bytes },
})
}
@@ -88,14 +88,14 @@ impl AddressesVecs {
pub fn truncate(
&mut self,
height: Height,
p2pk65addressindex: P2PK65AddressIndex,
p2pk33addressindex: P2PK33AddressIndex,
p2pkhaddressindex: P2PKHAddressIndex,
p2shaddressindex: P2SHAddressIndex,
p2wpkhaddressindex: P2WPKHAddressIndex,
p2wshaddressindex: P2WSHAddressIndex,
p2traddressindex: P2TRAddressIndex,
p2aaddressindex: P2AAddressIndex,
p2pk65_address_index: P2PK65AddressIndex,
p2pk33_address_index: P2PK33AddressIndex,
p2pkh_address_index: P2PKHAddressIndex,
p2sh_address_index: P2SHAddressIndex,
p2wpkh_address_index: P2WPKHAddressIndex,
p2wsh_address_index: P2WSHAddressIndex,
p2tr_address_index: P2TRAddressIndex,
p2a_address_index: P2AAddressIndex,
stamp: Stamp,
) -> Result<()> {
self.p2pk65.first_index
@@ -115,21 +115,21 @@ impl AddressesVecs {
self.p2a.first_index
.truncate_if_needed_with_stamp(height, stamp)?;
self.p2pk65.bytes
.truncate_if_needed_with_stamp(p2pk65addressindex, stamp)?;
.truncate_if_needed_with_stamp(p2pk65_address_index, stamp)?;
self.p2pk33.bytes
.truncate_if_needed_with_stamp(p2pk33addressindex, stamp)?;
.truncate_if_needed_with_stamp(p2pk33_address_index, stamp)?;
self.p2pkh.bytes
.truncate_if_needed_with_stamp(p2pkhaddressindex, stamp)?;
.truncate_if_needed_with_stamp(p2pkh_address_index, stamp)?;
self.p2sh.bytes
.truncate_if_needed_with_stamp(p2shaddressindex, stamp)?;
.truncate_if_needed_with_stamp(p2sh_address_index, stamp)?;
self.p2wpkh.bytes
.truncate_if_needed_with_stamp(p2wpkhaddressindex, stamp)?;
.truncate_if_needed_with_stamp(p2wpkh_address_index, stamp)?;
self.p2wsh.bytes
.truncate_if_needed_with_stamp(p2wshaddressindex, stamp)?;
.truncate_if_needed_with_stamp(p2wsh_address_index, stamp)?;
self.p2tr.bytes
.truncate_if_needed_with_stamp(p2traddressindex, stamp)?;
.truncate_if_needed_with_stamp(p2tr_address_index, stamp)?;
self.p2a.bytes
.truncate_if_needed_with_stamp(p2aaddressindex, stamp)?;
.truncate_if_needed_with_stamp(p2a_address_index, stamp)?;
Ok(())
}
@@ -159,42 +159,42 @@ impl AddressesVecs {
/// Returns None if the index doesn't exist yet.
pub fn get_bytes_by_type(
&self,
addresstype: OutputType,
typeindex: TypeIndex,
address_type: OutputType,
type_index: TypeIndex,
readers: &AddressReaders,
) -> Option<AddressBytes> {
match addresstype {
match address_type {
OutputType::P2PK65 => self
.p2pk65.bytes
.get_pushed_or_read(typeindex.into(), &readers.p2pk65)
.get_pushed_or_read(type_index.into(), &readers.p2pk65)
.map(AddressBytes::from),
OutputType::P2PK33 => self
.p2pk33.bytes
.get_pushed_or_read(typeindex.into(), &readers.p2pk33)
.get_pushed_or_read(type_index.into(), &readers.p2pk33)
.map(AddressBytes::from),
OutputType::P2PKH => self
.p2pkh.bytes
.get_pushed_or_read(typeindex.into(), &readers.p2pkh)
.get_pushed_or_read(type_index.into(), &readers.p2pkh)
.map(AddressBytes::from),
OutputType::P2SH => self
.p2sh.bytes
.get_pushed_or_read(typeindex.into(), &readers.p2sh)
.get_pushed_or_read(type_index.into(), &readers.p2sh)
.map(AddressBytes::from),
OutputType::P2WPKH => self
.p2wpkh.bytes
.get_pushed_or_read(typeindex.into(), &readers.p2wpkh)
.get_pushed_or_read(type_index.into(), &readers.p2wpkh)
.map(AddressBytes::from),
OutputType::P2WSH => self
.p2wsh.bytes
.get_pushed_or_read(typeindex.into(), &readers.p2wsh)
.get_pushed_or_read(type_index.into(), &readers.p2wsh)
.map(AddressBytes::from),
OutputType::P2TR => self
.p2tr.bytes
.get_pushed_or_read(typeindex.into(), &readers.p2tr)
.get_pushed_or_read(type_index.into(), &readers.p2tr)
.map(AddressBytes::from),
OutputType::P2A => self
.p2a.bytes
.get_pushed_or_read(typeindex.into(), &readers.p2a)
.get_pushed_or_read(type_index.into(), &readers.p2a)
.map(AddressBytes::from),
_ => unreachable!("get_bytes_by_type called with non-address type"),
}
+26 -26
View File
@@ -8,52 +8,52 @@ use crate::parallel_import;
#[derive(Traversable)]
pub struct InputsVecs<M: StorageMode = Rw> {
pub first_txinindex: M::Stored<PcoVec<Height, TxInIndex>>,
pub first_txin_index: M::Stored<PcoVec<Height, TxInIndex>>,
pub outpoint: M::Stored<PcoVec<TxInIndex, OutPoint>>,
pub txindex: M::Stored<PcoVec<TxInIndex, TxIndex>>,
pub outputtype: M::Stored<PcoVec<TxInIndex, OutputType>>,
pub typeindex: M::Stored<PcoVec<TxInIndex, TypeIndex>>,
pub tx_index: M::Stored<PcoVec<TxInIndex, TxIndex>>,
pub output_type: M::Stored<PcoVec<TxInIndex, OutputType>>,
pub type_index: M::Stored<PcoVec<TxInIndex, TypeIndex>>,
}
impl InputsVecs {
pub fn forced_import(db: &Database, version: Version) -> Result<Self> {
let (first_txinindex, outpoint, txindex, outputtype, typeindex) = parallel_import! {
first_txinindex = PcoVec::forced_import(db, "first_txinindex", version),
let (first_txin_index, outpoint, tx_index, output_type, type_index) = parallel_import! {
first_txin_index = PcoVec::forced_import(db, "first_txin_index", version),
outpoint = PcoVec::forced_import(db, "outpoint", version),
txindex = PcoVec::forced_import(db, "txindex", version),
outputtype = PcoVec::forced_import(db, "outputtype", version),
typeindex = PcoVec::forced_import(db, "typeindex", version),
tx_index = PcoVec::forced_import(db, "tx_index", version),
output_type = PcoVec::forced_import(db, "output_type", version),
type_index = PcoVec::forced_import(db, "type_index", version),
};
Ok(Self {
first_txinindex,
first_txin_index,
outpoint,
txindex,
outputtype,
typeindex,
tx_index,
output_type,
type_index,
})
}
pub fn truncate(&mut self, height: Height, txinindex: TxInIndex, stamp: Stamp) -> Result<()> {
self.first_txinindex
pub fn truncate(&mut self, height: Height, txin_index: TxInIndex, stamp: Stamp) -> Result<()> {
self.first_txin_index
.truncate_if_needed_with_stamp(height, stamp)?;
self.outpoint
.truncate_if_needed_with_stamp(txinindex, stamp)?;
self.txindex
.truncate_if_needed_with_stamp(txinindex, stamp)?;
self.outputtype
.truncate_if_needed_with_stamp(txinindex, stamp)?;
self.typeindex
.truncate_if_needed_with_stamp(txinindex, stamp)?;
.truncate_if_needed_with_stamp(txin_index, stamp)?;
self.tx_index
.truncate_if_needed_with_stamp(txin_index, stamp)?;
self.output_type
.truncate_if_needed_with_stamp(txin_index, stamp)?;
self.type_index
.truncate_if_needed_with_stamp(txin_index, stamp)?;
Ok(())
}
pub fn par_iter_mut_any(&mut self) -> impl ParallelIterator<Item = &mut dyn AnyStoredVec> {
[
&mut self.first_txinindex as &mut dyn AnyStoredVec,
&mut self.first_txin_index as &mut dyn AnyStoredVec,
&mut self.outpoint,
&mut self.txindex,
&mut self.outputtype,
&mut self.typeindex,
&mut self.tx_index,
&mut self.output_type,
&mut self.type_index,
]
.into_par_iter()
}
+15 -15
View File
@@ -87,33 +87,33 @@ impl Vecs {
self.blocks.truncate(starting_indexes.height, stamp)?;
self.transactions
.truncate(starting_indexes.height, starting_indexes.txindex, stamp)?;
.truncate(starting_indexes.height, starting_indexes.tx_index, stamp)?;
self.inputs
.truncate(starting_indexes.height, starting_indexes.txinindex, stamp)?;
.truncate(starting_indexes.height, starting_indexes.txin_index, stamp)?;
self.outputs
.truncate(starting_indexes.height, starting_indexes.txoutindex, stamp)?;
.truncate(starting_indexes.height, starting_indexes.txout_index, stamp)?;
self.addresses.truncate(
starting_indexes.height,
starting_indexes.p2pk65addressindex,
starting_indexes.p2pk33addressindex,
starting_indexes.p2pkhaddressindex,
starting_indexes.p2shaddressindex,
starting_indexes.p2wpkhaddressindex,
starting_indexes.p2wshaddressindex,
starting_indexes.p2traddressindex,
starting_indexes.p2aaddressindex,
starting_indexes.p2pk65_address_index,
starting_indexes.p2pk33_address_index,
starting_indexes.p2pkh_address_index,
starting_indexes.p2sh_address_index,
starting_indexes.p2wpkh_address_index,
starting_indexes.p2wsh_address_index,
starting_indexes.p2tr_address_index,
starting_indexes.p2a_address_index,
stamp,
)?;
self.scripts.truncate(
starting_indexes.height,
starting_indexes.emptyoutputindex,
starting_indexes.opreturnindex,
starting_indexes.p2msoutputindex,
starting_indexes.unknownoutputindex,
starting_indexes.empty_output_index,
starting_indexes.op_return_index,
starting_indexes.p2ms_output_index,
starting_indexes.unknown_output_index,
stamp,
)?;
+26 -26
View File
@@ -10,52 +10,52 @@ use crate::parallel_import;
#[derive(Traversable)]
pub struct OutputsVecs<M: StorageMode = Rw> {
pub first_txoutindex: M::Stored<PcoVec<Height, TxOutIndex>>,
pub first_txout_index: M::Stored<PcoVec<Height, TxOutIndex>>,
pub value: M::Stored<BytesVec<TxOutIndex, Sats>>,
pub outputtype: M::Stored<BytesVec<TxOutIndex, OutputType>>,
pub typeindex: M::Stored<BytesVec<TxOutIndex, TypeIndex>>,
pub txindex: M::Stored<PcoVec<TxOutIndex, TxIndex>>,
pub output_type: M::Stored<BytesVec<TxOutIndex, OutputType>>,
pub type_index: M::Stored<BytesVec<TxOutIndex, TypeIndex>>,
pub tx_index: M::Stored<PcoVec<TxOutIndex, TxIndex>>,
}
impl OutputsVecs {
pub fn forced_import(db: &Database, version: Version) -> Result<Self> {
let (first_txoutindex, value, outputtype, typeindex, txindex) = parallel_import! {
first_txoutindex = PcoVec::forced_import(db, "first_txoutindex", version),
let (first_txout_index, value, output_type, type_index, tx_index) = parallel_import! {
first_txout_index = PcoVec::forced_import(db, "first_txout_index", version),
value = BytesVec::forced_import(db, "value", version),
outputtype = BytesVec::forced_import(db, "outputtype", version),
typeindex = BytesVec::forced_import(db, "typeindex", version),
txindex = PcoVec::forced_import(db, "txindex", version),
output_type = BytesVec::forced_import(db, "output_type", version),
type_index = BytesVec::forced_import(db, "type_index", version),
tx_index = PcoVec::forced_import(db, "tx_index", version),
};
Ok(Self {
first_txoutindex,
first_txout_index,
value,
outputtype,
typeindex,
txindex,
output_type,
type_index,
tx_index,
})
}
pub fn truncate(&mut self, height: Height, txoutindex: TxOutIndex, stamp: Stamp) -> Result<()> {
self.first_txoutindex
pub fn truncate(&mut self, height: Height, txout_index: TxOutIndex, stamp: Stamp) -> Result<()> {
self.first_txout_index
.truncate_if_needed_with_stamp(height, stamp)?;
self.value
.truncate_if_needed_with_stamp(txoutindex, stamp)?;
self.outputtype
.truncate_if_needed_with_stamp(txoutindex, stamp)?;
self.typeindex
.truncate_if_needed_with_stamp(txoutindex, stamp)?;
self.txindex
.truncate_if_needed_with_stamp(txoutindex, stamp)?;
.truncate_if_needed_with_stamp(txout_index, stamp)?;
self.output_type
.truncate_if_needed_with_stamp(txout_index, stamp)?;
self.type_index
.truncate_if_needed_with_stamp(txout_index, stamp)?;
self.tx_index
.truncate_if_needed_with_stamp(txout_index, stamp)?;
Ok(())
}
pub fn par_iter_mut_any(&mut self) -> impl ParallelIterator<Item = &mut dyn AnyStoredVec> {
[
&mut self.first_txoutindex as &mut dyn AnyStoredVec,
&mut self.first_txout_index as &mut dyn AnyStoredVec,
&mut self.value,
&mut self.outputtype,
&mut self.typeindex,
&mut self.txindex,
&mut self.output_type,
&mut self.type_index,
&mut self.tx_index,
]
.into_par_iter()
}
+37 -37
View File
@@ -16,7 +16,7 @@ use crate::parallel_import;
#[derive(Traversable)]
pub struct ScriptTypeVecs<I: VecIndex + PcoVecValue + Formattable + Serialize + JsonSchema, M: StorageMode = Rw> {
pub first_index: M::Stored<PcoVec<Height, I>>,
pub to_txindex: M::Stored<PcoVec<I, TxIndex>>,
pub to_tx_index: M::Stored<PcoVec<I, TxIndex>>,
}
#[derive(Traversable)]
@@ -30,39 +30,39 @@ pub struct ScriptsVecs<M: StorageMode = Rw> {
impl ScriptsVecs {
pub fn forced_import(db: &Database, version: Version) -> Result<Self> {
let (
first_emptyoutputindex,
first_opreturnindex,
first_p2msoutputindex,
first_unknownoutputindex,
emptyoutputindex_to_txindex,
opreturnindex_to_txindex,
p2msoutputindex_to_txindex,
unknownoutputindex_to_txindex,
first_empty_output_index,
first_op_return_index,
first_p2ms_output_index,
first_unknown_output_index,
empty_output_index_to_tx_index,
op_return_index_to_tx_index,
p2ms_output_index_to_tx_index,
unknown_output_index_to_tx_index,
) = parallel_import! {
first_emptyoutputindex = PcoVec::forced_import(db, "first_emptyoutputindex", version),
first_opreturnindex = PcoVec::forced_import(db, "first_opreturnindex", version),
first_p2msoutputindex = PcoVec::forced_import(db, "first_p2msoutputindex", version),
first_unknownoutputindex = PcoVec::forced_import(db, "first_unknownoutputindex", version),
emptyoutputindex_to_txindex = PcoVec::forced_import(db, "txindex", version),
opreturnindex_to_txindex = PcoVec::forced_import(db, "txindex", version),
p2msoutputindex_to_txindex = PcoVec::forced_import(db, "txindex", version),
unknownoutputindex_to_txindex = PcoVec::forced_import(db, "txindex", version),
first_empty_output_index = PcoVec::forced_import(db, "first_empty_output_index", version),
first_op_return_index = PcoVec::forced_import(db, "first_op_return_index", version),
first_p2ms_output_index = PcoVec::forced_import(db, "first_p2ms_output_index", version),
first_unknown_output_index = PcoVec::forced_import(db, "first_unknown_output_index", version),
empty_output_index_to_tx_index = PcoVec::forced_import(db, "tx_index", version),
op_return_index_to_tx_index = PcoVec::forced_import(db, "tx_index", version),
p2ms_output_index_to_tx_index = PcoVec::forced_import(db, "tx_index", version),
unknown_output_index_to_tx_index = PcoVec::forced_import(db, "tx_index", version),
};
Ok(Self {
empty: ScriptTypeVecs { first_index: first_emptyoutputindex, to_txindex: emptyoutputindex_to_txindex },
opreturn: ScriptTypeVecs { first_index: first_opreturnindex, to_txindex: opreturnindex_to_txindex },
p2ms: ScriptTypeVecs { first_index: first_p2msoutputindex, to_txindex: p2msoutputindex_to_txindex },
unknown: ScriptTypeVecs { first_index: first_unknownoutputindex, to_txindex: unknownoutputindex_to_txindex },
empty: ScriptTypeVecs { first_index: first_empty_output_index, to_tx_index: empty_output_index_to_tx_index },
opreturn: ScriptTypeVecs { first_index: first_op_return_index, to_tx_index: op_return_index_to_tx_index },
p2ms: ScriptTypeVecs { first_index: first_p2ms_output_index, to_tx_index: p2ms_output_index_to_tx_index },
unknown: ScriptTypeVecs { first_index: first_unknown_output_index, to_tx_index: unknown_output_index_to_tx_index },
})
}
pub fn truncate(
&mut self,
height: Height,
emptyoutputindex: EmptyOutputIndex,
opreturnindex: OpReturnIndex,
p2msoutputindex: P2MSOutputIndex,
unknownoutputindex: UnknownOutputIndex,
empty_output_index: EmptyOutputIndex,
op_return_index: OpReturnIndex,
p2ms_output_index: P2MSOutputIndex,
unknown_output_index: UnknownOutputIndex,
stamp: Stamp,
) -> Result<()> {
self.empty.first_index
@@ -73,14 +73,14 @@ impl ScriptsVecs {
.truncate_if_needed_with_stamp(height, stamp)?;
self.unknown.first_index
.truncate_if_needed_with_stamp(height, stamp)?;
self.empty.to_txindex
.truncate_if_needed_with_stamp(emptyoutputindex, stamp)?;
self.opreturn.to_txindex
.truncate_if_needed_with_stamp(opreturnindex, stamp)?;
self.p2ms.to_txindex
.truncate_if_needed_with_stamp(p2msoutputindex, stamp)?;
self.unknown.to_txindex
.truncate_if_needed_with_stamp(unknownoutputindex, stamp)?;
self.empty.to_tx_index
.truncate_if_needed_with_stamp(empty_output_index, stamp)?;
self.opreturn.to_tx_index
.truncate_if_needed_with_stamp(op_return_index, stamp)?;
self.p2ms.to_tx_index
.truncate_if_needed_with_stamp(p2ms_output_index, stamp)?;
self.unknown.to_tx_index
.truncate_if_needed_with_stamp(unknown_output_index, stamp)?;
Ok(())
}
@@ -90,10 +90,10 @@ impl ScriptsVecs {
&mut self.opreturn.first_index,
&mut self.p2ms.first_index,
&mut self.unknown.first_index,
&mut self.empty.to_txindex,
&mut self.opreturn.to_txindex,
&mut self.p2ms.to_txindex,
&mut self.unknown.to_txindex,
&mut self.empty.to_tx_index,
&mut self.opreturn.to_tx_index,
&mut self.p2ms.to_tx_index,
&mut self.unknown.to_tx_index,
]
.into_par_iter()
}
+46 -46
View File
@@ -13,23 +13,23 @@ use crate::parallel_import;
#[derive(Traversable)]
pub struct TransactionsVecs<M: StorageMode = Rw> {
pub first_txindex: M::Stored<PcoVec<Height, TxIndex>>,
pub first_tx_index: M::Stored<PcoVec<Height, TxIndex>>,
pub height: M::Stored<PcoVec<TxIndex, Height>>,
pub txid: M::Stored<BytesVec<TxIndex, Txid>>,
pub txversion: M::Stored<PcoVec<TxIndex, TxVersion>>,
pub rawlocktime: M::Stored<PcoVec<TxIndex, RawLockTime>>,
pub tx_version: M::Stored<PcoVec<TxIndex, TxVersion>>,
pub raw_locktime: M::Stored<PcoVec<TxIndex, RawLockTime>>,
pub base_size: M::Stored<PcoVec<TxIndex, StoredU32>>,
pub total_size: M::Stored<PcoVec<TxIndex, StoredU32>>,
pub is_explicitly_rbf: M::Stored<PcoVec<TxIndex, StoredBool>>,
pub first_txinindex: M::Stored<PcoVec<TxIndex, TxInIndex>>,
pub first_txoutindex: M::Stored<BytesVec<TxIndex, TxOutIndex>>,
pub first_txin_index: M::Stored<PcoVec<TxIndex, TxInIndex>>,
pub first_txout_index: M::Stored<BytesVec<TxIndex, TxOutIndex>>,
}
pub struct TxMetadataVecs<'a> {
pub height: &'a mut PcoVec<TxIndex, Height>,
pub txversion: &'a mut PcoVec<TxIndex, TxVersion>,
pub tx_version: &'a mut PcoVec<TxIndex, TxVersion>,
pub txid: &'a mut BytesVec<TxIndex, Txid>,
pub rawlocktime: &'a mut PcoVec<TxIndex, RawLockTime>,
pub raw_locktime: &'a mut PcoVec<TxIndex, RawLockTime>,
pub base_size: &'a mut PcoVec<TxIndex, StoredU32>,
pub total_size: &'a mut PcoVec<TxIndex, StoredU32>,
pub is_explicitly_rbf: &'a mut PcoVec<TxIndex, StoredBool>,
@@ -44,13 +44,13 @@ impl TransactionsVecs {
TxMetadataVecs<'_>,
) {
(
&mut self.first_txoutindex,
&mut self.first_txinindex,
&mut self.first_txout_index,
&mut self.first_txin_index,
TxMetadataVecs {
height: &mut self.height,
txversion: &mut self.txversion,
tx_version: &mut self.tx_version,
txid: &mut self.txid,
rawlocktime: &mut self.rawlocktime,
raw_locktime: &mut self.raw_locktime,
base_size: &mut self.base_size,
total_size: &mut self.total_size,
is_explicitly_rbf: &mut self.is_explicitly_rbf,
@@ -60,76 +60,76 @@ impl TransactionsVecs {
pub fn forced_import(db: &Database, version: Version) -> Result<Self> {
let (
first_txindex,
first_tx_index,
height,
txid,
txversion,
rawlocktime,
tx_version,
raw_locktime,
base_size,
total_size,
is_explicitly_rbf,
first_txinindex,
first_txoutindex,
first_txin_index,
first_txout_index,
) = parallel_import! {
first_txindex = PcoVec::forced_import(db, "first_txindex", version),
first_tx_index = PcoVec::forced_import(db, "first_tx_index", version),
height = PcoVec::forced_import(db, "height", version),
txid = BytesVec::forced_import(db, "txid", version),
txversion = PcoVec::forced_import(db, "txversion", version),
rawlocktime = PcoVec::forced_import(db, "rawlocktime", version),
tx_version = PcoVec::forced_import(db, "tx_version", version),
raw_locktime = PcoVec::forced_import(db, "raw_locktime", version),
base_size = PcoVec::forced_import(db, "base_size", version),
total_size = PcoVec::forced_import(db, "total_size", version),
is_explicitly_rbf = PcoVec::forced_import(db, "is_explicitly_rbf", version),
first_txinindex = PcoVec::forced_import(db, "first_txinindex", version),
first_txoutindex = BytesVec::forced_import(db, "first_txoutindex", version),
first_txin_index = PcoVec::forced_import(db, "first_txin_index", version),
first_txout_index = BytesVec::forced_import(db, "first_txout_index", version),
};
Ok(Self {
first_txindex,
first_tx_index,
height,
txid,
txversion,
rawlocktime,
tx_version,
raw_locktime,
base_size,
total_size,
is_explicitly_rbf,
first_txinindex,
first_txoutindex,
first_txin_index,
first_txout_index,
})
}
pub fn truncate(&mut self, height: Height, txindex: TxIndex, stamp: Stamp) -> Result<()> {
self.first_txindex
pub fn truncate(&mut self, height: Height, tx_index: TxIndex, stamp: Stamp) -> Result<()> {
self.first_tx_index
.truncate_if_needed_with_stamp(height, stamp)?;
self.height.truncate_if_needed_with_stamp(txindex, stamp)?;
self.txid.truncate_if_needed_with_stamp(txindex, stamp)?;
self.txversion
.truncate_if_needed_with_stamp(txindex, stamp)?;
self.rawlocktime
.truncate_if_needed_with_stamp(txindex, stamp)?;
self.height.truncate_if_needed_with_stamp(tx_index, stamp)?;
self.txid.truncate_if_needed_with_stamp(tx_index, stamp)?;
self.tx_version
.truncate_if_needed_with_stamp(tx_index, stamp)?;
self.raw_locktime
.truncate_if_needed_with_stamp(tx_index, stamp)?;
self.base_size
.truncate_if_needed_with_stamp(txindex, stamp)?;
.truncate_if_needed_with_stamp(tx_index, stamp)?;
self.total_size
.truncate_if_needed_with_stamp(txindex, stamp)?;
.truncate_if_needed_with_stamp(tx_index, stamp)?;
self.is_explicitly_rbf
.truncate_if_needed_with_stamp(txindex, stamp)?;
self.first_txinindex
.truncate_if_needed_with_stamp(txindex, stamp)?;
self.first_txoutindex
.truncate_if_needed_with_stamp(txindex, stamp)?;
.truncate_if_needed_with_stamp(tx_index, stamp)?;
self.first_txin_index
.truncate_if_needed_with_stamp(tx_index, stamp)?;
self.first_txout_index
.truncate_if_needed_with_stamp(tx_index, stamp)?;
Ok(())
}
pub fn par_iter_mut_any(&mut self) -> impl ParallelIterator<Item = &mut dyn AnyStoredVec> {
[
&mut self.first_txindex as &mut dyn AnyStoredVec,
&mut self.first_tx_index as &mut dyn AnyStoredVec,
&mut self.height,
&mut self.txid,
&mut self.txversion,
&mut self.rawlocktime,
&mut self.tx_version,
&mut self.raw_locktime,
&mut self.base_size,
&mut self.total_size,
&mut self.is_explicitly_rbf,
&mut self.first_txinindex,
&mut self.first_txoutindex,
&mut self.first_txin_index,
&mut self.first_txout_index,
]
.into_par_iter()
}
+6 -6
View File
@@ -153,15 +153,15 @@ fn main() {
let total_txs = indexer.vecs.transactions.height.len();
let total_outputs = indexer.vecs.outputs.value.len();
let first_txindex: Vec<TxIndex> = indexer.vecs.transactions.first_txindex.collect();
let out_first: Vec<TxOutIndex> = indexer.vecs.outputs.first_txoutindex.collect();
let first_tx_index: Vec<TxIndex> = indexer.vecs.transactions.first_tx_index.collect();
let out_first: Vec<TxOutIndex> = indexer.vecs.outputs.first_txout_index.collect();
let ref_config = Config::default();
let earliest_start = *start_heights.iter().min().unwrap();
for h in START_HEIGHT..total_heights {
let ft = first_txindex[h];
let next_ft = first_txindex
let ft = first_tx_index[h];
let next_ft = first_tx_index
.get(h + 1)
.copied()
.unwrap_or(TxIndex::from(total_txs));
@@ -170,7 +170,7 @@ fn main() {
indexer
.vecs
.transactions
.first_txoutindex
.first_txout_index
.collect_one(ft + 1)
.unwrap()
.to_usize()
@@ -199,7 +199,7 @@ fn main() {
let output_types: Vec<OutputType> = indexer
.vecs
.outputs
.outputtype
.output_type
.collect_range_at(out_start, out_end);
// Build full histogram and per-digit histograms.
+6 -6
View File
@@ -49,8 +49,8 @@ fn main() {
let total_txs = indexer.vecs.transactions.height.len();
let total_outputs = indexer.vecs.outputs.value.len();
let first_txindex: Vec<TxIndex> = indexer.vecs.transactions.first_txindex.collect();
let out_first: Vec<TxOutIndex> = indexer.vecs.outputs.first_txoutindex.collect();
let first_tx_index: Vec<TxIndex> = indexer.vecs.transactions.first_tx_index.collect();
let out_first: Vec<TxOutIndex> = indexer.vecs.outputs.first_txout_index.collect();
let ref_config = Config::default();
@@ -74,8 +74,8 @@ fn main() {
let end_height = (last_start + window_size + 100).min(total_heights);
for h in START_HEIGHT..end_height {
let ft = first_txindex[h];
let next_ft = first_txindex
let ft = first_tx_index[h];
let next_ft = first_tx_index
.get(h + 1)
.copied()
.unwrap_or(TxIndex::from(total_txs));
@@ -84,7 +84,7 @@ fn main() {
indexer
.vecs
.transactions
.first_txoutindex
.first_txout_index
.collect_one(ft + 1)
.unwrap()
.to_usize()
@@ -109,7 +109,7 @@ fn main() {
let output_types: Vec<OutputType> = indexer
.vecs
.outputs
.outputtype
.output_type
.collect_range_at(out_start, out_end);
let mut hist = [0u32; NUM_BINS];
+12 -12
View File
@@ -94,9 +94,9 @@ fn main() {
let total_txs = indexer.vecs.transactions.height.len();
let total_outputs = indexer.vecs.outputs.value.len();
let first_txoutindex_reader = indexer.vecs.transactions.first_txoutindex.reader();
let first_txout_index_reader = indexer.vecs.transactions.first_txout_index.reader();
let value_reader = indexer.vecs.outputs.value.reader();
let outputtype_reader = indexer.vecs.outputs.outputtype.reader();
let output_type_reader = indexer.vecs.outputs.output_type.reader();
let config = Config::default();
let total_blocks = total_heights - lowest;
@@ -110,28 +110,28 @@ fn main() {
let mut blocks: Vec<BlockData> = Vec::with_capacity(total_blocks);
for h in lowest..total_heights {
let first_txindex: TxIndex = indexer
let first_tx_index: TxIndex = indexer
.vecs
.transactions
.first_txindex
.first_tx_index
.collect_one_at(h)
.unwrap();
let next_first_txindex: TxIndex = indexer
let next_first_tx_index: TxIndex = indexer
.vecs
.transactions
.first_txindex
.first_tx_index
.collect_one_at(h + 1)
.unwrap_or(TxIndex::from(total_txs));
let out_start = if first_txindex.to_usize() + 1 < next_first_txindex.to_usize() {
first_txoutindex_reader
.get(first_txindex.to_usize() + 1)
let out_start = if first_tx_index.to_usize() + 1 < next_first_tx_index.to_usize() {
first_txout_index_reader
.get(first_tx_index.to_usize() + 1)
.to_usize()
} else {
indexer
.vecs
.outputs
.first_txoutindex
.first_txout_index
.collect_one_at(h + 1)
.unwrap_or(TxOutIndex::from(total_outputs))
.to_usize()
@@ -139,7 +139,7 @@ fn main() {
let out_end: usize = indexer
.vecs
.outputs
.first_txoutindex
.first_txout_index
.collect_one_at(h + 1)
.unwrap_or(TxOutIndex::from(total_outputs))
.to_usize();
@@ -147,7 +147,7 @@ fn main() {
let mut hist = Box::new([0u32; NUM_BINS]);
for i in out_start..out_end {
let sats: Sats = value_reader.get(i);
let output_type = outputtype_reader.get(i);
let output_type = output_type_reader.get(i);
if config.excluded_output_types.contains(&output_type) {
continue;
}
+6 -6
View File
@@ -185,8 +185,8 @@ fn main() {
let total_outputs = indexer.vecs.outputs.value.len();
// Pre-collect height-indexed vecs (small). Transaction-indexed vecs are too large.
let first_txindex: Vec<TxIndex> = indexer.vecs.transactions.first_txindex.collect();
let out_first: Vec<TxOutIndex> = indexer.vecs.outputs.first_txoutindex.collect();
let first_tx_index: Vec<TxIndex> = indexer.vecs.transactions.first_tx_index.collect();
let out_first: Vec<TxOutIndex> = indexer.vecs.outputs.first_txout_index.collect();
let ref_config = Config::default();
@@ -200,8 +200,8 @@ fn main() {
let mut current_di: Option<usize> = None;
for h in START_HEIGHT..total_heights {
let ft = first_txindex[h];
let next_ft = first_txindex
let ft = first_tx_index[h];
let next_ft = first_tx_index
.get(h + 1)
.copied()
.unwrap_or(TxIndex::from(total_txs));
@@ -210,7 +210,7 @@ fn main() {
indexer
.vecs
.transactions
.first_txoutindex
.first_txout_index
.collect_one(ft + 1)
.unwrap()
.to_usize()
@@ -235,7 +235,7 @@ fn main() {
let output_types: Vec<OutputType> = indexer
.vecs
.outputs
.outputtype
.output_type
.collect_range_at(out_start, out_end);
let mut hist = [0u32; NUM_BINS];
+6 -6
View File
@@ -166,16 +166,16 @@ fn main() {
let total_txs = indexer.vecs.transactions.height.len();
let total_outputs = indexer.vecs.outputs.value.len();
let first_txindex: Vec<TxIndex> = indexer.vecs.transactions.first_txindex.collect();
let out_first: Vec<TxOutIndex> = indexer.vecs.outputs.first_txoutindex.collect();
let first_tx_index: Vec<TxIndex> = indexer.vecs.transactions.first_tx_index.collect();
let out_first: Vec<TxOutIndex> = indexer.vecs.outputs.first_txout_index.collect();
let ref_config = Config::default();
let total_blocks = total_heights - sweep_start;
let mut blocks: Vec<BlockData> = Vec::with_capacity(total_blocks);
for h in START_HEIGHT..total_heights {
let ft = first_txindex[h];
let next_ft = first_txindex
let ft = first_tx_index[h];
let next_ft = first_tx_index
.get(h + 1)
.copied()
.unwrap_or(TxIndex::from(total_txs));
@@ -184,7 +184,7 @@ fn main() {
indexer
.vecs
.transactions
.first_txoutindex
.first_txout_index
.collect_one(ft + 1)
.unwrap()
.to_usize()
@@ -213,7 +213,7 @@ fn main() {
let output_types: Vec<OutputType> = indexer
.vecs
.outputs
.outputtype
.output_type
.collect_range_at(out_start, out_end);
let mut full_hist = Box::new([0u32; NUM_BINS]);
@@ -164,8 +164,8 @@ fn main() {
let total_txs = indexer.vecs.transactions.height.len();
let total_outputs = indexer.vecs.outputs.value.len();
let first_txindex: Vec<TxIndex> = indexer.vecs.transactions.first_txindex.collect();
let out_first: Vec<TxOutIndex> = indexer.vecs.outputs.first_txoutindex.collect();
let first_tx_index: Vec<TxIndex> = indexer.vecs.transactions.first_tx_index.collect();
let out_first: Vec<TxOutIndex> = indexer.vecs.outputs.first_txout_index.collect();
let ref_config = Config::default();
let total_blocks = total_heights - sweep_start;
@@ -176,8 +176,8 @@ fn main() {
let max_tolerance: f64 = 0.05;
for h in START_HEIGHT..total_heights {
let ft = first_txindex[h];
let next_ft = first_txindex
let ft = first_tx_index[h];
let next_ft = first_tx_index
.get(h + 1)
.copied()
.unwrap_or(TxIndex::from(total_txs));
@@ -186,7 +186,7 @@ fn main() {
indexer
.vecs
.transactions
.first_txoutindex
.first_txout_index
.collect_one(ft + 1)
.unwrap()
.to_usize()
@@ -215,7 +215,7 @@ fn main() {
let output_types: Vec<OutputType> = indexer
.vecs
.outputs
.outputtype
.output_type
.collect_range_at(out_start, out_end);
let mut full_hist = Box::new([0u32; NUM_BINS]);
+6 -6
View File
@@ -152,14 +152,14 @@ fn main() {
let total_outputs = indexer.vecs.outputs.value.len();
// Pre-collect height-indexed vecs (small). Transaction-indexed vecs are too large.
let first_txindex: Vec<TxIndex> = indexer.vecs.transactions.first_txindex.collect();
let out_first: Vec<TxOutIndex> = indexer.vecs.outputs.first_txoutindex.collect();
let first_tx_index: Vec<TxIndex> = indexer.vecs.transactions.first_tx_index.collect();
let out_first: Vec<TxOutIndex> = indexer.vecs.outputs.first_txout_index.collect();
let ref_config = Config::default();
for h in START_HEIGHT..total_heights {
let ft = first_txindex[h];
let next_ft = first_txindex
let ft = first_tx_index[h];
let next_ft = first_tx_index
.get(h + 1)
.copied()
.unwrap_or(TxIndex::from(total_txs));
@@ -168,7 +168,7 @@ fn main() {
indexer
.vecs
.transactions
.first_txoutindex
.first_txout_index
.collect_one(ft + 1)
.unwrap()
.to_usize()
@@ -194,7 +194,7 @@ fn main() {
let output_types: Vec<OutputType> = indexer
.vecs
.outputs
.outputtype
.output_type
.collect_range_at(out_start, out_end);
let mut hist = [0u32; NUM_BINS];
+1 -1
View File
@@ -48,7 +48,7 @@ pub fn main() -> Result<()> {
dbg!(
indexer
.stores
.addresstype_to_addresshash_to_addressindex
.address_type_to_address_hash_to_address_index
.get_unwrap(OutputType::P2WSH)
.approximate_len()
);
+33 -33
View File
@@ -32,16 +32,16 @@ impl Query {
return Err(Error::InvalidAddress);
};
let outputtype = OutputType::from(&script);
let Ok(bytes) = AddressBytes::try_from((&script, outputtype)) else {
let output_type = OutputType::from(&script);
let Ok(bytes) = AddressBytes::try_from((&script, output_type)) else {
return Err(Error::InvalidAddress);
};
let addresstype = outputtype;
let address_type = output_type;
let hash = AddressHash::from(&bytes);
let Ok(Some(type_index)) = stores
.addresstype_to_addresshash_to_addressindex
.get_unwrap(addresstype)
.address_type_to_address_hash_to_address_index
.get_unwrap(address_type)
.get(&hash)
.map(|opt| opt.map(|cow| cow.into_owned()))
else {
@@ -51,7 +51,7 @@ impl Query {
let any_address_index = computer
.distribution
.any_address_indexes
.get_once(outputtype, type_index)?;
.get_once(output_type, type_index)?;
let address_data = match any_address_index.to_enum() {
AnyAddressDataIndexEnum::Funded(index) => computer
@@ -99,7 +99,7 @@ impl Query {
let txindices = self.address_txindices(&address, after_txid, limit)?;
txindices
.into_iter()
.map(|txindex| self.transaction_by_index(txindex))
.map(|tx_index| self.transaction_by_index(tx_index))
.collect()
}
@@ -113,7 +113,7 @@ impl Query {
let txid_reader = self.indexer().vecs.transactions.txid.reader();
let txids = txindices
.into_iter()
.map(|txindex| txid_reader.get(txindex.to_usize()))
.map(|tx_index| txid_reader.get(tx_index.to_usize()))
.collect();
Ok(txids)
}
@@ -127,23 +127,23 @@ impl Query {
let indexer = self.indexer();
let stores = &indexer.stores;
let (outputtype, type_index) = self.resolve_address(address)?;
let (output_type, type_index) = self.resolve_address(address)?;
let store = stores
.addresstype_to_addressindex_and_txindex
.get(outputtype)
.address_type_to_address_index_and_tx_index
.get(output_type)
.unwrap();
let prefix = u32::from(type_index).to_be_bytes();
let after_txindex = if let Some(after_txid) = after_txid {
let txindex = stores
.txidprefix_to_txindex
let after_tx_index = if let Some(after_txid) = after_txid {
let tx_index = stores
.txid_prefix_to_tx_index
.get(&after_txid.into())
.map_err(|_| Error::UnknownTxid)?
.ok_or(Error::UnknownTxid)?
.into_owned();
Some(txindex)
Some(tx_index)
} else {
None
};
@@ -152,14 +152,14 @@ impl Query {
.prefix(prefix)
.rev()
.filter(|(key, _): &(AddressIndexTxIndex, Unit)| {
if let Some(after) = after_txindex {
key.txindex() < after
if let Some(after) = after_tx_index {
key.tx_index() < after
} else {
true
}
})
.take(limit)
.map(|(key, _)| key.txindex())
.map(|(key, _)| key.tx_index())
.collect())
}
@@ -168,37 +168,37 @@ impl Query {
let stores = &indexer.stores;
let vecs = &indexer.vecs;
let (outputtype, type_index) = self.resolve_address(&address)?;
let (output_type, type_index) = self.resolve_address(&address)?;
let store = stores
.addresstype_to_addressindex_and_unspentoutpoint
.get(outputtype)
.address_type_to_address_index_and_unspent_outpoint
.get(output_type)
.unwrap();
let prefix = u32::from(type_index).to_be_bytes();
let outpoints: Vec<(TxIndex, Vout)> = store
.prefix(prefix)
.map(|(key, _): (AddressIndexOutPoint, Unit)| (key.txindex(), key.vout()))
.map(|(key, _): (AddressIndexOutPoint, Unit)| (key.tx_index(), key.vout()))
.collect();
let txid_reader = vecs.transactions.txid.reader();
let first_txoutindex_reader = vecs.transactions.first_txoutindex.reader();
let first_txout_index_reader = vecs.transactions.first_txout_index.reader();
let value_reader = vecs.outputs.value.reader();
let blockhash_reader = vecs.blocks.blockhash.reader();
let utxos: Vec<Utxo> = outpoints
.into_iter()
.map(|(txindex, vout)| {
let txid: Txid = txid_reader.get(txindex.to_usize());
.map(|(tx_index, vout)| {
let txid: Txid = txid_reader.get(tx_index.to_usize());
let height = vecs
.transactions
.height
.collect_one_at(txindex.to_usize())
.collect_one_at(tx_index.to_usize())
.unwrap();
let first_txoutindex = first_txoutindex_reader.get(txindex.to_usize());
let txoutindex = first_txoutindex + vout;
let value: Sats = value_reader.get(usize::from(txoutindex));
let first_txout_index = first_txout_index_reader.get(tx_index.to_usize());
let txout_index = first_txout_index + vout;
let value: Sats = value_reader.get(usize::from(txout_index));
let block_hash = blockhash_reader.get(usize::from(height));
let block_time = vecs
.blocks
@@ -252,12 +252,12 @@ impl Query {
let stores = &self.indexer().stores;
let bytes = AddressBytes::from_str(address)?;
let outputtype = OutputType::from(&bytes);
let output_type = OutputType::from(&bytes);
let hash = AddressHash::from(&bytes);
let Ok(Some(type_index)) = stores
.addresstype_to_addresshash_to_addressindex
.get(outputtype)
.address_type_to_address_hash_to_address_index
.get(output_type)
.unwrap()
.get(&hash)
.map(|opt| opt.map(|cow| cow.into_owned()))
@@ -265,6 +265,6 @@ impl Query {
return Err(Error::UnknownAddress);
};
Ok((outputtype, type_index))
Ok((output_type, type_index))
}
}
+16 -16
View File
@@ -64,28 +64,28 @@ impl Query {
let sizes = indexer.vecs.blocks.total.collect_range_at(begin, end);
let weights = indexer.vecs.blocks.weight.collect_range_at(begin, end);
// Batch-read first_txindex for tx_count computation (need one extra for next boundary)
let txindex_end = if end <= max_height.to_usize() {
// Batch-read first_tx_index for tx_count computation (need one extra for next boundary)
let tx_index_end = if end <= max_height.to_usize() {
end + 1
} else {
end
};
let first_txindexes: Vec<TxIndex> = indexer
let first_tx_indexes: Vec<TxIndex> = indexer
.vecs
.transactions
.first_txindex
.collect_range_at(begin, txindex_end);
let total_txs = computer.indexes.txindex.identity.len();
.first_tx_index
.collect_range_at(begin, tx_index_end);
let total_txs = computer.indexes.tx_index.identity.len();
let mut blocks = Vec::with_capacity(count);
for i in (0..count).rev() {
let height = Height::from(begin + i);
let blockhash = indexer.vecs.blocks.blockhash.read_once(height)?;
let tx_count = if i + 1 < first_txindexes.len() {
first_txindexes[i + 1].to_usize() - first_txindexes[i].to_usize()
let tx_count = if i + 1 < first_tx_indexes.len() {
first_tx_indexes[i + 1].to_usize() - first_tx_indexes[i].to_usize()
} else {
total_txs - first_txindexes[i].to_usize()
total_txs - first_tx_indexes[i].to_usize()
};
blocks.push(BlockInfo {
@@ -111,7 +111,7 @@ impl Query {
indexer
.stores
.blockhashprefix_to_height
.blockhash_prefix_to_height
.get(&prefix)?
.map(|h| *h)
.ok_or(Error::NotFound("Block not found".into()))
@@ -125,23 +125,23 @@ impl Query {
let indexer = self.indexer();
let computer = self.computer();
let first_txindex = indexer
let first_tx_index = indexer
.vecs
.transactions
.first_txindex
.first_tx_index
.collect_one(height)
.unwrap();
let next_first_txindex = if height < max_height {
let next_first_tx_index = if height < max_height {
indexer
.vecs
.transactions
.first_txindex
.first_tx_index
.collect_one(height.incremented())
.unwrap()
} else {
TxIndex::from(computer.indexes.txindex.identity.len())
TxIndex::from(computer.indexes.tx_index.identity.len())
};
Ok((next_first_txindex.to_usize() - first_txindex.to_usize()) as u32)
Ok((next_first_tx_index.to_usize() - first_tx_index.to_usize()) as u32)
}
}
+22 -22
View File
@@ -31,21 +31,21 @@ impl Query {
return Err(Error::OutOfRange("Block height out of range".into()));
}
let first_txindex = indexer
let first_tx_index = indexer
.vecs
.transactions
.first_txindex
.first_tx_index
.collect_one(height)
.unwrap();
let next_first_txindex = indexer
let next_first_tx_index = indexer
.vecs
.transactions
.first_txindex
.first_tx_index
.collect_one(height.incremented())
.unwrap_or_else(|| TxIndex::from(indexer.vecs.transactions.txid.len()));
let first: usize = first_txindex.into();
let next: usize = next_first_txindex.into();
let first: usize = first_tx_index.into();
let next: usize = next_first_tx_index.into();
let txids: Vec<Txid> = indexer.vecs.transactions.txid.collect_range_at(first, next);
@@ -60,21 +60,21 @@ impl Query {
return Err(Error::OutOfRange("Block height out of range".into()));
}
let first_txindex = indexer
let first_tx_index = indexer
.vecs
.transactions
.first_txindex
.first_tx_index
.collect_one(height)
.unwrap();
let next_first_txindex = indexer
let next_first_tx_index = indexer
.vecs
.transactions
.first_txindex
.first_tx_index
.collect_one(height.incremented())
.unwrap_or_else(|| TxIndex::from(indexer.vecs.transactions.txid.len()));
let first: usize = first_txindex.into();
let next: usize = next_first_txindex.into();
let first: usize = first_tx_index.into();
let next: usize = next_first_tx_index.into();
let tx_count = next - first;
if start_index >= tx_count {
@@ -86,8 +86,8 @@ impl Query {
let mut txs = Vec::with_capacity(count);
for i in start_index..end_index {
let txindex = TxIndex::from(first + i);
let tx = self.transaction_by_index(txindex)?;
let tx_index = TxIndex::from(first + i);
let tx = self.transaction_by_index(tx_index)?;
txs.push(tx);
}
@@ -102,29 +102,29 @@ impl Query {
return Err(Error::OutOfRange("Block height out of range".into()));
}
let first_txindex = indexer
let first_tx_index = indexer
.vecs
.transactions
.first_txindex
.first_tx_index
.collect_one(height)
.unwrap();
let next_first_txindex = indexer
let next_first_tx_index = indexer
.vecs
.transactions
.first_txindex
.first_tx_index
.collect_one(height.incremented())
.unwrap_or_else(|| TxIndex::from(indexer.vecs.transactions.txid.len()));
let first: usize = first_txindex.into();
let next: usize = next_first_txindex.into();
let first: usize = first_tx_index.into();
let next: usize = next_first_tx_index.into();
let tx_count = next - first;
if index >= tx_count {
return Err(Error::OutOfRange("Transaction index out of range".into()));
}
let txindex = first + index;
let txid = indexer.vecs.transactions.txid.reader().get(txindex);
let tx_index = first + index;
let txid = indexer.vecs.transactions.txid.reader().get(tx_index);
Ok(txid)
}
@@ -1,8 +1,8 @@
// TODO: INCOMPLETE - indexes_to_fee_rate.day1 doesn't have percentile fields
// because from_txindex.rs calls remove_percentiles() before creating day1.
// because from_tx_index.rs calls remove_percentiles() before creating day1.
// Need to either:
// 1. Use .height instead and convert height to day1 for iteration
// 2. Fix from_txindex.rs to preserve percentiles for day1
// 2. Fix from_tx_index.rs to preserve percentiles for day1
// 3. Create a separate day1 computation path with percentiles
#![allow(dead_code)]
+74 -74
View File
@@ -22,16 +22,16 @@ impl Query {
// Look up confirmed transaction by txid prefix
let prefix = TxidPrefix::from(&txid);
let indexer = self.indexer();
let Ok(Some(txindex)) = indexer
let Ok(Some(tx_index)) = indexer
.stores
.txidprefix_to_txindex
.txid_prefix_to_tx_index
.get(&prefix)
.map(|opt| opt.map(|cow| cow.into_owned()))
else {
return Err(Error::UnknownTxid);
};
self.transaction_by_index(txindex)
self.transaction_by_index(tx_index)
}
pub fn transaction_status(&self, TxidParam { txid }: TxidParam) -> Result<TxStatus> {
@@ -45,9 +45,9 @@ impl Query {
// Look up confirmed transaction by txid prefix
let prefix = TxidPrefix::from(&txid);
let indexer = self.indexer();
let Ok(Some(txindex)) = indexer
let Ok(Some(tx_index)) = indexer
.stores
.txidprefix_to_txindex
.txid_prefix_to_tx_index
.get(&prefix)
.map(|opt| opt.map(|cow| cow.into_owned()))
else {
@@ -59,7 +59,7 @@ impl Query {
.vecs
.transactions
.height
.collect_one(txindex)
.collect_one(tx_index)
.unwrap();
let block_hash = indexer.vecs.blocks.blockhash.read_once(height)?;
let block_time = indexer.vecs.blocks.timestamp.collect_one(height).unwrap();
@@ -83,16 +83,16 @@ impl Query {
// Look up confirmed transaction by txid prefix
let prefix = TxidPrefix::from(&txid);
let indexer = self.indexer();
let Ok(Some(txindex)) = indexer
let Ok(Some(tx_index)) = indexer
.stores
.txidprefix_to_txindex
.txid_prefix_to_tx_index
.get(&prefix)
.map(|opt| opt.map(|cow| cow.into_owned()))
else {
return Err(Error::UnknownTxid);
};
self.transaction_hex_by_index(txindex)
self.transaction_hex_by_index(tx_index)
}
pub fn outspend(&self, TxidParam { txid }: TxidParam, vout: Vout) -> Result<TxOutspend> {
@@ -106,32 +106,32 @@ impl Query {
// Look up confirmed transaction
let prefix = TxidPrefix::from(&txid);
let indexer = self.indexer();
let Ok(Some(txindex)) = indexer
let Ok(Some(tx_index)) = indexer
.stores
.txidprefix_to_txindex
.txid_prefix_to_tx_index
.get(&prefix)
.map(|opt| opt.map(|cow| cow.into_owned()))
else {
return Err(Error::UnknownTxid);
};
// Calculate txoutindex
let first_txoutindex = indexer
// Calculate txout_index
let first_txout_index = indexer
.vecs
.transactions
.first_txoutindex
.read_once(txindex)?;
let txoutindex = first_txoutindex + vout;
.first_txout_index
.read_once(tx_index)?;
let txout_index = first_txout_index + vout;
// Look up spend status
let computer = self.computer();
let txinindex = computer.outputs.spent.txinindex.read_once(txoutindex)?;
let txin_index = computer.outputs.spent.txin_index.read_once(txout_index)?;
if txinindex == TxInIndex::UNSPENT {
if txin_index == TxInIndex::UNSPENT {
return Ok(TxOutspend::UNSPENT);
}
self.outspend_details(txinindex)
self.outspend_details(txin_index)
}
pub fn outspends(&self, TxidParam { txid }: TxidParam) -> Result<Vec<TxOutspend>> {
@@ -146,9 +146,9 @@ impl Query {
// Look up confirmed transaction
let prefix = TxidPrefix::from(&txid);
let indexer = self.indexer();
let Ok(Some(txindex)) = indexer
let Ok(Some(tx_index)) = indexer
.stores
.txidprefix_to_txindex
.txid_prefix_to_tx_index
.get(&prefix)
.map(|opt| opt.map(|cow| cow.into_owned()))
else {
@@ -156,31 +156,31 @@ impl Query {
};
// Get output range
let first_txoutindex = indexer
let first_txout_index = indexer
.vecs
.transactions
.first_txoutindex
.read_once(txindex)?;
let next_first_txoutindex = indexer
.first_txout_index
.read_once(tx_index)?;
let next_first_txout_index = indexer
.vecs
.transactions
.first_txoutindex
.read_once(txindex.incremented())?;
let output_count = usize::from(next_first_txoutindex) - usize::from(first_txoutindex);
.first_txout_index
.read_once(tx_index.incremented())?;
let output_count = usize::from(next_first_txout_index) - usize::from(first_txout_index);
// Get spend status for each output
let computer = self.computer();
let txinindex_reader = computer.outputs.spent.txinindex.reader();
let txin_index_reader = computer.outputs.spent.txin_index.reader();
let mut outspends = Vec::with_capacity(output_count);
for i in 0..output_count {
let txoutindex = first_txoutindex + Vout::from(i);
let txinindex = txinindex_reader.get(usize::from(txoutindex));
let txout_index = first_txout_index + Vout::from(i);
let txin_index = txin_index_reader.get(usize::from(txout_index));
if txinindex == TxInIndex::UNSPENT {
if txin_index == TxInIndex::UNSPENT {
outspends.push(TxOutspend::UNSPENT);
} else {
outspends.push(self.outspend_details(txinindex)?);
outspends.push(self.outspend_details(txin_index)?);
}
}
@@ -189,44 +189,44 @@ impl Query {
// === Helper methods ===
pub fn transaction_by_index(&self, txindex: TxIndex) -> Result<Transaction> {
pub fn transaction_by_index(&self, tx_index: TxIndex) -> Result<Transaction> {
let indexer = self.indexer();
let reader = self.reader();
let computer = self.computer();
// Get tx metadata using collect_one for PcoVec, read_once for BytesVec
let txid = indexer.vecs.transactions.txid.read_once(txindex)?;
let txid = indexer.vecs.transactions.txid.read_once(tx_index)?;
let height = indexer
.vecs
.transactions
.height
.collect_one(txindex)
.collect_one(tx_index)
.unwrap();
let version = indexer
.vecs
.transactions
.txversion
.collect_one(txindex)
.tx_version
.collect_one(tx_index)
.unwrap();
let lock_time = indexer
.vecs
.transactions
.rawlocktime
.collect_one(txindex)
.raw_locktime
.collect_one(tx_index)
.unwrap();
let total_size = indexer
.vecs
.transactions
.total_size
.collect_one(txindex)
.collect_one(tx_index)
.unwrap();
let first_txinindex = indexer
let first_txin_index = indexer
.vecs
.transactions
.first_txinindex
.collect_one(txindex)
.first_txin_index
.collect_one(tx_index)
.unwrap();
let position = computer.positions.tx.collect_one(txindex).unwrap();
let position = computer.positions.tx.collect_one(tx_index).unwrap();
// Get block info for status
let block_hash = indexer.vecs.blocks.blockhash.read_once(height)?;
@@ -240,16 +240,16 @@ impl Query {
// Create readers for random access lookups
let txid_reader = indexer.vecs.transactions.txid.reader();
let first_txoutindex_reader = indexer.vecs.transactions.first_txoutindex.reader();
let first_txout_index_reader = indexer.vecs.transactions.first_txout_index.reader();
let value_reader = indexer.vecs.outputs.value.reader();
let outputtype_reader = indexer.vecs.outputs.outputtype.reader();
let typeindex_reader = indexer.vecs.outputs.typeindex.reader();
let output_type_reader = indexer.vecs.outputs.output_type.reader();
let type_index_reader = indexer.vecs.outputs.type_index.reader();
let address_readers = indexer.vecs.addresses.address_readers();
// Batch-read outpoints for all inputs (avoids per-input PcoVec page decompression)
let outpoints: Vec<_> = indexer.vecs.inputs.outpoint.collect_range_at(
usize::from(first_txinindex),
usize::from(first_txinindex) + tx.input.len(),
usize::from(first_txin_index),
usize::from(first_txin_index) + tx.input.len(),
);
// Build inputs with prevout information
@@ -266,21 +266,21 @@ impl Query {
let (prev_txid, prev_vout, prevout) = if is_coinbase {
(Txid::COINBASE, Vout::MAX, None)
} else {
let prev_txindex = outpoint.txindex();
let prev_tx_index = outpoint.tx_index();
let prev_vout = outpoint.vout();
let prev_txid = txid_reader.get(prev_txindex.to_usize());
let prev_txid = txid_reader.get(prev_tx_index.to_usize());
// Calculate the txoutindex for the prevout
let prev_first_txoutindex =
first_txoutindex_reader.get(prev_txindex.to_usize());
let prev_txoutindex = prev_first_txoutindex + prev_vout;
// Calculate the txout_index for the prevout
let prev_first_txout_index =
first_txout_index_reader.get(prev_tx_index.to_usize());
let prev_txout_index = prev_first_txout_index + prev_vout;
let prev_value = value_reader.get(usize::from(prev_txoutindex));
let prev_outputtype: OutputType =
outputtype_reader.get(usize::from(prev_txoutindex));
let prev_typeindex = typeindex_reader.get(usize::from(prev_txoutindex));
let prev_value = value_reader.get(usize::from(prev_txout_index));
let prev_output_type: OutputType =
output_type_reader.get(usize::from(prev_txout_index));
let prev_type_index = type_index_reader.get(usize::from(prev_txout_index));
let script_pubkey =
address_readers.script_pubkey(prev_outputtype, prev_typeindex);
address_readers.script_pubkey(prev_output_type, prev_type_index);
let prevout = Some(TxOut::from((script_pubkey, prev_value)));
@@ -318,7 +318,7 @@ impl Query {
};
let mut transaction = Transaction {
index: Some(txindex),
index: Some(tx_index),
txid,
version,
lock_time,
@@ -337,7 +337,7 @@ impl Query {
Ok(transaction)
}
fn transaction_hex_by_index(&self, txindex: TxIndex) -> Result<String> {
fn transaction_hex_by_index(&self, tx_index: TxIndex) -> Result<String> {
let indexer = self.indexer();
let reader = self.reader();
let computer = self.computer();
@@ -346,37 +346,37 @@ impl Query {
.vecs
.transactions
.total_size
.collect_one(txindex)
.collect_one(tx_index)
.unwrap();
let position = computer.positions.tx.collect_one(txindex).unwrap();
let position = computer.positions.tx.collect_one(tx_index).unwrap();
let buffer = reader.read_raw_bytes(position, *total_size as usize)?;
Ok(buffer.to_lower_hex_string())
}
fn outspend_details(&self, txinindex: TxInIndex) -> Result<TxOutspend> {
fn outspend_details(&self, txin_index: TxInIndex) -> Result<TxOutspend> {
let indexer = self.indexer();
// Look up spending txindex directly
let spending_txindex = indexer.vecs.inputs.txindex.collect_one(txinindex).unwrap();
// Look up spending tx_index directly
let spending_tx_index = indexer.vecs.inputs.tx_index.collect_one(txin_index).unwrap();
// Calculate vin
let spending_first_txinindex = indexer
let spending_first_txin_index = indexer
.vecs
.transactions
.first_txinindex
.collect_one(spending_txindex)
.first_txin_index
.collect_one(spending_tx_index)
.unwrap();
let vin = Vin::from(usize::from(txinindex) - usize::from(spending_first_txinindex));
let vin = Vin::from(usize::from(txin_index) - usize::from(spending_first_txin_index));
// Get spending tx details
let spending_txid = indexer.vecs.transactions.txid.read_once(spending_txindex)?;
let spending_txid = indexer.vecs.transactions.txid.read_once(spending_tx_index)?;
let spending_height = indexer
.vecs
.transactions
.height
.collect_one(spending_txindex)
.collect_one(spending_tx_index)
.unwrap();
let block_hash = indexer.vecs.blocks.blockhash.read_once(spending_height)?;
let block_time = indexer
+4 -4
View File
@@ -42,14 +42,14 @@ impl TryFrom<&ScriptBuf> for Address {
impl TryFrom<(&ScriptBuf, OutputType)> for Address {
type Error = Error;
fn try_from((script, outputtype): (&ScriptBuf, OutputType)) -> Result<Self, Self::Error> {
match outputtype {
fn try_from((script, output_type): (&ScriptBuf, OutputType)) -> Result<Self, Self::Error> {
match output_type {
OutputType::P2PK65 | OutputType::P2PK33 => {
// P2PK has no standard address encoding, use raw pubkey hex
let bytes = AddressBytes::try_from((script, outputtype))?;
let bytes = AddressBytes::try_from((script, output_type))?;
Ok(Self(bytes_to_hex(bytes.as_slice())))
}
_ if outputtype.is_address() => {
_ if output_type.is_address() => {
let addr = bitcoin::Address::from_script(script, bitcoin::Network::Bitcoin)
.map_err(|_| Error::InvalidAddress)?;
Ok(Self(addr.to_string()))
+4 -4
View File
@@ -79,9 +79,9 @@ impl TryFrom<&ScriptBuf> for AddressBytes {
impl TryFrom<(&ScriptBuf, OutputType)> for AddressBytes {
type Error = Error;
fn try_from(tuple: (&ScriptBuf, OutputType)) -> Result<Self, Self::Error> {
let (script, outputtype) = tuple;
let (script, output_type) = tuple;
match outputtype {
match output_type {
OutputType::P2PK65 => {
let bytes = script.as_bytes();
let bytes = match bytes.len() {
@@ -219,7 +219,7 @@ impl FromStr for AddressBytes {
fn from_str(s: &str) -> Result<Self, Self::Err> {
let script = Self::address_to_script(s)?;
let outputtype = OutputType::from(&script);
Self::try_from((&script, outputtype))
let output_type = OutputType::from(&script);
Self::try_from((&script, output_type))
}
}
@@ -11,14 +11,14 @@ use super::{OutPoint, TxIndex, TypeIndex};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Serialize)]
#[repr(C)]
pub struct AddressIndexOutPoint {
addressindextxindex: AddressIndexTxIndex, // u64
address_index_tx_index: AddressIndexTxIndex, // u64
vout: Vout, // u16
}
impl AddressIndexOutPoint {
#[inline]
pub fn txindex(&self) -> TxIndex {
self.addressindextxindex.txindex()
pub fn tx_index(&self) -> TxIndex {
self.address_index_tx_index.tx_index()
}
#[inline]
@@ -30,7 +30,7 @@ impl AddressIndexOutPoint {
impl Hash for AddressIndexOutPoint {
fn hash<H: Hasher>(&self, state: &mut H) {
let mut buf = [0u8; 10];
buf[0..8].copy_from_slice(&self.addressindextxindex.to_bytes());
buf[0..8].copy_from_slice(&self.address_index_tx_index.to_bytes());
buf[8..].copy_from_slice(&self.vout.to_bytes());
state.write(&buf);
}
@@ -38,9 +38,9 @@ impl Hash for AddressIndexOutPoint {
impl From<(TypeIndex, OutPoint)> for AddressIndexOutPoint {
#[inline]
fn from((addressindex, outpoint): (TypeIndex, OutPoint)) -> Self {
fn from((address_index, outpoint): (TypeIndex, OutPoint)) -> Self {
Self {
addressindextxindex: AddressIndexTxIndex::from((addressindex, outpoint.txindex())),
address_index_tx_index: AddressIndexTxIndex::from((address_index, outpoint.tx_index())),
vout: outpoint.vout(),
}
}
@@ -50,7 +50,7 @@ impl From<ByteView> for AddressIndexOutPoint {
#[inline]
fn from(value: ByteView) -> Self {
Self {
addressindextxindex: AddressIndexTxIndex::from(ByteView::new(&value[..8])),
address_index_tx_index: AddressIndexTxIndex::from(ByteView::new(&value[..8])),
vout: Vout::from(u16::from_be_bytes([value[8], value[9]])),
}
}
@@ -67,7 +67,7 @@ impl From<&AddressIndexOutPoint> for ByteView {
fn from(value: &AddressIndexOutPoint) -> Self {
ByteView::from(
[
&ByteView::from(value.addressindextxindex),
&ByteView::from(value.address_index_tx_index),
value.vout.to_be_bytes().as_slice(),
]
.concat(),
@@ -10,27 +10,27 @@ use super::{TxIndex, TypeIndex};
pub struct AddressIndexTxIndex(u64);
impl AddressIndexTxIndex {
pub fn addressindex(&self) -> u32 {
pub fn address_index(&self) -> u32 {
(self.0 >> 32) as u32
}
pub fn txindex(&self) -> TxIndex {
pub fn tx_index(&self) -> TxIndex {
TxIndex::from(self.0 as u32)
}
pub fn min_for_address(addressindex: TypeIndex) -> Self {
Self(u64::from(addressindex) << 32)
pub fn min_for_address(address_index: TypeIndex) -> Self {
Self(u64::from(address_index) << 32)
}
pub fn max_for_address(addressindex: TypeIndex) -> Self {
Self((u64::from(addressindex) << 32) | u64::MAX >> 32)
pub fn max_for_address(address_index: TypeIndex) -> Self {
Self((u64::from(address_index) << 32) | u64::MAX >> 32)
}
}
impl From<(TypeIndex, TxIndex)> for AddressIndexTxIndex {
#[inline]
fn from((addressindex, txindex): (TypeIndex, TxIndex)) -> Self {
Self((u64::from(addressindex) << 32) | u64::from(txindex))
fn from((address_index, tx_index): (TypeIndex, TxIndex)) -> Self {
Self((u64::from(address_index) << 32) | u64::from(tx_index))
}
}
+2 -2
View File
@@ -66,11 +66,11 @@ impl CheckedSub<EmptyAddressIndex> for EmptyAddressIndex {
impl PrintableIndex for EmptyAddressIndex {
fn to_string() -> &'static str {
"emptyaddressindex"
"empty_address_index"
}
fn to_possible_strings() -> &'static [&'static str] {
&["emptyaddr", "emptyaddressindex"]
&["emptyaddr", "empty_address_index"]
}
}
+2 -2
View File
@@ -63,11 +63,11 @@ impl CheckedSub<EmptyOutputIndex> for EmptyOutputIndex {
impl PrintableIndex for EmptyOutputIndex {
fn to_string() -> &'static str {
"emptyoutputindex"
"empty_output_index"
}
fn to_possible_strings() -> &'static [&'static str] {
&["emptyout", "emptyoutputindex"]
&["emptyout", "empty_output_index"]
}
}
+2 -2
View File
@@ -62,11 +62,11 @@ impl CheckedSub<FundedAddressIndex> for FundedAddressIndex {
}
impl PrintableIndex for FundedAddressIndex {
fn to_string() -> &'static str {
"fundedaddressindex"
"funded_address_index"
}
fn to_possible_strings() -> &'static [&'static str] {
&["fundedaddr", "fundedaddressindex"]
&["fundedaddr", "funded_address_index"]
}
}
+3 -3
View File
@@ -18,7 +18,7 @@ use super::{
};
/// Aggregation dimension for querying metrics. Includes time-based (date, week, month, year),
/// block-based (height, txindex), and address/output type indexes.
/// block-based (height, tx_index), and address/output type indexes.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, JsonSchema)]
#[serde(rename_all = "lowercase")]
#[schemars(example = Index::Day1)]
@@ -347,7 +347,7 @@ mod tests {
}
#[test]
fn test_is_not_date_based_txindex() {
fn test_is_not_date_based_tx_index() {
assert!(!Index::TxIndex.is_date_based());
}
@@ -405,7 +405,7 @@ mod tests {
}
#[test]
fn test_index_to_date_txindex_returns_none() {
fn test_index_to_date_tx_index_returns_none() {
assert!(Index::TxIndex.index_to_date(100).is_none());
}
+39 -39
View File
@@ -9,55 +9,55 @@ use crate::{
/// Used by brk_indexer during block processing.
#[derive(Debug, Default, Clone)]
pub struct Indexes {
pub emptyoutputindex: EmptyOutputIndex,
pub empty_output_index: EmptyOutputIndex,
pub height: Height,
pub opreturnindex: OpReturnIndex,
pub p2msoutputindex: P2MSOutputIndex,
pub p2pk33addressindex: P2PK33AddressIndex,
pub p2pk65addressindex: P2PK65AddressIndex,
pub p2pkhaddressindex: P2PKHAddressIndex,
pub p2shaddressindex: P2SHAddressIndex,
pub p2traddressindex: P2TRAddressIndex,
pub p2wpkhaddressindex: P2WPKHAddressIndex,
pub p2wshaddressindex: P2WSHAddressIndex,
pub p2aaddressindex: P2AAddressIndex,
pub txindex: TxIndex,
pub txinindex: TxInIndex,
pub txoutindex: TxOutIndex,
pub unknownoutputindex: UnknownOutputIndex,
pub op_return_index: OpReturnIndex,
pub p2ms_output_index: P2MSOutputIndex,
pub p2pk33_address_index: P2PK33AddressIndex,
pub p2pk65_address_index: P2PK65AddressIndex,
pub p2pkh_address_index: P2PKHAddressIndex,
pub p2sh_address_index: P2SHAddressIndex,
pub p2tr_address_index: P2TRAddressIndex,
pub p2wpkh_address_index: P2WPKHAddressIndex,
pub p2wsh_address_index: P2WSHAddressIndex,
pub p2a_address_index: P2AAddressIndex,
pub tx_index: TxIndex,
pub txin_index: TxInIndex,
pub txout_index: TxOutIndex,
pub unknown_output_index: UnknownOutputIndex,
}
impl Indexes {
pub fn to_typeindex(&self, outputtype: OutputType) -> TypeIndex {
match outputtype {
OutputType::Empty => *self.emptyoutputindex,
OutputType::OpReturn => *self.opreturnindex,
OutputType::P2A => *self.p2aaddressindex,
OutputType::P2MS => *self.p2msoutputindex,
OutputType::P2PK33 => *self.p2pk33addressindex,
OutputType::P2PK65 => *self.p2pk65addressindex,
OutputType::P2PKH => *self.p2pkhaddressindex,
OutputType::P2SH => *self.p2shaddressindex,
OutputType::P2TR => *self.p2traddressindex,
OutputType::P2WPKH => *self.p2wpkhaddressindex,
OutputType::P2WSH => *self.p2wshaddressindex,
OutputType::Unknown => *self.unknownoutputindex,
pub fn to_type_index(&self, output_type: OutputType) -> TypeIndex {
match output_type {
OutputType::Empty => *self.empty_output_index,
OutputType::OpReturn => *self.op_return_index,
OutputType::P2A => *self.p2a_address_index,
OutputType::P2MS => *self.p2ms_output_index,
OutputType::P2PK33 => *self.p2pk33_address_index,
OutputType::P2PK65 => *self.p2pk65_address_index,
OutputType::P2PKH => *self.p2pkh_address_index,
OutputType::P2SH => *self.p2sh_address_index,
OutputType::P2TR => *self.p2tr_address_index,
OutputType::P2WPKH => *self.p2wpkh_address_index,
OutputType::P2WSH => *self.p2wsh_address_index,
OutputType::Unknown => *self.unknown_output_index,
}
}
/// Increments the address index for the given address type and returns the previous value.
/// Only call this for address types (P2PK65, P2PK33, P2PKH, P2SH, P2WPKH, P2WSH, P2TR, P2A).
#[inline]
pub fn increment_address_index(&mut self, addresstype: OutputType) -> TypeIndex {
match addresstype {
OutputType::P2PK65 => self.p2pk65addressindex.copy_then_increment(),
OutputType::P2PK33 => self.p2pk33addressindex.copy_then_increment(),
OutputType::P2PKH => self.p2pkhaddressindex.copy_then_increment(),
OutputType::P2SH => self.p2shaddressindex.copy_then_increment(),
OutputType::P2WPKH => self.p2wpkhaddressindex.copy_then_increment(),
OutputType::P2WSH => self.p2wshaddressindex.copy_then_increment(),
OutputType::P2TR => self.p2traddressindex.copy_then_increment(),
OutputType::P2A => self.p2aaddressindex.copy_then_increment(),
pub fn increment_address_index(&mut self, address_type: OutputType) -> TypeIndex {
match address_type {
OutputType::P2PK65 => self.p2pk65_address_index.copy_then_increment(),
OutputType::P2PK33 => self.p2pk33_address_index.copy_then_increment(),
OutputType::P2PKH => self.p2pkh_address_index.copy_then_increment(),
OutputType::P2SH => self.p2sh_address_index.copy_then_increment(),
OutputType::P2WPKH => self.p2wpkh_address_index.copy_then_increment(),
OutputType::P2WSH => self.p2wsh_address_index.copy_then_increment(),
OutputType::P2TR => self.p2tr_address_index.copy_then_increment(),
OutputType::P2A => self.p2a_address_index.copy_then_increment(),
_ => unreachable!(),
}
}
+216 -216
View File
@@ -3,41 +3,41 @@
pub use vecdb::{CheckedSub, Exit, PrintableIndex, Version};
mod address;
mod addressbytes;
mod addresschainstats;
mod addresshash;
mod addressindexoutpoint;
mod addressindextxindex;
mod addressmempoolstats;
mod addressparam;
mod addressstats;
mod addresstxidsparam;
mod addressvalidation;
mod address_bytes;
mod address_chain_stats;
mod address_hash;
mod address_index_outpoint;
mod address_index_tx_index;
mod address_mempool_stats;
mod address_param;
mod address_stats;
mod address_txids_param;
mod address_validation;
mod age;
mod anyaddressindex;
mod any_address_index;
mod basis_points_16;
mod basis_points_32;
mod basis_points_signed_16;
mod basis_points_signed_32;
mod bitcoin;
mod blkmetadata;
mod blkposition;
mod blk_metadata;
mod blk_position;
mod block;
mod blockcountparam;
mod blockfeesentry;
mod blockferatesentry;
mod block_count_param;
mod block_fees_entry;
mod block_fee_rates_entry;
mod blockhash;
mod blockhashparam;
mod blockhashprefix;
mod blockhashstartindex;
mod blockhashtxindex;
mod blockinfo;
mod blockrewardsentry;
mod blocksizeentry;
mod blocksizesweights;
mod blockstatus;
mod blocktimestamp;
mod blockweightentry;
mod blockhash_param;
mod blockhash_prefix;
mod blockhash_start_index;
mod blockhash_tx_index;
mod block_info;
mod block_rewards_entry;
mod block_size_entry;
mod block_sizes_weights;
mod block_status;
mod block_timestamp;
mod block_weight_entry;
mod bytes;
mod cents;
mod cents_compact;
@@ -48,109 +48,109 @@ mod cost_basis_bucket;
mod cost_basis_distribution;
mod cost_basis_params;
mod cost_basis_value;
mod datarange;
mod datarangeformat;
mod data_range;
mod data_range_format;
mod date;
mod day1;
mod day3;
mod deser;
mod difficultyadjustment;
mod difficultyadjustmententry;
mod difficultyentry;
mod diskusage;
mod difficulty_adjustment;
mod difficulty_adjustment_entry;
mod difficulty_entry;
mod disk_usage;
mod dollars;
mod emptyaddressdata;
mod emptyaddressindex;
mod emptyoutputindex;
mod empty_address_data;
mod empty_address_index;
mod empty_output_index;
mod epoch;
mod etag;
mod feerate;
mod feeratepercentiles;
mod feerate_percentiles;
mod format;
mod formatresponse;
mod format_response;
mod from_coarser;
mod fundedaddressdata;
mod fundedaddressindex;
mod funded_address_data;
mod funded_address_index;
mod halving;
mod hashrateentry;
mod hashratesummary;
mod hashrate_entry;
mod hashrate_summary;
mod health;
mod height;
mod heightparam;
mod height_param;
mod hex;
mod hour1;
mod hour12;
mod hour4;
mod index;
mod indexes;
mod indexinfo;
mod index_info;
mod limit;
mod limitparam;
mod mempoolblock;
mod mempoolentryinfo;
mod mempoolinfo;
mod limit_param;
mod mempool_block;
mod mempool_entry_info;
mod mempool_info;
mod metric;
mod metriccount;
mod metricdata;
mod metricinfo;
mod metricoutput;
mod metricparam;
mod metric_count;
mod metric_data;
mod metric_info;
mod metric_output;
mod metric_param;
mod metrics;
mod metricselection;
mod metricselectionlegacy;
mod metricspaginated;
mod metricwithindex;
mod metric_selection;
mod metric_selection_legacy;
mod metrics_paginated;
mod metric_with_index;
mod minute10;
mod minute30;
mod month1;
mod month3;
mod month6;
mod ohlc;
mod opreturnindex;
mod op_return_index;
mod option_ext;
mod oracle_bins;
mod outpoint;
mod output;
mod outputtype;
mod p2aaddressindex;
mod p2abytes;
mod p2msoutputindex;
mod p2pk33addressindex;
mod p2pk33bytes;
mod p2pk65addressindex;
mod p2pk65bytes;
mod p2pkhaddressindex;
mod p2pkhbytes;
mod p2shaddressindex;
mod p2shbytes;
mod p2traddressindex;
mod p2trbytes;
mod p2wpkhaddressindex;
mod p2wpkhbytes;
mod p2wshaddressindex;
mod p2wshbytes;
mod output_type;
mod p2a_address_index;
mod p2a_bytes;
mod p2ms_output_index;
mod p2pk33_address_index;
mod p2pk33_bytes;
mod p2pk65_address_index;
mod p2pk65_bytes;
mod p2pkh_address_index;
mod p2pkh_bytes;
mod p2sh_address_index;
mod p2sh_bytes;
mod p2tr_address_index;
mod p2tr_bytes;
mod p2wpkh_address_index;
mod p2wpkh_bytes;
mod p2wsh_address_index;
mod p2wsh_bytes;
mod pagination;
mod paginationindex;
mod pairoutputindex;
mod pagination_index;
mod pair_output_index;
mod percentile;
mod pool;
mod pooldetail;
mod poolinfo;
mod pool_detail;
mod pool_info;
mod pools;
mod poolslug;
mod poolslugparam;
mod poolssummary;
mod poolstats;
mod pool_slug;
mod pool_slug_param;
mod pools_summary;
mod pool_stats;
mod port;
mod range_map;
mod rangeindex;
mod rawlocktime;
mod recommendedfees;
mod rewardstats;
mod range_index;
mod raw_locktime;
mod recommended_fees;
mod reward_stats;
mod sats;
mod sats_signed;
mod satsfract;
mod searchquery;
mod sats_fract;
mod search_query;
mod stored_bool;
mod stored_f32;
mod stored_f64;
@@ -163,32 +163,32 @@ mod stored_u32;
mod stored_u64;
mod stored_u8;
mod supply_state;
mod syncstatus;
mod sync_status;
mod term;
mod timeperiod;
mod timeperiodparam;
mod time_period;
mod time_period_param;
mod timestamp;
mod timestampparam;
mod treenode;
mod timestamp_param;
mod tree_node;
mod tx;
mod txid;
mod txidparam;
mod txidprefix;
mod txidvout;
mod txid_param;
mod txid_prefix;
mod txid_vout;
mod txin;
mod txindex;
mod txinindex;
mod tx_index;
mod txin_index;
mod txout;
mod txoutindex;
mod txoutspend;
mod txstatus;
mod txversion;
mod txwithhex;
mod typeindex;
mod txout_index;
mod txout_spend;
mod tx_status;
mod tx_version;
mod tx_with_hex;
mod type_index;
mod unit;
mod unknownoutputindex;
mod unknown_output_index;
mod utxo;
mod validateaddressparam;
mod validate_address_param;
mod vin;
mod vout;
mod vsize;
@@ -199,41 +199,41 @@ mod year1;
mod year10;
pub use address::*;
pub use addressbytes::*;
pub use addresschainstats::*;
pub use addresshash::*;
pub use addressindexoutpoint::*;
pub use addressindextxindex::*;
pub use addressmempoolstats::*;
pub use addressparam::*;
pub use addressstats::*;
pub use addresstxidsparam::*;
pub use addressvalidation::*;
pub use address_bytes::*;
pub use address_chain_stats::*;
pub use address_hash::*;
pub use address_index_outpoint::*;
pub use address_index_tx_index::*;
pub use address_mempool_stats::*;
pub use address_param::*;
pub use address_stats::*;
pub use address_txids_param::*;
pub use address_validation::*;
pub use age::*;
pub use anyaddressindex::*;
pub use any_address_index::*;
pub use basis_points_16::*;
pub use basis_points_32::*;
pub use basis_points_signed_16::*;
pub use basis_points_signed_32::*;
pub use bitcoin::*;
pub use blkmetadata::*;
pub use blkposition::*;
pub use blk_metadata::*;
pub use blk_position::*;
pub use block::*;
pub use blockcountparam::*;
pub use blockfeesentry::*;
pub use blockferatesentry::*;
pub use block_count_param::*;
pub use block_fees_entry::*;
pub use block_fee_rates_entry::*;
pub use blockhash::*;
pub use blockhashparam::*;
pub use blockhashprefix::*;
pub use blockhashstartindex::*;
pub use blockhashtxindex::*;
pub use blockinfo::*;
pub use blockrewardsentry::*;
pub use blocksizeentry::*;
pub use blocksizesweights::*;
pub use blockstatus::*;
pub use blocktimestamp::*;
pub use blockweightentry::*;
pub use blockhash_param::*;
pub use blockhash_prefix::*;
pub use blockhash_start_index::*;
pub use blockhash_tx_index::*;
pub use block_info::*;
pub use block_rewards_entry::*;
pub use block_size_entry::*;
pub use block_sizes_weights::*;
pub use block_status::*;
pub use block_timestamp::*;
pub use block_weight_entry::*;
pub use bytes::*;
pub use cents::*;
pub use cents_compact::*;
@@ -244,109 +244,109 @@ pub use cost_basis_bucket::*;
pub use cost_basis_distribution::*;
pub use cost_basis_params::*;
pub use cost_basis_value::*;
pub use datarange::*;
pub use datarangeformat::*;
pub use data_range::*;
pub use data_range_format::*;
pub use date::*;
pub use day1::*;
pub use day3::*;
pub use deser::*;
pub use difficultyadjustment::*;
pub use difficultyadjustmententry::*;
pub use difficultyentry::*;
pub use diskusage::*;
pub use difficulty_adjustment::*;
pub use difficulty_adjustment_entry::*;
pub use difficulty_entry::*;
pub use disk_usage::*;
pub use dollars::*;
pub use emptyaddressdata::*;
pub use emptyaddressindex::*;
pub use emptyoutputindex::*;
pub use empty_address_data::*;
pub use empty_address_index::*;
pub use empty_output_index::*;
pub use epoch::*;
pub use etag::*;
pub use feerate::*;
pub use feeratepercentiles::*;
pub use feerate_percentiles::*;
pub use format::*;
pub use formatresponse::*;
pub use format_response::*;
pub use from_coarser::*;
pub use fundedaddressdata::*;
pub use fundedaddressindex::*;
pub use funded_address_data::*;
pub use funded_address_index::*;
pub use halving::*;
pub use hashrateentry::*;
pub use hashratesummary::*;
pub use hashrate_entry::*;
pub use hashrate_summary::*;
pub use health::*;
pub use height::*;
pub use heightparam::*;
pub use height_param::*;
pub use hex::*;
pub use hour1::*;
pub use hour4::*;
pub use hour12::*;
pub use index::*;
pub use indexes::*;
pub use indexinfo::*;
pub use index_info::*;
pub use limit::*;
pub use limitparam::*;
pub use mempoolblock::*;
pub use mempoolentryinfo::*;
pub use mempoolinfo::*;
pub use limit_param::*;
pub use mempool_block::*;
pub use mempool_entry_info::*;
pub use mempool_info::*;
pub use metric::*;
pub use metriccount::*;
pub use metricdata::*;
pub use metricinfo::*;
pub use metricoutput::*;
pub use metricparam::*;
pub use metric_count::*;
pub use metric_data::*;
pub use metric_info::*;
pub use metric_output::*;
pub use metric_param::*;
pub use metrics::*;
pub use metricselection::*;
pub use metricselectionlegacy::*;
pub use metricspaginated::*;
pub use metricwithindex::*;
pub use metric_selection::*;
pub use metric_selection_legacy::*;
pub use metrics_paginated::*;
pub use metric_with_index::*;
pub use minute10::*;
pub use minute30::*;
pub use month1::*;
pub use month3::*;
pub use month6::*;
pub use ohlc::*;
pub use opreturnindex::*;
pub use op_return_index::*;
pub use option_ext::*;
pub use oracle_bins::*;
pub use outpoint::*;
pub use output::*;
pub use outputtype::*;
pub use p2aaddressindex::*;
pub use p2abytes::*;
pub use p2msoutputindex::*;
pub use p2pk33addressindex::*;
pub use p2pk33bytes::*;
pub use p2pk65addressindex::*;
pub use p2pk65bytes::*;
pub use p2pkhaddressindex::*;
pub use p2pkhbytes::*;
pub use p2shaddressindex::*;
pub use p2shbytes::*;
pub use p2traddressindex::*;
pub use p2trbytes::*;
pub use p2wpkhaddressindex::*;
pub use p2wpkhbytes::*;
pub use p2wshaddressindex::*;
pub use p2wshbytes::*;
pub use output_type::*;
pub use p2a_address_index::*;
pub use p2a_bytes::*;
pub use p2ms_output_index::*;
pub use p2pk33_address_index::*;
pub use p2pk33_bytes::*;
pub use p2pk65_address_index::*;
pub use p2pk65_bytes::*;
pub use p2pkh_address_index::*;
pub use p2pkh_bytes::*;
pub use p2sh_address_index::*;
pub use p2sh_bytes::*;
pub use p2tr_address_index::*;
pub use p2tr_bytes::*;
pub use p2wpkh_address_index::*;
pub use p2wpkh_bytes::*;
pub use p2wsh_address_index::*;
pub use p2wsh_bytes::*;
pub use pagination::*;
pub use paginationindex::*;
pub use pairoutputindex::*;
pub use pagination_index::*;
pub use pair_output_index::*;
pub use percentile::*;
pub use pool::*;
pub use pooldetail::*;
pub use poolinfo::*;
pub use pool_detail::*;
pub use pool_info::*;
pub use pools::*;
pub use poolslug::*;
pub use poolslugparam::*;
pub use poolssummary::*;
pub use poolstats::*;
pub use pool_slug::*;
pub use pool_slug_param::*;
pub use pools_summary::*;
pub use pool_stats::*;
pub use port::*;
pub use range_map::*;
pub use rangeindex::*;
pub use rawlocktime::*;
pub use recommendedfees::*;
pub use rewardstats::*;
pub use range_index::*;
pub use raw_locktime::*;
pub use recommended_fees::*;
pub use reward_stats::*;
pub use sats::*;
pub use sats_signed::*;
pub use satsfract::*;
pub use searchquery::*;
pub use sats_fract::*;
pub use search_query::*;
pub use stored_bool::*;
pub use stored_f32::*;
pub use stored_f64::*;
@@ -359,32 +359,32 @@ pub use stored_u16::*;
pub use stored_u32::*;
pub use stored_u64::*;
pub use supply_state::*;
pub use syncstatus::*;
pub use sync_status::*;
pub use term::*;
pub use timeperiod::*;
pub use timeperiodparam::*;
pub use time_period::*;
pub use time_period_param::*;
pub use timestamp::*;
pub use timestampparam::*;
pub use treenode::*;
pub use timestamp_param::*;
pub use tree_node::*;
pub use tx::*;
pub use txid::*;
pub use txidparam::*;
pub use txidprefix::*;
pub use txidvout::*;
pub use txid_param::*;
pub use txid_prefix::*;
pub use txid_vout::*;
pub use txin::*;
pub use txindex::*;
pub use txinindex::*;
pub use tx_index::*;
pub use txin_index::*;
pub use txout::*;
pub use txoutindex::*;
pub use txoutspend::*;
pub use txstatus::*;
pub use txversion::*;
pub use txwithhex::*;
pub use typeindex::*;
pub use txout_index::*;
pub use txout_spend::*;
pub use tx_status::*;
pub use tx_version::*;
pub use tx_with_hex::*;
pub use type_index::*;
pub use unit::*;
pub use unknownoutputindex::*;
pub use unknown_output_index::*;
pub use utxo::*;
pub use validateaddressparam::*;
pub use validate_address_param::*;
pub use vin::*;
pub use vout::*;
pub use vsize::*;
+2 -2
View File
@@ -68,11 +68,11 @@ impl CheckedSub<OpReturnIndex> for OpReturnIndex {
impl PrintableIndex for OpReturnIndex {
fn to_string() -> &'static str {
"opreturnindex"
"op_return_index"
}
fn to_possible_strings() -> &'static [&'static str] {
&["op", "opreturn", "opreturnindex"]
&["op", "opreturn", "op_return_index"]
}
}
+8 -8
View File
@@ -10,14 +10,14 @@ pub struct OutPoint(u64);
impl OutPoint {
pub const COINBASE: Self = Self(u64::MAX);
pub fn new(txindex: TxIndex, vout: Vout) -> Self {
let txindex_bits = u64::from(txindex) << 32;
pub fn new(tx_index: TxIndex, vout: Vout) -> Self {
let tx_index_bits = u64::from(tx_index) << 32;
let vout_bits = u64::from(vout);
Self(txindex_bits | vout_bits)
Self(tx_index_bits | vout_bits)
}
#[inline(always)]
pub fn txindex(self) -> TxIndex {
pub fn tx_index(self) -> TxIndex {
TxIndex::from((self.0 >> 32) as u32)
}
@@ -42,7 +42,7 @@ impl OutPoint {
impl std::fmt::Display for OutPoint {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "txindex: {}, vout: {}", self.txindex(), self.vout())
write!(f, "tx_index: {}, vout: {}", self.tx_index(), self.vout())
}
}
@@ -78,7 +78,7 @@ impl Serialize for OutPoint {
{
use serde::ser::SerializeStruct;
let mut state = serializer.serialize_struct("OutPoint", 2)?;
state.serialize_field("txindex", &self.txindex())?;
state.serialize_field("tx_index", &self.tx_index())?;
state.serialize_field("vout", &self.vout())?;
state.end()
}
@@ -91,10 +91,10 @@ impl<'de> Deserialize<'de> for OutPoint {
{
#[derive(Deserialize)]
struct Helper {
txindex: TxIndex,
tx_index: TxIndex,
vout: Vout,
}
let h = Helper::deserialize(deserializer)?;
Ok(Self::new(h.txindex, h.vout))
Ok(Self::new(h.tx_index, h.vout))
}
}
+2 -2
View File
@@ -89,11 +89,11 @@ impl CheckedSub<P2AAddressIndex> for P2AAddressIndex {
impl PrintableIndex for P2AAddressIndex {
fn to_string() -> &'static str {
"p2aaddressindex"
"p2a_address_index"
}
fn to_possible_strings() -> &'static [&'static str] {
&["aaddr", "p2aaddr", "p2aaddressindex"]
&["aaddr", "p2aaddr", "p2a_address_index"]
}
}
+2 -2
View File
@@ -68,11 +68,11 @@ impl CheckedSub<P2MSOutputIndex> for P2MSOutputIndex {
impl PrintableIndex for P2MSOutputIndex {
fn to_string() -> &'static str {
"p2msoutputindex"
"p2ms_output_index"
}
fn to_possible_strings() -> &'static [&'static str] {
&["msout", "p2msout", "p2msoutputindex"]
&["msout", "p2msout", "p2ms_output_index"]
}
}
+2 -2
View File
@@ -89,11 +89,11 @@ impl CheckedSub<P2PK33AddressIndex> for P2PK33AddressIndex {
impl PrintableIndex for P2PK33AddressIndex {
fn to_string() -> &'static str {
"p2pk33addressindex"
"p2pk33_address_index"
}
fn to_possible_strings() -> &'static [&'static str] {
&["pk33addr", "p2pk33addr", "p2pk33addressindex"]
&["pk33addr", "p2pk33addr", "p2pk33_address_index"]
}
}
+2 -2
View File
@@ -89,10 +89,10 @@ impl CheckedSub<P2PK65AddressIndex> for P2PK65AddressIndex {
impl PrintableIndex for P2PK65AddressIndex {
fn to_string() -> &'static str {
"p2pk65addressindex"
"p2pk65_address_index"
}
fn to_possible_strings() -> &'static [&'static str] {
&["pk65addr", "p2pk65addr", "p2pk65addressindex"]
&["pk65addr", "p2pk65addr", "p2pk65_address_index"]
}
}
+2 -2
View File
@@ -89,11 +89,11 @@ impl CheckedSub<P2PKHAddressIndex> for P2PKHAddressIndex {
impl PrintableIndex for P2PKHAddressIndex {
fn to_string() -> &'static str {
"p2pkhaddressindex"
"p2pkh_address_index"
}
fn to_possible_strings() -> &'static [&'static str] {
&["pkhaddr", "p2pkhaddr", "p2pkhaddressindex"]
&["pkhaddr", "p2pkhaddr", "p2pkh_address_index"]
}
}
+2 -2
View File
@@ -96,11 +96,11 @@ impl CheckedSub<P2SHAddressIndex> for P2SHAddressIndex {
impl PrintableIndex for P2SHAddressIndex {
fn to_string() -> &'static str {
"p2shaddressindex"
"p2sh_address_index"
}
fn to_possible_strings() -> &'static [&'static str] {
&["shaddr", "p2shaddr", "p2shaddressindex"]
&["shaddr", "p2shaddr", "p2sh_address_index"]
}
}
+2 -2
View File
@@ -89,11 +89,11 @@ impl CheckedSub<P2TRAddressIndex> for P2TRAddressIndex {
impl PrintableIndex for P2TRAddressIndex {
fn to_string() -> &'static str {
"p2traddressindex"
"p2tr_address_index"
}
fn to_possible_strings() -> &'static [&'static str] {
&["traddr", "p2traddr", "p2traddressindex"]
&["traddr", "p2traddr", "p2tr_address_index"]
}
}
+2 -2
View File
@@ -89,11 +89,11 @@ impl CheckedSub<P2WPKHAddressIndex> for P2WPKHAddressIndex {
impl PrintableIndex for P2WPKHAddressIndex {
fn to_string() -> &'static str {
"p2wpkhaddressindex"
"p2wpkh_address_index"
}
fn to_possible_strings() -> &'static [&'static str] {
&["wpkhaddr", "p2wpkhaddr", "p2wpkhaddressindex"]
&["wpkhaddr", "p2wpkhaddr", "p2wpkh_address_index"]
}
}
+2 -2
View File
@@ -89,11 +89,11 @@ impl CheckedSub<P2WSHAddressIndex> for P2WSHAddressIndex {
impl PrintableIndex for P2WSHAddressIndex {
fn to_string() -> &'static str {
"p2wshaddressindex"
"p2wsh_address_index"
}
fn to_possible_strings() -> &'static [&'static str] {
&["wshaddr", "p2wshaddr", "p2wshaddressindex"]
&["wshaddr", "p2wshaddr", "p2wsh_address_index"]
}
}

Some files were not shown because too many files have changed in this diff Show More