global: from custom unsafe_slice to zerocopy

This commit is contained in:
nym21
2025-02-05 16:42:53 +01:00
parent 138ca80c10
commit d86d614520
43 changed files with 684 additions and 366 deletions
+17 -15
View File
@@ -9,7 +9,7 @@ use std::{
pub use biter::*;
use bitcoin::{Transaction, TxIn, TxOut, Txid};
use bitcoin::{Transaction, TxIn, TxOut};
use color_eyre::eyre::{eyre, ContextCompat};
use exit::Exit;
use rayon::prelude::*;
@@ -19,7 +19,7 @@ mod storage;
mod structs;
pub use storage::{AnyStorableVec, StorableVec, Store, StoreMeta};
pub use structs::Version;
use structs::{BlockHash, Txid};
use storage::{Fjalls, StorableVecs};
pub use structs::{
@@ -98,6 +98,7 @@ impl Indexer<CACHED_GETS> {
.try_for_each(|(_height, block, blockhash)| -> color_eyre::Result<()> {
println!("Processing block {_height}...");
let blockhash = BlockHash::from(blockhash);
height = Height::from(_height);
if let Some(saved_blockhash) = vecs.height_to_blockhash.get(height)? {
@@ -124,9 +125,9 @@ impl Indexer<CACHED_GETS> {
vecs.height_to_blockhash.push_if_needed(height, blockhash)?;
vecs.height_to_difficulty.push_if_needed(height, block.header.difficulty_float())?;
vecs.height_to_timestamp.push_if_needed(height, Timestamp::try_from(block.header.time)?)?;
vecs.height_to_timestamp.push_if_needed(height, Timestamp::from(block.header.time))?;
vecs.height_to_size.push_if_needed(height, block.total_size())?;
vecs.height_to_weight.push_if_needed(height, block.weight())?;
vecs.height_to_weight.push_if_needed(height, block.weight().into())?;
vecs.height_to_first_txindex.push_if_needed(height, txindex_global)?;
vecs.height_to_first_txinindex
.push_if_needed(height, txinindex_global)?;
@@ -192,7 +193,7 @@ impl Indexer<CACHED_GETS> {
.par_iter()
.enumerate()
.map(|(index, tx)| -> color_eyre::Result<_> {
let txid = tx.compute_txid();
let txid = Txid::from(tx.compute_txid());
let txid_prefix = TxidPrefix::try_from(&txid)?;
@@ -233,6 +234,7 @@ impl Indexer<CACHED_GETS> {
// dbg!((txindex, txinindex, vin));
let outpoint = txin.previous_output;
let txid = Txid::from(outpoint.txid);
if tx.is_coinbase() {
return Ok((txinindex, InputSource::SameBlock((tx, txindex, txin, vin))));
@@ -240,7 +242,7 @@ impl Indexer<CACHED_GETS> {
let prev_txindex = if let Some(txindex) = trees
.txid_prefix_to_txindex
.get(&TxidPrefix::try_from(&outpoint.txid)?)?
.get(&TxidPrefix::try_from(&txid)?)?
.map(|v| *v)
.and_then(|txindex| {
// Checking if not finding txindex from the future
@@ -537,7 +539,7 @@ impl Indexer<CACHED_GETS> {
}
let outpoint = txin.previous_output;
let txid = outpoint.txid;
let txid = Txid::from(outpoint.txid);
let vout = Vout::from(outpoint.vout);
let block_txindex = txid_prefix_to_txid_and_block_txindex_and_prev_txindex
@@ -604,7 +606,7 @@ impl Indexer<CACHED_GETS> {
.get(prev_txindex)?
.context("To have txid for txindex")
.inspect_err(|_| {
dbg!(txindex, txid, len);
dbg!(txindex, len);
})?;
// #[allow(clippy::redundant_locals)]
@@ -614,12 +616,12 @@ impl Indexer<CACHED_GETS> {
// If another Txid needs to be added to the list
// We need to check that it's also a coinbase tx otherwise par_iter inputs needs to be updated
let only_known_dup_txids = [
Txid::from_str(
bitcoin::Txid::from_str(
"d5d27987d2a3dfc724e359870c6644b40e497bdc0589a033220fe15429d88599",
)?,
Txid::from_str(
)?.into(),
bitcoin::Txid::from_str(
"e3bf3d07d4b0375638d5f1db5255fe07ba2c4cb067cd81b84ee974b6585fb468",
)?,
)?.into(),
];
let is_dup = only_known_dup_txids.contains(prev_txid);
@@ -627,7 +629,7 @@ impl Indexer<CACHED_GETS> {
if !is_dup {
let prev_height =
vecs.txindex_to_height.get(prev_txindex)?.expect("To have height");
dbg!(height, txid, txindex, prev_height, prev_txid, prev_txindex);
dbg!(height, txindex, prev_height, prev_txid, prev_txindex);
return Err(eyre!("Expect none"));
}
}
@@ -640,10 +642,10 @@ impl Indexer<CACHED_GETS> {
txindex_to_tx_and_txid
.into_iter()
.try_for_each(|(txindex, (tx, txid))| -> color_eyre::Result<()> {
vecs.txindex_to_txversion.push_if_needed(txindex, tx.version)?;
vecs.txindex_to_txversion.push_if_needed(txindex, tx.version.into())?;
vecs.txindex_to_txid.push_if_needed(txindex, txid)?;
vecs.txindex_to_height.push_if_needed(txindex, height)?;
vecs.txindex_to_locktime.push_if_needed(txindex, tx.lock_time)?;
vecs.txindex_to_locktime.push_if_needed(txindex, tx.lock_time.into())?;
Ok(())
})?;
+5 -5
View File
@@ -4,10 +4,10 @@ use fjall::{
PartitionCreateOptions, PersistMode, ReadTransaction, Result, Slice, TransactionalKeyspace,
TransactionalPartitionHandle,
};
use storable_vec::Value;
use unsafe_slice_serde::UnsafeSliceSerde;
use storable_vec::{Value, Version};
use zerocopy::{Immutable, IntoBytes};
use crate::structs::{Height, Version};
use crate::structs::Height;
use super::StoreMeta;
@@ -21,7 +21,7 @@ pub struct Store<Key, Value> {
impl<K, V> Store<K, V>
where
K: Into<Slice> + Ord,
K: Into<Slice> + Ord + Immutable + IntoBytes,
V: Into<Slice> + TryFrom<Slice>,
<V as TryFrom<Slice>>::Error: error::Error + Send + Sync + 'static,
{
@@ -54,7 +54,7 @@ where
pub fn get(&self, key: &K) -> color_eyre::Result<Option<Value<V>>> {
if let Some(v) = self.puts.get(key) {
Ok(Some(Value::Ref(v)))
} else if let Some(slice) = self.rtx.get(&self.part, key.unsafe_as_slice())? {
} else if let Some(slice) = self.rtx.get(&self.part, key.as_bytes())? {
Ok(Some(Value::Owned(V::try_from(slice)?)))
} else {
Ok(None)
+5 -4
View File
@@ -3,9 +3,10 @@ use std::{
path::{Path, PathBuf},
};
use unsafe_slice_serde::UnsafeSliceSerde;
use storable_vec::Version;
use zerocopy::{FromBytes, IntoBytes};
use super::{Height, Version};
use super::Height;
pub struct StoreMeta {
pathbuf: PathBuf,
@@ -87,14 +88,14 @@ impl StoreMeta {
// }
fn read_length_(path: &Path) -> color_eyre::Result<usize> {
Ok(fs::read(Self::path_length(path))
.map(|v| usize::unsafe_try_from_slice(v.as_slice()).cloned().unwrap_or_default())
.map(|v| usize::read_from_bytes(v.as_slice()).unwrap_or_default())
.unwrap_or_default())
}
fn write_length(&self) -> io::Result<()> {
Self::write_length_(&self.pathbuf, self.len)
}
fn write_length_(path: &Path, len: usize) -> Result<(), io::Error> {
fs::write(Self::path_length(path), len.to_le_bytes())
fs::write(Self::path_length(path), len.as_bytes())
}
fn path_length(path: &Path) -> PathBuf {
path.join("length")
+4 -1
View File
@@ -1,9 +1,12 @@
use std::{path::Path, thread};
use crate::{structs::Version, AddressHash, Addressindex, BlockHashPrefix, Height, TxidPrefix, Txindex};
use storable_vec::Version;
use crate::{AddressHash, Addressindex, BlockHashPrefix, Height, TxidPrefix, Txindex};
mod base;
mod meta;
// mod version;
pub use base::*;
pub use meta::*;
+51
View File
@@ -0,0 +1,51 @@
use std::{fs, io, path::Path};
use derive_deref::Deref;
use fjall::Slice;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Deref)]
pub struct Version(u32);
impl Version {
pub fn write(&self, path: &Path) -> Result<(), io::Error> {
fs::write(path, self.to_ne_bytes())
}
}
impl From<u32> for Version {
fn from(value: u32) -> Self {
Self(value)
}
}
impl TryFrom<&Path> for Version {
type Error = io::Error;
fn try_from(value: &Path) -> Result<Self, Self::Error> {
Self::try_from(&fs::read(value)?)
}
}
impl TryFrom<Slice> for Version {
type Error = fjall::Error;
fn try_from(value: Slice) -> Result<Self, Self::Error> {
Self::from(&value)
}
}
impl TryFrom<&[u8]> for Version {
type Error = storable_vec::Error;
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
let mut buf: [u8; 4] = [0; 4];
let buf_len = buf.len();
if value.len() != buf_len {
panic!();
}
value.iter().enumerate().for_each(|(i, r)| {
buf[i] = *r;
});
Ok(Self(u32::from_ne_bytes(buf)))
}
}
impl From<Version> for Slice {
fn from(value: Version) -> Self {
Self::new(&value.to_ne_bytes())
}
}
+3 -3
View File
@@ -34,7 +34,7 @@ where
self.vec.flush()
}
pub fn height(&self) -> color_eyre::Result<Height> {
pub fn height(&self) -> storable_vec::Result<Height> {
Height::try_from(self.path_height().as_path())
}
fn path_height(&self) -> PathBuf {
@@ -66,7 +66,7 @@ impl<I, T, const MODE: u8> DerefMut for StorableVec<I, T, MODE> {
}
pub trait AnyStorableVec {
fn height(&self) -> color_eyre::Result<Height>;
fn height(&self) -> storable_vec::Result<Height>;
fn flush(&mut self, height: Height) -> io::Result<()>;
}
@@ -75,7 +75,7 @@ where
I: StorableVecIndex,
T: StorableVecType,
{
fn height(&self) -> color_eyre::Result<Height> {
fn height(&self) -> storable_vec::Result<Height> {
self.height()
}
+5 -6
View File
@@ -1,14 +1,13 @@
use std::{fs, io, path::Path};
use biter::bitcoin::{self, transaction, BlockHash, Txid, Weight};
use exit::Exit;
use rayon::prelude::*;
use storable_vec::{Version, CACHED_GETS};
use crate::structs::{
Addressbytes, Addressindex, Addresstype, Addresstypeindex, Amount, Height, P2PK33AddressBytes, P2PK65AddressBytes,
P2PKHAddressBytes, P2SHAddressBytes, P2TRAddressBytes, P2WPKHAddressBytes, P2WSHAddressBytes, Timestamp, Txindex,
Txinindex, Txoutindex,
Addressbytes, Addressindex, Addresstype, Addresstypeindex, Amount, BlockHash, Height, LockTime, P2PK33AddressBytes,
P2PK65AddressBytes, P2PKHAddressBytes, P2SHAddressBytes, P2TRAddressBytes, P2WPKHAddressBytes, P2WSHAddressBytes,
Timestamp, TxVersion, Txid, Txindex, Txinindex, Txoutindex, Weight,
};
mod base;
@@ -50,9 +49,9 @@ pub struct StorableVecs<const MODE: u8> {
pub txindex_to_first_txinindex: StorableVec<Txindex, Txinindex, MODE>,
pub txindex_to_first_txoutindex: StorableVec<Txindex, Txoutindex, MODE>,
pub txindex_to_height: StorableVec<Txindex, Height, MODE>,
pub txindex_to_locktime: StorableVec<Txindex, bitcoin::absolute::LockTime, MODE>,
pub txindex_to_locktime: StorableVec<Txindex, LockTime, MODE>,
pub txindex_to_txid: StorableVec<Txindex, Txid, MODE>,
pub txindex_to_txversion: StorableVec<Txindex, transaction::Version, MODE>,
pub txindex_to_txversion: StorableVec<Txindex, TxVersion, MODE>,
pub txinindex_to_txoutindex: StorableVec<Txinindex, Txoutindex, MODE>,
pub txoutindex_to_addressindex: StorableVec<Txoutindex, Addressindex, MODE>,
pub txoutindex_to_amount: StorableVec<Txoutindex, Amount, MODE>,
+13 -12
View File
@@ -1,6 +1,7 @@
use biter::bitcoin::ScriptBuf;
use color_eyre::eyre::eyre;
use derive_deref::{Deref, DerefMut};
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
use super::Addresstype;
@@ -122,28 +123,28 @@ impl From<P2TRAddressBytes> for Addressbytes {
}
}
#[derive(Debug, Clone, Deref, PartialEq, Eq)]
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct P2PK65AddressBytes(U8x65);
#[derive(Debug, Clone, Deref, PartialEq, Eq)]
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct P2PK33AddressBytes(U8x33);
#[derive(Debug, Clone, Deref, PartialEq, Eq)]
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct P2PKHAddressBytes(U8x20);
#[derive(Debug, Clone, Deref, PartialEq, Eq)]
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct P2SHAddressBytes(U8x20);
#[derive(Debug, Clone, Deref, PartialEq, Eq)]
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct P2WPKHAddressBytes(U8x20);
#[derive(Debug, Clone, Deref, PartialEq, Eq)]
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct P2WSHAddressBytes(U8x32);
#[derive(Debug, Clone, Deref, PartialEq, Eq)]
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct P2TRAddressBytes(U8x32);
#[derive(Debug, Clone, Deref, DerefMut, PartialEq, Eq)]
#[derive(Debug, Clone, Deref, DerefMut, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct U8x20([u8; 20]);
impl From<&[u8]> for U8x20 {
fn from(slice: &[u8]) -> Self {
@@ -153,7 +154,7 @@ impl From<&[u8]> for U8x20 {
}
}
#[derive(Debug, Clone, Deref, DerefMut, PartialEq, Eq)]
#[derive(Debug, Clone, Deref, DerefMut, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct U8x32([u8; 32]);
impl From<&[u8]> for U8x32 {
fn from(slice: &[u8]) -> Self {
@@ -163,7 +164,7 @@ impl From<&[u8]> for U8x32 {
}
}
#[derive(Debug, Clone, Deref, DerefMut, PartialEq, Eq)]
#[derive(Debug, Clone, Deref, DerefMut, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct U8x33([u8; 33]);
impl From<&[u8]> for U8x33 {
fn from(slice: &[u8]) -> Self {
@@ -173,7 +174,7 @@ impl From<&[u8]> for U8x33 {
}
}
#[derive(Debug, Clone, Deref, DerefMut, PartialEq, Eq)]
#[derive(Debug, Clone, Deref, DerefMut, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct U8x64([u8; 64]);
impl From<&[u8]> for U8x64 {
fn from(slice: &[u8]) -> Self {
@@ -183,7 +184,7 @@ impl From<&[u8]> for U8x64 {
}
}
#[derive(Debug, Clone, Deref, DerefMut, PartialEq, Eq)]
#[derive(Debug, Clone, Deref, DerefMut, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct U8x65([u8; 65]);
impl From<&[u8]> for U8x65 {
fn from(slice: &[u8]) -> Self {
+20 -5
View File
@@ -2,9 +2,24 @@ use std::ops::Add;
use derive_deref::{Deref, DerefMut};
use fjall::Slice;
use unsafe_slice_serde::UnsafeSliceSerde;
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Deref, DerefMut, Default)]
#[derive(
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Clone,
Copy,
Deref,
DerefMut,
Default,
FromBytes,
Immutable,
IntoBytes,
KnownLayout,
)]
pub struct Addressindex(u32);
impl Addressindex {
@@ -52,14 +67,14 @@ impl From<Addressindex> for usize {
}
impl TryFrom<Slice> for Addressindex {
type Error = unsafe_slice_serde::Error;
type Error = storable_vec::Error;
fn try_from(value: Slice) -> Result<Self, Self::Error> {
Ok(*Self::unsafe_try_from_slice(&value)?)
Ok(Self::read_from_bytes(&value)?)
}
}
impl From<Addressindex> for Slice {
fn from(value: Addressindex) -> Self {
Self::new(value.unsafe_as_slice())
Self::new(value.as_bytes())
}
}
+3 -1
View File
@@ -1,6 +1,8 @@
use biter::bitcoin::ScriptBuf;
use zerocopy::{Immutable, IntoBytes, KnownLayout, TryFromBytes};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, TryFromBytes, Immutable, IntoBytes, KnownLayout)]
#[repr(u8)]
pub enum Addresstype {
P2PK65,
P2PK33,
+17 -1
View File
@@ -1,8 +1,24 @@
use std::ops::Add;
use derive_deref::{Deref, DerefMut};
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Deref, DerefMut, Default)]
#[derive(
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Clone,
Copy,
Deref,
DerefMut,
Default,
FromBytes,
Immutable,
IntoBytes,
KnownLayout,
)]
pub struct Addresstypeindex(u32);
impl Addresstypeindex {
+34 -13
View File
@@ -5,14 +5,30 @@ use std::{
use biter::bitcoin;
use derive_deref::{Deref, DerefMut};
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
use super::Height;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Deref, DerefMut, Default)]
pub struct Amount(bitcoin::Amount);
#[derive(
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Clone,
Copy,
Deref,
DerefMut,
Default,
FromBytes,
Immutable,
IntoBytes,
KnownLayout,
)]
pub struct Amount(u64);
impl Amount {
pub const ZERO: Self = Self(bitcoin::Amount::ZERO);
pub const ZERO: Self = Self(0);
pub const ONE_BTC_F32: f32 = 100_000_000.0;
pub const ONE_BTC_F64: f64 = 100_000_000.0;
@@ -24,65 +40,70 @@ impl Amount {
impl Add for Amount {
type Output = Amount;
fn add(self, rhs: Amount) -> Self::Output {
Amount::from(self.to_sat() + rhs.to_sat())
Amount::from(*self + *rhs)
}
}
impl AddAssign for Amount {
fn add_assign(&mut self, rhs: Self) {
*self = Amount::from(self.to_sat() + rhs.to_sat());
*self = *self + rhs;
}
}
impl Sub for Amount {
type Output = Amount;
fn sub(self, rhs: Amount) -> Self::Output {
Amount::from(self.to_sat() - rhs.to_sat())
Amount::from(*self - *rhs)
}
}
impl SubAssign for Amount {
fn sub_assign(&mut self, rhs: Self) {
*self = Amount::from(self.to_sat() - rhs.to_sat());
*self = *self - rhs;
}
}
impl Mul<Amount> for Amount {
type Output = Amount;
fn mul(self, rhs: Amount) -> Self::Output {
Amount::from(self.to_sat() * rhs.to_sat())
Amount::from(*self * *rhs)
}
}
impl Mul<u64> for Amount {
type Output = Amount;
fn mul(self, rhs: u64) -> Self::Output {
Amount::from(self.to_sat() * rhs)
Amount::from(*self * rhs)
}
}
impl Mul<Height> for Amount {
type Output = Amount;
fn mul(self, rhs: Height) -> Self::Output {
Amount::from(self.to_sat() * *rhs as u64)
Amount::from(*self * *rhs as u64)
}
}
impl Sum for Amount {
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
let sats: u64 = iter.map(|amt| amt.to_sat()).sum();
let sats: u64 = iter.map(|amt| *amt).sum();
Amount::from(sats)
}
}
impl From<u64> for Amount {
fn from(value: u64) -> Self {
Self(bitcoin::Amount::from_sat(value))
Self(value)
}
}
impl From<bitcoin::Amount> for Amount {
fn from(value: bitcoin::Amount) -> Self {
Self(value)
Self(value.to_sat())
}
}
impl From<Amount> for bitcoin::Amount {
fn from(value: Amount) -> Self {
Self::from_sat(value.0)
}
}
+19
View File
@@ -0,0 +1,19 @@
use std::mem;
use derive_deref::Deref;
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
#[derive(Debug, Deref, Clone, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct BlockHash([u8; 32]);
impl From<bitcoin::BlockHash> for BlockHash {
fn from(value: bitcoin::BlockHash) -> Self {
unsafe { mem::transmute(value) }
}
}
impl From<BlockHash> for bitcoin::BlockHash {
fn from(value: BlockHash) -> Self {
unsafe { mem::transmute(value) }
}
}
+28 -17
View File
@@ -1,13 +1,12 @@
use std::hash::Hasher;
use biter::bitcoin::{BlockHash, Txid};
use derive_deref::Deref;
use fjall::Slice;
use unsafe_slice_serde::UnsafeSliceSerde;
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
use super::{Addressbytes, Addresstype, SliceExtended};
use super::{Addressbytes, Addresstype, BlockHash, Txid};
#[derive(Debug, Deref, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Debug, Deref, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, FromBytes, Immutable, IntoBytes, KnownLayout)]
pub struct AddressHash([u8; 8]);
impl From<(&Addressbytes, Addresstype)> for AddressHash {
fn from((addressbytes, addresstype): (&Addressbytes, Addresstype)) -> Self {
@@ -24,14 +23,14 @@ impl From<[u8; 8]> for AddressHash {
}
}
impl TryFrom<Slice> for AddressHash {
type Error = color_eyre::Report;
type Error = storable_vec::Error;
fn try_from(value: Slice) -> Result<Self, Self::Error> {
Ok(*Self::unsafe_try_from_slice(&value)?)
Ok(Self::read_from_bytes(&value)?)
}
}
impl From<&AddressHash> for Slice {
fn from(value: &AddressHash) -> Self {
Self::new(value.unsafe_as_slice())
Self::new(value.as_bytes())
}
}
impl From<AddressHash> for Slice {
@@ -40,23 +39,23 @@ impl From<AddressHash> for Slice {
}
}
#[derive(Debug, Deref, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Debug, Deref, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, FromBytes, Immutable, IntoBytes, KnownLayout)]
pub struct BlockHashPrefix([u8; 8]);
impl TryFrom<&BlockHash> for BlockHashPrefix {
type Error = color_eyre::Report;
fn try_from(value: &BlockHash) -> Result<Self, Self::Error> {
Ok(Self((&value[..]).read_8x_u8()?))
Ok(Self(copy_first_8bytes(&value[..])))
}
}
impl TryFrom<Slice> for BlockHashPrefix {
type Error = color_eyre::Report;
type Error = storable_vec::Error;
fn try_from(value: Slice) -> Result<Self, Self::Error> {
Ok(*Self::unsafe_try_from_slice(&value)?)
Ok(Self::read_from_bytes(&value)?)
}
}
impl From<&BlockHashPrefix> for Slice {
fn from(value: &BlockHashPrefix) -> Self {
Self::new(value.unsafe_as_slice())
Self::new(value.as_bytes())
}
}
impl From<BlockHashPrefix> for Slice {
@@ -65,23 +64,23 @@ impl From<BlockHashPrefix> for Slice {
}
}
#[derive(Debug, Deref, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Debug, Deref, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, FromBytes, Immutable, IntoBytes, KnownLayout)]
pub struct TxidPrefix([u8; 8]);
impl TryFrom<&Txid> for TxidPrefix {
type Error = color_eyre::Report;
fn try_from(value: &Txid) -> Result<Self, Self::Error> {
Ok(Self((&value[..]).read_8x_u8()?))
Ok(Self(copy_first_8bytes(&value[..])))
}
}
impl TryFrom<Slice> for TxidPrefix {
type Error = color_eyre::Report;
type Error = storable_vec::Error;
fn try_from(value: Slice) -> Result<Self, Self::Error> {
Ok(*Self::unsafe_try_from_slice(&value)?)
Ok(Self::read_from_bytes(&value)?)
}
}
impl From<&TxidPrefix> for Slice {
fn from(value: &TxidPrefix) -> Self {
Self::new(value.unsafe_as_slice())
Self::new(value.as_bytes())
}
}
impl From<TxidPrefix> for Slice {
@@ -89,3 +88,15 @@ impl From<TxidPrefix> for Slice {
Self::from(&value)
}
}
fn copy_first_8bytes(slice: &[u8]) -> [u8; 8] {
let mut buf: [u8; 8] = [0; 8];
let buf_len = buf.len();
if slice.len() < buf_len {
panic!("bad len");
}
slice.iter().take(buf_len).enumerate().for_each(|(i, r)| {
buf[i] = *r;
});
buf
}
+35 -8
View File
@@ -7,14 +7,29 @@ use std::{
use biter::rpc::{self, RpcApi};
use derive_deref::{Deref, DerefMut};
use fjall::Slice;
use unsafe_slice_serde::UnsafeSliceSerde;
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
#[derive(Debug, Clone, Copy, Deref, DerefMut, PartialEq, Eq, PartialOrd, Ord, Default)]
#[derive(
Debug,
Clone,
Copy,
Deref,
DerefMut,
PartialEq,
Eq,
PartialOrd,
Ord,
Default,
FromBytes,
Immutable,
IntoBytes,
KnownLayout,
)]
pub struct Height(u32);
impl Height {
pub fn write(&self, path: &Path) -> Result<(), io::Error> {
fs::write(path, self.unsafe_as_slice())
fs::write(path, self.as_bytes())
}
}
@@ -113,9 +128,9 @@ impl From<Height> for usize {
}
impl TryFrom<&Path> for Height {
type Error = color_eyre::Report;
type Error = storable_vec::Error;
fn try_from(value: &Path) -> Result<Self, Self::Error> {
Ok(Self::unsafe_try_from_slice(fs::read(value)?.as_slice())?.to_owned())
Ok(Self::read_from_bytes(fs::read(value)?.as_slice())?.to_owned())
}
}
@@ -127,13 +142,25 @@ impl TryFrom<&rpc::Client> for Height {
}
impl TryFrom<Slice> for Height {
type Error = unsafe_slice_serde::Error;
type Error = storable_vec::Error;
fn try_from(value: Slice) -> Result<Self, Self::Error> {
Ok(*Self::unsafe_try_from_slice(&value)?)
Ok(Self::read_from_bytes(&value)?)
}
}
impl From<Height> for Slice {
fn from(value: Height) -> Self {
Self::new(value.unsafe_as_slice())
Self::new(value.as_bytes())
}
}
impl From<bitcoin::locktime::absolute::Height> for Height {
fn from(value: bitcoin::locktime::absolute::Height) -> Self {
Self(value.to_consensus_u32())
}
}
impl From<Height> for bitcoin::locktime::absolute::Height {
fn from(value: Height) -> Self {
bitcoin::locktime::absolute::Height::from_consensus(*value).unwrap()
}
}
+28
View File
@@ -0,0 +1,28 @@
use zerocopy::{Immutable, IntoBytes, KnownLayout, TryFromBytes};
use super::{Height, Timestamp};
#[derive(Debug, Immutable, Clone, Copy, IntoBytes, KnownLayout, TryFromBytes)]
#[repr(C)]
pub enum LockTime {
Height(Height),
Timestamp(Timestamp),
}
impl From<bitcoin::absolute::LockTime> for LockTime {
fn from(value: bitcoin::absolute::LockTime) -> Self {
match value {
bitcoin::absolute::LockTime::Blocks(h) => LockTime::Height(h.into()),
bitcoin::absolute::LockTime::Seconds(t) => LockTime::Timestamp(t.into()),
}
}
}
impl From<LockTime> for bitcoin::absolute::LockTime {
fn from(value: LockTime) -> Self {
match value {
LockTime::Height(h) => bitcoin::absolute::LockTime::Blocks(h.into()),
LockTime::Timestamp(t) => bitcoin::absolute::LockTime::Seconds(t.into()),
}
}
}
+10 -4
View File
@@ -3,29 +3,35 @@ mod addressindex;
mod addresstype;
mod addresstypeindex;
mod amount;
mod blockhash;
mod compressed;
mod height;
mod slice;
mod locktime;
mod timestamp;
mod txid;
mod txindex;
mod txinindex;
mod txoutindex;
mod version;
mod txversion;
mod vin;
mod vout;
mod weight;
pub use addressbytes::*;
pub use addressindex::*;
pub use addresstype::*;
pub use addresstypeindex::*;
pub use amount::*;
pub use blockhash::*;
pub use compressed::*;
pub use height::*;
pub use slice::*;
pub use locktime::*;
pub use timestamp::*;
pub use txid::*;
pub use txindex::*;
pub use txinindex::*;
pub use txoutindex::*;
pub use version::*;
pub use txversion::*;
pub use vin::*;
pub use vout::*;
pub use weight::*;
-55
View File
@@ -1,55 +0,0 @@
use color_eyre::eyre::eyre;
#[allow(unused)]
pub trait SliceExtended {
fn read_8x_u8(&self) -> color_eyre::Result<[u8; 8]>;
fn read_be_u8(&self) -> color_eyre::Result<u8>;
fn read_be_u16(&self) -> color_eyre::Result<u16>;
fn read_be_u32(&self) -> color_eyre::Result<u32>;
fn read_be_u64(&self) -> color_eyre::Result<u64>;
fn read_exact(&self, buf: &mut [u8]) -> color_eyre::Result<()>;
}
impl SliceExtended for &[u8] {
fn read_8x_u8(&self) -> color_eyre::Result<[u8; 8]> {
let mut buf: [u8; 8] = [0; 8];
(&self[..8]).read_exact(&mut buf)?;
Ok(buf)
}
fn read_be_u8(&self) -> color_eyre::Result<u8> {
let mut buf: [u8; 1] = [0; 1];
self.read_exact(&mut buf)?;
Ok(u8::from_be_bytes(buf))
}
fn read_be_u16(&self) -> color_eyre::Result<u16> {
let mut buf: [u8; 2] = [0; 2];
self.read_exact(&mut buf)?;
Ok(u16::from_be_bytes(buf))
}
fn read_be_u32(&self) -> color_eyre::Result<u32> {
let mut buf: [u8; 4] = [0; 4];
self.read_exact(&mut buf)?;
Ok(u32::from_be_bytes(buf))
}
fn read_be_u64(&self) -> color_eyre::Result<u64> {
let mut buf: [u8; 8] = [0; 8];
self.read_exact(&mut buf)?;
Ok(u64::from_be_bytes(buf))
}
fn read_exact(&self, buf: &mut [u8]) -> color_eyre::Result<()> {
let buf_len = buf.len();
if self.len() != buf_len {
dbg!(self.len(), buf_len);
return Err(eyre!("Not exact len"));
}
self.iter().take(buf_len).enumerate().for_each(|(i, r)| {
buf[i] = *r;
});
Ok(())
}
}
+24 -6
View File
@@ -1,11 +1,29 @@
use derive_deref::Deref;
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
#[derive(Debug, Deref, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Timestamp(jiff::Timestamp);
#[derive(Debug, Deref, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, FromBytes, Immutable, IntoBytes, KnownLayout)]
pub struct Timestamp(u32);
impl TryFrom<u32> for Timestamp {
type Error = jiff::Error;
fn try_from(value: u32) -> Result<Self, Self::Error> {
Ok(Self(jiff::Timestamp::from_second(value as i64)?))
impl From<u32> for Timestamp {
fn from(value: u32) -> Self {
Self(value)
}
}
impl From<Timestamp> for jiff::Timestamp {
fn from(value: Timestamp) -> Self {
jiff::Timestamp::from_second(*value as i64).unwrap()
}
}
impl From<bitcoin::locktime::absolute::Time> for Timestamp {
fn from(value: bitcoin::locktime::absolute::Time) -> Self {
Self(value.to_consensus_u32())
}
}
impl From<Timestamp> for bitcoin::locktime::absolute::Time {
fn from(value: Timestamp) -> Self {
bitcoin::locktime::absolute::Time::from_consensus(*value).unwrap()
}
}
+19
View File
@@ -0,0 +1,19 @@
use std::mem;
use derive_deref::Deref;
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
#[derive(Debug, Deref, Clone, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct Txid([u8; 32]);
impl From<bitcoin::Txid> for Txid {
fn from(value: bitcoin::Txid) -> Self {
unsafe { mem::transmute(value) }
}
}
impl From<Txid> for bitcoin::Txid {
fn from(value: Txid) -> Self {
unsafe { mem::transmute(value) }
}
}
+20 -5
View File
@@ -2,9 +2,24 @@ use std::ops::{Add, AddAssign, Sub};
use derive_deref::{Deref, DerefMut};
use fjall::Slice;
use unsafe_slice_serde::UnsafeSliceSerde;
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Deref, DerefMut, Default)]
#[derive(
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Clone,
Copy,
Deref,
DerefMut,
Default,
FromBytes,
Immutable,
IntoBytes,
KnownLayout,
)]
pub struct Txindex(u32);
impl Txindex {
@@ -73,13 +88,13 @@ impl From<Txindex> for usize {
}
impl TryFrom<Slice> for Txindex {
type Error = unsafe_slice_serde::Error;
type Error = storable_vec::Error;
fn try_from(value: Slice) -> Result<Self, Self::Error> {
Ok(*Self::unsafe_try_from_slice(&value)?)
Ok(Self::read_from_bytes(&value)?)
}
}
impl From<Txindex> for Slice {
fn from(value: Txindex) -> Self {
Self::new(value.unsafe_as_slice())
Self::new(value.as_bytes())
}
}
+17 -1
View File
@@ -1,10 +1,26 @@
use std::ops::{Add, AddAssign, Sub};
use derive_deref::{Deref, DerefMut};
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
use super::Vin;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Deref, DerefMut, Default)]
#[derive(
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Clone,
Copy,
Deref,
DerefMut,
Default,
FromBytes,
Immutable,
IntoBytes,
KnownLayout,
)]
pub struct Txinindex(u64);
impl Txinindex {
+17 -1
View File
@@ -1,10 +1,26 @@
use std::ops::{Add, AddAssign, Sub};
use derive_deref::{Deref, DerefMut};
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
use super::Vout;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Deref, DerefMut, Default)]
#[derive(
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Clone,
Copy,
Deref,
DerefMut,
Default,
FromBytes,
Immutable,
IntoBytes,
KnownLayout,
)]
pub struct Txoutindex(u64);
impl Txoutindex {
+17
View File
@@ -0,0 +1,17 @@
use derive_deref::Deref;
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
#[derive(Debug, Deref, Clone, Copy, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct TxVersion(i32);
impl From<bitcoin::transaction::Version> for TxVersion {
fn from(value: bitcoin::transaction::Version) -> Self {
Self(value.0)
}
}
impl From<TxVersion> for bitcoin::transaction::Version {
fn from(value: TxVersion) -> Self {
Self(value.0)
}
}
-38
View File
@@ -1,38 +0,0 @@
use std::{fs, io, path::Path};
use fjall::Slice;
use unsafe_slice_serde::UnsafeSliceSerde;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Version(u32);
impl Version {
pub fn write(&self, path: &Path) -> Result<(), io::Error> {
fs::write(path, self.unsafe_as_slice())
}
}
impl From<u32> for Version {
fn from(value: u32) -> Self {
Self(value)
}
}
impl TryFrom<&Path> for Version {
type Error = color_eyre::Report;
fn try_from(value: &Path) -> Result<Self, Self::Error> {
Ok(Self::unsafe_try_from_slice(fs::read(value)?.as_slice())?.to_owned())
}
}
impl TryFrom<Slice> for Version {
type Error = color_eyre::Report;
fn try_from(value: Slice) -> Result<Self, Self::Error> {
Ok(*Self::unsafe_try_from_slice(&value)?)
}
}
impl From<Version> for Slice {
fn from(value: Version) -> Self {
Self::new(value.unsafe_as_slice())
}
}
+17
View File
@@ -0,0 +1,17 @@
use derive_deref::Deref;
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
#[derive(Debug, Deref, Clone, Copy, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct Weight(u64);
impl From<bitcoin::Weight> for Weight {
fn from(value: bitcoin::Weight) -> Self {
Self(value.to_wu())
}
}
impl From<Weight> for bitcoin::Weight {
fn from(value: Weight) -> Self {
Self::from_wu(*value)
}
}