feat(db): Refactor storage libraries (#371)

This commit is contained in:
rakita
2022-12-10 08:14:07 +01:00
committed by GitHub
parent 37e016d4a3
commit e014eaad33
139 changed files with 790 additions and 604 deletions

42
Cargo.lock generated
View File

@ -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",

View File

@ -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"]

View File

@ -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"}

View File

@ -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");

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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"] }

View File

@ -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::*;

View File

@ -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,

View File

@ -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"] }

View File

@ -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.

View File

@ -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)
}
}
};
}

View File

@ -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;

View File

@ -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 },
}

View File

@ -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};

View File

@ -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::*;

View File

@ -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"

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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};

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

@ -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;

View File

@ -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 }

View File

@ -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" }

View File

@ -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};

View File

@ -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;

View File

@ -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};

View File

@ -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].

View File

@ -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,

View File

@ -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]

View File

@ -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},

View File

@ -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()

View File

@ -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;

View File

@ -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>,
{

View File

@ -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

View File

@ -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]]

View File

@ -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 {

View File

@ -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(),
));
}

View 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};

View 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()
}
}

View 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)
}
}

View File

@ -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!()
}
}

View 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;

View File

@ -1,4 +1,4 @@
use super::Error;
use crate::Error;
use bytes::Bytes;
use std::{
fmt::Debug,

View 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>;
}

View File

@ -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()))
}

View File

@ -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();
}
}

View File

@ -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;

View File

@ -0,0 +1,2 @@
#[cfg(feature = "mdbx")]
pub(crate) mod mdbx;

View 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::*;

View File

@ -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::*;

View File

@ -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.

View File

@ -4,6 +4,6 @@ mod compact;
pub use compact::CompactU256;
pub mod fuzz;
mod postcard;
#[cfg(not(feature = "bench-postcard"))]
mod scale;

View File

@ -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);

View File

@ -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::*;

View File

@ -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();

View File

@ -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};

View File

@ -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};

View File

@ -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;

View File

@ -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,
};

View File

@ -1,6 +1,6 @@
//! Sharded key
use crate::db::{
use crate::{
table::{Decode, Encode},
Error,
};

View File

@ -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.

View 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