mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat(db): Refactor storage libraries (#371)
This commit is contained in:
42
Cargo.lock
generated
42
Cargo.lock
generated
@ -3094,6 +3094,7 @@ dependencies = [
|
||||
"eyre",
|
||||
"reth-interfaces",
|
||||
"reth-primitives",
|
||||
"reth-provider",
|
||||
"reth-rlp",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
@ -3107,22 +3108,31 @@ version = "0.1.0"
|
||||
name = "reth-db"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"arbitrary",
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"criterion",
|
||||
"eyre",
|
||||
"futures",
|
||||
"heapless",
|
||||
"iai",
|
||||
"modular-bitfield",
|
||||
"page_size",
|
||||
"parity-scale-codec",
|
||||
"postcard",
|
||||
"rand 0.8.5",
|
||||
"reth-codecs",
|
||||
"reth-db",
|
||||
"reth-interfaces",
|
||||
"reth-libmdbx",
|
||||
"reth-primitives",
|
||||
"secp256k1",
|
||||
"serde",
|
||||
"tempfile",
|
||||
"test-fuzz",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3217,6 +3227,7 @@ dependencies = [
|
||||
"reth-db",
|
||||
"reth-interfaces",
|
||||
"reth-primitives",
|
||||
"reth-provider",
|
||||
"reth-rlp",
|
||||
"revm",
|
||||
"rlp",
|
||||
@ -3335,6 +3346,7 @@ dependencies = [
|
||||
"reth-eth-wire",
|
||||
"reth-interfaces",
|
||||
"reth-primitives",
|
||||
"reth-provider",
|
||||
"reth-rlp",
|
||||
"reth-rlp-derive",
|
||||
"reth-tasks",
|
||||
@ -3390,6 +3402,34 @@ dependencies = [
|
||||
"triehash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reth-provider"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"arbitrary",
|
||||
"async-trait",
|
||||
"auto_impl",
|
||||
"bytes",
|
||||
"futures",
|
||||
"heapless",
|
||||
"hex-literal",
|
||||
"modular-bitfield",
|
||||
"parity-scale-codec",
|
||||
"postcard",
|
||||
"rand 0.8.5",
|
||||
"reth-codecs",
|
||||
"reth-db",
|
||||
"reth-interfaces",
|
||||
"reth-primitives",
|
||||
"reth-rpc-types",
|
||||
"secp256k1",
|
||||
"serde",
|
||||
"test-fuzz",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reth-rlp"
|
||||
version = "0.1.2"
|
||||
@ -3425,6 +3465,7 @@ dependencies = [
|
||||
"jsonrpsee",
|
||||
"reth-interfaces",
|
||||
"reth-primitives",
|
||||
"reth-provider",
|
||||
"reth-rpc-api",
|
||||
"reth-rpc-types",
|
||||
"reth-transaction-pool",
|
||||
@ -3472,6 +3513,7 @@ dependencies = [
|
||||
"reth-headers-downloaders",
|
||||
"reth-interfaces",
|
||||
"reth-primitives",
|
||||
"reth-provider",
|
||||
"reth-rlp",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
|
||||
@ -5,7 +5,6 @@ members = [
|
||||
"crates/common/rlp",
|
||||
"crates/common/rlp-derive",
|
||||
"crates/consensus",
|
||||
"crates/db",
|
||||
"crates/executor",
|
||||
"crates/interfaces",
|
||||
"crates/net/p2p",
|
||||
@ -21,11 +20,13 @@ members = [
|
||||
"crates/net/bodies-downloaders",
|
||||
"crates/primitives",
|
||||
"crates/stages",
|
||||
"crates/storage/codecs",
|
||||
"crates/storage/db",
|
||||
"crates/storage/libmdbx-rs",
|
||||
"crates/storage/libmdbx-rs/mdbx-sys",
|
||||
"crates/storage/provider",
|
||||
"crates/tracing",
|
||||
"crates/tasks",
|
||||
"crates/transaction-pool",
|
||||
"crates/db",
|
||||
"crates/libmdbx-rs",
|
||||
"crates/libmdbx-rs/mdbx-sys",
|
||||
]
|
||||
default-members = ["bin/reth"]
|
||||
@ -9,7 +9,7 @@ readme = "README.md"
|
||||
[dependencies]
|
||||
# reth
|
||||
reth-primitives = { path = "../../crates/primitives" }
|
||||
reth-db = {path = "../../crates/db"}
|
||||
reth-db = {path = "../../crates/storage/db", features = ["mdbx"]}
|
||||
reth-stages = {path = "../../crates/stages"}
|
||||
reth-interfaces = {path = "../../crates/interfaces"}
|
||||
reth-transaction-pool = {path = "../../crates/transaction-pool"}
|
||||
|
||||
@ -24,9 +24,9 @@ impl Command {
|
||||
let path = shellexpand::full(&self.db)?.into_owned();
|
||||
let expanded_db_path = Path::new(&path);
|
||||
std::fs::create_dir_all(expanded_db_path)?;
|
||||
let db = Arc::new(reth_db::kv::Env::<reth_db::mdbx::WriteMap>::open(
|
||||
let db = Arc::new(reth_db::mdbx::Env::<reth_db::mdbx::WriteMap>::open(
|
||||
expanded_db_path,
|
||||
reth_db::kv::EnvKind::RW,
|
||||
reth_db::mdbx::EnvKind::RW,
|
||||
)?);
|
||||
info!("DB opened");
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@ readme = "README.md"
|
||||
# reth
|
||||
reth-primitives = { path = "../primitives" }
|
||||
reth-interfaces = { path = "../interfaces" }
|
||||
reth-provider = { path = "../storage/provider" }
|
||||
reth-rlp = {path = "../common/rlp"}
|
||||
|
||||
# common
|
||||
|
||||
@ -1,14 +1,11 @@
|
||||
//! ALl functions for verification of block
|
||||
use crate::{config, Config};
|
||||
use reth_interfaces::{
|
||||
consensus::Error,
|
||||
provider::{AccountProvider, HeaderProvider},
|
||||
Result as RethResult,
|
||||
};
|
||||
use reth_interfaces::{consensus::Error, Result as RethResult};
|
||||
use reth_primitives::{
|
||||
Account, BlockLocked, BlockNumber, SealedHeader, Transaction, TxEip1559, TxEip2930, TxLegacy,
|
||||
EMPTY_OMMER_ROOT, H256, U256,
|
||||
};
|
||||
use reth_provider::{AccountProvider, HeaderProvider};
|
||||
use std::time::SystemTime;
|
||||
|
||||
/// Validate header standalone
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
//! Module that interacts with MDBX.
|
||||
|
||||
#![warn(missing_debug_implementations, missing_docs, unreachable_pub)]
|
||||
#![deny(unused_must_use, rust_2018_idioms)]
|
||||
#![doc(test(
|
||||
no_crate_inject,
|
||||
attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
|
||||
))]
|
||||
|
||||
/// Rust bindings for [MDBX](https://libmdbx.dqdkfa.ru/).
|
||||
pub mod mdbx {
|
||||
pub use reth_libmdbx::*;
|
||||
}
|
||||
|
||||
pub mod kv;
|
||||
mod utils;
|
||||
@ -11,6 +11,8 @@ readme = "README.md"
|
||||
reth-primitives = { path = "../primitives" }
|
||||
reth-interfaces = { path = "../interfaces" }
|
||||
reth-rlp = { path = "../common/rlp" }
|
||||
reth-db = { path = "../storage/db" }
|
||||
reth-provider = { path = "../storage/provider" }
|
||||
reth-consensus = { path = "../consensus" }
|
||||
|
||||
revm = "2.3"
|
||||
@ -34,4 +36,4 @@ sha3 = { version = "0.10", default-features = false }
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
reth-db = { path = "../db", features = ["test-utils"]}
|
||||
reth-db = { path = "../storage/db", features = ["test-utils"] }
|
||||
|
||||
@ -4,15 +4,13 @@ use crate::{
|
||||
Config,
|
||||
};
|
||||
use hashbrown::hash_map::Entry;
|
||||
use reth_interfaces::{
|
||||
db::{models::AccountBeforeTx, tables, DbTxMut, Error as DbError},
|
||||
executor::Error,
|
||||
provider::StateProvider,
|
||||
};
|
||||
use reth_db::{models::AccountBeforeTx, tables, transaction::DbTxMut, Error as DbError};
|
||||
use reth_interfaces::executor::Error;
|
||||
use reth_primitives::{
|
||||
bloom::logs_bloom, Account, Address, Bloom, Header, Log, Receipt, TransactionSignedEcRecovered,
|
||||
H256, U256,
|
||||
};
|
||||
use reth_provider::StateProvider;
|
||||
use revm::{
|
||||
db::AccountState, Account as RevmAccount, AccountInfo, AnalysisKind, Bytecode, Database, EVM,
|
||||
};
|
||||
@ -414,17 +412,15 @@ mod tests {
|
||||
|
||||
use crate::{config::SpecUpgrades, revm_wrap::State};
|
||||
use reth_db::{
|
||||
kv::{test_utils, Env, EnvKind},
|
||||
mdbx::WriteMap,
|
||||
};
|
||||
use reth_interfaces::{
|
||||
db::{Database, DbTx},
|
||||
provider::{AccountProvider, StateProvider},
|
||||
database::Database,
|
||||
mdbx::{test_utils, Env, EnvKind, WriteMap},
|
||||
transaction::DbTx,
|
||||
};
|
||||
use reth_primitives::{
|
||||
hex_literal::hex, keccak256, Account, Address, BlockLocked, Bytes, StorageKey, H160, H256,
|
||||
U256,
|
||||
};
|
||||
use reth_provider::{AccountProvider, StateProvider};
|
||||
use reth_rlp::Decodable;
|
||||
|
||||
use super::*;
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
use reth_interfaces::{provider::StateProvider, Error};
|
||||
use reth_interfaces::Error;
|
||||
use reth_primitives::{
|
||||
Account, Header, Transaction, TransactionKind, TransactionSignedEcRecovered, TxEip1559,
|
||||
TxEip2930, TxLegacy, H160, H256, KECCAK_EMPTY, U256,
|
||||
};
|
||||
use reth_provider::StateProvider;
|
||||
use revm::{
|
||||
db::{CacheDB, DatabaseRef},
|
||||
BlockEnv, TransactTo, TxEnv,
|
||||
|
||||
@ -7,7 +7,7 @@ repository = "https://github.com/paradigmxyz/reth"
|
||||
readme = "README.md"
|
||||
|
||||
[dependencies]
|
||||
reth-codecs = { path = "../codecs" }
|
||||
reth-codecs = { path = "../storage/codecs" }
|
||||
reth-primitives = { path = "../primitives" }
|
||||
reth-rpc-types = { path = "../net/rpc-types" }
|
||||
async-trait = "0.1.57"
|
||||
@ -32,7 +32,7 @@ secp256k1 = { version = "0.24.0", default-features = false, features = ["alloc",
|
||||
modular-bitfield = "0.11.2"
|
||||
|
||||
[dev-dependencies]
|
||||
reth-db = { path = "../db", features = ["test-utils"] }
|
||||
reth-db = { path = "../storage/db", features = ["test-utils"] }
|
||||
test-fuzz = "3.0.4"
|
||||
tokio = { version = "1.21.2", features = ["full"] }
|
||||
tokio-stream = { version = "0.1.11", features = ["sync"] }
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/// KV error type. They are using u32 to represent error code.
|
||||
/// Database error type. They are using u32 to represent error code.
|
||||
#[derive(Debug, thiserror::Error, PartialEq, Eq, Clone)]
|
||||
pub enum Error {
|
||||
/// Failed to open database.
|
||||
@ -1,289 +0,0 @@
|
||||
pub mod codecs;
|
||||
mod error;
|
||||
pub mod mock;
|
||||
pub mod models;
|
||||
mod table;
|
||||
pub mod tables;
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub use error::Error;
|
||||
pub use table::*;
|
||||
|
||||
// Sealed trait helper to prevent misuse of the API.
|
||||
mod sealed {
|
||||
pub trait Sealed: Sized {}
|
||||
pub struct Bounds<T>(T);
|
||||
impl<T> Sealed for Bounds<T> {}
|
||||
}
|
||||
use sealed::{Bounds, Sealed};
|
||||
|
||||
/// Implements the GAT method from:
|
||||
/// https://sabrinajewson.org/blog/the-better-alternative-to-lifetime-gats#the-better-gats.
|
||||
///
|
||||
/// Sealed trait which cannot be implemented by 3rd parties, exposed only for implementers
|
||||
pub trait DatabaseGAT<'a, __ImplicitBounds: Sealed = Bounds<&'a Self>>: Send + Sync {
|
||||
/// RO database transaction
|
||||
type TX: DbTx<'a> + Send + Sync;
|
||||
/// RW database transaction
|
||||
type TXMut: DbTxMut<'a> + DbTx<'a> + Send + Sync;
|
||||
}
|
||||
|
||||
/// Main Database trait that spawns transactions to be executed.
|
||||
pub trait Database: for<'a> DatabaseGAT<'a> {
|
||||
/// Create read only transaction.
|
||||
fn tx(&self) -> Result<<Self as DatabaseGAT<'_>>::TX, Error>;
|
||||
|
||||
/// Create read write transaction only possible if database is open with write access.
|
||||
fn tx_mut(&self) -> Result<<Self as DatabaseGAT<'_>>::TXMut, Error>;
|
||||
|
||||
/// Takes a function and passes a read-only transaction into it, making sure it's closed in the
|
||||
/// end of the execution.
|
||||
fn view<T, F>(&self, f: F) -> Result<T, Error>
|
||||
where
|
||||
F: Fn(&<Self as DatabaseGAT<'_>>::TX) -> T,
|
||||
{
|
||||
let tx = self.tx()?;
|
||||
|
||||
let res = f(&tx);
|
||||
tx.commit()?;
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
/// Takes a function and passes a write-read transaction into it, making sure it's committed in
|
||||
/// the end of the execution.
|
||||
fn update<T, F>(&self, f: F) -> Result<T, Error>
|
||||
where
|
||||
F: Fn(&<Self as DatabaseGAT<'_>>::TXMut) -> T,
|
||||
{
|
||||
let tx = self.tx_mut()?;
|
||||
|
||||
let res = f(&tx);
|
||||
tx.commit()?;
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
/// Implements the GAT method from:
|
||||
/// https://sabrinajewson.org/blog/the-better-alternative-to-lifetime-gats#the-better-gats.
|
||||
///
|
||||
/// Sealed trait which cannot be implemented by 3rd parties, exposed only for implementers
|
||||
pub trait DbTxGAT<'a, __ImplicitBounds: Sealed = Bounds<&'a Self>>: Send + Sync {
|
||||
/// Cursor GAT
|
||||
type Cursor<T: Table>: DbCursorRO<'a, T> + Send + Sync;
|
||||
/// DupCursor GAT
|
||||
type DupCursor<T: DupSort>: DbDupCursorRO<'a, T> + DbCursorRO<'a, T> + Send + Sync;
|
||||
}
|
||||
|
||||
/// Implements the GAT method from:
|
||||
/// https://sabrinajewson.org/blog/the-better-alternative-to-lifetime-gats#the-better-gats.
|
||||
///
|
||||
/// Sealed trait which cannot be implemented by 3rd parties, exposed only for implementers
|
||||
pub trait DbTxMutGAT<'a, __ImplicitBounds: Sealed = Bounds<&'a Self>>: Send + Sync {
|
||||
/// Cursor GAT
|
||||
type CursorMut<T: Table>: DbCursorRW<'a, T> + DbCursorRO<'a, T> + Send + Sync;
|
||||
/// DupCursor GAT
|
||||
type DupCursorMut<T: DupSort>: DbDupCursorRW<'a, T>
|
||||
+ DbCursorRW<'a, T>
|
||||
+ DbDupCursorRO<'a, T>
|
||||
+ DbCursorRO<'a, T>
|
||||
+ Send
|
||||
+ Sync;
|
||||
}
|
||||
|
||||
/// Read only transaction
|
||||
pub trait DbTx<'tx>: for<'a> DbTxGAT<'a> {
|
||||
/// Get value
|
||||
fn get<T: Table>(&self, key: T::Key) -> Result<Option<T::Value>, Error>;
|
||||
/// Commit for read only transaction will consume and free transaction and allows
|
||||
/// freeing of memory pages
|
||||
fn commit(self) -> Result<bool, Error>;
|
||||
/// Iterate over read only values in table.
|
||||
fn cursor<T: Table>(&self) -> Result<<Self as DbTxGAT<'_>>::Cursor<T>, Error>;
|
||||
/// Iterate over read only values in dup sorted table.
|
||||
fn cursor_dup<T: DupSort>(&self) -> Result<<Self as DbTxGAT<'_>>::DupCursor<T>, Error>;
|
||||
}
|
||||
|
||||
/// Read write transaction that allows writing to database
|
||||
pub trait DbTxMut<'tx>: for<'a> DbTxMutGAT<'a> {
|
||||
/// Put value to database
|
||||
fn put<T: Table>(&self, key: T::Key, value: T::Value) -> Result<(), Error>;
|
||||
/// Delete value from database
|
||||
fn delete<T: Table>(&self, key: T::Key, value: Option<T::Value>) -> Result<bool, Error>;
|
||||
/// Clears database.
|
||||
fn clear<T: Table>(&self) -> Result<(), Error>;
|
||||
/// Cursor mut
|
||||
fn cursor_mut<T: Table>(&self) -> Result<<Self as DbTxMutGAT<'_>>::CursorMut<T>, Error>;
|
||||
/// DupCursor mut.
|
||||
fn cursor_dup_mut<T: DupSort>(
|
||||
&self,
|
||||
) -> Result<<Self as DbTxMutGAT<'_>>::DupCursorMut<T>, Error>;
|
||||
}
|
||||
|
||||
/// Alias type for a `(key, value)` result coming from a cursor.
|
||||
pub type PairResult<T> = Result<Option<(<T as Table>::Key, <T as Table>::Value)>, Error>;
|
||||
/// Alias type for a `(key, value)` result coming from an iterator.
|
||||
pub type IterPairResult<T> = Option<Result<(<T as Table>::Key, <T as Table>::Value), Error>>;
|
||||
/// Alias type for a value result coming from a cursor without its key.
|
||||
pub type ValueOnlyResult<T> = Result<Option<<T as Table>::Value>, Error>;
|
||||
|
||||
/// Read only cursor over table.
|
||||
pub trait DbCursorRO<'tx, T: Table> {
|
||||
/// First item in table
|
||||
fn first(&mut self) -> PairResult<T>;
|
||||
|
||||
/// Seeks for the exact `(key, value)` pair with `key`.
|
||||
fn seek_exact(&mut self, key: T::Key) -> PairResult<T>;
|
||||
|
||||
/// Returns the next `(key, value)` pair.
|
||||
#[allow(clippy::should_implement_trait)]
|
||||
fn next(&mut self) -> PairResult<T>;
|
||||
|
||||
/// Returns the previous `(key, value)` pair.
|
||||
fn prev(&mut self) -> PairResult<T>;
|
||||
|
||||
/// Returns the last `(key, value)` pair.
|
||||
fn last(&mut self) -> PairResult<T>;
|
||||
|
||||
/// Returns the current `(key, value)` pair of the cursor.
|
||||
fn current(&mut self) -> PairResult<T>;
|
||||
|
||||
/// Returns an iterator starting at a key greater or equal than `start_key`.
|
||||
fn walk<'cursor>(
|
||||
&'cursor mut self,
|
||||
start_key: T::Key,
|
||||
) -> Result<Walker<'cursor, 'tx, T, Self>, Error>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
/// Read only curor over DupSort table.
|
||||
pub trait DbDupCursorRO<'tx, T: DupSort> {
|
||||
/// Seeks for a `(key, value)` pair greater or equal than `key`.
|
||||
fn seek(&mut self, key: T::SubKey) -> PairResult<T>;
|
||||
|
||||
/// Returns the next `(key, value)` pair of a DUPSORT table.
|
||||
fn next_dup(&mut self) -> PairResult<T>;
|
||||
|
||||
/// Returns the next `(key, value)` pair skipping the duplicates.
|
||||
fn next_no_dup(&mut self) -> PairResult<T>;
|
||||
|
||||
/// Returns the next `value` of a duplicate `key`.
|
||||
fn next_dup_val(&mut self) -> ValueOnlyResult<T>;
|
||||
|
||||
/// Returns an iterator starting at a key greater or equal than `start_key` of a DUPSORT
|
||||
/// table.
|
||||
fn walk_dup<'cursor>(
|
||||
&'cursor mut self,
|
||||
key: T::Key,
|
||||
subkey: T::SubKey,
|
||||
) -> Result<DupWalker<'cursor, 'tx, T, Self>, Error>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
/// Read write cursor over table.
|
||||
pub trait DbCursorRW<'tx, T: Table> {
|
||||
/// Database operation that will update an existing row if a specified value already
|
||||
/// exists in a table, and insert a new row if the specified value doesn't already exist
|
||||
fn upsert(&mut self, key: T::Key, value: T::Value) -> Result<(), Error>;
|
||||
|
||||
/// Database operation that will insert a row at a given key. If the key is already
|
||||
/// present, the operation will result in an error.
|
||||
fn insert(&mut self, key: T::Key, value: T::Value) -> Result<(), Error>;
|
||||
|
||||
/// Append value to next cursor item.
|
||||
///
|
||||
/// This is efficient for pre-sorted data. If the data is not pre-sorted, use [`insert`].
|
||||
fn append(&mut self, key: T::Key, value: T::Value) -> Result<(), Error>;
|
||||
|
||||
/// Delete current value that cursor points to
|
||||
fn delete_current(&mut self) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
/// Read Write Cursor over DupSorted table.
|
||||
pub trait DbDupCursorRW<'tx, T: DupSort> {
|
||||
/// Append value to next cursor item
|
||||
fn delete_current_duplicates(&mut self) -> Result<(), Error>;
|
||||
|
||||
/// Append duplicate value.
|
||||
///
|
||||
/// This is efficient for pre-sorted data. If the data is not pre-sorted, use [`insert`].
|
||||
fn append_dup(&mut self, key: T::Key, value: T::Value) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
/// Provides an iterator to `Cursor` when handling `Table`.
|
||||
///
|
||||
/// Reason why we have two lifetimes is to distinguish between `'cursor` lifetime
|
||||
/// and inherited `'tx` lifetime. If there is only one, rust would short circle
|
||||
/// the Cursor lifetime and it wouldn't be possible to use Walker.
|
||||
pub struct Walker<'cursor, 'tx, T: Table, CURSOR: DbCursorRO<'tx, T>> {
|
||||
/// Cursor to be used to walk through the table.
|
||||
pub cursor: &'cursor mut CURSOR,
|
||||
/// `(key, value)` where to start the walk.
|
||||
pub start: IterPairResult<T>,
|
||||
/// Phantom data for 'tx. As it is only used for `DbCursorRO`.
|
||||
pub _tx_phantom: PhantomData<&'tx T>,
|
||||
}
|
||||
|
||||
impl<'cursor, 'tx, T: Table, CURSOR: DbCursorRO<'tx, T>> std::iter::Iterator
|
||||
for Walker<'cursor, 'tx, T, CURSOR>
|
||||
{
|
||||
type Item = Result<(T::Key, T::Value), Error>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let start = self.start.take();
|
||||
if start.is_some() {
|
||||
return start
|
||||
}
|
||||
|
||||
self.cursor.next().transpose()
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides an iterator to `Cursor` when handling a `DupSort` table.
|
||||
///
|
||||
/// Reason why we have two lifetimes is to distinguish between `'cursor` lifetime
|
||||
/// and inherited `'tx` lifetime. If there is only one, rust would short circle
|
||||
/// the Cursor lifetime and it wouldn't be possible to use Walker.
|
||||
pub struct DupWalker<'cursor, 'tx, T: DupSort, CURSOR: DbDupCursorRO<'tx, T>> {
|
||||
/// Cursor to be used to walk through the table.
|
||||
pub cursor: &'cursor mut CURSOR,
|
||||
/// Value where to start the walk.
|
||||
pub start: IterPairResult<T>,
|
||||
/// Phantom data for 'tx. As it is only used for `DbDupCursorRO`.
|
||||
pub _tx_phantom: PhantomData<&'tx T>,
|
||||
}
|
||||
|
||||
impl<'cursor, 'tx, T: DupSort, CURSOR: DbDupCursorRO<'tx, T>> std::iter::Iterator
|
||||
for DupWalker<'cursor, 'tx, T, CURSOR>
|
||||
{
|
||||
type Item = Result<(T::Key, T::Value), Error>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let start = self.start.take();
|
||||
if start.is_some() {
|
||||
return start
|
||||
}
|
||||
self.cursor.next_dup().transpose()
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
/// Implements the [`arbitrary::Arbitrary`] trait for types with fixed array types.
|
||||
macro_rules! impl_fixed_arbitrary {
|
||||
($name:tt, $size:tt) => {
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
use arbitrary::{Arbitrary, Unstructured};
|
||||
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
impl<'a> Arbitrary<'a> for $name {
|
||||
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self, arbitrary::Error> {
|
||||
let mut buffer = vec![0; $size];
|
||||
u.fill_buffer(buffer.as_mut_slice())?;
|
||||
|
||||
Decode::decode(buffer).map_err(|_| arbitrary::Error::IncorrectFormat)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -13,11 +13,12 @@ pub mod executor;
|
||||
/// Consensus traits.
|
||||
pub mod consensus;
|
||||
|
||||
/// Database traits.
|
||||
pub mod db;
|
||||
/// Traits that provide chain access.
|
||||
/// Provider error
|
||||
pub mod provider;
|
||||
|
||||
/// Database error
|
||||
pub mod db;
|
||||
|
||||
/// P2P traits.
|
||||
pub mod p2p;
|
||||
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
use reth_primitives::{BlockHash, BlockNumber};
|
||||
|
||||
use crate::db::models::BlockNumHash;
|
||||
|
||||
/// KV error type. They are using u32 to represent error code.
|
||||
#[allow(missing_docs)]
|
||||
#[derive(Debug, thiserror::Error, PartialEq, Eq, Clone)]
|
||||
@ -12,6 +10,6 @@ pub enum Error {
|
||||
BlockTxNumberNotExists { block_hash: BlockHash },
|
||||
#[error("Block hash {block_hash:?} does not exists in Headers table")]
|
||||
BlockHashNotExist { block_hash: BlockHash },
|
||||
#[error("Block body not exists {block_num_hash:?}")]
|
||||
BlockBodyNotExist { block_num_hash: BlockNumHash },
|
||||
#[error("Block body not exists #{block_number} {block_hash}")]
|
||||
BlockBodyNotExist { block_number: BlockNumber, block_hash: BlockHash },
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
mod block;
|
||||
pub mod db_provider;
|
||||
mod error;
|
||||
mod state;
|
||||
|
||||
pub use block::{
|
||||
get_cumulative_tx_count_by_hash, insert_canonical_block, BlockProvider, ChainInfo,
|
||||
HeaderProvider,
|
||||
};
|
||||
pub use db_provider::{self as db, ProviderImpl};
|
||||
pub use error::Error;
|
||||
pub use state::{AccountProvider, StateProvider, StateProviderFactory};
|
||||
@ -1,10 +1,8 @@
|
||||
mod api;
|
||||
mod bodies;
|
||||
mod headers;
|
||||
|
||||
/// Generators for different data structures like block headers, block bodies and ranges of those.
|
||||
pub mod generators;
|
||||
|
||||
pub use api::TestApi;
|
||||
pub use bodies::*;
|
||||
pub use headers::*;
|
||||
|
||||
@ -20,6 +20,7 @@ reth-rlp = { path = "../../common/rlp" }
|
||||
reth-rlp-derive = { path = "../../common/rlp-derive" }
|
||||
reth-tasks = { path = "../../tasks" }
|
||||
reth-transaction-pool = { path = "../../transaction-pool" }
|
||||
reth-provider = { path = "../../storage/provider"}
|
||||
|
||||
# async/futures
|
||||
futures = "0.3"
|
||||
@ -47,6 +48,7 @@ secp256k1 = { version = "0.24", features = [
|
||||
[dev-dependencies]
|
||||
# reth
|
||||
reth-interfaces = { path = "../../interfaces", features = ["test-utils"] }
|
||||
reth-provider = { path = "../../storage/provider", features = ["test-utils"] }
|
||||
reth-tracing = { path = "../../tracing" }
|
||||
|
||||
rand = "0.8"
|
||||
|
||||
@ -6,11 +6,9 @@ use reth_eth_wire::{
|
||||
BlockBodies, BlockBody, BlockHeaders, GetBlockBodies, GetBlockHeaders, GetNodeData,
|
||||
GetReceipts, NodeData, Receipts,
|
||||
};
|
||||
use reth_interfaces::{
|
||||
p2p::error::RequestResult,
|
||||
provider::{BlockProvider, HeaderProvider},
|
||||
};
|
||||
use reth_interfaces::p2p::error::RequestResult;
|
||||
use reth_primitives::{BlockHashOrNumber, Header, HeadersDirection, PeerId};
|
||||
use reth_provider::{BlockProvider, HeaderProvider};
|
||||
use std::{
|
||||
borrow::Borrow,
|
||||
future::Future,
|
||||
|
||||
@ -37,8 +37,8 @@ use reth_eth_wire::{
|
||||
capability::{Capabilities, CapabilityMessage},
|
||||
DisconnectReason,
|
||||
};
|
||||
use reth_interfaces::provider::BlockProvider;
|
||||
use reth_primitives::{PeerId, H256};
|
||||
use reth_provider::BlockProvider;
|
||||
use std::{
|
||||
net::SocketAddr,
|
||||
pin::Pin,
|
||||
|
||||
@ -14,8 +14,8 @@ use crate::{
|
||||
use reth_eth_wire::{
|
||||
capability::Capabilities, BlockHashNumber, DisconnectReason, NewBlockHashes, Status,
|
||||
};
|
||||
use reth_interfaces::provider::BlockProvider;
|
||||
use reth_primitives::{PeerId, H256};
|
||||
use reth_provider::BlockProvider;
|
||||
use std::{
|
||||
collections::{HashMap, VecDeque},
|
||||
net::SocketAddr,
|
||||
|
||||
@ -10,8 +10,8 @@ use reth_eth_wire::{
|
||||
capability::{Capabilities, CapabilityMessage},
|
||||
error::EthStreamError,
|
||||
};
|
||||
use reth_interfaces::provider::BlockProvider;
|
||||
use reth_primitives::PeerId;
|
||||
use reth_provider::BlockProvider;
|
||||
use std::{
|
||||
io,
|
||||
net::SocketAddr,
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
use super::testnet::Testnet;
|
||||
use futures::StreamExt;
|
||||
use reth_discv4::{bootnodes::mainnet_nodes, Discv4Config};
|
||||
use reth_interfaces::test_utils::TestApi;
|
||||
use reth_network::{NetworkConfig, NetworkEvent, NetworkManager};
|
||||
use reth_provider::test_utils::TestApi;
|
||||
use secp256k1::SecretKey;
|
||||
use std::{collections::HashSet, sync::Arc};
|
||||
|
||||
|
||||
@ -3,10 +3,6 @@
|
||||
use futures::{FutureExt, StreamExt};
|
||||
use parking_lot::Mutex;
|
||||
use pin_project::pin_project;
|
||||
use reth_interfaces::{
|
||||
provider::{BlockProvider, ChainInfo, HeaderProvider},
|
||||
test_utils::TestApi,
|
||||
};
|
||||
use reth_network::{
|
||||
error::NetworkError, eth_requests::EthRequestHandler, NetworkConfig, NetworkEvent,
|
||||
NetworkHandle, NetworkManager,
|
||||
@ -15,6 +11,7 @@ use reth_primitives::{
|
||||
rpc::{BlockId, BlockNumber},
|
||||
Block, BlockHash, Header, PeerId, H256, U256,
|
||||
};
|
||||
use reth_provider::{test_utils::TestApi, BlockProvider, ChainInfo, HeaderProvider};
|
||||
use secp256k1::SecretKey;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
|
||||
@ -14,6 +14,7 @@ reth-interfaces = { path = "../../interfaces" }
|
||||
reth-primitives = { path = "../../primitives" }
|
||||
reth-rpc-api = { path = "../rpc-api" }
|
||||
reth-rpc-types = { path = "../rpc-types" }
|
||||
reth-provider = { path = "../../storage/provider"}
|
||||
reth-transaction-pool = { path = "../../transaction-pool" }
|
||||
|
||||
# rpc
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
//! Provides everything related to `eth_` namespace
|
||||
|
||||
use reth_interfaces::{
|
||||
provider::{BlockProvider, StateProviderFactory},
|
||||
Result,
|
||||
};
|
||||
use reth_interfaces::Result;
|
||||
use reth_primitives::{Transaction, U256, U64};
|
||||
use reth_provider::{BlockProvider, StateProviderFactory};
|
||||
use reth_transaction_pool::TransactionPool;
|
||||
use std::sync::Arc;
|
||||
|
||||
|
||||
@ -3,11 +3,11 @@
|
||||
|
||||
use crate::{eth::api::EthApi, result::ToRpcResult};
|
||||
use jsonrpsee::core::RpcResult as Result;
|
||||
use reth_interfaces::provider::{BlockProvider, StateProviderFactory};
|
||||
use reth_primitives::{
|
||||
rpc::{transaction::eip2930::AccessListWithGasUsed, BlockId},
|
||||
Address, BlockNumber, Bytes, Transaction, H256, H64, U256, U64,
|
||||
};
|
||||
use reth_provider::{BlockProvider, StateProviderFactory};
|
||||
use reth_rpc_api::EthApiServer;
|
||||
use reth_rpc_types::{
|
||||
CallRequest, EIP1186AccountProofResponse, FeeHistory, Index, RichBlock, SyncStatus,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
//! `eth_` PubSub RPC handler implementation
|
||||
|
||||
use jsonrpsee::{types::SubscriptionResult, SubscriptionSink};
|
||||
use reth_interfaces::provider::BlockProvider;
|
||||
use reth_provider::BlockProvider;
|
||||
use reth_rpc_api::EthPubSubApiServer;
|
||||
use reth_rpc_types::pubsub::{Kind, Params};
|
||||
use reth_transaction_pool::TransactionPool;
|
||||
|
||||
@ -14,7 +14,7 @@ reth-rlp = { path = "../common/rlp", features = [
|
||||
"derive",
|
||||
"ethereum-types",
|
||||
] }
|
||||
reth-codecs = { version = "0.1.0", path = "../codecs" }
|
||||
reth-codecs = { version = "0.1.0", path = "../storage/codecs" }
|
||||
|
||||
# ethereum
|
||||
ethers-core = { git = "https://github.com/gakonst/ethers-rs", default-features = false }
|
||||
|
||||
@ -11,9 +11,10 @@ description = "Staged syncing primitives used in reth."
|
||||
# reth libs
|
||||
reth-primitives = { path = "../primitives" }
|
||||
reth-interfaces = { path = "../interfaces" }
|
||||
reth-db = { path = "../db" }
|
||||
reth-executor = { path = "../executor" }
|
||||
reth-rlp = { path = "../common/rlp" }
|
||||
reth-db = { path = "../storage/db" }
|
||||
reth-provider = { path = "../storage/provider"}
|
||||
|
||||
#async
|
||||
tokio = { version = "1.21.2", features = ["sync"] }
|
||||
@ -29,9 +30,11 @@ itertools = "0.10.5"
|
||||
rayon = "1.6.0"
|
||||
|
||||
[dev-dependencies]
|
||||
reth-db = { path = "../db", features = ["test-utils"] }
|
||||
# reth
|
||||
reth-db = { path = "../storage/db", features = ["test-utils", "mdbx"] }
|
||||
reth-interfaces = { path = "../interfaces", features = ["test-utils"] }
|
||||
reth-bodies-downloaders = { path = "../net/bodies-downloaders" }
|
||||
|
||||
# TODO(onbjerg): We only need this for [BlockBody]
|
||||
reth-eth-wire = { path = "../net/eth-wire" }
|
||||
reth-headers-downloaders = { path = "../net/headers-downloaders" }
|
||||
|
||||
@ -3,9 +3,14 @@ use std::{
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
use reth_interfaces::db::{
|
||||
use reth_db::{
|
||||
cursor::{DbCursorRO, DbCursorRW},
|
||||
database::{Database, DatabaseGAT},
|
||||
models::{BlockNumHash, NumTransactions},
|
||||
tables, Database, DatabaseGAT, DbCursorRO, DbCursorRW, DbTx, DbTxMut, Error, Table,
|
||||
table::Table,
|
||||
tables,
|
||||
transaction::{DbTx, DbTxMut},
|
||||
Error,
|
||||
};
|
||||
use reth_primitives::{BlockHash, BlockNumber, TxNumber};
|
||||
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
use metrics::counter;
|
||||
use reth_interfaces::db::{tables::SyncStage, DbTx, DbTxMut, Error as DbError};
|
||||
use reth_db::{
|
||||
tables::SyncStage,
|
||||
transaction::{DbTx, DbTxMut},
|
||||
Error as DbError,
|
||||
};
|
||||
use reth_primitives::BlockNumber;
|
||||
use std::fmt::Display;
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ use crate::{
|
||||
db::StageDB, error::*, util::opt::MaybeSender, ExecInput, ExecOutput, Stage, StageError,
|
||||
StageId, UnwindInput,
|
||||
};
|
||||
use reth_interfaces::db::{Database, DbTx};
|
||||
use reth_db::{database::Database, transaction::DbTx};
|
||||
use reth_primitives::BlockNumber;
|
||||
use std::{
|
||||
fmt::{Debug, Formatter},
|
||||
@ -365,10 +365,7 @@ impl<DB: Database> QueuedStage<DB> {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{StageId, UnwindOutput};
|
||||
use reth_db::{
|
||||
kv::{test_utils, Env, EnvKind},
|
||||
mdbx::{self, WriteMap},
|
||||
};
|
||||
use reth_db::mdbx::{self, test_utils, Env, EnvKind, WriteMap};
|
||||
use reth_interfaces::consensus;
|
||||
use tokio::sync::mpsc::channel;
|
||||
use tokio_stream::{wrappers::ReceiverStream, StreamExt};
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use crate::{db::StageDB, error::StageError, id::StageId};
|
||||
use async_trait::async_trait;
|
||||
use reth_interfaces::db::Database;
|
||||
use reth_db::database::Database;
|
||||
use reth_primitives::BlockNumber;
|
||||
|
||||
/// Stage execution input, see [Stage::execute].
|
||||
|
||||
@ -3,14 +3,14 @@ use crate::{
|
||||
UnwindInput, UnwindOutput,
|
||||
};
|
||||
use futures_util::TryStreamExt;
|
||||
use reth_interfaces::{
|
||||
consensus::Consensus,
|
||||
db::{
|
||||
models::StoredBlockOmmers, tables, Database, DatabaseGAT, DbCursorRO, DbCursorRW, DbTx,
|
||||
DbTxMut,
|
||||
},
|
||||
p2p::bodies::downloader::BodyDownloader,
|
||||
use reth_db::{
|
||||
cursor::{DbCursorRO, DbCursorRW},
|
||||
database::{Database, DatabaseGAT},
|
||||
models::StoredBlockOmmers,
|
||||
tables,
|
||||
transaction::{DbTx, DbTxMut},
|
||||
};
|
||||
use reth_interfaces::{consensus::Consensus, p2p::bodies::downloader::BodyDownloader};
|
||||
use reth_primitives::{
|
||||
proofs::{EMPTY_LIST_HASH, EMPTY_ROOT},
|
||||
BlockLocked, BlockNumber, SealedHeader, H256,
|
||||
@ -477,12 +477,14 @@ mod tests {
|
||||
ExecInput, ExecOutput, UnwindInput,
|
||||
};
|
||||
use assert_matches::assert_matches;
|
||||
use reth_db::{
|
||||
cursor::DbCursorRO,
|
||||
models::{BlockNumHash, NumTransactions, StoredBlockOmmers},
|
||||
tables,
|
||||
transaction::{DbTx, DbTxMut},
|
||||
};
|
||||
use reth_eth_wire::BlockBody;
|
||||
use reth_interfaces::{
|
||||
db::{
|
||||
models::{BlockNumHash, NumTransactions, StoredBlockOmmers},
|
||||
tables, DbCursorRO, DbTx, DbTxMut,
|
||||
},
|
||||
p2p::{
|
||||
bodies::{
|
||||
client::BodiesClient,
|
||||
|
||||
@ -2,20 +2,21 @@ use crate::{
|
||||
db::StageDB, DatabaseIntegrityError, ExecInput, ExecOutput, Stage, StageError, StageId,
|
||||
UnwindInput, UnwindOutput,
|
||||
};
|
||||
use reth_db::{
|
||||
cursor::{DbCursorRO, DbCursorRW, DbDupCursorRO},
|
||||
database::Database,
|
||||
models::{BlockNumHash, TxNumberAddress},
|
||||
tables,
|
||||
transaction::{DbTx, DbTxMut},
|
||||
};
|
||||
use reth_executor::{
|
||||
config::SpecUpgrades,
|
||||
executor::AccountChangeSet,
|
||||
revm_wrap::{State, SubState},
|
||||
Config,
|
||||
};
|
||||
use reth_interfaces::{
|
||||
db::{
|
||||
models::{BlockNumHash, TxNumberAddress},
|
||||
tables, Database, DbCursorRO, DbCursorRW, DbDupCursorRO, DbTx, DbTxMut,
|
||||
},
|
||||
provider::db::StateProviderImplRefLatest,
|
||||
};
|
||||
use reth_primitives::{Address, StorageEntry, TransactionSignedEcRecovered, H256, U256};
|
||||
use reth_provider::StateProviderImplRefLatest;
|
||||
use std::{fmt::Debug, ops::DerefMut};
|
||||
|
||||
const EXECUTION: StageId = StageId("Execution");
|
||||
@ -423,12 +424,9 @@ mod tests {
|
||||
use std::ops::Deref;
|
||||
|
||||
use super::*;
|
||||
use reth_db::{
|
||||
kv::{test_utils::create_test_db, EnvKind},
|
||||
mdbx::WriteMap,
|
||||
};
|
||||
use reth_interfaces::provider::insert_canonical_block;
|
||||
use reth_db::mdbx::{test_utils::create_test_db, EnvKind, WriteMap};
|
||||
use reth_primitives::{hex_literal::hex, keccak256, Account, BlockLocked, H160, U256};
|
||||
use reth_provider::insert_canonical_block;
|
||||
use reth_rlp::Decodable;
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@ -3,9 +3,15 @@ use crate::{
|
||||
UnwindInput, UnwindOutput,
|
||||
};
|
||||
use futures_util::StreamExt;
|
||||
use reth_db::{
|
||||
cursor::{DbCursorRO, DbCursorRW},
|
||||
database::Database,
|
||||
models::blocks::BlockNumHash,
|
||||
tables,
|
||||
transaction::{DbTx, DbTxMut},
|
||||
};
|
||||
use reth_interfaces::{
|
||||
consensus::{Consensus, ForkchoiceState},
|
||||
db::{models::blocks::BlockNumHash, tables, Database, DbCursorRO, DbCursorRW, DbTx, DbTxMut},
|
||||
p2p::headers::{
|
||||
client::HeadersClient,
|
||||
downloader::{ensure_parent, HeaderDownloader},
|
||||
@ -342,9 +348,9 @@ mod tests {
|
||||
},
|
||||
ExecInput, ExecOutput, UnwindInput,
|
||||
};
|
||||
use reth_db::{models::blocks::BlockNumHash, tables, transaction::DbTx};
|
||||
use reth_headers_downloaders::linear::{LinearDownloadBuilder, LinearDownloader};
|
||||
use reth_interfaces::{
|
||||
db::{models::blocks::BlockNumHash, tables, DbTx},
|
||||
p2p::headers::downloader::HeaderDownloader,
|
||||
test_utils::{
|
||||
generators::{random_header, random_header_range},
|
||||
|
||||
@ -3,7 +3,13 @@ use crate::{
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use rayon::prelude::*;
|
||||
use reth_interfaces::db::{self, tables, Database, DbCursorRO, DbCursorRW, DbTx, DbTxMut};
|
||||
use reth_db::{
|
||||
cursor::{DbCursorRO, DbCursorRW},
|
||||
database::Database,
|
||||
tables,
|
||||
transaction::{DbTx, DbTxMut},
|
||||
Error as DbError,
|
||||
};
|
||||
use reth_primitives::TxNumber;
|
||||
use std::fmt::Debug;
|
||||
use thiserror::Error;
|
||||
@ -79,7 +85,7 @@ impl<DB: Database> Stage<DB> for SendersStage {
|
||||
|
||||
// Iterate over transactions in chunks
|
||||
for chunk in &entries.chunks(self.batch_size) {
|
||||
let transactions = chunk.collect::<Result<Vec<_>, db::Error>>()?;
|
||||
let transactions = chunk.collect::<Result<Vec<_>, DbError>>()?;
|
||||
// Recover signers for the chunk in parallel
|
||||
let recovered = transactions
|
||||
.into_par_iter()
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use reth_db::{kv::Env, mdbx::WriteMap};
|
||||
use reth_db::mdbx::{Env, WriteMap};
|
||||
use std::borrow::Borrow;
|
||||
use tokio::sync::oneshot;
|
||||
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
use reth_db::{
|
||||
kv::{test_utils::create_test_db, tx::Tx, Env, EnvKind},
|
||||
mdbx::{WriteMap, RW},
|
||||
};
|
||||
use reth_interfaces::db::{
|
||||
self, models::BlockNumHash, tables, DbCursorRO, DbCursorRW, DbTx, DbTxMut, Table,
|
||||
cursor::{DbCursorRO, DbCursorRW},
|
||||
mdbx::{test_utils::create_test_db, tx::Tx, Env, EnvKind, WriteMap, RW},
|
||||
models::BlockNumHash,
|
||||
table::Table,
|
||||
tables,
|
||||
transaction::{DbTx, DbTxMut},
|
||||
Error as DbError,
|
||||
};
|
||||
use reth_primitives::{BlockNumber, SealedHeader, U256};
|
||||
use std::{borrow::Borrow, sync::Arc};
|
||||
@ -40,9 +42,9 @@ impl TestStageDB {
|
||||
}
|
||||
|
||||
/// Invoke a callback with transaction committing it afterwards
|
||||
pub(crate) fn commit<F>(&self, f: F) -> Result<(), db::Error>
|
||||
pub(crate) fn commit<F>(&self, f: F) -> Result<(), DbError>
|
||||
where
|
||||
F: FnOnce(&mut Tx<'_, RW, WriteMap>) -> Result<(), db::Error>,
|
||||
F: FnOnce(&mut Tx<'_, RW, WriteMap>) -> Result<(), DbError>,
|
||||
{
|
||||
let mut db = self.inner();
|
||||
f(&mut db)?;
|
||||
@ -51,15 +53,15 @@ impl TestStageDB {
|
||||
}
|
||||
|
||||
/// Invoke a callback with a read transaction
|
||||
pub(crate) fn query<F, R>(&self, f: F) -> Result<R, db::Error>
|
||||
pub(crate) fn query<F, R>(&self, f: F) -> Result<R, DbError>
|
||||
where
|
||||
F: FnOnce(&Tx<'_, RW, WriteMap>) -> Result<R, db::Error>,
|
||||
F: FnOnce(&Tx<'_, RW, WriteMap>) -> Result<R, DbError>,
|
||||
{
|
||||
f(&self.inner())
|
||||
}
|
||||
|
||||
/// Check if the table is empty
|
||||
pub(crate) fn table_is_empty<T: Table>(&self) -> Result<bool, db::Error> {
|
||||
pub(crate) fn table_is_empty<T: Table>(&self) -> Result<bool, DbError> {
|
||||
self.query(|tx| {
|
||||
let last = tx.cursor::<T>()?.last()?;
|
||||
Ok(last.is_none())
|
||||
@ -74,7 +76,7 @@ impl TestStageDB {
|
||||
/// db.map_put::<Table, _, _>(&items, |item| item)?;
|
||||
/// ```
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn map_put<T, S, F>(&self, values: &[S], mut map: F) -> Result<(), db::Error>
|
||||
pub(crate) fn map_put<T, S, F>(&self, values: &[S], mut map: F) -> Result<(), DbError>
|
||||
where
|
||||
T: Table,
|
||||
S: Clone,
|
||||
@ -102,7 +104,7 @@ impl TestStageDB {
|
||||
&self,
|
||||
values: &[S],
|
||||
mut transform: F,
|
||||
) -> Result<(), db::Error>
|
||||
) -> Result<(), DbError>
|
||||
where
|
||||
T: Table,
|
||||
<T as Table>::Value: Clone,
|
||||
@ -126,7 +128,7 @@ impl TestStageDB {
|
||||
&self,
|
||||
num: u64,
|
||||
mut selector: F,
|
||||
) -> Result<(), db::Error>
|
||||
) -> Result<(), DbError>
|
||||
where
|
||||
T: Table,
|
||||
F: FnMut(T::Key) -> BlockNumber,
|
||||
@ -146,7 +148,7 @@ impl TestStageDB {
|
||||
&self,
|
||||
num: u64,
|
||||
mut selector: F,
|
||||
) -> Result<(), db::Error>
|
||||
) -> Result<(), DbError>
|
||||
where
|
||||
T: Table,
|
||||
F: FnMut(T::Value) -> BlockNumber,
|
||||
@ -162,7 +164,7 @@ impl TestStageDB {
|
||||
|
||||
/// Insert ordered collection of [SealedHeader] into the corresponding tables
|
||||
/// that are supposed to be populated by the headers stage.
|
||||
pub(crate) fn insert_headers<'a, I>(&self, headers: I) -> Result<(), db::Error>
|
||||
pub(crate) fn insert_headers<'a, I>(&self, headers: I) -> Result<(), DbError>
|
||||
where
|
||||
I: Iterator<Item = &'a SealedHeader>,
|
||||
{
|
||||
|
||||
@ -4,7 +4,7 @@ This crate allows to easily configure different codecs for different purposes (b
|
||||
|
||||
Examples:
|
||||
|
||||
- [`Header` struct](../primitives/src/header.rs)
|
||||
- [`Header` struct](../../primitives/src/header.rs)
|
||||
- [DB usage](../db/src/kv/codecs/scale.rs)
|
||||
|
||||
### Features
|
||||
@ -9,14 +9,22 @@ description = "Staged syncing primitives used in reth."
|
||||
|
||||
[dependencies]
|
||||
# reth
|
||||
reth-primitives = { path = "../primitives" }
|
||||
reth-interfaces = { path = "../interfaces" }
|
||||
reth-libmdbx = { path = "../libmdbx-rs" }
|
||||
reth-primitives = { path = "../../primitives" }
|
||||
reth-interfaces = { path = "../../interfaces" }
|
||||
reth-codecs = { path = "../codecs" }
|
||||
reth-libmdbx = { path = "../libmdbx-rs", optional = true }
|
||||
|
||||
# codecs
|
||||
serde = { version = "1.0.*", default-features = false }
|
||||
postcard = { version = "1.0.2", features = ["alloc"] }
|
||||
heapless = "0.7.16"
|
||||
parity-scale-codec = { version = "3.2.1", features = ["bytes"] }
|
||||
futures = "0.3.25"
|
||||
tokio-stream = "0.1.11"
|
||||
rand = "0.8.5"
|
||||
arbitrary = { version = "1.1.7", features = ["derive"], optional = true }
|
||||
secp256k1 = { version = "0.24.0", default-features = false, features = ["alloc", "recovery", "rand"], optional = true }
|
||||
modular-bitfield = "0.11.2"
|
||||
|
||||
# misc
|
||||
bytes = "1.2.1"
|
||||
@ -25,19 +33,24 @@ thiserror = "1.0.37"
|
||||
tempfile = { version = "3.3.0", optional = true }
|
||||
eyre = "0.6.8"
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.3.0"
|
||||
test-fuzz = "3.0.4"
|
||||
criterion = "0.4.0"
|
||||
iai = "0.1.1"
|
||||
tokio = { version = "1.21.2", features = ["full"] }
|
||||
arbitrary = { version = "1.1.7", features = ["derive"]}
|
||||
reth-db = { path = ".", features = ["test-utils","bench"]}
|
||||
|
||||
reth-interfaces = { path = "../interfaces",features=["bench"] }
|
||||
reth-interfaces = { path = "../../interfaces",features=["bench"] }
|
||||
async-trait = "0.1.58"
|
||||
|
||||
[features]
|
||||
default = ["mdbx"]
|
||||
test-utils = ["tempfile"]
|
||||
bench-postcard = ["bench"]
|
||||
mdbx = ["reth-libmdbx"]
|
||||
bench = []
|
||||
|
||||
[[bench]]
|
||||
@ -8,9 +8,9 @@ macro_rules! impl_criterion_encoding_benchmark {
|
||||
c.bench_function(stringify!($name), |b| {
|
||||
b.iter(|| {
|
||||
let encoded_size =
|
||||
reth_interfaces::db::codecs::fuzz::IntegerList::encode_and_decode(
|
||||
black_box(reth_primitives::IntegerList::default()),
|
||||
)
|
||||
reth_db::tables::codecs::fuzz::IntegerList::encode_and_decode(black_box(
|
||||
reth_primitives::IntegerList::default(),
|
||||
))
|
||||
.0;
|
||||
|
||||
if size == 0 {
|
||||
@ -1,11 +1,11 @@
|
||||
use iai::{black_box, main};
|
||||
use reth_interfaces::db;
|
||||
use reth_db::tables::codecs;
|
||||
|
||||
/// Benchmarks the encoding and decoding of `Header` using iai.
|
||||
macro_rules! impl_iai_encoding_benchmark {
|
||||
($name:tt) => {
|
||||
fn $name() {
|
||||
db::codecs::fuzz::IntegerList::encode_and_decode(black_box(
|
||||
codecs::fuzz::IntegerList::encode_and_decode(black_box(
|
||||
reth_primitives::IntegerList::default(),
|
||||
));
|
||||
}
|
||||
16
crates/storage/db/src/abstraction/common.rs
Normal file
16
crates/storage/db/src/abstraction/common.rs
Normal file
@ -0,0 +1,16 @@
|
||||
/// Alias type for a `(key, value)` result coming from a cursor.
|
||||
pub type PairResult<T> = Result<Option<(<T as Table>::Key, <T as Table>::Value)>, Error>;
|
||||
/// Alias type for a `(key, value)` result coming from an iterator.
|
||||
pub type IterPairResult<T> = Option<Result<(<T as Table>::Key, <T as Table>::Value), Error>>;
|
||||
/// Alias type for a value result coming from a cursor without its key.
|
||||
pub type ValueOnlyResult<T> = Result<Option<<T as Table>::Value>, Error>;
|
||||
|
||||
use crate::{abstraction::table::*, Error};
|
||||
|
||||
// Sealed trait helper to prevent misuse of the API.
|
||||
mod sealed {
|
||||
pub trait Sealed: Sized {}
|
||||
pub struct Bounds<T>(T);
|
||||
impl<T> Sealed for Bounds<T> {}
|
||||
}
|
||||
pub(crate) use sealed::{Bounds, Sealed};
|
||||
147
crates/storage/db/src/abstraction/cursor.rs
Normal file
147
crates/storage/db/src/abstraction/cursor.rs
Normal file
@ -0,0 +1,147 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use crate::{
|
||||
common::{IterPairResult, PairResult, ValueOnlyResult},
|
||||
table::{DupSort, Table},
|
||||
Error,
|
||||
};
|
||||
|
||||
/// Read only cursor over table.
|
||||
pub trait DbCursorRO<'tx, T: Table> {
|
||||
/// First item in table
|
||||
fn first(&mut self) -> PairResult<T>;
|
||||
|
||||
/// Seeks for the exact `(key, value)` pair with `key`.
|
||||
fn seek_exact(&mut self, key: T::Key) -> PairResult<T>;
|
||||
|
||||
/// Returns the next `(key, value)` pair.
|
||||
#[allow(clippy::should_implement_trait)]
|
||||
fn next(&mut self) -> PairResult<T>;
|
||||
|
||||
/// Returns the previous `(key, value)` pair.
|
||||
fn prev(&mut self) -> PairResult<T>;
|
||||
|
||||
/// Returns the last `(key, value)` pair.
|
||||
fn last(&mut self) -> PairResult<T>;
|
||||
|
||||
/// Returns the current `(key, value)` pair of the cursor.
|
||||
fn current(&mut self) -> PairResult<T>;
|
||||
|
||||
/// Returns an iterator starting at a key greater or equal than `start_key`.
|
||||
fn walk<'cursor>(
|
||||
&'cursor mut self,
|
||||
start_key: T::Key,
|
||||
) -> Result<Walker<'cursor, 'tx, T, Self>, Error>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
/// Read only curor over DupSort table.
|
||||
pub trait DbDupCursorRO<'tx, T: DupSort> {
|
||||
/// Seeks for a `(key, value)` pair greater or equal than `key`.
|
||||
fn seek(&mut self, key: T::SubKey) -> PairResult<T>;
|
||||
|
||||
/// Returns the next `(key, value)` pair of a DUPSORT table.
|
||||
fn next_dup(&mut self) -> PairResult<T>;
|
||||
|
||||
/// Returns the next `(key, value)` pair skipping the duplicates.
|
||||
fn next_no_dup(&mut self) -> PairResult<T>;
|
||||
|
||||
/// Returns the next `value` of a duplicate `key`.
|
||||
fn next_dup_val(&mut self) -> ValueOnlyResult<T>;
|
||||
|
||||
/// Returns an iterator starting at a key greater or equal than `start_key` of a DUPSORT
|
||||
/// table.
|
||||
fn walk_dup<'cursor>(
|
||||
&'cursor mut self,
|
||||
key: T::Key,
|
||||
subkey: T::SubKey,
|
||||
) -> Result<DupWalker<'cursor, 'tx, T, Self>, Error>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
/// Read write cursor over table.
|
||||
pub trait DbCursorRW<'tx, T: Table> {
|
||||
/// Database operation that will update an existing row if a specified value already
|
||||
/// exists in a table, and insert a new row if the specified value doesn't already exist
|
||||
fn upsert(&mut self, key: T::Key, value: T::Value) -> Result<(), Error>;
|
||||
|
||||
/// Database operation that will insert a row at a given key. If the key is already
|
||||
/// present, the operation will result in an error.
|
||||
fn insert(&mut self, key: T::Key, value: T::Value) -> Result<(), Error>;
|
||||
|
||||
/// Append value to next cursor item.
|
||||
///
|
||||
/// This is efficient for pre-sorted data. If the data is not pre-sorted, use [`insert`].
|
||||
fn append(&mut self, key: T::Key, value: T::Value) -> Result<(), Error>;
|
||||
|
||||
/// Delete current value that cursor points to
|
||||
fn delete_current(&mut self) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
/// Read Write Cursor over DupSorted table.
|
||||
pub trait DbDupCursorRW<'tx, T: DupSort> {
|
||||
/// Append value to next cursor item
|
||||
fn delete_current_duplicates(&mut self) -> Result<(), Error>;
|
||||
|
||||
/// Append duplicate value.
|
||||
///
|
||||
/// This is efficient for pre-sorted data. If the data is not pre-sorted, use [`insert`].
|
||||
fn append_dup(&mut self, key: T::Key, value: T::Value) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
/// Provides an iterator to `Cursor` when handling `Table`.
|
||||
///
|
||||
/// Reason why we have two lifetimes is to distinguish between `'cursor` lifetime
|
||||
/// and inherited `'tx` lifetime. If there is only one, rust would short circle
|
||||
/// the Cursor lifetime and it wouldn't be possible to use Walker.
|
||||
pub struct Walker<'cursor, 'tx, T: Table, CURSOR: DbCursorRO<'tx, T>> {
|
||||
/// Cursor to be used to walk through the table.
|
||||
pub cursor: &'cursor mut CURSOR,
|
||||
/// `(key, value)` where to start the walk.
|
||||
pub start: IterPairResult<T>,
|
||||
/// Phantom data for 'tx. As it is only used for `DbCursorRO`.
|
||||
pub _tx_phantom: PhantomData<&'tx T>,
|
||||
}
|
||||
|
||||
impl<'cursor, 'tx, T: Table, CURSOR: DbCursorRO<'tx, T>> std::iter::Iterator
|
||||
for Walker<'cursor, 'tx, T, CURSOR>
|
||||
{
|
||||
type Item = Result<(T::Key, T::Value), Error>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let start = self.start.take();
|
||||
if start.is_some() {
|
||||
return start
|
||||
}
|
||||
|
||||
self.cursor.next().transpose()
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides an iterator to `Cursor` when handling a `DupSort` table.
|
||||
///
|
||||
/// Reason why we have two lifetimes is to distinguish between `'cursor` lifetime
|
||||
/// and inherited `'tx` lifetime. If there is only one, rust would short circle
|
||||
/// the Cursor lifetime and it wouldn't be possible to use Walker.
|
||||
pub struct DupWalker<'cursor, 'tx, T: DupSort, CURSOR: DbDupCursorRO<'tx, T>> {
|
||||
/// Cursor to be used to walk through the table.
|
||||
pub cursor: &'cursor mut CURSOR,
|
||||
/// Value where to start the walk.
|
||||
pub start: IterPairResult<T>,
|
||||
/// Phantom data for 'tx. As it is only used for `DbDupCursorRO`.
|
||||
pub _tx_phantom: PhantomData<&'tx T>,
|
||||
}
|
||||
|
||||
impl<'cursor, 'tx, T: DupSort, CURSOR: DbDupCursorRO<'tx, T>> std::iter::Iterator
|
||||
for DupWalker<'cursor, 'tx, T, CURSOR>
|
||||
{
|
||||
type Item = Result<(T::Key, T::Value), Error>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let start = self.start.take();
|
||||
if start.is_some() {
|
||||
return start
|
||||
}
|
||||
self.cursor.next_dup().transpose()
|
||||
}
|
||||
}
|
||||
53
crates/storage/db/src/abstraction/database.rs
Normal file
53
crates/storage/db/src/abstraction/database.rs
Normal file
@ -0,0 +1,53 @@
|
||||
use crate::{
|
||||
common::{Bounds, Sealed},
|
||||
transaction::{DbTx, DbTxMut},
|
||||
Error,
|
||||
};
|
||||
|
||||
/// Implements the GAT method from:
|
||||
/// https://sabrinajewson.org/blog/the-better-alternative-to-lifetime-gats#the-better-gats.
|
||||
///
|
||||
/// Sealed trait which cannot be implemented by 3rd parties, exposed only for implementers
|
||||
pub trait DatabaseGAT<'a, __ImplicitBounds: Sealed = Bounds<&'a Self>>: Send + Sync {
|
||||
/// RO database transaction
|
||||
type TX: DbTx<'a> + Send + Sync;
|
||||
/// RW database transaction
|
||||
type TXMut: DbTxMut<'a> + DbTx<'a> + Send + Sync;
|
||||
}
|
||||
|
||||
/// Main Database trait that spawns transactions to be executed.
|
||||
pub trait Database: for<'a> DatabaseGAT<'a> {
|
||||
/// Create read only transaction.
|
||||
fn tx(&self) -> Result<<Self as DatabaseGAT<'_>>::TX, Error>;
|
||||
|
||||
/// Create read write transaction only possible if database is open with write access.
|
||||
fn tx_mut(&self) -> Result<<Self as DatabaseGAT<'_>>::TXMut, Error>;
|
||||
|
||||
/// Takes a function and passes a read-only transaction into it, making sure it's closed in the
|
||||
/// end of the execution.
|
||||
fn view<T, F>(&self, f: F) -> Result<T, Error>
|
||||
where
|
||||
F: Fn(&<Self as DatabaseGAT<'_>>::TX) -> T,
|
||||
{
|
||||
let tx = self.tx()?;
|
||||
|
||||
let res = f(&tx);
|
||||
tx.commit()?;
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
/// Takes a function and passes a write-read transaction into it, making sure it's committed in
|
||||
/// the end of the execution.
|
||||
fn update<T, F>(&self, f: F) -> Result<T, Error>
|
||||
where
|
||||
F: Fn(&<Self as DatabaseGAT<'_>>::TXMut) -> T,
|
||||
{
|
||||
let tx = self.tx_mut()?;
|
||||
|
||||
let res = f(&tx);
|
||||
tx.commit()?;
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,13 @@
|
||||
//! Mock database
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use super::{
|
||||
Database, DatabaseGAT, DbCursorRO, DbCursorRW, DbDupCursorRO, DbDupCursorRW, DbTx, DbTxGAT,
|
||||
DbTxMut, DbTxMutGAT, DupSort, DupWalker, Error, Table, Walker,
|
||||
use crate::{
|
||||
common::{PairResult, ValueOnlyResult},
|
||||
cursor::{DbCursorRO, DbCursorRW, DbDupCursorRO, DbDupCursorRW, DupWalker, Walker},
|
||||
database::{Database, DatabaseGAT},
|
||||
table::{DupSort, Table},
|
||||
transaction::{DbTx, DbTxGAT, DbTxMut, DbTxMutGAT},
|
||||
Error,
|
||||
};
|
||||
|
||||
/// Mock database used for testing with inner BTreeMap structure
|
||||
@ -15,11 +19,11 @@ pub struct DatabaseMock {
|
||||
}
|
||||
|
||||
impl Database for DatabaseMock {
|
||||
fn tx(&self) -> Result<<Self as DatabaseGAT<'_>>::TX, super::Error> {
|
||||
fn tx(&self) -> Result<<Self as DatabaseGAT<'_>>::TX, Error> {
|
||||
Ok(TxMock::default())
|
||||
}
|
||||
|
||||
fn tx_mut(&self) -> Result<<Self as DatabaseGAT<'_>>::TXMut, super::Error> {
|
||||
fn tx_mut(&self) -> Result<<Self as DatabaseGAT<'_>>::TXMut, Error> {
|
||||
Ok(TxMock::default())
|
||||
}
|
||||
}
|
||||
@ -48,51 +52,43 @@ impl<'a> DbTxMutGAT<'a> for TxMock {
|
||||
}
|
||||
|
||||
impl<'a> DbTx<'a> for TxMock {
|
||||
fn get<T: super::Table>(&self, _key: T::Key) -> Result<Option<T::Value>, super::Error> {
|
||||
fn get<T: Table>(&self, _key: T::Key) -> Result<Option<T::Value>, Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn commit(self) -> Result<bool, super::Error> {
|
||||
fn commit(self) -> Result<bool, Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn cursor<T: super::Table>(&self) -> Result<<Self as DbTxGAT<'_>>::Cursor<T>, super::Error> {
|
||||
fn cursor<T: Table>(&self) -> Result<<Self as DbTxGAT<'_>>::Cursor<T>, Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn cursor_dup<T: super::DupSort>(
|
||||
&self,
|
||||
) -> Result<<Self as DbTxGAT<'_>>::DupCursor<T>, super::Error> {
|
||||
fn cursor_dup<T: DupSort>(&self) -> Result<<Self as DbTxGAT<'_>>::DupCursor<T>, Error> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> DbTxMut<'a> for TxMock {
|
||||
fn put<T: super::Table>(&self, _key: T::Key, _value: T::Value) -> Result<(), super::Error> {
|
||||
fn put<T: Table>(&self, _key: T::Key, _value: T::Value) -> Result<(), Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn delete<T: super::Table>(
|
||||
fn delete<T: Table>(&self, _key: T::Key, _value: Option<T::Value>) -> Result<bool, Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn cursor_mut<T: Table>(&self) -> Result<<Self as DbTxMutGAT<'_>>::CursorMut<T>, Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn cursor_dup_mut<T: DupSort>(
|
||||
&self,
|
||||
_key: T::Key,
|
||||
_value: Option<T::Value>,
|
||||
) -> Result<bool, super::Error> {
|
||||
) -> Result<<Self as DbTxMutGAT<'_>>::DupCursorMut<T>, Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn cursor_mut<T: super::Table>(
|
||||
&self,
|
||||
) -> Result<<Self as DbTxMutGAT<'_>>::CursorMut<T>, super::Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn cursor_dup_mut<T: super::DupSort>(
|
||||
&self,
|
||||
) -> Result<<Self as DbTxMutGAT<'_>>::DupCursorMut<T>, super::Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn clear<T: Table>(&self) -> Result<(), super::Error> {
|
||||
fn clear<T: Table>(&self) -> Result<(), Error> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@ -103,27 +99,27 @@ pub struct CursorMock {
|
||||
}
|
||||
|
||||
impl<'tx, T: Table> DbCursorRO<'tx, T> for CursorMock {
|
||||
fn first(&mut self) -> super::PairResult<T> {
|
||||
fn first(&mut self) -> PairResult<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn seek_exact(&mut self, _key: T::Key) -> super::PairResult<T> {
|
||||
fn seek_exact(&mut self, _key: T::Key) -> PairResult<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn next(&mut self) -> super::PairResult<T> {
|
||||
fn next(&mut self) -> PairResult<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn prev(&mut self) -> super::PairResult<T> {
|
||||
fn prev(&mut self) -> PairResult<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn last(&mut self) -> super::PairResult<T> {
|
||||
fn last(&mut self) -> PairResult<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn current(&mut self) -> super::PairResult<T> {
|
||||
fn current(&mut self) -> PairResult<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@ -139,19 +135,19 @@ impl<'tx, T: Table> DbCursorRO<'tx, T> for CursorMock {
|
||||
}
|
||||
|
||||
impl<'tx, T: DupSort> DbDupCursorRO<'tx, T> for CursorMock {
|
||||
fn next_dup(&mut self) -> super::PairResult<T> {
|
||||
fn next_dup(&mut self) -> PairResult<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn seek(&mut self, _key: T::SubKey) -> super::PairResult<T> {
|
||||
fn seek(&mut self, _key: T::SubKey) -> PairResult<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn next_no_dup(&mut self) -> super::PairResult<T> {
|
||||
fn next_no_dup(&mut self) -> PairResult<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn next_dup_val(&mut self) -> super::ValueOnlyResult<T> {
|
||||
fn next_dup_val(&mut self) -> ValueOnlyResult<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@ -172,7 +168,7 @@ impl<'tx, T: Table> DbCursorRW<'tx, T> for CursorMock {
|
||||
&mut self,
|
||||
_key: <T as Table>::Key,
|
||||
_value: <T as Table>::Value,
|
||||
) -> Result<(), super::Error> {
|
||||
) -> Result<(), Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@ -180,7 +176,7 @@ impl<'tx, T: Table> DbCursorRW<'tx, T> for CursorMock {
|
||||
&mut self,
|
||||
_key: <T as Table>::Key,
|
||||
_value: <T as Table>::Value,
|
||||
) -> Result<(), super::Error> {
|
||||
) -> Result<(), Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@ -188,21 +184,21 @@ impl<'tx, T: Table> DbCursorRW<'tx, T> for CursorMock {
|
||||
&mut self,
|
||||
_key: <T as Table>::Key,
|
||||
_value: <T as Table>::Value,
|
||||
) -> Result<(), super::Error> {
|
||||
) -> Result<(), Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn delete_current(&mut self) -> Result<(), super::Error> {
|
||||
fn delete_current(&mut self) -> Result<(), Error> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tx, T: DupSort> DbDupCursorRW<'tx, T> for CursorMock {
|
||||
fn delete_current_duplicates(&mut self) -> Result<(), super::Error> {
|
||||
fn delete_current_duplicates(&mut self) -> Result<(), Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn append_dup(&mut self, _key: <T>::Key, _value: <T>::Value) -> Result<(), super::Error> {
|
||||
fn append_dup(&mut self, _key: <T>::Key, _value: <T>::Value) -> Result<(), Error> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
12
crates/storage/db/src/abstraction/mod.rs
Normal file
12
crates/storage/db/src/abstraction/mod.rs
Normal file
@ -0,0 +1,12 @@
|
||||
/// Commont return types
|
||||
pub mod common;
|
||||
/// Cursor database traits.
|
||||
pub mod cursor;
|
||||
/// Database traits.
|
||||
pub mod database;
|
||||
/// mock
|
||||
pub mod mock;
|
||||
/// Table traits
|
||||
pub mod table;
|
||||
/// Transaction database traits.
|
||||
pub mod transaction;
|
||||
@ -1,4 +1,4 @@
|
||||
use super::Error;
|
||||
use crate::Error;
|
||||
use bytes::Bytes;
|
||||
use std::{
|
||||
fmt::Debug,
|
||||
62
crates/storage/db/src/abstraction/transaction.rs
Normal file
62
crates/storage/db/src/abstraction/transaction.rs
Normal file
@ -0,0 +1,62 @@
|
||||
use crate::{
|
||||
common::{Bounds, Sealed},
|
||||
cursor::{DbCursorRO, DbCursorRW, DbDupCursorRO, DbDupCursorRW},
|
||||
table::{DupSort, Table},
|
||||
Error,
|
||||
};
|
||||
|
||||
/// Implements the GAT method from:
|
||||
/// https://sabrinajewson.org/blog/the-better-alternative-to-lifetime-gats#the-better-gats.
|
||||
///
|
||||
/// Sealed trait which cannot be implemented by 3rd parties, exposed only for implementers
|
||||
pub trait DbTxGAT<'a, __ImplicitBounds: Sealed = Bounds<&'a Self>>: Send + Sync {
|
||||
/// Cursor GAT
|
||||
type Cursor<T: Table>: DbCursorRO<'a, T> + Send + Sync;
|
||||
/// DupCursor GAT
|
||||
type DupCursor<T: DupSort>: DbDupCursorRO<'a, T> + DbCursorRO<'a, T> + Send + Sync;
|
||||
}
|
||||
|
||||
/// Implements the GAT method from:
|
||||
/// https://sabrinajewson.org/blog/the-better-alternative-to-lifetime-gats#the-better-gats.
|
||||
///
|
||||
/// Sealed trait which cannot be implemented by 3rd parties, exposed only for implementers
|
||||
pub trait DbTxMutGAT<'a, __ImplicitBounds: Sealed = Bounds<&'a Self>>: Send + Sync {
|
||||
/// Cursor GAT
|
||||
type CursorMut<T: Table>: DbCursorRW<'a, T> + DbCursorRO<'a, T> + Send + Sync;
|
||||
/// DupCursor GAT
|
||||
type DupCursorMut<T: DupSort>: DbDupCursorRW<'a, T>
|
||||
+ DbCursorRW<'a, T>
|
||||
+ DbDupCursorRO<'a, T>
|
||||
+ DbCursorRO<'a, T>
|
||||
+ Send
|
||||
+ Sync;
|
||||
}
|
||||
|
||||
/// Read only transaction
|
||||
pub trait DbTx<'tx>: for<'a> DbTxGAT<'a> {
|
||||
/// Get value
|
||||
fn get<T: Table>(&self, key: T::Key) -> Result<Option<T::Value>, Error>;
|
||||
/// Commit for read only transaction will consume and free transaction and allows
|
||||
/// freeing of memory pages
|
||||
fn commit(self) -> Result<bool, Error>;
|
||||
/// Iterate over read only values in table.
|
||||
fn cursor<T: Table>(&self) -> Result<<Self as DbTxGAT<'_>>::Cursor<T>, Error>;
|
||||
/// Iterate over read only values in dup sorted table.
|
||||
fn cursor_dup<T: DupSort>(&self) -> Result<<Self as DbTxGAT<'_>>::DupCursor<T>, Error>;
|
||||
}
|
||||
|
||||
/// Read write transaction that allows writing to database
|
||||
pub trait DbTxMut<'tx>: for<'a> DbTxMutGAT<'a> {
|
||||
/// Put value to database
|
||||
fn put<T: Table>(&self, key: T::Key, value: T::Value) -> Result<(), Error>;
|
||||
/// Delete value from database
|
||||
fn delete<T: Table>(&self, key: T::Key, value: Option<T::Value>) -> Result<bool, Error>;
|
||||
/// Clears database.
|
||||
fn clear<T: Table>(&self) -> Result<(), Error>;
|
||||
/// Cursor mut
|
||||
fn cursor_mut<T: Table>(&self) -> Result<<Self as DbTxMutGAT<'_>>::CursorMut<T>, Error>;
|
||||
/// DupCursor mut.
|
||||
fn cursor_dup_mut<T: DupSort>(
|
||||
&self,
|
||||
) -> Result<<Self as DbTxMutGAT<'_>>::DupCursorMut<T>, Error>;
|
||||
}
|
||||
@ -2,10 +2,11 @@
|
||||
|
||||
use std::{borrow::Cow, marker::PhantomData};
|
||||
|
||||
use crate::utils::*;
|
||||
use reth_interfaces::db::{
|
||||
Compress, DbCursorRO, DbCursorRW, DbDupCursorRO, DbDupCursorRW, DupSort, DupWalker, Encode,
|
||||
Error, Table, Walker,
|
||||
use crate::{
|
||||
cursor::{DbCursorRO, DbCursorRW, DbDupCursorRO, DbDupCursorRW, DupWalker, Walker},
|
||||
table::{Compress, DupSort, Encode, Table},
|
||||
tables::utils::*,
|
||||
Error,
|
||||
};
|
||||
use reth_libmdbx::{self, TransactionKind, WriteFlags, RO, RW};
|
||||
|
||||
@ -41,27 +42,27 @@ macro_rules! decode {
|
||||
}
|
||||
|
||||
impl<'tx, K: TransactionKind, T: Table> DbCursorRO<'tx, T> for Cursor<'tx, K, T> {
|
||||
fn first(&mut self) -> reth_interfaces::db::PairResult<T> {
|
||||
fn first(&mut self) -> PairResult<T> {
|
||||
decode!(self.inner.first())
|
||||
}
|
||||
|
||||
fn seek_exact(&mut self, key: <T as Table>::Key) -> reth_interfaces::db::PairResult<T> {
|
||||
fn seek_exact(&mut self, key: <T as Table>::Key) -> PairResult<T> {
|
||||
decode!(self.inner.set_key(key.encode().as_ref()))
|
||||
}
|
||||
|
||||
fn next(&mut self) -> reth_interfaces::db::PairResult<T> {
|
||||
fn next(&mut self) -> PairResult<T> {
|
||||
decode!(self.inner.next())
|
||||
}
|
||||
|
||||
fn prev(&mut self) -> reth_interfaces::db::PairResult<T> {
|
||||
fn prev(&mut self) -> PairResult<T> {
|
||||
decode!(self.inner.prev())
|
||||
}
|
||||
|
||||
fn last(&mut self) -> reth_interfaces::db::PairResult<T> {
|
||||
fn last(&mut self) -> PairResult<T> {
|
||||
decode!(self.inner.last())
|
||||
}
|
||||
|
||||
fn current(&mut self) -> reth_interfaces::db::PairResult<T> {
|
||||
fn current(&mut self) -> PairResult<T> {
|
||||
decode!(self.inner.get_current())
|
||||
}
|
||||
|
||||
@ -83,7 +84,7 @@ impl<'tx, K: TransactionKind, T: Table> DbCursorRO<'tx, T> for Cursor<'tx, K, T>
|
||||
}
|
||||
|
||||
impl<'tx, K: TransactionKind, T: DupSort> DbDupCursorRO<'tx, T> for Cursor<'tx, K, T> {
|
||||
fn seek(&mut self, key: <T as DupSort>::SubKey) -> reth_interfaces::db::PairResult<T> {
|
||||
fn seek(&mut self, key: <T as DupSort>::SubKey) -> PairResult<T> {
|
||||
decode!(self.inner.set_range(key.encode().as_ref()))
|
||||
}
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
//! Module that interacts with MDBX.
|
||||
|
||||
use crate::utils::default_page_size;
|
||||
use reth_interfaces::db::{
|
||||
use crate::{
|
||||
database::{Database, DatabaseGAT},
|
||||
tables::{TableType, TABLES},
|
||||
Database, DatabaseGAT, Error,
|
||||
utils::default_page_size,
|
||||
Error,
|
||||
};
|
||||
use reth_libmdbx::{
|
||||
DatabaseFlags, Environment, EnvironmentFlags, EnvironmentKind, Geometry, Mode, PageSize,
|
||||
@ -138,16 +139,13 @@ pub mod test_utils {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{test_utils, Env, EnvKind};
|
||||
use reth_interfaces::{
|
||||
db::{
|
||||
self,
|
||||
use crate::{
|
||||
cursor::{DbCursorRO, DbCursorRW, DbDupCursorRO},
|
||||
database::Database,
|
||||
models::ShardedKey,
|
||||
tables::{
|
||||
AccountHistory, CanonicalHeaders, Headers, PlainAccountState, PlainStorageState,
|
||||
},
|
||||
Database, DbCursorRO, DbCursorRW, DbDupCursorRO, DbTx, DbTxMut,
|
||||
},
|
||||
provider::{ProviderImpl, StateProviderFactory},
|
||||
tables::{AccountHistory, CanonicalHeaders, Headers, PlainAccountState, PlainStorageState},
|
||||
transaction::{DbTx, DbTxMut},
|
||||
Error,
|
||||
};
|
||||
use reth_libmdbx::{NoWriteMap, WriteMap};
|
||||
use reth_primitives::{Account, Address, Header, IntegerList, StorageEntry, H256, U256};
|
||||
@ -261,7 +259,7 @@ mod tests {
|
||||
assert_eq!(cursor.current(), Ok(Some((key_to_insert, H256::zero()))));
|
||||
|
||||
// INSERT (failure)
|
||||
assert_eq!(cursor.insert(key_to_insert, H256::zero()), Err(db::Error::Write(4294936497)));
|
||||
assert_eq!(cursor.insert(key_to_insert, H256::zero()), Err(Error::Write(4294936497)));
|
||||
assert_eq!(cursor.current(), Ok(Some((key_to_insert, H256::zero()))));
|
||||
}
|
||||
|
||||
@ -282,7 +280,7 @@ mod tests {
|
||||
let tx = db.tx_mut().expect(ERROR_INIT_TX);
|
||||
let mut cursor = tx.cursor_mut::<CanonicalHeaders>().unwrap();
|
||||
cursor.seek_exact(1).unwrap();
|
||||
assert_eq!(cursor.append(key_to_append, H256::zero()), Err(db::Error::Write(4294936878)));
|
||||
assert_eq!(cursor.append(key_to_append, H256::zero()), Err(Error::Write(4294936878)));
|
||||
assert_eq!(cursor.current(), Ok(Some((5, H256::zero())))); // the end of table
|
||||
}
|
||||
|
||||
@ -396,11 +394,4 @@ mod tests {
|
||||
assert_eq!(list200, list);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn common_history_provider() {
|
||||
let db = test_utils::create_test_db::<WriteMap>(EnvKind::RW);
|
||||
let provider = ProviderImpl::new(db);
|
||||
let _ = provider.latest();
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,11 @@
|
||||
//! Transaction wrapper for libmdbx-sys.
|
||||
|
||||
use crate::{kv::cursor::Cursor, utils::decode_one};
|
||||
use reth_interfaces::db::{
|
||||
Compress, DbTx, DbTxGAT, DbTxMut, DbTxMutGAT, DupSort, Encode, Error, Table,
|
||||
use super::cursor::Cursor;
|
||||
use crate::{
|
||||
table::{Compress, DupSort, Encode, Table},
|
||||
tables::utils::decode_one,
|
||||
transaction::{DbTx, DbTxGAT, DbTxMut, DbTxMutGAT},
|
||||
Error,
|
||||
};
|
||||
use reth_libmdbx::{EnvironmentKind, Transaction, TransactionKind, WriteFlags, RW};
|
||||
use std::marker::PhantomData;
|
||||
2
crates/storage/db/src/implementation/mod.rs
Normal file
2
crates/storage/db/src/implementation/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
#[cfg(feature = "mdbx")]
|
||||
pub(crate) mod mdbx;
|
||||
26
crates/storage/db/src/lib.rs
Normal file
26
crates/storage/db/src/lib.rs
Normal file
@ -0,0 +1,26 @@
|
||||
//! Rust database abstraction and concrete database implementations.
|
||||
|
||||
#![warn(missing_docs, unreachable_pub)]
|
||||
#![deny(unused_must_use, rust_2018_idioms)]
|
||||
#![doc(test(
|
||||
no_crate_inject,
|
||||
attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
|
||||
))]
|
||||
|
||||
/// Abstracted part of database, containing traits for transactions and cursors.
|
||||
pub mod abstraction;
|
||||
|
||||
mod implementation;
|
||||
pub mod tables;
|
||||
mod utils;
|
||||
|
||||
#[cfg(feature = "mdbx")]
|
||||
/// Bindings for [MDBX](https://libmdbx.dqdkfa.ru/).
|
||||
pub mod mdbx {
|
||||
pub use crate::implementation::mdbx::*;
|
||||
pub use reth_libmdbx::*;
|
||||
}
|
||||
|
||||
pub use abstraction::*;
|
||||
pub use reth_interfaces::db::Error;
|
||||
pub use tables::*;
|
||||
@ -1,6 +1,7 @@
|
||||
use crate::db::{
|
||||
models::{accounts::AccountBeforeTx, StoredBlockOmmers},
|
||||
Compress, Decompress, Error,
|
||||
use crate::{
|
||||
table::{Compress, Decompress},
|
||||
tables::models::*,
|
||||
Error,
|
||||
};
|
||||
use reth_codecs::{main_codec, Compact};
|
||||
use reth_primitives::*;
|
||||
@ -14,7 +14,7 @@ macro_rules! impl_fuzzer_with_input {
|
||||
#[allow(non_snake_case)]
|
||||
#[cfg(any(test, feature = "bench"))]
|
||||
pub mod $name {
|
||||
use crate::db::table;
|
||||
use crate::table;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use reth_primitives::*;
|
||||
@ -23,7 +23,7 @@ macro_rules! impl_fuzzer_with_input {
|
||||
use super::inputs::*;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use crate::db::models::*;
|
||||
use crate::tables::models::*;
|
||||
|
||||
/// Encodes and decodes table types returning its encoded size and the decoded object.
|
||||
/// This method is used for benchmarking, so its parameter should be the actual type that is being tested.
|
||||
@ -4,6 +4,6 @@ mod compact;
|
||||
pub use compact::CompactU256;
|
||||
|
||||
pub mod fuzz;
|
||||
|
||||
mod postcard;
|
||||
#[cfg(not(feature = "bench-postcard"))]
|
||||
mod scale;
|
||||
@ -1,6 +1,9 @@
|
||||
#![allow(unused)]
|
||||
|
||||
use crate::db::{Decode, Encode, Error};
|
||||
use crate::{
|
||||
table::{Decode, Encode},
|
||||
Error,
|
||||
};
|
||||
use postcard::{from_bytes, to_allocvec, to_vec};
|
||||
use reth_primitives::*;
|
||||
|
||||
@ -26,7 +29,7 @@ macro_rules! impl_postcard {
|
||||
}
|
||||
|
||||
impl Decode for $name {
|
||||
fn decode<B: Into<bytes::Bytes>>(value: B) -> Result<Self, KVError> {
|
||||
fn decode<B: Into<bytes::Bytes>>(value: B) -> Result<Self, Error> {
|
||||
from_bytes(&value.into()).map_err(|e| Error::Decode(e.into()))
|
||||
}
|
||||
}
|
||||
@ -36,5 +39,5 @@ macro_rules! impl_postcard {
|
||||
|
||||
type VecU8 = Vec<u8>;
|
||||
|
||||
#[cfg(feature = "bench-postcard")]
|
||||
impl_postcard!(VecU8, Receipt, H256, U256, H160, u8, u16, u64, Header, Account, Log, TxType);
|
||||
//#[cfg(feature = "bench-postcard")]
|
||||
//impl_postcard!(VecU8, Receipt, H256, U256, H160, u8, u16, u64, Header, Account, Log, TxType);
|
||||
@ -1,4 +1,7 @@
|
||||
use crate::db::{Compress, Decompress, Error};
|
||||
use crate::{
|
||||
table::{Compress, Decompress},
|
||||
Error,
|
||||
};
|
||||
use parity_scale_codec::decode_from_bytes;
|
||||
use reth_primitives::*;
|
||||
|
||||
@ -1,13 +1,20 @@
|
||||
//! Declaration of all Database tables.
|
||||
//! Table and data structures
|
||||
|
||||
use crate::db::{
|
||||
pub mod codecs;
|
||||
pub mod models;
|
||||
pub mod utils;
|
||||
|
||||
/// Declaration of all Database tables.
|
||||
use crate::{
|
||||
table::DupSort,
|
||||
tables::{
|
||||
codecs::CompactU256,
|
||||
models::{
|
||||
accounts::{AccountBeforeTx, TxNumberAddress},
|
||||
blocks::{BlockNumHash, HeaderHash, NumTransactions, StoredBlockOmmers},
|
||||
ShardedKey,
|
||||
blocks::{HeaderHash, NumTransactions, StoredBlockOmmers},
|
||||
BlockNumHash, ShardedKey,
|
||||
},
|
||||
},
|
||||
DupSort,
|
||||
};
|
||||
use reth_primitives::{
|
||||
Account, Address, BlockHash, BlockNumber, Header, IntegerList, Receipt, StorageEntry,
|
||||
@ -57,7 +64,7 @@ macro_rules! table {
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct $table_name;
|
||||
|
||||
impl $crate::db::table::Table for $table_name {
|
||||
impl $crate::table::Table for $table_name {
|
||||
const NAME: &'static str = $table_name::const_name();
|
||||
type Key = $key;
|
||||
type Value = $value;
|
||||
@ -171,10 +178,10 @@ table!(
|
||||
///
|
||||
/// ```
|
||||
/// use reth_primitives::{Address, IntegerList};
|
||||
/// use reth_interfaces::db::{DbTx, DbTxMut, DbCursorRO, Database, models::ShardedKey, tables::AccountHistory};
|
||||
/// use reth_db::{kv::{EnvKind, Env, test_utils}, mdbx::WriteMap};
|
||||
/// use reth_db::{transaction::{DbTxMut,DbTx}, mdbx::{EnvKind, Env, test_utils,WriteMap}, cursor::DbCursorRO,database::Database, tables::{AccountHistory,models::ShardedKey}};
|
||||
/// use std::{str::FromStr,sync::Arc};
|
||||
///
|
||||
///
|
||||
/// fn main() {
|
||||
/// let db: Arc<Env<WriteMap>> = test_utils::create_test_db(EnvKind::RW);
|
||||
/// let account = Address::from_str("0xa2c122be93b0074270ebee7f6b7292c7deb45047").unwrap();
|
||||
@ -1,11 +1,9 @@
|
||||
//! Account related models and types.
|
||||
|
||||
use crate::{
|
||||
db::{
|
||||
impl_fixed_arbitrary,
|
||||
table::{Decode, Encode},
|
||||
Error,
|
||||
},
|
||||
impl_fixed_arbitrary,
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use reth_codecs::{main_codec, Compact};
|
||||
@ -1,11 +1,9 @@
|
||||
//! Block related models and types.
|
||||
|
||||
use crate::{
|
||||
db::{
|
||||
impl_fixed_arbitrary,
|
||||
table::{Decode, Encode},
|
||||
Error,
|
||||
},
|
||||
impl_fixed_arbitrary,
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use reth_codecs::{main_codec, Compact};
|
||||
@ -1,8 +1,8 @@
|
||||
//! Implements [`Compress`] and [`Decompress`] for [`IntegerList`]
|
||||
|
||||
use crate::db::{
|
||||
error::Error,
|
||||
use crate::{
|
||||
table::{Compress, Decompress},
|
||||
Error,
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use reth_primitives::IntegerList;
|
||||
@ -10,7 +10,7 @@ pub use blocks::*;
|
||||
use reth_primitives::{Address, H256};
|
||||
pub use sharded_key::ShardedKey;
|
||||
|
||||
use crate::db::{
|
||||
use crate::{
|
||||
table::{Decode, Encode},
|
||||
Error,
|
||||
};
|
||||
@ -1,6 +1,6 @@
|
||||
//! Sharded key
|
||||
|
||||
use crate::db::{
|
||||
use crate::{
|
||||
table::{Decode, Encode},
|
||||
Error,
|
||||
};
|
||||
@ -1,22 +1,28 @@
|
||||
//! Utils crate for `db`.
|
||||
|
||||
//suse crate::kv::Error;
|
||||
//! Small database table utilities and helper functions
|
||||
use crate::{
|
||||
table::{Decode, Decompress, Table},
|
||||
Error,
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use reth_interfaces::db::{Decode, Decompress, Error, Table};
|
||||
use std::borrow::Cow;
|
||||
|
||||
/// Returns the default page size that can be used in this OS.
|
||||
pub(crate) fn default_page_size() -> usize {
|
||||
let os_page_size = page_size::get();
|
||||
#[macro_export]
|
||||
/// Implements the [`arbitrary::Arbitrary`] trait for types with fixed array types.
|
||||
macro_rules! impl_fixed_arbitrary {
|
||||
($name:tt, $size:tt) => {
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
use arbitrary::{Arbitrary, Unstructured};
|
||||
|
||||
// source: https://gitflic.ru/project/erthink/libmdbx/blob?file=mdbx.h#line-num-821
|
||||
let libmdbx_max_page_size = 0x10000;
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
impl<'a> Arbitrary<'a> for $name {
|
||||
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self, arbitrary::Error> {
|
||||
let mut buffer = vec![0; $size];
|
||||
u.fill_buffer(buffer.as_mut_slice())?;
|
||||
|
||||
// May lead to errors if it's reduced further because of the potential size of the
|
||||
// data.
|
||||
let min_page_size = 4096;
|
||||
|
||||
os_page_size.clamp(min_page_size, libmdbx_max_page_size)
|
||||
Decode::decode(buffer).map_err(|_| arbitrary::Error::IncorrectFormat)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Helper function to decode a `(key, value)` pair.
|
||||
15
crates/storage/db/src/utils.rs
Normal file
15
crates/storage/db/src/utils.rs
Normal file
@ -0,0 +1,15 @@
|
||||
//! Utils crate for `db`.
|
||||
|
||||
/// Returns the default page size that can be used in this OS.
|
||||
pub(crate) fn default_page_size() -> usize {
|
||||
let os_page_size = page_size::get();
|
||||
|
||||
// source: https://gitflic.ru/project/erthink/libmdbx/blob?file=mdbx.h#line-num-821
|
||||
let libmdbx_max_page_size = 0x10000;
|
||||
|
||||
// May lead to errors if it's reduced further because of the potential size of the
|
||||
// data.
|
||||
let min_page_size = 4096;
|
||||
|
||||
os_page_size.clamp(min_page_size, libmdbx_max_page_size)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user