bindex: converted txindex_to_txoutindex_in to storable vecs

This commit is contained in:
nym21
2025-01-26 17:42:47 +01:00
parent b94d94e116
commit 4923c2e204
14 changed files with 300 additions and 200 deletions

View File

@@ -10,6 +10,7 @@ color-eyre = "0.6.3"
derive_deref = "1.1.1"
exit = { path = "../exit" }
jiff = "0.1.24"
rapidhash = "1.3.0"
rayon = "1.10.0"
snkrj = { path = "../snkrj" }
storable_vec = { path = "../storable_vec" }

View File

@@ -10,30 +10,25 @@ use biter::{
bitcoin::{Transaction, TxIn, TxOut, Txid},
rpc,
};
use exit::Exit;
use crate::storage::{Stores, Vecs};
use crate::structs::{
Addressbytes, AddressbytesPrefix, Addressindex, Addresstype, Amount, BlockHashPrefix, Height, Timestamp,
TxidPrefix, Txindex, Txoutindex, Vout,
};
use color_eyre::eyre::{eyre, ContextCompat};
use exit::Exit;
use rayon::prelude::*;
#[derive(Debug)]
enum TxInOrAddressindextoutindex<'a> {
TxIn(&'a TxIn),
AddressTxTxoutIndexes((Addressindex, Txindex, Txoutindex)),
}
mod storage;
mod structs;
use storage::{Stores, Vecs};
use structs::{
Addressbytes, AddressbytesPrefix, Addressindex, Addresstype, Amount, BlockHashPrefix, Height, Timestamp,
TxidPrefix, Txindex, Txinindex, Txoutindex, Vin, Vout,
};
const UNSAFE_BLOCKS: u32 = 100;
const DAILY_BLOCK_TARGET: usize = 144;
const SNAPSHOT_BLOCK_RANGE: usize = DAILY_BLOCK_TARGET * 10;
#[derive(Debug, Default)]
pub struct Indexer {
//
}
#[derive(Debug)]
pub struct Indexer;
impl Indexer {
pub fn index(indexes_dir: &Path, bitcoin_dir: &Path, rpc: rpc::Client, exit: Exit) -> color_eyre::Result<()> {
@@ -54,6 +49,7 @@ impl Indexer {
// let mut height = Height::default();
let mut txindex_global = vecs.height_to_first_txindex.get_or_default(height)?;
let mut txinindex_global = vecs.height_to_first_txinindex.get_or_default(height)?;
let mut txoutindex_global = vecs.height_to_first_txoutindex.get_or_default(height)?;
let mut addressindex_global = vecs.height_to_first_addressindex.get_or_default(height)?;
let mut emptyindex_global = vecs.height_to_first_emptyindex.get_or_default(height)?;
@@ -146,6 +142,8 @@ impl Indexer {
vecs.height_to_size.push_if_needed(height, block.total_size())?;
vecs.height_to_weight.push_if_needed(height, block.weight())?;
vecs.height_to_first_txindex.push_if_needed(height, txindex_global)?;
vecs.height_to_first_txinindex
.push_if_needed(height, txinindex_global)?;
vecs.height_to_first_txoutindex
.push_if_needed(height, txoutindex_global)?;
vecs.height_to_first_addressindex
@@ -168,6 +166,18 @@ impl Indexer {
vecs.height_to_p2wpkhindex.push_if_needed(height, p2wpkhindex_global)?;
vecs.height_to_p2wshindex.push_if_needed(height, p2wshindex_global)?;
let inputs = block
.txdata
.iter()
.enumerate()
.flat_map(|(index, tx)| {
tx.input
.iter()
.enumerate()
.map(move |(vin, txin)| (Txindex::from(index), Vin::from(vin), txin, tx))
})
.collect::<Vec<_>>();
let outputs = block
.txdata
.iter()
@@ -182,10 +192,11 @@ impl Indexer {
let tx_len = block.txdata.len();
let outputs_len = outputs.len();
let inputs_len = inputs.len();
let (
txid_prefix_to_txid_and_block_txindex_and_prev_txindex_join_handle,
txin_or_addressindextxoutindex_vec_handle,
input_source_vec_handle,
txoutindex_to_txout_addresstype_addressbytes_res_addressindex_opt_handle,
) = thread::scope(|scope| {
let txid_prefix_to_txid_and_block_txindex_and_prev_txindex_handle =
@@ -225,69 +236,78 @@ impl Indexer {
})
});
let txin_or_addressindextxoutindex_vec_handle =
scope.spawn(|| -> color_eyre::Result<Vec<TxInOrAddressindextoutindex>> {
block
.txdata
.par_iter()
.filter(|tx| !tx.is_coinbase())
.flat_map(|tx| &tx.input)
.map(|txin| -> color_eyre::Result<_> {
let outpoint = txin.previous_output;
let txid = outpoint.txid;
let vout = Vout::from(outpoint.vout);
let input_source_vec_handle = scope.spawn(|| {
inputs
.into_par_iter()
.enumerate()
.map(|(block_txinindex, (block_txindex, vin, txin, tx))| -> color_eyre::Result<(Txinindex, InputSource)> {
let txindex = txindex_global + block_txindex;
let txinindex = txinindex_global + Txinindex::from(block_txinindex);
let txindex = if let Some(txindex) = stores
.txid_prefix_to_txindex
.get(&TxidPrefix::try_from(&txid)?)?
.and_then(|txindex| {
// Checking if not finding txindex from the future
(txindex < &txindex_global).then_some(txindex)
}) {
*txindex
} else {
return Ok(TxInOrAddressindextoutindex::TxIn(txin));
};
// dbg!((txindex, txinindex, vin));
let txoutindex = *vecs
.txindex_to_first_txoutindex
.get(txindex)?
.context("Expect txoutindex to not be none")
.inspect_err(|_| {
dbg!(outpoint.txid, txindex, vout);
})?
+ vout;
let outpoint = txin.previous_output;
let addressindex = *vecs
.txoutindex_to_addressindex
.get(txoutindex)?
.context("Expect addressindex to not be none")
.inspect_err(|_| {
// let height = vecdisks.txindex_to_height.get(txindex.into()).expect("txindex_to_height get not fail")
// .expect("Expect height for txindex");
dbg!(outpoint.txid, txindex, vout, txoutindex);
})?;
if tx.is_coinbase() {
return Ok((txinindex, InputSource::SameBlock((tx, txindex, txin, vin))));
}
Ok(TxInOrAddressindextoutindex::AddressTxTxoutIndexes((
addressindex,
txindex,
txoutindex,
)))
})
.try_fold(Vec::new, |mut vec, res| {
vec.push(res?);
Ok(vec)
})
.try_reduce(Vec::new, |mut v, mut v2| {
if v.len() > v2.len() {
v.append(&mut v2);
Ok(v)
} else {
v2.append(&mut v);
Ok(v2)
}
})
});
let prev_txindex = if let Some(txindex) = stores
.txid_prefix_to_txindex
.get(&TxidPrefix::try_from(&outpoint.txid)?)?
.and_then(|txindex| {
// Checking if not finding txindex from the future
(txindex < &txindex_global).then_some(txindex)
}) {
*txindex
} else {
// dbg!(txindex_global + block_txindex, txindex, txin, vin);
return Ok((txinindex, InputSource::SameBlock((tx, txindex, txin, vin))));
};
let vout = Vout::from(outpoint.vout);
let txoutindex = *vecs
.txindex_to_first_txoutindex
.get(prev_txindex)?
.context("Expect txoutindex to not be none")
.inspect_err(|_| {
dbg!(outpoint.txid, prev_txindex, vout);
})?
+ vout;
let addressindex = *vecs
.txoutindex_to_addressindex
.get(txoutindex)?
.context("Expect addressindex to not be none")
.inspect_err(|_| {
// let height = vecdisks.txindex_to_height.get(txindex.into()).expect("txindex_to_height get not fail")
// .expect("Expect height for txindex");
dbg!(outpoint.txid, prev_txindex, vout, txoutindex);
})?;
Ok((txinindex, InputSource::PreviousBlock((
vin,
txindex,
txoutindex,
addressindex,
))))
})
.try_fold(BTreeMap::new, |mut map, tuple| -> color_eyre::Result<_> {
let (key, value) = tuple?;
map.insert(key, value);
Ok(map)
})
.try_reduce(BTreeMap::new, |mut map, mut map2| {
if map.len() > map2.len() {
map.append(&mut map2);
Ok(map)
} else {
map2.append(&mut map);
Ok(map2)
}
})
});
let txoutindex_to_txout_addresstype_addressbytes_res_addressindex_opt_handle = scope.spawn(|| {
outputs
@@ -410,7 +430,7 @@ impl Indexer {
(
txid_prefix_to_txid_and_block_txindex_and_prev_txindex_handle.join(),
txin_or_addressindextxoutindex_vec_handle.join(),
input_source_vec_handle.join(),
txoutindex_to_txout_addresstype_addressbytes_res_addressindex_opt_handle.join(),
)
});
@@ -422,9 +442,9 @@ impl Indexer {
"Expect txid_prefix_to_txid_and_block_txindex_and_prev_txindex_join_handle to join",
)??;
let txin_or_addressindextxoutindex_vec = txin_or_addressindextxoutindex_vec_handle
let input_source_vec = input_source_vec_handle
.ok()
.context("Export txin_or_addressindextxoutindex_vec_handle to join")??;
.context("Export input_source_vec_handle to join")??;
let txoutindex_to_txout_addresstype_addressbytes_res_addressindex_opt =
txoutindex_to_txout_addresstype_addressbytes_res_addressindex_opt_handle
@@ -433,9 +453,9 @@ impl Indexer {
"Expect txoutindex_to_txout_addresstype_addressbytes_res_addressindex_opt_handle to join",
)??;
let mut new_txindexvout_to_addressindextxoutindex: BTreeMap<
let mut new_txindexvout_to_txoutindex: BTreeMap<
(Txindex, Vout),
(Addressindex, Txoutindex),
Txoutindex,
> = BTreeMap::new();
let mut already_added_addressbytes_prefix: BTreeMap<AddressbytesPrefix, Addressindex> = BTreeMap::new();
@@ -514,15 +534,15 @@ impl Indexer {
}
}
new_txindexvout_to_addressindextxoutindex
.insert((txindex, vout), (addressindex, txoutindex));
new_txindexvout_to_txoutindex
.insert((txindex, vout), txoutindex);
vecs.txoutindex_to_addressindex
.push_if_needed(txoutindex, addressindex)?;
stores
.addressindex_to_txoutindex_in
.insert_if_needed(addressindex, txoutindex, height);
// stores
// .addressindex_to_txoutindex_in
// .insert_if_needed(addressindex, txoutindex, height);
Ok(())
},
@@ -530,46 +550,63 @@ impl Indexer {
drop(already_added_addressbytes_prefix);
txin_or_addressindextxoutindex_vec
input_source_vec
.into_iter()
.map(
|txin_or_addressindextxoutindex| -> color_eyre::Result<(Addressindex, Txindex, Txoutindex)> {
match txin_or_addressindextxoutindex {
TxInOrAddressindextoutindex::AddressTxTxoutIndexes(triplet) => Ok(triplet),
TxInOrAddressindextoutindex::TxIn(txin) => {
#[allow(clippy::type_complexity)]
|(txinindex, input_source)| -> color_eyre::Result<(
Txinindex, Vin, Txindex, Option<(Addressindex, Txoutindex)>
)> {
match input_source {
InputSource::PreviousBlock((vin, txindex, txoutindex, addressindex)) => Ok((txinindex, vin, txindex, Some((addressindex, txoutindex)))),
InputSource::SameBlock((tx, txindex, txin, vin)) => {
if tx.is_coinbase() {
return Ok((txinindex, vin, txindex, None));
}
let outpoint = txin.previous_output;
let txid = outpoint.txid;
let vout = Vout::from(outpoint.vout);
let index = txid_prefix_to_txid_and_block_txindex_and_prev_txindex
let block_txindex = txid_prefix_to_txid_and_block_txindex_and_prev_txindex
.get(&TxidPrefix::try_from(&txid)?)
.context("txid should be in same block")?
.2;
let txindex = txindex_global + index;
let prev_txindex = txindex_global + block_txindex;
let (addressindex, txoutindex) = new_txindexvout_to_addressindextxoutindex
.remove(&(txindex, vout))
let prev_txoutindex = new_txindexvout_to_txoutindex
.remove(&(prev_txindex, vout))
.context("should have found addressindex from same block")
.inspect_err(|_| {
dbg!(&new_txindexvout_to_addressindextxoutindex, txin, txindex, vout, txid);
dbg!(&new_txindexvout_to_txoutindex, txin, prev_txindex, vout, txid);
})?;
Ok((addressindex, txindex, txoutindex))
Ok((txinindex, vin, txindex, Some((Addressindex::from(0_u32), prev_txoutindex))))
}
}
},
)
.try_for_each(|res| -> color_eyre::Result<()> {
let (addressindex, txindex, txoutindex) = res?;
stores
.addressindex_to_txoutindex_out
.insert_if_needed(addressindex, txoutindex, height);
stores
.txindex_to_txoutindex_in
.insert_if_needed(txindex, txoutindex, height);
let (txinindex, vin, txindex, addressindex_and_txoutindex_opt) = res?;
if vin.is_zero() {
vecs.txindex_to_first_txinindex.push_if_needed(txindex, txinindex)?;
}
let txoutindex = addressindex_and_txoutindex_opt.map_or(Txoutindex::MAX, |(_, txoutindex)| txoutindex);
vecs.txinindex_to_txoutindex.push_if_needed(txinindex, txoutindex)?;
// if let Some(addressindex) = addressindex_and_txoutindex_opt.map(|(addressindex, _)| addressindex) {
// stores
// .addressindex_to_txoutindex_out
// .insert_if_needed(addressindex, txoutindex, height);
// }
Ok(())
})?;
drop(new_txindexvout_to_addressindextxoutindex);
drop(new_txindexvout_to_txoutindex);
let mut txindex_to_tx_and_txid: BTreeMap<Txindex, (&Transaction, Txid)> = BTreeMap::default();
@@ -644,6 +681,7 @@ impl Indexer {
})?;
txindex_global += Txindex::from(tx_len);
txinindex_global += Txinindex::from(inputs_len);
txoutindex_global += Txoutindex::from(outputs_len);
let should_snapshot = _height != 0 && _height % SNAPSHOT_BLOCK_RANGE == 0 && !exit.active();
@@ -663,6 +701,13 @@ impl Indexer {
}
}
#[derive(Debug)]
enum InputSource<'a> {
PreviousBlock((Vin, Txindex, Txoutindex, Addressindex)),
SameBlock((&'a Transaction, Txindex, &'a TxIn, Vin)),
}
#[allow(unused)]
fn pause() {
let mut stdin = std::io::stdin();
let mut stdout = std::io::stdout();

View File

@@ -1,14 +1,8 @@
use std::path::Path;
use bindex::Indexer;
use biter::rpc;
mod indexer;
mod storage;
mod structs;
use exit::Exit;
use indexer::Indexer;
use structs::{AddressbytesPrefix, Addressindex, BlockHashPrefix, Height, TxidPrefix, Txindex, Txoutindex};
// https://github.com/romanz/electrs/blob/master/doc/schema.md

View File

@@ -14,11 +14,10 @@ use unique::*;
pub struct Stores {
pub addressbytes_prefix_to_addressindex: StoreUnique<AddressbytesPrefix, Addressindex>,
pub addressindex_to_txoutindex_in: StoreMulti<Addressindex, Txoutindex>, // Received
pub addressindex_to_txoutindex_out: StoreMulti<Addressindex, Txoutindex>, // Spent
// pub addressindex_to_txoutindex_in: StoreMulti<Addressindex, Txoutindex>, // Received
// pub addressindex_to_txoutindex_out: StoreMulti<Addressindex, Txoutindex>, // Spent
pub blockhash_prefix_to_height: StoreUnique<BlockHashPrefix, Height>,
pub txid_prefix_to_txindex: StoreUnique<TxidPrefix, Txindex>,
pub txindex_to_txoutindex_in: StoreMulti<Txindex, Txoutindex>, // Inputs
}
impl Stores {
@@ -28,17 +27,16 @@ impl Stores {
&path.join("addressbytes_prefix_to_addressindex"),
Version::from(1),
)?,
addressindex_to_txoutindex_in: StoreMulti::open(
&path.join("addressindex_to_txoutindex_in"),
Version::from(1),
)?,
addressindex_to_txoutindex_out: StoreMulti::open(
&path.join("addressindex_to_txoutindex_out"),
Version::from(1),
)?,
// addressindex_to_txoutindex_in: StoreMulti::open(
// &path.join("addressindex_to_txoutindex_in"),
// Version::from(1),
// )?,
// addressindex_to_txoutindex_out: StoreMulti::open(
// &path.join("addressindex_to_txoutindex_out"),
// Version::from(1),
// )?,
blockhash_prefix_to_height: StoreUnique::open(&path.join("blockhash_prefix_to_height"), Version::from(1))?,
txid_prefix_to_txindex: StoreUnique::open(&path.join("txid_prefix_to_txindex"), Version::from(1))?,
txindex_to_txoutindex_in: StoreMulti::open(&path.join("txindex_to_txoutindex_in"), Version::from(1))?,
})
}
@@ -164,11 +162,10 @@ impl Stores {
pub fn min_height(&self) -> Option<Height> {
[
self.addressbytes_prefix_to_addressindex.height(),
self.addressindex_to_txoutindex_in.height(),
self.addressindex_to_txoutindex_out.height(),
// self.addressindex_to_txoutindex_in.height(),
// self.addressindex_to_txoutindex_out.height(),
self.blockhash_prefix_to_height.height(),
self.txid_prefix_to_txindex.height(),
self.txindex_to_txoutindex_in.height(),
]
.into_iter()
.min()
@@ -180,11 +177,10 @@ impl Stores {
thread::scope(|scope| {
vec![
scope.spawn(|| self.addressbytes_prefix_to_addressindex.export(height)),
scope.spawn(|| self.addressindex_to_txoutindex_in.export(height)),
scope.spawn(|| self.addressindex_to_txoutindex_out.export(height)),
// scope.spawn(|| self.addressindex_to_txoutindex_in.export(height)),
// scope.spawn(|| self.addressindex_to_txoutindex_out.export(height)),
scope.spawn(|| self.blockhash_prefix_to_height.export(height)),
scope.spawn(|| self.txid_prefix_to_txindex.export(height)),
scope.spawn(|| self.txindex_to_txoutindex_in.export(height)),
]
.into_iter()
.try_for_each(|handle| -> Result<(), snkrj::Error> { handle.join().unwrap() })

View File

@@ -58,6 +58,7 @@ where
});
}
#[allow(unused)]
pub fn get(&self, key: &K) -> Result<Option<&V>, snkrj::Error> {
self.get_or_init_store(key).get(key)
}
@@ -92,6 +93,7 @@ where
pub fn height(&self) -> Option<&Height> {
self.meta.height()
}
#[allow(unused)]
pub fn needs(&self, height: Height) -> bool {
self.meta.needs(height)
}

View File

@@ -81,6 +81,7 @@ where
pub fn needs(&self, height: Height) -> bool {
self.height.is_none_or(|self_height| height > self_height)
}
#[allow(unused)]
pub fn has(&self, height: Height) -> bool {
!self.needs(height)
}

View File

@@ -1,15 +1,13 @@
use std::{fs, io, path::Path};
use biter::bitcoin::{self, transaction, BlockHash, Txid, Weight};
use color_eyre::eyre::eyre;
use exit::Exit;
use rayon::prelude::*;
use storable_vec::AnyStorableVec;
use crate::structs::{
Addressbytes, Addressindex, Addresstype, Addresstypeindex, Amount, Height, P2PK33AddressBytes, P2PK65AddressBytes,
P2PKHAddressBytes, P2SHAddressBytes, P2TRAddressBytes, P2WPKHAddressBytes, P2WSHAddressBytes, Timestamp, Txindex,
Txoutindex, Version,
Txinindex, Txoutindex, Version,
};
mod base;
@@ -27,6 +25,7 @@ pub struct Vecs {
pub height_to_first_opreturnindex: StorableVec<Height, Addresstypeindex>,
pub height_to_first_pushonlyindex: StorableVec<Height, Addresstypeindex>,
pub height_to_first_txindex: StorableVec<Height, Txindex>,
pub height_to_first_txinindex: StorableVec<Height, Txinindex>,
pub height_to_first_txoutindex: StorableVec<Height, Txoutindex>,
pub height_to_first_unknownindex: StorableVec<Height, Addresstypeindex>,
pub height_to_p2pk33index: StorableVec<Height, Addresstypeindex>,
@@ -46,11 +45,13 @@ pub struct Vecs {
pub p2trindex_to_p2traddressbytes: StorableVec<Addresstypeindex, P2TRAddressBytes>,
pub p2wpkhindex_to_p2wpkhaddressbytes: StorableVec<Addresstypeindex, P2WPKHAddressBytes>,
pub p2wshindex_to_p2wshaddressbytes: StorableVec<Addresstypeindex, P2WSHAddressBytes>,
pub txindex_to_first_txinindex: StorableVec<Txindex, Txinindex>,
pub txindex_to_first_txoutindex: StorableVec<Txindex, Txoutindex>,
pub txindex_to_height: StorableVec<Txindex, Height>,
pub txindex_to_locktime: StorableVec<Txindex, bitcoin::absolute::LockTime>,
pub txindex_to_txid: StorableVec<Txindex, Txid>,
pub txindex_to_txversion: StorableVec<Txindex, transaction::Version>,
pub txinindex_to_txoutindex: StorableVec<Txinindex, Txoutindex>,
pub txoutindex_to_addressindex: StorableVec<Txoutindex, Addressindex>,
pub txoutindex_to_amount: StorableVec<Txoutindex, Amount>,
// Can be computed later:
@@ -110,6 +111,7 @@ impl Vecs {
Version::from(1),
)?,
height_to_first_txindex: StorableVec::import(&path.join("height_to_first_txindex"), Version::from(1))?,
height_to_first_txinindex: StorableVec::import(&path.join("height_to_first_txinindex"), Version::from(1))?,
height_to_first_txoutindex: StorableVec::import(
&path.join("height_to_first_txoutindex"),
Version::from(1),
@@ -156,6 +158,10 @@ impl Vecs {
&path.join("p2wshindex_to_p2wshaddressbytes"),
Version::from(1),
)?,
txindex_to_first_txinindex: StorableVec::import(
&path.join("txindex_to_first_txinindex"),
Version::from(1),
)?,
txindex_to_first_txoutindex: StorableVec::import(
&path.join("txindex_to_first_txoutindex"),
Version::from(1),
@@ -164,6 +170,7 @@ impl Vecs {
txindex_to_locktime: StorableVec::import(&path.join("txindex_to_locktime"), Version::from(1))?,
txindex_to_txid: StorableVec::import(&path.join("txindex_to_txid"), Version::from(1))?,
txindex_to_txversion: StorableVec::import(&path.join("txindex_to_txversion"), Version::from(1))?,
txinindex_to_txoutindex: StorableVec::import(&path.join("txinindex_to_txoutindex"), Version::from(1))?,
txoutindex_to_addressindex: StorableVec::import(
&path.join("txoutindex_to_addressindex"),
Version::from(1),
@@ -361,7 +368,7 @@ impl Vecs {
.min())
}
pub fn as_slice(&self) -> [&dyn AnyBindexVec; 36] {
pub fn as_slice(&self) -> [&dyn AnyBindexVec; 39] {
[
&self.addressindex_to_addresstype as &dyn AnyBindexVec,
&self.addressindex_to_addresstypeindex,
@@ -373,6 +380,7 @@ impl Vecs {
&self.height_to_first_opreturnindex,
&self.height_to_first_pushonlyindex,
&self.height_to_first_txindex,
&self.height_to_first_txinindex,
&self.height_to_first_txoutindex,
&self.height_to_first_unknownindex,
&self.height_to_p2pk33index,
@@ -392,17 +400,19 @@ impl Vecs {
&self.p2trindex_to_p2traddressbytes,
&self.p2wpkhindex_to_p2wpkhaddressbytes,
&self.p2wshindex_to_p2wshaddressbytes,
&self.txindex_to_first_txinindex,
&self.txindex_to_first_txoutindex,
&self.txindex_to_height,
&self.txindex_to_locktime,
&self.txindex_to_txid,
&self.txindex_to_txversion,
&self.txinindex_to_txoutindex,
&self.txoutindex_to_addressindex,
&self.txoutindex_to_amount,
]
}
pub fn as_mut_slice(&mut self) -> [&mut (dyn AnyBindexVec + Send + Sync); 36] {
pub fn as_mut_slice(&mut self) -> [&mut (dyn AnyBindexVec + Send + Sync); 39] {
[
&mut self.addressindex_to_addresstype as &mut (dyn AnyBindexVec + Send + Sync),
&mut self.addressindex_to_addresstypeindex,
@@ -414,6 +424,7 @@ impl Vecs {
&mut self.height_to_first_opreturnindex,
&mut self.height_to_first_pushonlyindex,
&mut self.height_to_first_txindex,
&mut self.height_to_first_txinindex,
&mut self.height_to_first_txoutindex,
&mut self.height_to_first_unknownindex,
&mut self.height_to_p2pk33index,
@@ -433,11 +444,13 @@ impl Vecs {
&mut self.p2trindex_to_p2traddressbytes,
&mut self.p2wpkhindex_to_p2wpkhaddressbytes,
&mut self.p2wshindex_to_p2wshaddressbytes,
&mut self.txindex_to_first_txinindex,
&mut self.txindex_to_first_txoutindex,
&mut self.txindex_to_height,
&mut self.txindex_to_locktime,
&mut self.txindex_to_txid,
&mut self.txindex_to_txversion,
&mut self.txinindex_to_txoutindex,
&mut self.txoutindex_to_addressindex,
&mut self.txoutindex_to_amount,
]

View File

@@ -1,19 +0,0 @@
use snkrj::{direct_repr, Storable, UnsizedStorable};
use super::{Addressindex, Txoutindex};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Addressindextxoutindex {
addressindex: Addressindex,
txoutindex: Txoutindex,
}
direct_repr!(Addressindextxoutindex);
impl From<(Addressindex, Txoutindex)> for Addressindextxoutindex {
fn from(value: (Addressindex, Txoutindex)) -> Self {
Self {
addressindex: value.0,
txoutindex: value.1,
}
}
}

View File

@@ -8,8 +8,10 @@ mod prefix;
mod slice;
mod timestamp;
mod txindex;
mod txinindex;
mod txoutindex;
mod version;
mod vin;
mod vout;
pub use addressbytes::*;
@@ -22,6 +24,8 @@ pub use prefix::*;
pub use slice::*;
pub use timestamp::*;
pub use txindex::*;
pub use txinindex::*;
pub use txoutindex::*;
pub use version::*;
pub use vin::*;
pub use vout::*;

View File

@@ -1,3 +1,5 @@
use std::hash::Hasher;
use biter::bitcoin::{BlockHash, Txid};
use derive_deref::Deref;
use snkrj::{direct_repr, Storable, UnsizedStorable};
@@ -9,23 +11,11 @@ pub struct AddressbytesPrefix([u8; 8]);
direct_repr!(AddressbytesPrefix);
impl From<(&Addressbytes, Addresstype)> for AddressbytesPrefix {
fn from((addressbytes, addresstype): (&Addressbytes, Addresstype)) -> Self {
let shorten = |slice: &[u8]| {
let len = slice.len();
let mut buf: [u8; 8] = [0; 8];
// Using both ends for collision reasons despite rehashing the addresses
(0..4_usize).for_each(|i| {
buf[i] = slice[i];
buf[4 + i] = slice[len - 4 + i];
});
buf[4] = addresstype as u8;
// Put in the middle and not at the start because either the first or the last byte can be used to split and if the type is used it wouldn't have the 0..256 range
// End result:
// [ i=0, i=1, i=2, i=3, type as u8, i=len-3, i=len-2, i=len-1 ]
buf
};
Self(shorten(
bitcoin_hashes::hash160::Hash::hash(addressbytes.as_slice()).as_byte_array(),
))
let mut hasher = rapidhash::RapidHasher::default();
hasher.write(addressbytes.as_slice());
let mut slice = hasher.finish().to_le_bytes();
slice[0] = slice[0].wrapping_add(addresstype as u8);
Self(slice)
}
}
impl From<[u8; 8]> for AddressbytesPrefix {

View File

@@ -1,28 +0,0 @@
use snkrj::{direct_repr, Storable, UnsizedStorable};
use super::Txindex;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
pub struct Txindexvout {
pub txindex: Txindex,
pub vout: u32,
}
direct_repr!(Txindexvout);
impl From<Txindex> for Txindexvout {
fn from(value: Txindex) -> Self {
Self {
txindex: value,
vout: 0,
}
}
}
impl From<(Txindex, u32)> for Txindexvout {
fn from(value: (Txindex, u32)) -> Self {
Self {
txindex: value.0,
vout: value.1,
}
}
}

View File

@@ -0,0 +1,62 @@
use std::ops::{Add, AddAssign};
use derive_deref::{Deref, DerefMut};
use snkrj::{direct_repr, Storable, UnsizedStorable};
use super::Vout;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Deref, DerefMut, Default)]
pub struct Txinindex(u64);
direct_repr!(Txinindex);
impl Txinindex {
pub fn incremented(self) -> Self {
Self(*self + 1)
}
pub fn decremented(self) -> Self {
Self(*self - 1)
}
}
impl Add<Txinindex> for Txinindex {
type Output = Self;
fn add(self, rhs: Txinindex) -> Self::Output {
Self(self.0 + rhs.0)
}
}
impl Add<Vout> for Txinindex {
type Output = Self;
fn add(self, rhs: Vout) -> Self::Output {
Self(self.0 + u64::from(rhs))
}
}
impl AddAssign<Txinindex> for Txinindex {
fn add_assign(&mut self, rhs: Txinindex) {
self.0 += rhs.0
}
}
impl From<u64> for Txinindex {
fn from(value: u64) -> Self {
Self(value)
}
}
impl From<Txinindex> for u64 {
fn from(value: Txinindex) -> Self {
value.0
}
}
impl From<usize> for Txinindex {
fn from(value: usize) -> Self {
Self(value as u64)
}
}
impl From<Txinindex> for usize {
fn from(value: Txinindex) -> Self {
value.0 as usize
}
}

View File

@@ -1,4 +1,7 @@
use std::ops::{Add, AddAssign};
use std::{
ops::{Add, AddAssign},
u64,
};
use derive_deref::{Deref, DerefMut};
use snkrj::{direct_repr, Storable, UnsizedStorable};
@@ -10,6 +13,8 @@ pub struct Txoutindex(u64);
direct_repr!(Txoutindex);
impl Txoutindex {
pub const MAX: Self = Self(u64::MAX);
pub fn incremented(self) -> Self {
Self(*self + 1)
}
@@ -17,6 +22,10 @@ impl Txoutindex {
pub fn decremented(self) -> Self {
Self(*self - 1)
}
pub fn is_coinbase(self) -> bool {
self == Self::MAX
}
}
impl Add<Txoutindex> for Txoutindex {

30
bindex/src/structs/vin.rs Normal file
View File

@@ -0,0 +1,30 @@
use derive_deref::Deref;
#[derive(Debug, Deref, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Vin(u32);
impl Vin {
const ZERO: Self = Vin(0_u32);
pub fn is_zero(&self) -> bool {
*self == Self::ZERO
}
}
impl From<u32> for Vin {
fn from(value: u32) -> Self {
Self(value)
}
}
impl From<usize> for Vin {
fn from(value: usize) -> Self {
Self(value as u32)
}
}
impl From<Vin> for u64 {
fn from(value: Vin) -> Self {
value.0 as u64
}
}