mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-06-11 23:43:32 -07:00
bitbase: pre-rayon snapshot
This commit is contained in:
@@ -0,0 +1 @@
|
||||
max_width = 120
|
||||
+277
-111
@@ -1,4 +1,4 @@
|
||||
use std::{path::Path, str::FromStr};
|
||||
use std::{collections::BTreeMap, path::Path, str::FromStr};
|
||||
|
||||
use biter::{
|
||||
bitcoin::{hashes::Hash, Txid},
|
||||
@@ -9,9 +9,10 @@ mod structs;
|
||||
|
||||
use color_eyre::eyre::{eyre, ContextCompat};
|
||||
use fjall::{PersistMode, Slice, TransactionalKeyspace, WriteTransaction};
|
||||
use rayon::prelude::*;
|
||||
use structs::{
|
||||
Addressbytes, Addressindex, Addresstxoutindex, Addresstype, Amount, Exit, Height, Partitions,
|
||||
Prefix, SliceExtended, Txindex, Txoutindex,
|
||||
Addressbytes, Addressindex, Addresstxoutindex, Addresstype, Amount, Exit, Height, Partitions, Prefix,
|
||||
SliceExtended, Txindex, Txoutindex,
|
||||
};
|
||||
|
||||
// https://github.com/fjall-rs/fjall/discussions/72
|
||||
@@ -19,6 +20,7 @@ use structs::{
|
||||
|
||||
const DAILY_BLOCK_TARGET: usize = 144;
|
||||
const MONTHLY_BLOCK_TARGET: usize = DAILY_BLOCK_TARGET * 30;
|
||||
const U16MAX: usize = u16::MAX as usize;
|
||||
|
||||
fn main() -> color_eyre::Result<()> {
|
||||
let i = std::time::Instant::now();
|
||||
@@ -38,18 +40,13 @@ fn main() -> color_eyre::Result<()> {
|
||||
let mut height = parts.start_height();
|
||||
|
||||
let mut txindex = wtx
|
||||
.get(parts.height_to_last_txindex.data(), Slice::from(height))?
|
||||
.get(parts.height_to_first_txindex.data(), Slice::from(height))?
|
||||
.map(Txindex::from)
|
||||
.map(Txindex::incremented)
|
||||
.unwrap_or(Txindex::default());
|
||||
|
||||
let mut addressindex = wtx
|
||||
.get(
|
||||
parts.height_to_last_addressindex.data(),
|
||||
Slice::from(height),
|
||||
)?
|
||||
.get(parts.height_to_first_addressindex.data(), Slice::from(height))?
|
||||
.map(Addressindex::from)
|
||||
.map(Addressindex::incremented)
|
||||
.unwrap_or(Addressindex::default());
|
||||
|
||||
let export = |keyspace: &TransactionalKeyspace,
|
||||
@@ -72,37 +69,35 @@ fn main() -> color_eyre::Result<()> {
|
||||
biter::new(data_dir, Some(height.into()), None, rpc)
|
||||
.iter()
|
||||
.try_for_each(|(_height, block, blockhash)| -> color_eyre::Result<()> {
|
||||
let mut wtx = wtx_opt.take().context("option should've wtx")?;
|
||||
|
||||
println!("Processing block {_height}...");
|
||||
|
||||
height = Height::from(_height);
|
||||
|
||||
let has_different_blockhash = wtx
|
||||
.get(parts.height_to_blockhash.data(), Slice::from(height))?
|
||||
.is_some_and(|saved_blockhash_slice| blockhash[..] != saved_blockhash_slice[..]);
|
||||
let mut wtx = wtx_opt.take().context("option should have wtx")?;
|
||||
|
||||
if has_different_blockhash {
|
||||
parts.rollback_from(&mut wtx, height, &exit)?;
|
||||
let saved_blockhash_slice_opt = wtx.get(parts.height_to_blockhash.data(), Slice::from(height))?;
|
||||
if let Some(saved_blockhash_slice) = saved_blockhash_slice_opt {
|
||||
if blockhash[..] != saved_blockhash_slice[..] {
|
||||
parts.rollback_from(&mut wtx, height, &exit)?;
|
||||
} else {
|
||||
wtx_opt.replace(wtx);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
if parts.blockhash_prefix_to_height.needs(height) {
|
||||
if let Some(prev) = wtx.fetch_update(
|
||||
parts.blockhash_prefix_to_height.data(),
|
||||
blockhash.prefix(),
|
||||
|_| Some(Slice::from(height)),
|
||||
)? {
|
||||
dbg!(prev);
|
||||
return Err(eyre!("Expect none"));
|
||||
if let Some(prev_height_slice) =
|
||||
wtx.fetch_update(parts.blockhash_prefix_to_height.data(), blockhash.prefix(), |_| {
|
||||
Some(Slice::from(height))
|
||||
})?
|
||||
{
|
||||
dbg!(blockhash, Height::from(prev_height_slice));
|
||||
return Err(eyre!("Collision, expect prefix to need be set yet"));
|
||||
}
|
||||
}
|
||||
|
||||
if parts.height_to_blockhash.needs(height) {
|
||||
wtx.insert(
|
||||
parts.height_to_blockhash.data(),
|
||||
Slice::from(height),
|
||||
blockhash,
|
||||
);
|
||||
wtx.insert(parts.height_to_blockhash.data(), Slice::from(height), blockhash);
|
||||
}
|
||||
|
||||
if parts.height_to_first_addressindex.needs(height) {
|
||||
@@ -116,8 +111,99 @@ fn main() -> color_eyre::Result<()> {
|
||||
let txlen = block.txdata.len();
|
||||
let last_txi = txlen - 1;
|
||||
|
||||
block.txdata.into_iter().enumerate().try_for_each(
|
||||
|(txi, tx)| -> color_eyre::Result<()> {
|
||||
let mut txi_to_txid_and_prev_txindex_slice_opt = block
|
||||
.txdata
|
||||
.par_iter()
|
||||
.enumerate()
|
||||
.map(|(txi, tx)| -> color_eyre::Result<(usize, (Txid, Option<Slice>))> {
|
||||
let txid = tx.compute_txid();
|
||||
|
||||
let prev_txindex_slice_opt = wtx.get(parts.txid_prefix_to_txindex.data(), txid.prefix())?;
|
||||
|
||||
Ok((txi, (txid, prev_txindex_slice_opt)))
|
||||
})
|
||||
.try_fold(
|
||||
|| -> BTreeMap<usize, (Txid, Option<Slice>)> { BTreeMap::default() },
|
||||
|mut map, tuple| -> color_eyre::Result<BTreeMap<usize, (Txid, Option<Slice>)>> {
|
||||
let (txi, tuple) = tuple?;
|
||||
map.insert(txi, tuple);
|
||||
Ok(map)
|
||||
},
|
||||
)
|
||||
.try_reduce(BTreeMap::default, |mut map, mut map2| {
|
||||
if map.len() > map2.len() {
|
||||
map.append(&mut map2);
|
||||
Ok(map)
|
||||
} else {
|
||||
map2.append(&mut map);
|
||||
Ok(map2)
|
||||
}
|
||||
})?;
|
||||
|
||||
// let addresstxoutindexes_out = block
|
||||
// .txdata
|
||||
// .par_iter()
|
||||
// .filter(|tx| !tx.is_coinbase())
|
||||
// .flat_map(|tx| &tx.input)
|
||||
// .try_fold(
|
||||
// || -> Vec<Addresstxoutindex> { vec![] },
|
||||
// |mut vec, txin| -> color_eyre::Result<Vec<Addresstxoutindex>> {
|
||||
// let outpoint = txin.previous_output;
|
||||
// let txid_prefix = outpoint.txid.prefix();
|
||||
// let vout = outpoint.vout as u16;
|
||||
|
||||
// let txindex = Txindex::from(
|
||||
// wtx.get(parts.txid_prefix_to_txindex.data(), txid_prefix)?
|
||||
// .context("Expect txid to be saved")?,
|
||||
// );
|
||||
|
||||
// let txoutindex = Txoutindex::from((txindex, vout));
|
||||
|
||||
// let addressindex = Addressindex::from(
|
||||
// wtx.get(parts.txoutindex_to_addressindex.data(), Slice::from(txoutindex))?
|
||||
// .context("Expect addressindex to not be none")
|
||||
// .inspect_err(|_| {
|
||||
// let height = Height::from(
|
||||
// wtx.get(parts.txindex_to_height.data(), Slice::from(txindex))
|
||||
// .expect("txindex_to_height get not fail")
|
||||
// .expect("Expect height for txindex"),
|
||||
// );
|
||||
// dbg!(outpoint.txid, txindex, vout, txoutindex, height);
|
||||
// })?,
|
||||
// );
|
||||
|
||||
// if parts.addresstxoutindexes_out.needs(height) {
|
||||
// vec.push(Addresstxoutindex::from((addressindex, txoutindex)));
|
||||
// }
|
||||
|
||||
// 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)
|
||||
// }
|
||||
// })?;
|
||||
|
||||
// addresstxoutindexes_out.into_iter().for_each(|addresstxoutindex| {
|
||||
// wtx.insert(
|
||||
// parts.addresstxoutindexes_out.data(),
|
||||
// Slice::from(addresstxoutindex),
|
||||
// Slice::default(),
|
||||
// );
|
||||
// });
|
||||
|
||||
block
|
||||
.txdata
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.try_for_each(|(txi, tx)| -> color_eyre::Result<()> {
|
||||
let is_coinbase = tx.is_coinbase();
|
||||
|
||||
if txi == 0 && parts.height_to_first_txindex.needs(height) {
|
||||
wtx.insert(
|
||||
parts.height_to_first_txindex.data(),
|
||||
@@ -133,44 +219,47 @@ fn main() -> color_eyre::Result<()> {
|
||||
);
|
||||
}
|
||||
|
||||
if parts.txindex_to_txid.needs(height)
|
||||
|| parts.txid_prefix_to_txindex.needs(height)
|
||||
{
|
||||
let txid = tx.compute_txid();
|
||||
let mut bad_tx = false;
|
||||
|
||||
if parts.txindex_to_txid.needs(height) {
|
||||
wtx.insert(parts.txindex_to_txid.data(), Slice::from(txindex), txid);
|
||||
let (txid, prev_txindex_slice_opt) = txi_to_txid_and_prev_txindex_slice_opt
|
||||
.remove(&txi)
|
||||
.context("Par compute of tx should have worked")
|
||||
.inspect_err(|_| {
|
||||
dbg!(&txi_to_txid_and_prev_txindex_slice_opt, &txi, tx.compute_txid());
|
||||
})?;
|
||||
|
||||
if parts.txindex_to_txid.needs(height) {
|
||||
wtx.insert(parts.txindex_to_txid.data(), Slice::from(txindex), txid);
|
||||
}
|
||||
|
||||
match prev_txindex_slice_opt {
|
||||
None => {
|
||||
if parts.txid_prefix_to_txindex.needs(height) {
|
||||
wtx.insert(parts.txid_prefix_to_txindex.data(), txid.prefix(), Slice::from(txindex));
|
||||
}
|
||||
}
|
||||
Some(prev_txindex_slice) => {
|
||||
let prev_txid = Txid::from_slice(
|
||||
&wtx.get(parts.txindex_to_txid.data(), &prev_txindex_slice)?
|
||||
.expect("To have txid for txindex"),
|
||||
)?;
|
||||
|
||||
if parts.txid_prefix_to_txindex.needs(height) {
|
||||
if let Some(prev) = wtx.fetch_update(
|
||||
parts.txid_prefix_to_txindex.data(),
|
||||
txid.prefix(),
|
||||
|_| Some(Slice::from(txindex)),
|
||||
)? {
|
||||
let prev_txid = Txid::from_slice(&wtx
|
||||
.get(parts.txindex_to_txid.data(), &prev)?.expect("To have txid for txindex"))?;
|
||||
let only_known_dup_txids = [
|
||||
Txid::from_str("d5d27987d2a3dfc724e359870c6644b40e497bdc0589a033220fe15429d88599")?,
|
||||
Txid::from_str("e3bf3d07d4b0375638d5f1db5255fe07ba2c4cb067cd81b84ee974b6585fb468")?,
|
||||
];
|
||||
|
||||
let only_known_dup_txids = [Txid::from_str("d5d27987d2a3dfc724e359870c6644b40e497bdc0589a033220fe15429d88599")?, Txid::from_str("e3bf3d07d4b0375638d5f1db5255fe07ba2c4cb067cd81b84ee974b6585fb468")?];
|
||||
let is_dup = only_known_dup_txids.contains(&prev_txid);
|
||||
bad_tx = is_dup;
|
||||
|
||||
// TODO
|
||||
// link txindex to txid
|
||||
// txid_prefix should point to the first vout so no override
|
||||
// do not add vout as they're invalid
|
||||
|
||||
if !only_known_dup_txids.contains(&prev_txid) {
|
||||
let prev_height = Height::from(wtx.get(parts.txindex_to_height.data(), &prev)?.expect("To have height"));
|
||||
let prev_txindex = Txindex::from(prev);
|
||||
dbg!(
|
||||
height,
|
||||
txid,
|
||||
txindex,
|
||||
prev_height,
|
||||
prev_txid,
|
||||
prev_txindex,
|
||||
);
|
||||
return Err(eyre!("Expect none"));
|
||||
}
|
||||
if !is_dup {
|
||||
let prev_height = Height::from(
|
||||
wtx.get(parts.txindex_to_height.data(), &prev_txindex_slice)?
|
||||
.expect("To have height"),
|
||||
);
|
||||
let prev_txindex = Txindex::from(prev_txindex_slice);
|
||||
dbg!(height, txid, txindex, prev_height, prev_txid, prev_txindex,);
|
||||
return Err(eyre!("Expect none"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,15 +272,90 @@ fn main() -> color_eyre::Result<()> {
|
||||
);
|
||||
}
|
||||
|
||||
txindex.increment();
|
||||
tx.input
|
||||
.par_iter()
|
||||
// .into_par_iter()
|
||||
.try_fold(
|
||||
|| -> Vec<Addresstxoutindex> { vec![] },
|
||||
|mut vec, txin| -> color_eyre::Result<Vec<Addresstxoutindex>> {
|
||||
if is_coinbase {
|
||||
return Ok(vec);
|
||||
}
|
||||
|
||||
let outpoint = txin.previous_output;
|
||||
let txid_prefix = outpoint.txid.prefix();
|
||||
let vout = outpoint.vout as u16;
|
||||
|
||||
let txindex = Txindex::from(
|
||||
wtx.get(parts.txid_prefix_to_txindex.data(), txid_prefix)?
|
||||
.context("Expect txid to be saved")?,
|
||||
);
|
||||
|
||||
let txoutindex = Txoutindex::from((txindex, vout));
|
||||
|
||||
let addressindex = Addressindex::from(
|
||||
wtx.get(parts.txoutindex_to_addressindex.data(), Slice::from(txoutindex))?
|
||||
.context("Expect addressindex to not be none")
|
||||
.inspect_err(|_| {
|
||||
let height = Height::from(
|
||||
wtx.get(parts.txindex_to_height.data(), Slice::from(txindex))
|
||||
.expect("txindex_to_height get not fail")
|
||||
.expect("Expect height for txindex"),
|
||||
);
|
||||
dbg!(txid, outpoint.txid, txindex, vout, txoutindex, height);
|
||||
})?,
|
||||
);
|
||||
|
||||
if bad_tx {
|
||||
dbg!(tx.compute_txid(), outpoint);
|
||||
panic!("bad tx in input")
|
||||
}
|
||||
if !bad_tx && parts.addresstxoutindexes_out.needs(height) {
|
||||
vec.push(Addresstxoutindex::from((addressindex, txoutindex)));
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
})?
|
||||
.into_iter()
|
||||
.for_each(|addresstxoutindex| {
|
||||
wtx.insert(
|
||||
parts.addresstxoutindexes_out.data(),
|
||||
Slice::from(addresstxoutindex),
|
||||
Slice::default(),
|
||||
);
|
||||
});
|
||||
|
||||
tx.output
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.try_for_each(|(vout, txout)| -> color_eyre::Result<()> {
|
||||
if vout > U16MAX {
|
||||
return Err(eyre!("vout bigger than u16::MAX"));
|
||||
}
|
||||
|
||||
tx.output.iter().enumerate().try_for_each(
|
||||
|(vout, txout)| -> color_eyre::Result<()> {
|
||||
let vout = vout as u16;
|
||||
let txoutindex = Txoutindex::from((txindex, vout));
|
||||
let amount = Amount::from(txout.value);
|
||||
|
||||
if parts.txoutindex_to_amount.needs(height) {
|
||||
if amount.is_zero() {
|
||||
if parts.zero_txoutindexes.needs(height) {
|
||||
wtx.insert(
|
||||
parts.zero_txoutindexes.data(),
|
||||
Slice::from(txoutindex),
|
||||
Slice::default(),
|
||||
);
|
||||
}
|
||||
} else if parts.txoutindex_to_amount.needs(height) {
|
||||
wtx.insert(
|
||||
parts.txoutindex_to_amount.data(),
|
||||
Slice::from(txoutindex),
|
||||
@@ -201,40 +365,24 @@ fn main() -> color_eyre::Result<()> {
|
||||
|
||||
let script = &txout.script_pubkey;
|
||||
|
||||
let addresstype = Addresstype::from(script);
|
||||
let addressbytes =
|
||||
Addressbytes::try_from((script, addresstype, addressindex))
|
||||
.inspect_err(|_| {
|
||||
dbg!(&txout, height, txi, &tx.compute_txid());
|
||||
})?;
|
||||
|
||||
let mut addressindex_local = addressindex;
|
||||
|
||||
if let Some(addressindex_slice) = wtx.get(
|
||||
parts.addressbytes_prefix_to_addressindex.data(),
|
||||
Slice::from(&addressbytes),
|
||||
)? {
|
||||
let addresstype = Addresstype::from(script);
|
||||
|
||||
let addressbytes = Addressbytes::try_from((script, addresstype)).inspect_err(|_| {
|
||||
// dbg!(&txout, height, txi, &tx.compute_txid());
|
||||
});
|
||||
|
||||
if let Some(addressindex_slice) = addressbytes.as_ref().ok().and_then(|addressbytes| {
|
||||
wtx.get(
|
||||
parts.addressbytes_prefix_to_addressindex.data(),
|
||||
Slice::from(addressbytes),
|
||||
)
|
||||
.ok()
|
||||
.and_then(|s| s)
|
||||
}) {
|
||||
addressindex_local = addressindex_slice.into()
|
||||
} else {
|
||||
if parts.addressbytes_prefix_to_addressindex.needs(height) {
|
||||
if let Some(prev) = wtx.fetch_update(
|
||||
parts.addressbytes_prefix_to_addressindex.data(),
|
||||
Slice::from(&addressbytes),
|
||||
|_| Some(Slice::from(addressindex_local)),
|
||||
)? {
|
||||
dbg!(prev);
|
||||
return Err(eyre!("Expect none"));
|
||||
}
|
||||
}
|
||||
|
||||
if parts.addressindex_to_addressbytes.needs(height) {
|
||||
wtx.insert(
|
||||
parts.addressindex_to_addressbytes.data(),
|
||||
Slice::from(addressindex_local),
|
||||
Slice::from(&addressbytes),
|
||||
);
|
||||
}
|
||||
|
||||
if parts.addressindex_to_addresstype.needs(height) {
|
||||
wtx.insert(
|
||||
parts.addressindex_to_addresstype.data(),
|
||||
@@ -243,6 +391,27 @@ fn main() -> color_eyre::Result<()> {
|
||||
);
|
||||
}
|
||||
|
||||
if let Ok(addressbytes) = addressbytes {
|
||||
if parts.addressbytes_prefix_to_addressindex.needs(height) {
|
||||
if let Some(prev) = wtx.fetch_update(
|
||||
parts.addressbytes_prefix_to_addressindex.data(),
|
||||
Slice::from(&addressbytes),
|
||||
|_| Some(Slice::from(addressindex_local)),
|
||||
)? {
|
||||
dbg!(prev);
|
||||
return Err(eyre!("Expect none"));
|
||||
}
|
||||
}
|
||||
|
||||
if parts.addressindex_to_addressbytes.needs(height) {
|
||||
wtx.insert(
|
||||
parts.addressindex_to_addressbytes.data(),
|
||||
Slice::from(addressindex_local),
|
||||
Slice::from(&addressbytes),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
addressindex.increment();
|
||||
}
|
||||
|
||||
@@ -254,24 +423,23 @@ fn main() -> color_eyre::Result<()> {
|
||||
);
|
||||
}
|
||||
|
||||
if parts.addresstxoutindexes.needs(height) {
|
||||
let addresstxoutindex = Addresstxoutindex::from((addressindex_local, txoutindex));
|
||||
|
||||
if !bad_tx && parts.addresstxoutindexes_in.needs(height) {
|
||||
wtx.insert(
|
||||
parts.addresstxoutindexes.data(),
|
||||
Slice::from(Addresstxoutindex::from((
|
||||
addressindex_local,
|
||||
txoutindex,
|
||||
))),
|
||||
parts.addresstxoutindexes_in.data(),
|
||||
Slice::from(addresstxoutindex),
|
||||
Slice::default(),
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
})?;
|
||||
|
||||
txindex.increment();
|
||||
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
})?;
|
||||
|
||||
if parts.height_to_last_addressindex.needs(height) {
|
||||
wtx.insert(
|
||||
@@ -292,9 +460,7 @@ fn main() -> color_eyre::Result<()> {
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let wtx = wtx_opt
|
||||
.take()
|
||||
.context("option should have WriteTransaction")?;
|
||||
let wtx = wtx_opt.take().context("option should have WriteTransaction")?;
|
||||
export(&keyspace, wtx, &parts, height)?;
|
||||
|
||||
dbg!(i.elapsed());
|
||||
|
||||
@@ -3,60 +3,54 @@ use color_eyre::eyre::eyre;
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use fjall::Slice;
|
||||
|
||||
use super::{Addressindex, Addresstype};
|
||||
use super::Addresstype;
|
||||
|
||||
#[derive(Debug, Deref, DerefMut)]
|
||||
pub struct Addressbytes(Slice);
|
||||
|
||||
impl TryFrom<(&ScriptBuf, Addresstype, Addressindex)> for Addressbytes {
|
||||
impl TryFrom<(&ScriptBuf, Addresstype)> for Addressbytes {
|
||||
type Error = color_eyre::Report;
|
||||
fn try_from(tuple: (&ScriptBuf, Addresstype, Addressindex)) -> Result<Self, Self::Error> {
|
||||
let (script, addresstype, addressindex) = tuple;
|
||||
fn try_from(tuple: (&ScriptBuf, Addresstype)) -> Result<Self, Self::Error> {
|
||||
let (script, addresstype) = tuple;
|
||||
|
||||
match addresstype {
|
||||
Addresstype::P2PK => {
|
||||
let bytes = script.as_bytes();
|
||||
let bytes = match bytes.len() {
|
||||
67 => &script.as_bytes()[1..66],
|
||||
35 => &script.as_bytes()[1..34],
|
||||
67 => &bytes[1..66],
|
||||
35 => &bytes[1..34],
|
||||
_ => {
|
||||
dbg!(bytes);
|
||||
return Err(eyre!("Wrong len"));
|
||||
}
|
||||
};
|
||||
|
||||
if bytes[0] != 4 {
|
||||
dbg!(bytes);
|
||||
return Err(eyre!("Doesn't start with a 4"));
|
||||
}
|
||||
|
||||
Ok(Self(bytes.into()))
|
||||
}
|
||||
Addresstype::P2PKH => {
|
||||
let bytes = &script.as_bytes()[3..23];
|
||||
Ok(Self(bytes.into()))
|
||||
}
|
||||
_ => {
|
||||
if script.is_p2sh() {
|
||||
Err(eyre!("p2sh address type"))
|
||||
} else if script.is_p2wpkh() {
|
||||
Err(eyre!("p2wpkh address type"))
|
||||
} else if script.is_p2wsh() {
|
||||
Err(eyre!("p2wsh address type"))
|
||||
} else if script.is_p2tr() {
|
||||
Err(eyre!("p2tr address type"))
|
||||
} else if script.is_empty() {
|
||||
Err(eyre!("empty address type"))
|
||||
} else if script.is_op_return() {
|
||||
Err(eyre!("op_return address type"))
|
||||
} else if script.is_multisig() {
|
||||
Err(eyre!("multisig address type"))
|
||||
} else if script.is_push_only() {
|
||||
Err(eyre!("push only address type"))
|
||||
} else {
|
||||
Ok(Self(addressindex.into()))
|
||||
}
|
||||
Addresstype::P2SH => {
|
||||
let bytes = &script.as_bytes()[2..22];
|
||||
Ok(Self(bytes.into()))
|
||||
}
|
||||
Addresstype::P2WPKH => {
|
||||
let bytes = &script.as_bytes()[2..];
|
||||
Ok(Self(bytes.into()))
|
||||
}
|
||||
Addresstype::P2WSH => {
|
||||
let bytes = &script.as_bytes()[2..];
|
||||
Ok(Self(bytes.into()))
|
||||
}
|
||||
Addresstype::P2TR => {
|
||||
let bytes = &script.as_bytes()[2..];
|
||||
Ok(Self(bytes.into()))
|
||||
}
|
||||
Addresstype::Multisig => Err(eyre!("multisig address type")),
|
||||
Addresstype::PushOnly => Err(eyre!("push_only address type")),
|
||||
Addresstype::Unknown => Err(eyre!("unknown address type")),
|
||||
Addresstype::Empty => Err(eyre!("empty address type")),
|
||||
Addresstype::OpReturn => Err(eyre!("op_return address type")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,9 +18,9 @@ impl From<(Addressindex, Txoutindex)> for Addresstxoutindex {
|
||||
|
||||
impl From<Addresstxoutindex> for Slice {
|
||||
fn from(value: Addresstxoutindex) -> Self {
|
||||
let txindex_slice = Self::from(value.addressindex);
|
||||
let vout_slice = Self::from(value.txoutindex);
|
||||
Self::from([txindex_slice, vout_slice].concat())
|
||||
let addressindex_slice = Self::from(value.addressindex);
|
||||
let txoutindex_slice = Self::from(value.txoutindex);
|
||||
Self::from([addressindex_slice, txoutindex_slice].concat())
|
||||
}
|
||||
}
|
||||
impl From<Slice> for Addresstxoutindex {
|
||||
|
||||
@@ -16,6 +16,10 @@ impl Amount {
|
||||
pub const ZERO: Self = Self(bitcoin::Amount::ZERO);
|
||||
pub const ONE_BTC_F32: f32 = 100_000_000.0;
|
||||
pub const ONE_BTC_F64: f64 = 100_000_000.0;
|
||||
|
||||
pub fn is_zero(&self) -> bool {
|
||||
*self == Self::ZERO
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for Amount {
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
pub use fjall::{
|
||||
PartitionCreateOptions, PersistMode, Result, TransactionalKeyspace,
|
||||
TransactionalPartitionHandle,
|
||||
};
|
||||
pub use fjall::{PartitionCreateOptions, PersistMode, Result, TransactionalKeyspace, TransactionalPartitionHandle};
|
||||
|
||||
use crate::structs::{Height, Version};
|
||||
|
||||
@@ -18,12 +15,7 @@ impl Partition {
|
||||
pub const VERSION: &str = "version";
|
||||
pub const HEIGHT: &str = "height";
|
||||
|
||||
pub fn import(
|
||||
keyspace: &TransactionalKeyspace,
|
||||
name: &str,
|
||||
version: Version,
|
||||
exit: &Exit,
|
||||
) -> Result<Self> {
|
||||
pub fn import(keyspace: &TransactionalKeyspace, name: &str, version: Version, exit: &Exit) -> Result<Self> {
|
||||
let data = Self::open_data(keyspace, name)?;
|
||||
let meta = Self::open_meta(keyspace, name)?;
|
||||
|
||||
@@ -43,17 +35,11 @@ impl Partition {
|
||||
Ok(this)
|
||||
}
|
||||
|
||||
fn open_data(
|
||||
keyspace: &TransactionalKeyspace,
|
||||
name: &str,
|
||||
) -> Result<TransactionalPartitionHandle> {
|
||||
fn open_data(keyspace: &TransactionalKeyspace, name: &str) -> Result<TransactionalPartitionHandle> {
|
||||
keyspace.open_partition(&format!("{name}-data"), Self::create_options())
|
||||
}
|
||||
|
||||
fn open_meta(
|
||||
keyspace: &TransactionalKeyspace,
|
||||
name: &str,
|
||||
) -> Result<TransactionalPartitionHandle> {
|
||||
fn open_meta(keyspace: &TransactionalKeyspace, name: &str) -> Result<TransactionalPartitionHandle> {
|
||||
keyspace.open_partition(&format!("{name}-meta"), Self::create_options())
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ pub struct Partitions {
|
||||
pub addressbytes_prefix_to_addressindex: Partition,
|
||||
pub addressindex_to_addressbytes: Partition,
|
||||
pub addressindex_to_addresstype: Partition,
|
||||
pub addresstxoutindexes: Partition,
|
||||
pub addresstxoutindexes_in: Partition,
|
||||
pub addresstxoutindexes_out: Partition,
|
||||
pub blockhash_prefix_to_height: Partition,
|
||||
pub height_to_blockhash: Partition,
|
||||
pub height_to_first_addressindex: Partition,
|
||||
@@ -20,6 +21,7 @@ pub struct Partitions {
|
||||
pub txindex_to_txid: Partition,
|
||||
pub txoutindex_to_addressindex: Partition,
|
||||
pub txoutindex_to_amount: Partition,
|
||||
pub zero_txoutindexes: Partition,
|
||||
}
|
||||
|
||||
const UNSAFE_BLOCKS: usize = 100;
|
||||
@@ -45,78 +47,40 @@ impl Partitions {
|
||||
Version::from(1),
|
||||
exit,
|
||||
)?,
|
||||
addresstxoutindexes: Partition::import(
|
||||
keyspace,
|
||||
"addresstxoutindexes",
|
||||
Version::from(1),
|
||||
exit,
|
||||
)?,
|
||||
addresstxoutindexes_in: Partition::import(keyspace, "addresstxoutindexes_in", Version::from(1), exit)?,
|
||||
addresstxoutindexes_out: Partition::import(keyspace, "addresstxoutindexes_out", Version::from(1), exit)?,
|
||||
blockhash_prefix_to_height: Partition::import(
|
||||
keyspace,
|
||||
"blockhash_prefix_to_height",
|
||||
Version::from(1),
|
||||
exit,
|
||||
)?,
|
||||
height_to_blockhash: Partition::import(
|
||||
keyspace,
|
||||
"height_to_blockhash",
|
||||
Version::from(1),
|
||||
exit,
|
||||
)?,
|
||||
height_to_blockhash: Partition::import(keyspace, "height_to_blockhash", Version::from(1), exit)?,
|
||||
height_to_first_addressindex: Partition::import(
|
||||
keyspace,
|
||||
"height_to_first_addressindex",
|
||||
Version::from(1),
|
||||
exit,
|
||||
)?,
|
||||
height_to_first_txindex: Partition::import(
|
||||
keyspace,
|
||||
"height_to_first_txindex",
|
||||
Version::from(1),
|
||||
exit,
|
||||
)?,
|
||||
height_to_first_txindex: Partition::import(keyspace, "height_to_first_txindex", Version::from(1), exit)?,
|
||||
height_to_last_addressindex: Partition::import(
|
||||
keyspace,
|
||||
"height_to_last_addressindex",
|
||||
Version::from(1),
|
||||
exit,
|
||||
)?,
|
||||
height_to_last_txindex: Partition::import(
|
||||
keyspace,
|
||||
"height_to_last_txindex",
|
||||
Version::from(1),
|
||||
exit,
|
||||
)?,
|
||||
txid_prefix_to_txindex: Partition::import(
|
||||
keyspace,
|
||||
"txid_prefix_to_txindex",
|
||||
Version::from(1),
|
||||
exit,
|
||||
)?,
|
||||
txindex_to_height: Partition::import(
|
||||
keyspace,
|
||||
"txindex_to_height",
|
||||
Version::from(1),
|
||||
exit,
|
||||
)?,
|
||||
txindex_to_txid: Partition::import(
|
||||
keyspace,
|
||||
"txindex_to_txid",
|
||||
Version::from(1),
|
||||
exit,
|
||||
)?,
|
||||
height_to_last_txindex: Partition::import(keyspace, "height_to_last_txindex", Version::from(1), exit)?,
|
||||
txid_prefix_to_txindex: Partition::import(keyspace, "txid_prefix_to_txindex", Version::from(1), exit)?,
|
||||
txindex_to_height: Partition::import(keyspace, "txindex_to_height", Version::from(1), exit)?,
|
||||
txindex_to_txid: Partition::import(keyspace, "txindex_to_txid", Version::from(1), exit)?,
|
||||
txoutindex_to_addressindex: Partition::import(
|
||||
keyspace,
|
||||
"txoutindex_to_addressindex",
|
||||
Version::from(1),
|
||||
exit,
|
||||
)?,
|
||||
txoutindex_to_amount: Partition::import(
|
||||
keyspace,
|
||||
"txoutindex_to_amount",
|
||||
Version::from(1),
|
||||
exit,
|
||||
)?,
|
||||
txoutindex_to_amount: Partition::import(keyspace, "txoutindex_to_amount", Version::from(1), exit)?,
|
||||
zero_txoutindexes: Partition::import(keyspace, "zero_txoutindexes", Version::from(1), exit)?,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -252,6 +216,11 @@ impl Partitions {
|
||||
|
||||
// Ok(())
|
||||
// })?;
|
||||
//
|
||||
|
||||
// todo!("clear addresstxoutindexes_out")
|
||||
// todo!("clear addresstxoutindexes_in")
|
||||
// todo!("clear zero_txoutindexes")
|
||||
|
||||
// Ok(())
|
||||
}
|
||||
@@ -261,7 +230,8 @@ impl Partitions {
|
||||
&self.addressbytes_prefix_to_addressindex,
|
||||
&self.addressindex_to_addressbytes,
|
||||
&self.addressindex_to_addresstype,
|
||||
&self.addresstxoutindexes,
|
||||
&self.addresstxoutindexes_in,
|
||||
&self.addresstxoutindexes_out,
|
||||
&self.blockhash_prefix_to_height,
|
||||
&self.height_to_blockhash,
|
||||
&self.height_to_first_addressindex,
|
||||
@@ -273,6 +243,7 @@ impl Partitions {
|
||||
&self.txindex_to_txid,
|
||||
&self.txoutindex_to_addressindex,
|
||||
&self.txoutindex_to_amount,
|
||||
&self.zero_txoutindexes,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user