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", "eyre",
"reth-interfaces", "reth-interfaces",
"reth-primitives", "reth-primitives",
"reth-provider",
"reth-rlp", "reth-rlp",
"thiserror", "thiserror",
"tokio", "tokio",
@ -3107,22 +3108,31 @@ version = "0.1.0"
name = "reth-db" name = "reth-db"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"arbitrary",
"async-trait", "async-trait",
"bytes", "bytes",
"criterion", "criterion",
"eyre", "eyre",
"futures",
"heapless",
"iai", "iai",
"modular-bitfield",
"page_size", "page_size",
"parity-scale-codec", "parity-scale-codec",
"postcard", "postcard",
"rand 0.8.5",
"reth-codecs",
"reth-db",
"reth-interfaces", "reth-interfaces",
"reth-libmdbx", "reth-libmdbx",
"reth-primitives", "reth-primitives",
"secp256k1",
"serde", "serde",
"tempfile", "tempfile",
"test-fuzz", "test-fuzz",
"thiserror", "thiserror",
"tokio", "tokio",
"tokio-stream",
] ]
[[package]] [[package]]
@ -3217,6 +3227,7 @@ dependencies = [
"reth-db", "reth-db",
"reth-interfaces", "reth-interfaces",
"reth-primitives", "reth-primitives",
"reth-provider",
"reth-rlp", "reth-rlp",
"revm", "revm",
"rlp", "rlp",
@ -3335,6 +3346,7 @@ dependencies = [
"reth-eth-wire", "reth-eth-wire",
"reth-interfaces", "reth-interfaces",
"reth-primitives", "reth-primitives",
"reth-provider",
"reth-rlp", "reth-rlp",
"reth-rlp-derive", "reth-rlp-derive",
"reth-tasks", "reth-tasks",
@ -3390,6 +3402,34 @@ dependencies = [
"triehash", "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]] [[package]]
name = "reth-rlp" name = "reth-rlp"
version = "0.1.2" version = "0.1.2"
@ -3425,6 +3465,7 @@ dependencies = [
"jsonrpsee", "jsonrpsee",
"reth-interfaces", "reth-interfaces",
"reth-primitives", "reth-primitives",
"reth-provider",
"reth-rpc-api", "reth-rpc-api",
"reth-rpc-types", "reth-rpc-types",
"reth-transaction-pool", "reth-transaction-pool",
@ -3472,6 +3513,7 @@ dependencies = [
"reth-headers-downloaders", "reth-headers-downloaders",
"reth-interfaces", "reth-interfaces",
"reth-primitives", "reth-primitives",
"reth-provider",
"reth-rlp", "reth-rlp",
"tempfile", "tempfile",
"thiserror", "thiserror",

View File

@ -5,7 +5,6 @@ members = [
"crates/common/rlp", "crates/common/rlp",
"crates/common/rlp-derive", "crates/common/rlp-derive",
"crates/consensus", "crates/consensus",
"crates/db",
"crates/executor", "crates/executor",
"crates/interfaces", "crates/interfaces",
"crates/net/p2p", "crates/net/p2p",
@ -21,11 +20,13 @@ members = [
"crates/net/bodies-downloaders", "crates/net/bodies-downloaders",
"crates/primitives", "crates/primitives",
"crates/stages", "crates/stages",
"crates/storage/codecs",
"crates/storage/db",
"crates/storage/libmdbx-rs",
"crates/storage/libmdbx-rs/mdbx-sys",
"crates/storage/provider",
"crates/tracing", "crates/tracing",
"crates/tasks", "crates/tasks",
"crates/transaction-pool", "crates/transaction-pool",
"crates/db",
"crates/libmdbx-rs",
"crates/libmdbx-rs/mdbx-sys",
] ]
default-members = ["bin/reth"] default-members = ["bin/reth"]

View File

@ -9,7 +9,7 @@ readme = "README.md"
[dependencies] [dependencies]
# reth # reth
reth-primitives = { path = "../../crates/primitives" } reth-primitives = { path = "../../crates/primitives" }
reth-db = {path = "../../crates/db"} reth-db = {path = "../../crates/storage/db", features = ["mdbx"]}
reth-stages = {path = "../../crates/stages"} reth-stages = {path = "../../crates/stages"}
reth-interfaces = {path = "../../crates/interfaces"} reth-interfaces = {path = "../../crates/interfaces"}
reth-transaction-pool = {path = "../../crates/transaction-pool"} reth-transaction-pool = {path = "../../crates/transaction-pool"}

View File

@ -24,9 +24,9 @@ impl Command {
let path = shellexpand::full(&self.db)?.into_owned(); let path = shellexpand::full(&self.db)?.into_owned();
let expanded_db_path = Path::new(&path); let expanded_db_path = Path::new(&path);
std::fs::create_dir_all(expanded_db_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, expanded_db_path,
reth_db::kv::EnvKind::RW, reth_db::mdbx::EnvKind::RW,
)?); )?);
info!("DB opened"); info!("DB opened");

View File

@ -10,6 +10,7 @@ readme = "README.md"
# reth # reth
reth-primitives = { path = "../primitives" } reth-primitives = { path = "../primitives" }
reth-interfaces = { path = "../interfaces" } reth-interfaces = { path = "../interfaces" }
reth-provider = { path = "../storage/provider" }
reth-rlp = {path = "../common/rlp"} reth-rlp = {path = "../common/rlp"}
# common # common

View File

@ -1,14 +1,11 @@
//! ALl functions for verification of block //! ALl functions for verification of block
use crate::{config, Config}; use crate::{config, Config};
use reth_interfaces::{ use reth_interfaces::{consensus::Error, Result as RethResult};
consensus::Error,
provider::{AccountProvider, HeaderProvider},
Result as RethResult,
};
use reth_primitives::{ use reth_primitives::{
Account, BlockLocked, BlockNumber, SealedHeader, Transaction, TxEip1559, TxEip2930, TxLegacy, Account, BlockLocked, BlockNumber, SealedHeader, Transaction, TxEip1559, TxEip2930, TxLegacy,
EMPTY_OMMER_ROOT, H256, U256, EMPTY_OMMER_ROOT, H256, U256,
}; };
use reth_provider::{AccountProvider, HeaderProvider};
use std::time::SystemTime; use std::time::SystemTime;
/// Validate header standalone /// 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-primitives = { path = "../primitives" }
reth-interfaces = { path = "../interfaces" } reth-interfaces = { path = "../interfaces" }
reth-rlp = { path = "../common/rlp" } reth-rlp = { path = "../common/rlp" }
reth-db = { path = "../storage/db" }
reth-provider = { path = "../storage/provider" }
reth-consensus = { path = "../consensus" } reth-consensus = { path = "../consensus" }
revm = "2.3" revm = "2.3"
@ -34,4 +36,4 @@ sha3 = { version = "0.10", default-features = false }
[dev-dependencies] [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, Config,
}; };
use hashbrown::hash_map::Entry; use hashbrown::hash_map::Entry;
use reth_interfaces::{ use reth_db::{models::AccountBeforeTx, tables, transaction::DbTxMut, Error as DbError};
db::{models::AccountBeforeTx, tables, DbTxMut, Error as DbError}, use reth_interfaces::executor::Error;
executor::Error,
provider::StateProvider,
};
use reth_primitives::{ use reth_primitives::{
bloom::logs_bloom, Account, Address, Bloom, Header, Log, Receipt, TransactionSignedEcRecovered, bloom::logs_bloom, Account, Address, Bloom, Header, Log, Receipt, TransactionSignedEcRecovered,
H256, U256, H256, U256,
}; };
use reth_provider::StateProvider;
use revm::{ use revm::{
db::AccountState, Account as RevmAccount, AccountInfo, AnalysisKind, Bytecode, Database, EVM, db::AccountState, Account as RevmAccount, AccountInfo, AnalysisKind, Bytecode, Database, EVM,
}; };
@ -414,17 +412,15 @@ mod tests {
use crate::{config::SpecUpgrades, revm_wrap::State}; use crate::{config::SpecUpgrades, revm_wrap::State};
use reth_db::{ use reth_db::{
kv::{test_utils, Env, EnvKind}, database::Database,
mdbx::WriteMap, mdbx::{test_utils, Env, EnvKind, WriteMap},
}; transaction::DbTx,
use reth_interfaces::{
db::{Database, DbTx},
provider::{AccountProvider, StateProvider},
}; };
use reth_primitives::{ use reth_primitives::{
hex_literal::hex, keccak256, Account, Address, BlockLocked, Bytes, StorageKey, H160, H256, hex_literal::hex, keccak256, Account, Address, BlockLocked, Bytes, StorageKey, H160, H256,
U256, U256,
}; };
use reth_provider::{AccountProvider, StateProvider};
use reth_rlp::Decodable; use reth_rlp::Decodable;
use super::*; use super::*;

View File

@ -1,8 +1,9 @@
use reth_interfaces::{provider::StateProvider, Error}; use reth_interfaces::Error;
use reth_primitives::{ use reth_primitives::{
Account, Header, Transaction, TransactionKind, TransactionSignedEcRecovered, TxEip1559, Account, Header, Transaction, TransactionKind, TransactionSignedEcRecovered, TxEip1559,
TxEip2930, TxLegacy, H160, H256, KECCAK_EMPTY, U256, TxEip2930, TxLegacy, H160, H256, KECCAK_EMPTY, U256,
}; };
use reth_provider::StateProvider;
use revm::{ use revm::{
db::{CacheDB, DatabaseRef}, db::{CacheDB, DatabaseRef},
BlockEnv, TransactTo, TxEnv, BlockEnv, TransactTo, TxEnv,

View File

@ -7,7 +7,7 @@ repository = "https://github.com/paradigmxyz/reth"
readme = "README.md" readme = "README.md"
[dependencies] [dependencies]
reth-codecs = { path = "../codecs" } reth-codecs = { path = "../storage/codecs" }
reth-primitives = { path = "../primitives" } reth-primitives = { path = "../primitives" }
reth-rpc-types = { path = "../net/rpc-types" } reth-rpc-types = { path = "../net/rpc-types" }
async-trait = "0.1.57" async-trait = "0.1.57"
@ -32,7 +32,7 @@ secp256k1 = { version = "0.24.0", default-features = false, features = ["alloc",
modular-bitfield = "0.11.2" modular-bitfield = "0.11.2"
[dev-dependencies] [dev-dependencies]
reth-db = { path = "../db", features = ["test-utils"] } reth-db = { path = "../storage/db", features = ["test-utils"] }
test-fuzz = "3.0.4" test-fuzz = "3.0.4"
tokio = { version = "1.21.2", features = ["full"] } tokio = { version = "1.21.2", features = ["full"] }
tokio-stream = { version = "0.1.11", features = ["sync"] } 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)] #[derive(Debug, thiserror::Error, PartialEq, Eq, Clone)]
pub enum Error { pub enum Error {
/// Failed to open database. /// 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. /// Consensus traits.
pub mod consensus; pub mod consensus;
/// Database traits. /// Provider error
pub mod db;
/// Traits that provide chain access.
pub mod provider; pub mod provider;
/// Database error
pub mod db;
/// P2P traits. /// P2P traits.
pub mod p2p; pub mod p2p;

View File

@ -1,7 +1,5 @@
use reth_primitives::{BlockHash, BlockNumber}; use reth_primitives::{BlockHash, BlockNumber};
use crate::db::models::BlockNumHash;
/// KV error type. They are using u32 to represent error code. /// KV error type. They are using u32 to represent error code.
#[allow(missing_docs)] #[allow(missing_docs)]
#[derive(Debug, thiserror::Error, PartialEq, Eq, Clone)] #[derive(Debug, thiserror::Error, PartialEq, Eq, Clone)]
@ -12,6 +10,6 @@ pub enum Error {
BlockTxNumberNotExists { block_hash: BlockHash }, BlockTxNumberNotExists { block_hash: BlockHash },
#[error("Block hash {block_hash:?} does not exists in Headers table")] #[error("Block hash {block_hash:?} does not exists in Headers table")]
BlockHashNotExist { block_hash: BlockHash }, BlockHashNotExist { block_hash: BlockHash },
#[error("Block body not exists {block_num_hash:?}")] #[error("Block body not exists #{block_number} {block_hash}")]
BlockBodyNotExist { block_num_hash: BlockNumHash }, 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 bodies;
mod headers; mod headers;
/// Generators for different data structures like block headers, block bodies and ranges of those. /// Generators for different data structures like block headers, block bodies and ranges of those.
pub mod generators; pub mod generators;
pub use api::TestApi;
pub use bodies::*; pub use bodies::*;
pub use headers::*; pub use headers::*;

View File

@ -20,6 +20,7 @@ reth-rlp = { path = "../../common/rlp" }
reth-rlp-derive = { path = "../../common/rlp-derive" } reth-rlp-derive = { path = "../../common/rlp-derive" }
reth-tasks = { path = "../../tasks" } reth-tasks = { path = "../../tasks" }
reth-transaction-pool = { path = "../../transaction-pool" } reth-transaction-pool = { path = "../../transaction-pool" }
reth-provider = { path = "../../storage/provider"}
# async/futures # async/futures
futures = "0.3" futures = "0.3"
@ -47,6 +48,7 @@ secp256k1 = { version = "0.24", features = [
[dev-dependencies] [dev-dependencies]
# reth # reth
reth-interfaces = { path = "../../interfaces", features = ["test-utils"] } reth-interfaces = { path = "../../interfaces", features = ["test-utils"] }
reth-provider = { path = "../../storage/provider", features = ["test-utils"] }
reth-tracing = { path = "../../tracing" } reth-tracing = { path = "../../tracing" }
rand = "0.8" rand = "0.8"

View File

@ -6,11 +6,9 @@ use reth_eth_wire::{
BlockBodies, BlockBody, BlockHeaders, GetBlockBodies, GetBlockHeaders, GetNodeData, BlockBodies, BlockBody, BlockHeaders, GetBlockBodies, GetBlockHeaders, GetNodeData,
GetReceipts, NodeData, Receipts, GetReceipts, NodeData, Receipts,
}; };
use reth_interfaces::{ use reth_interfaces::p2p::error::RequestResult;
p2p::error::RequestResult,
provider::{BlockProvider, HeaderProvider},
};
use reth_primitives::{BlockHashOrNumber, Header, HeadersDirection, PeerId}; use reth_primitives::{BlockHashOrNumber, Header, HeadersDirection, PeerId};
use reth_provider::{BlockProvider, HeaderProvider};
use std::{ use std::{
borrow::Borrow, borrow::Borrow,
future::Future, future::Future,

View File

@ -37,8 +37,8 @@ use reth_eth_wire::{
capability::{Capabilities, CapabilityMessage}, capability::{Capabilities, CapabilityMessage},
DisconnectReason, DisconnectReason,
}; };
use reth_interfaces::provider::BlockProvider;
use reth_primitives::{PeerId, H256}; use reth_primitives::{PeerId, H256};
use reth_provider::BlockProvider;
use std::{ use std::{
net::SocketAddr, net::SocketAddr,
pin::Pin, pin::Pin,

View File

@ -14,8 +14,8 @@ use crate::{
use reth_eth_wire::{ use reth_eth_wire::{
capability::Capabilities, BlockHashNumber, DisconnectReason, NewBlockHashes, Status, capability::Capabilities, BlockHashNumber, DisconnectReason, NewBlockHashes, Status,
}; };
use reth_interfaces::provider::BlockProvider;
use reth_primitives::{PeerId, H256}; use reth_primitives::{PeerId, H256};
use reth_provider::BlockProvider;
use std::{ use std::{
collections::{HashMap, VecDeque}, collections::{HashMap, VecDeque},
net::SocketAddr, net::SocketAddr,

View File

@ -10,8 +10,8 @@ use reth_eth_wire::{
capability::{Capabilities, CapabilityMessage}, capability::{Capabilities, CapabilityMessage},
error::EthStreamError, error::EthStreamError,
}; };
use reth_interfaces::provider::BlockProvider;
use reth_primitives::PeerId; use reth_primitives::PeerId;
use reth_provider::BlockProvider;
use std::{ use std::{
io, io,
net::SocketAddr, net::SocketAddr,

View File

@ -3,8 +3,8 @@
use super::testnet::Testnet; use super::testnet::Testnet;
use futures::StreamExt; use futures::StreamExt;
use reth_discv4::{bootnodes::mainnet_nodes, Discv4Config}; use reth_discv4::{bootnodes::mainnet_nodes, Discv4Config};
use reth_interfaces::test_utils::TestApi;
use reth_network::{NetworkConfig, NetworkEvent, NetworkManager}; use reth_network::{NetworkConfig, NetworkEvent, NetworkManager};
use reth_provider::test_utils::TestApi;
use secp256k1::SecretKey; use secp256k1::SecretKey;
use std::{collections::HashSet, sync::Arc}; use std::{collections::HashSet, sync::Arc};

View File

@ -3,10 +3,6 @@
use futures::{FutureExt, StreamExt}; use futures::{FutureExt, StreamExt};
use parking_lot::Mutex; use parking_lot::Mutex;
use pin_project::pin_project; use pin_project::pin_project;
use reth_interfaces::{
provider::{BlockProvider, ChainInfo, HeaderProvider},
test_utils::TestApi,
};
use reth_network::{ use reth_network::{
error::NetworkError, eth_requests::EthRequestHandler, NetworkConfig, NetworkEvent, error::NetworkError, eth_requests::EthRequestHandler, NetworkConfig, NetworkEvent,
NetworkHandle, NetworkManager, NetworkHandle, NetworkManager,
@ -15,6 +11,7 @@ use reth_primitives::{
rpc::{BlockId, BlockNumber}, rpc::{BlockId, BlockNumber},
Block, BlockHash, Header, PeerId, H256, U256, Block, BlockHash, Header, PeerId, H256, U256,
}; };
use reth_provider::{test_utils::TestApi, BlockProvider, ChainInfo, HeaderProvider};
use secp256k1::SecretKey; use secp256k1::SecretKey;
use std::{ use std::{
collections::HashMap, collections::HashMap,

View File

@ -14,6 +14,7 @@ reth-interfaces = { path = "../../interfaces" }
reth-primitives = { path = "../../primitives" } reth-primitives = { path = "../../primitives" }
reth-rpc-api = { path = "../rpc-api" } reth-rpc-api = { path = "../rpc-api" }
reth-rpc-types = { path = "../rpc-types" } reth-rpc-types = { path = "../rpc-types" }
reth-provider = { path = "../../storage/provider"}
reth-transaction-pool = { path = "../../transaction-pool" } reth-transaction-pool = { path = "../../transaction-pool" }
# rpc # rpc

View File

@ -1,10 +1,8 @@
//! Provides everything related to `eth_` namespace //! Provides everything related to `eth_` namespace
use reth_interfaces::{ use reth_interfaces::Result;
provider::{BlockProvider, StateProviderFactory},
Result,
};
use reth_primitives::{Transaction, U256, U64}; use reth_primitives::{Transaction, U256, U64};
use reth_provider::{BlockProvider, StateProviderFactory};
use reth_transaction_pool::TransactionPool; use reth_transaction_pool::TransactionPool;
use std::sync::Arc; use std::sync::Arc;

View File

@ -3,11 +3,11 @@
use crate::{eth::api::EthApi, result::ToRpcResult}; use crate::{eth::api::EthApi, result::ToRpcResult};
use jsonrpsee::core::RpcResult as Result; use jsonrpsee::core::RpcResult as Result;
use reth_interfaces::provider::{BlockProvider, StateProviderFactory};
use reth_primitives::{ use reth_primitives::{
rpc::{transaction::eip2930::AccessListWithGasUsed, BlockId}, rpc::{transaction::eip2930::AccessListWithGasUsed, BlockId},
Address, BlockNumber, Bytes, Transaction, H256, H64, U256, U64, Address, BlockNumber, Bytes, Transaction, H256, H64, U256, U64,
}; };
use reth_provider::{BlockProvider, StateProviderFactory};
use reth_rpc_api::EthApiServer; use reth_rpc_api::EthApiServer;
use reth_rpc_types::{ use reth_rpc_types::{
CallRequest, EIP1186AccountProofResponse, FeeHistory, Index, RichBlock, SyncStatus, CallRequest, EIP1186AccountProofResponse, FeeHistory, Index, RichBlock, SyncStatus,

View File

@ -1,7 +1,7 @@
//! `eth_` PubSub RPC handler implementation //! `eth_` PubSub RPC handler implementation
use jsonrpsee::{types::SubscriptionResult, SubscriptionSink}; use jsonrpsee::{types::SubscriptionResult, SubscriptionSink};
use reth_interfaces::provider::BlockProvider; use reth_provider::BlockProvider;
use reth_rpc_api::EthPubSubApiServer; use reth_rpc_api::EthPubSubApiServer;
use reth_rpc_types::pubsub::{Kind, Params}; use reth_rpc_types::pubsub::{Kind, Params};
use reth_transaction_pool::TransactionPool; use reth_transaction_pool::TransactionPool;

View File

@ -14,7 +14,7 @@ reth-rlp = { path = "../common/rlp", features = [
"derive", "derive",
"ethereum-types", "ethereum-types",
] } ] }
reth-codecs = { version = "0.1.0", path = "../codecs" } reth-codecs = { version = "0.1.0", path = "../storage/codecs" }
# ethereum # ethereum
ethers-core = { git = "https://github.com/gakonst/ethers-rs", default-features = false } 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 libs
reth-primitives = { path = "../primitives" } reth-primitives = { path = "../primitives" }
reth-interfaces = { path = "../interfaces" } reth-interfaces = { path = "../interfaces" }
reth-db = { path = "../db" }
reth-executor = { path = "../executor" } reth-executor = { path = "../executor" }
reth-rlp = { path = "../common/rlp" } reth-rlp = { path = "../common/rlp" }
reth-db = { path = "../storage/db" }
reth-provider = { path = "../storage/provider"}
#async #async
tokio = { version = "1.21.2", features = ["sync"] } tokio = { version = "1.21.2", features = ["sync"] }
@ -29,9 +30,11 @@ itertools = "0.10.5"
rayon = "1.6.0" rayon = "1.6.0"
[dev-dependencies] [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-interfaces = { path = "../interfaces", features = ["test-utils"] }
reth-bodies-downloaders = { path = "../net/bodies-downloaders" } reth-bodies-downloaders = { path = "../net/bodies-downloaders" }
# TODO(onbjerg): We only need this for [BlockBody] # TODO(onbjerg): We only need this for [BlockBody]
reth-eth-wire = { path = "../net/eth-wire" } reth-eth-wire = { path = "../net/eth-wire" }
reth-headers-downloaders = { path = "../net/headers-downloaders" } reth-headers-downloaders = { path = "../net/headers-downloaders" }

View File

@ -3,9 +3,14 @@ use std::{
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
}; };
use reth_interfaces::db::{ use reth_db::{
cursor::{DbCursorRO, DbCursorRW},
database::{Database, DatabaseGAT},
models::{BlockNumHash, NumTransactions}, 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}; use reth_primitives::{BlockHash, BlockNumber, TxNumber};

View File

@ -1,5 +1,9 @@
use metrics::counter; 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 reth_primitives::BlockNumber;
use std::fmt::Display; use std::fmt::Display;

View File

@ -2,7 +2,7 @@ use crate::{
db::StageDB, error::*, util::opt::MaybeSender, ExecInput, ExecOutput, Stage, StageError, db::StageDB, error::*, util::opt::MaybeSender, ExecInput, ExecOutput, Stage, StageError,
StageId, UnwindInput, StageId, UnwindInput,
}; };
use reth_interfaces::db::{Database, DbTx}; use reth_db::{database::Database, transaction::DbTx};
use reth_primitives::BlockNumber; use reth_primitives::BlockNumber;
use std::{ use std::{
fmt::{Debug, Formatter}, fmt::{Debug, Formatter},
@ -365,10 +365,7 @@ impl<DB: Database> QueuedStage<DB> {
mod tests { mod tests {
use super::*; use super::*;
use crate::{StageId, UnwindOutput}; use crate::{StageId, UnwindOutput};
use reth_db::{ use reth_db::mdbx::{self, test_utils, Env, EnvKind, WriteMap};
kv::{test_utils, Env, EnvKind},
mdbx::{self, WriteMap},
};
use reth_interfaces::consensus; use reth_interfaces::consensus;
use tokio::sync::mpsc::channel; use tokio::sync::mpsc::channel;
use tokio_stream::{wrappers::ReceiverStream, StreamExt}; use tokio_stream::{wrappers::ReceiverStream, StreamExt};

View File

@ -1,6 +1,6 @@
use crate::{db::StageDB, error::StageError, id::StageId}; use crate::{db::StageDB, error::StageError, id::StageId};
use async_trait::async_trait; use async_trait::async_trait;
use reth_interfaces::db::Database; use reth_db::database::Database;
use reth_primitives::BlockNumber; use reth_primitives::BlockNumber;
/// Stage execution input, see [Stage::execute]. /// Stage execution input, see [Stage::execute].

View File

@ -3,14 +3,14 @@ use crate::{
UnwindInput, UnwindOutput, UnwindInput, UnwindOutput,
}; };
use futures_util::TryStreamExt; use futures_util::TryStreamExt;
use reth_interfaces::{ use reth_db::{
consensus::Consensus, cursor::{DbCursorRO, DbCursorRW},
db::{ database::{Database, DatabaseGAT},
models::StoredBlockOmmers, tables, Database, DatabaseGAT, DbCursorRO, DbCursorRW, DbTx, models::StoredBlockOmmers,
DbTxMut, tables,
}, transaction::{DbTx, DbTxMut},
p2p::bodies::downloader::BodyDownloader,
}; };
use reth_interfaces::{consensus::Consensus, p2p::bodies::downloader::BodyDownloader};
use reth_primitives::{ use reth_primitives::{
proofs::{EMPTY_LIST_HASH, EMPTY_ROOT}, proofs::{EMPTY_LIST_HASH, EMPTY_ROOT},
BlockLocked, BlockNumber, SealedHeader, H256, BlockLocked, BlockNumber, SealedHeader, H256,
@ -477,12 +477,14 @@ mod tests {
ExecInput, ExecOutput, UnwindInput, ExecInput, ExecOutput, UnwindInput,
}; };
use assert_matches::assert_matches; 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_eth_wire::BlockBody;
use reth_interfaces::{ use reth_interfaces::{
db::{
models::{BlockNumHash, NumTransactions, StoredBlockOmmers},
tables, DbCursorRO, DbTx, DbTxMut,
},
p2p::{ p2p::{
bodies::{ bodies::{
client::BodiesClient, client::BodiesClient,

View File

@ -2,20 +2,21 @@ use crate::{
db::StageDB, DatabaseIntegrityError, ExecInput, ExecOutput, Stage, StageError, StageId, db::StageDB, DatabaseIntegrityError, ExecInput, ExecOutput, Stage, StageError, StageId,
UnwindInput, UnwindOutput, UnwindInput, UnwindOutput,
}; };
use reth_db::{
cursor::{DbCursorRO, DbCursorRW, DbDupCursorRO},
database::Database,
models::{BlockNumHash, TxNumberAddress},
tables,
transaction::{DbTx, DbTxMut},
};
use reth_executor::{ use reth_executor::{
config::SpecUpgrades, config::SpecUpgrades,
executor::AccountChangeSet, executor::AccountChangeSet,
revm_wrap::{State, SubState}, revm_wrap::{State, SubState},
Config, 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_primitives::{Address, StorageEntry, TransactionSignedEcRecovered, H256, U256};
use reth_provider::StateProviderImplRefLatest;
use std::{fmt::Debug, ops::DerefMut}; use std::{fmt::Debug, ops::DerefMut};
const EXECUTION: StageId = StageId("Execution"); const EXECUTION: StageId = StageId("Execution");
@ -423,12 +424,9 @@ mod tests {
use std::ops::Deref; use std::ops::Deref;
use super::*; use super::*;
use reth_db::{ use reth_db::mdbx::{test_utils::create_test_db, EnvKind, WriteMap};
kv::{test_utils::create_test_db, EnvKind},
mdbx::WriteMap,
};
use reth_interfaces::provider::insert_canonical_block;
use reth_primitives::{hex_literal::hex, keccak256, Account, BlockLocked, H160, U256}; use reth_primitives::{hex_literal::hex, keccak256, Account, BlockLocked, H160, U256};
use reth_provider::insert_canonical_block;
use reth_rlp::Decodable; use reth_rlp::Decodable;
#[tokio::test] #[tokio::test]

View File

@ -3,9 +3,15 @@ use crate::{
UnwindInput, UnwindOutput, UnwindInput, UnwindOutput,
}; };
use futures_util::StreamExt; use futures_util::StreamExt;
use reth_db::{
cursor::{DbCursorRO, DbCursorRW},
database::Database,
models::blocks::BlockNumHash,
tables,
transaction::{DbTx, DbTxMut},
};
use reth_interfaces::{ use reth_interfaces::{
consensus::{Consensus, ForkchoiceState}, consensus::{Consensus, ForkchoiceState},
db::{models::blocks::BlockNumHash, tables, Database, DbCursorRO, DbCursorRW, DbTx, DbTxMut},
p2p::headers::{ p2p::headers::{
client::HeadersClient, client::HeadersClient,
downloader::{ensure_parent, HeaderDownloader}, downloader::{ensure_parent, HeaderDownloader},
@ -342,9 +348,9 @@ mod tests {
}, },
ExecInput, ExecOutput, UnwindInput, ExecInput, ExecOutput, UnwindInput,
}; };
use reth_db::{models::blocks::BlockNumHash, tables, transaction::DbTx};
use reth_headers_downloaders::linear::{LinearDownloadBuilder, LinearDownloader}; use reth_headers_downloaders::linear::{LinearDownloadBuilder, LinearDownloader};
use reth_interfaces::{ use reth_interfaces::{
db::{models::blocks::BlockNumHash, tables, DbTx},
p2p::headers::downloader::HeaderDownloader, p2p::headers::downloader::HeaderDownloader,
test_utils::{ test_utils::{
generators::{random_header, random_header_range}, generators::{random_header, random_header_range},

View File

@ -3,7 +3,13 @@ use crate::{
}; };
use itertools::Itertools; use itertools::Itertools;
use rayon::prelude::*; 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 reth_primitives::TxNumber;
use std::fmt::Debug; use std::fmt::Debug;
use thiserror::Error; use thiserror::Error;
@ -79,7 +85,7 @@ impl<DB: Database> Stage<DB> for SendersStage {
// Iterate over transactions in chunks // Iterate over transactions in chunks
for chunk in &entries.chunks(self.batch_size) { 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 // Recover signers for the chunk in parallel
let recovered = transactions let recovered = transactions
.into_par_iter() .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 std::borrow::Borrow;
use tokio::sync::oneshot; use tokio::sync::oneshot;

View File

@ -1,9 +1,11 @@
use reth_db::{ use reth_db::{
kv::{test_utils::create_test_db, tx::Tx, Env, EnvKind}, cursor::{DbCursorRO, DbCursorRW},
mdbx::{WriteMap, RW}, mdbx::{test_utils::create_test_db, tx::Tx, Env, EnvKind, WriteMap, RW},
}; models::BlockNumHash,
use reth_interfaces::db::{ table::Table,
self, models::BlockNumHash, tables, DbCursorRO, DbCursorRW, DbTx, DbTxMut, Table, tables,
transaction::{DbTx, DbTxMut},
Error as DbError,
}; };
use reth_primitives::{BlockNumber, SealedHeader, U256}; use reth_primitives::{BlockNumber, SealedHeader, U256};
use std::{borrow::Borrow, sync::Arc}; use std::{borrow::Borrow, sync::Arc};
@ -40,9 +42,9 @@ impl TestStageDB {
} }
/// Invoke a callback with transaction committing it afterwards /// 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 where
F: FnOnce(&mut Tx<'_, RW, WriteMap>) -> Result<(), db::Error>, F: FnOnce(&mut Tx<'_, RW, WriteMap>) -> Result<(), DbError>,
{ {
let mut db = self.inner(); let mut db = self.inner();
f(&mut db)?; f(&mut db)?;
@ -51,15 +53,15 @@ impl TestStageDB {
} }
/// Invoke a callback with a read transaction /// 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 where
F: FnOnce(&Tx<'_, RW, WriteMap>) -> Result<R, db::Error>, F: FnOnce(&Tx<'_, RW, WriteMap>) -> Result<R, DbError>,
{ {
f(&self.inner()) f(&self.inner())
} }
/// Check if the table is empty /// 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| { self.query(|tx| {
let last = tx.cursor::<T>()?.last()?; let last = tx.cursor::<T>()?.last()?;
Ok(last.is_none()) Ok(last.is_none())
@ -74,7 +76,7 @@ impl TestStageDB {
/// db.map_put::<Table, _, _>(&items, |item| item)?; /// db.map_put::<Table, _, _>(&items, |item| item)?;
/// ``` /// ```
#[allow(dead_code)] #[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 where
T: Table, T: Table,
S: Clone, S: Clone,
@ -102,7 +104,7 @@ impl TestStageDB {
&self, &self,
values: &[S], values: &[S],
mut transform: F, mut transform: F,
) -> Result<(), db::Error> ) -> Result<(), DbError>
where where
T: Table, T: Table,
<T as Table>::Value: Clone, <T as Table>::Value: Clone,
@ -126,7 +128,7 @@ impl TestStageDB {
&self, &self,
num: u64, num: u64,
mut selector: F, mut selector: F,
) -> Result<(), db::Error> ) -> Result<(), DbError>
where where
T: Table, T: Table,
F: FnMut(T::Key) -> BlockNumber, F: FnMut(T::Key) -> BlockNumber,
@ -146,7 +148,7 @@ impl TestStageDB {
&self, &self,
num: u64, num: u64,
mut selector: F, mut selector: F,
) -> Result<(), db::Error> ) -> Result<(), DbError>
where where
T: Table, T: Table,
F: FnMut(T::Value) -> BlockNumber, F: FnMut(T::Value) -> BlockNumber,
@ -162,7 +164,7 @@ impl TestStageDB {
/// Insert ordered collection of [SealedHeader] into the corresponding tables /// Insert ordered collection of [SealedHeader] into the corresponding tables
/// that are supposed to be populated by the headers stage. /// 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 where
I: Iterator<Item = &'a SealedHeader>, I: Iterator<Item = &'a SealedHeader>,
{ {

View File

@ -4,7 +4,7 @@ This crate allows to easily configure different codecs for different purposes (b
Examples: Examples:
- [`Header` struct](../primitives/src/header.rs) - [`Header` struct](../../primitives/src/header.rs)
- [DB usage](../db/src/kv/codecs/scale.rs) - [DB usage](../db/src/kv/codecs/scale.rs)
### Features ### Features

View File

@ -9,14 +9,22 @@ description = "Staged syncing primitives used in reth."
[dependencies] [dependencies]
# reth # reth
reth-primitives = { path = "../primitives" } reth-primitives = { path = "../../primitives" }
reth-interfaces = { path = "../interfaces" } reth-interfaces = { path = "../../interfaces" }
reth-libmdbx = { path = "../libmdbx-rs" } reth-codecs = { path = "../codecs" }
reth-libmdbx = { path = "../libmdbx-rs", optional = true }
# codecs # codecs
serde = { version = "1.0.*", default-features = false } serde = { version = "1.0.*", default-features = false }
postcard = { version = "1.0.2", features = ["alloc"] } postcard = { version = "1.0.2", features = ["alloc"] }
heapless = "0.7.16"
parity-scale-codec = { version = "3.2.1", features = ["bytes"] } 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 # misc
bytes = "1.2.1" bytes = "1.2.1"
@ -25,19 +33,24 @@ thiserror = "1.0.37"
tempfile = { version = "3.3.0", optional = true } tempfile = { version = "3.3.0", optional = true }
eyre = "0.6.8" eyre = "0.6.8"
[dev-dependencies] [dev-dependencies]
tempfile = "3.3.0" tempfile = "3.3.0"
test-fuzz = "3.0.4" test-fuzz = "3.0.4"
criterion = "0.4.0" criterion = "0.4.0"
iai = "0.1.1" iai = "0.1.1"
tokio = { version = "1.21.2", features = ["full"] } 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" async-trait = "0.1.58"
[features] [features]
default = ["mdbx"]
test-utils = ["tempfile"] test-utils = ["tempfile"]
bench-postcard = ["bench"] bench-postcard = ["bench"]
mdbx = ["reth-libmdbx"]
bench = [] bench = []
[[bench]] [[bench]]

View File

@ -8,9 +8,9 @@ macro_rules! impl_criterion_encoding_benchmark {
c.bench_function(stringify!($name), |b| { c.bench_function(stringify!($name), |b| {
b.iter(|| { b.iter(|| {
let encoded_size = let encoded_size =
reth_interfaces::db::codecs::fuzz::IntegerList::encode_and_decode( reth_db::tables::codecs::fuzz::IntegerList::encode_and_decode(black_box(
black_box(reth_primitives::IntegerList::default()), reth_primitives::IntegerList::default(),
) ))
.0; .0;
if size == 0 { if size == 0 {

View File

@ -1,11 +1,11 @@
use iai::{black_box, main}; use iai::{black_box, main};
use reth_interfaces::db; use reth_db::tables::codecs;
/// Benchmarks the encoding and decoding of `Header` using iai. /// Benchmarks the encoding and decoding of `Header` using iai.
macro_rules! impl_iai_encoding_benchmark { macro_rules! impl_iai_encoding_benchmark {
($name:tt) => { ($name:tt) => {
fn $name() { fn $name() {
db::codecs::fuzz::IntegerList::encode_and_decode(black_box( codecs::fuzz::IntegerList::encode_and_decode(black_box(
reth_primitives::IntegerList::default(), 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 //! Mock database
use std::collections::BTreeMap; use std::collections::BTreeMap;
use super::{ use crate::{
Database, DatabaseGAT, DbCursorRO, DbCursorRW, DbDupCursorRO, DbDupCursorRW, DbTx, DbTxGAT, common::{PairResult, ValueOnlyResult},
DbTxMut, DbTxMutGAT, DupSort, DupWalker, Error, Table, Walker, 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 /// Mock database used for testing with inner BTreeMap structure
@ -15,11 +19,11 @@ pub struct DatabaseMock {
} }
impl Database for 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()) 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()) Ok(TxMock::default())
} }
} }
@ -48,51 +52,43 @@ impl<'a> DbTxMutGAT<'a> for TxMock {
} }
impl<'a> DbTx<'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!() todo!()
} }
fn commit(self) -> Result<bool, super::Error> { fn commit(self) -> Result<bool, Error> {
todo!() 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!() todo!()
} }
fn cursor_dup<T: super::DupSort>( fn cursor_dup<T: DupSort>(&self) -> Result<<Self as DbTxGAT<'_>>::DupCursor<T>, Error> {
&self,
) -> Result<<Self as DbTxGAT<'_>>::DupCursor<T>, super::Error> {
todo!() todo!()
} }
} }
impl<'a> DbTxMut<'a> for TxMock { 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!() 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, &self,
_key: T::Key, ) -> Result<<Self as DbTxMutGAT<'_>>::DupCursorMut<T>, Error> {
_value: Option<T::Value>,
) -> Result<bool, super::Error> {
todo!() todo!()
} }
fn cursor_mut<T: super::Table>( fn clear<T: Table>(&self) -> Result<(), Error> {
&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> {
todo!() todo!()
} }
} }
@ -103,27 +99,27 @@ pub struct CursorMock {
} }
impl<'tx, T: Table> DbCursorRO<'tx, T> for CursorMock { impl<'tx, T: Table> DbCursorRO<'tx, T> for CursorMock {
fn first(&mut self) -> super::PairResult<T> { fn first(&mut self) -> PairResult<T> {
todo!() todo!()
} }
fn seek_exact(&mut self, _key: T::Key) -> super::PairResult<T> { fn seek_exact(&mut self, _key: T::Key) -> PairResult<T> {
todo!() todo!()
} }
fn next(&mut self) -> super::PairResult<T> { fn next(&mut self) -> PairResult<T> {
todo!() todo!()
} }
fn prev(&mut self) -> super::PairResult<T> { fn prev(&mut self) -> PairResult<T> {
todo!() todo!()
} }
fn last(&mut self) -> super::PairResult<T> { fn last(&mut self) -> PairResult<T> {
todo!() todo!()
} }
fn current(&mut self) -> super::PairResult<T> { fn current(&mut self) -> PairResult<T> {
todo!() todo!()
} }
@ -139,19 +135,19 @@ impl<'tx, T: Table> DbCursorRO<'tx, T> for CursorMock {
} }
impl<'tx, T: DupSort> DbDupCursorRO<'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!() todo!()
} }
fn seek(&mut self, _key: T::SubKey) -> super::PairResult<T> { fn seek(&mut self, _key: T::SubKey) -> PairResult<T> {
todo!() todo!()
} }
fn next_no_dup(&mut self) -> super::PairResult<T> { fn next_no_dup(&mut self) -> PairResult<T> {
todo!() todo!()
} }
fn next_dup_val(&mut self) -> super::ValueOnlyResult<T> { fn next_dup_val(&mut self) -> ValueOnlyResult<T> {
todo!() todo!()
} }
@ -172,7 +168,7 @@ impl<'tx, T: Table> DbCursorRW<'tx, T> for CursorMock {
&mut self, &mut self,
_key: <T as Table>::Key, _key: <T as Table>::Key,
_value: <T as Table>::Value, _value: <T as Table>::Value,
) -> Result<(), super::Error> { ) -> Result<(), Error> {
todo!() todo!()
} }
@ -180,7 +176,7 @@ impl<'tx, T: Table> DbCursorRW<'tx, T> for CursorMock {
&mut self, &mut self,
_key: <T as Table>::Key, _key: <T as Table>::Key,
_value: <T as Table>::Value, _value: <T as Table>::Value,
) -> Result<(), super::Error> { ) -> Result<(), Error> {
todo!() todo!()
} }
@ -188,21 +184,21 @@ impl<'tx, T: Table> DbCursorRW<'tx, T> for CursorMock {
&mut self, &mut self,
_key: <T as Table>::Key, _key: <T as Table>::Key,
_value: <T as Table>::Value, _value: <T as Table>::Value,
) -> Result<(), super::Error> { ) -> Result<(), Error> {
todo!() todo!()
} }
fn delete_current(&mut self) -> Result<(), super::Error> { fn delete_current(&mut self) -> Result<(), Error> {
todo!() todo!()
} }
} }
impl<'tx, T: DupSort> DbDupCursorRW<'tx, T> for CursorMock { 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!() 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!() 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 bytes::Bytes;
use std::{ use std::{
fmt::Debug, 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 std::{borrow::Cow, marker::PhantomData};
use crate::utils::*; use crate::{
use reth_interfaces::db::{ cursor::{DbCursorRO, DbCursorRW, DbDupCursorRO, DbDupCursorRW, DupWalker, Walker},
Compress, DbCursorRO, DbCursorRW, DbDupCursorRO, DbDupCursorRW, DupSort, DupWalker, Encode, table::{Compress, DupSort, Encode, Table},
Error, Table, Walker, tables::utils::*,
Error,
}; };
use reth_libmdbx::{self, TransactionKind, WriteFlags, RO, RW}; 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> { 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()) 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())) 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()) decode!(self.inner.next())
} }
fn prev(&mut self) -> reth_interfaces::db::PairResult<T> { fn prev(&mut self) -> PairResult<T> {
decode!(self.inner.prev()) decode!(self.inner.prev())
} }
fn last(&mut self) -> reth_interfaces::db::PairResult<T> { fn last(&mut self) -> PairResult<T> {
decode!(self.inner.last()) decode!(self.inner.last())
} }
fn current(&mut self) -> reth_interfaces::db::PairResult<T> { fn current(&mut self) -> PairResult<T> {
decode!(self.inner.get_current()) 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> { 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())) decode!(self.inner.set_range(key.encode().as_ref()))
} }

View File

@ -1,9 +1,10 @@
//! Module that interacts with MDBX. //! Module that interacts with MDBX.
use crate::utils::default_page_size; use crate::{
use reth_interfaces::db::{ database::{Database, DatabaseGAT},
tables::{TableType, TABLES}, tables::{TableType, TABLES},
Database, DatabaseGAT, Error, utils::default_page_size,
Error,
}; };
use reth_libmdbx::{ use reth_libmdbx::{
DatabaseFlags, Environment, EnvironmentFlags, EnvironmentKind, Geometry, Mode, PageSize, DatabaseFlags, Environment, EnvironmentFlags, EnvironmentKind, Geometry, Mode, PageSize,
@ -138,16 +139,13 @@ pub mod test_utils {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{test_utils, Env, EnvKind}; use super::{test_utils, Env, EnvKind};
use reth_interfaces::{ use crate::{
db::{ cursor::{DbCursorRO, DbCursorRW, DbDupCursorRO},
self, database::Database,
models::ShardedKey, models::ShardedKey,
tables::{ tables::{AccountHistory, CanonicalHeaders, Headers, PlainAccountState, PlainStorageState},
AccountHistory, CanonicalHeaders, Headers, PlainAccountState, PlainStorageState, transaction::{DbTx, DbTxMut},
}, Error,
Database, DbCursorRO, DbCursorRW, DbDupCursorRO, DbTx, DbTxMut,
},
provider::{ProviderImpl, StateProviderFactory},
}; };
use reth_libmdbx::{NoWriteMap, WriteMap}; use reth_libmdbx::{NoWriteMap, WriteMap};
use reth_primitives::{Account, Address, Header, IntegerList, StorageEntry, H256, U256}; 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())))); assert_eq!(cursor.current(), Ok(Some((key_to_insert, H256::zero()))));
// INSERT (failure) // 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())))); 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 tx = db.tx_mut().expect(ERROR_INIT_TX);
let mut cursor = tx.cursor_mut::<CanonicalHeaders>().unwrap(); let mut cursor = tx.cursor_mut::<CanonicalHeaders>().unwrap();
cursor.seek_exact(1).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 assert_eq!(cursor.current(), Ok(Some((5, H256::zero())))); // the end of table
} }
@ -396,11 +394,4 @@ mod tests {
assert_eq!(list200, list); 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. //! Transaction wrapper for libmdbx-sys.
use crate::{kv::cursor::Cursor, utils::decode_one}; use super::cursor::Cursor;
use reth_interfaces::db::{ use crate::{
Compress, DbTx, DbTxGAT, DbTxMut, DbTxMutGAT, DupSort, Encode, Error, Table, table::{Compress, DupSort, Encode, Table},
tables::utils::decode_one,
transaction::{DbTx, DbTxGAT, DbTxMut, DbTxMutGAT},
Error,
}; };
use reth_libmdbx::{EnvironmentKind, Transaction, TransactionKind, WriteFlags, RW}; use reth_libmdbx::{EnvironmentKind, Transaction, TransactionKind, WriteFlags, RW};
use std::marker::PhantomData; 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::{ use crate::{
models::{accounts::AccountBeforeTx, StoredBlockOmmers}, table::{Compress, Decompress},
Compress, Decompress, Error, tables::models::*,
Error,
}; };
use reth_codecs::{main_codec, Compact}; use reth_codecs::{main_codec, Compact};
use reth_primitives::*; use reth_primitives::*;

View File

@ -14,7 +14,7 @@ macro_rules! impl_fuzzer_with_input {
#[allow(non_snake_case)] #[allow(non_snake_case)]
#[cfg(any(test, feature = "bench"))] #[cfg(any(test, feature = "bench"))]
pub mod $name { pub mod $name {
use crate::db::table; use crate::table;
#[allow(unused_imports)] #[allow(unused_imports)]
use reth_primitives::*; use reth_primitives::*;
@ -23,7 +23,7 @@ macro_rules! impl_fuzzer_with_input {
use super::inputs::*; use super::inputs::*;
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::db::models::*; use crate::tables::models::*;
/// Encodes and decodes table types returning its encoded size and the decoded object. /// 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. /// 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 use compact::CompactU256;
pub mod fuzz; pub mod fuzz;
mod postcard; mod postcard;
#[cfg(not(feature = "bench-postcard"))]
mod scale; mod scale;

View File

@ -1,6 +1,9 @@
#![allow(unused)] #![allow(unused)]
use crate::db::{Decode, Encode, Error}; use crate::{
table::{Decode, Encode},
Error,
};
use postcard::{from_bytes, to_allocvec, to_vec}; use postcard::{from_bytes, to_allocvec, to_vec};
use reth_primitives::*; use reth_primitives::*;
@ -26,7 +29,7 @@ macro_rules! impl_postcard {
} }
impl Decode for $name { 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())) from_bytes(&value.into()).map_err(|e| Error::Decode(e.into()))
} }
} }
@ -36,5 +39,5 @@ macro_rules! impl_postcard {
type VecU8 = Vec<u8>; type VecU8 = Vec<u8>;
#[cfg(feature = "bench-postcard")] //#[cfg(feature = "bench-postcard")]
impl_postcard!(VecU8, Receipt, H256, U256, H160, u8, u16, u64, Header, Account, Log, TxType); //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 parity_scale_codec::decode_from_bytes;
use reth_primitives::*; use reth_primitives::*;

View File

@ -1,13 +1,20 @@
//! Declaration of all Database tables. //! Table and data structures
use crate::db::{ pub mod codecs;
codecs::CompactU256, pub mod models;
models::{ pub mod utils;
accounts::{AccountBeforeTx, TxNumberAddress},
blocks::{BlockNumHash, HeaderHash, NumTransactions, StoredBlockOmmers}, /// Declaration of all Database tables.
ShardedKey, use crate::{
table::DupSort,
tables::{
codecs::CompactU256,
models::{
accounts::{AccountBeforeTx, TxNumberAddress},
blocks::{HeaderHash, NumTransactions, StoredBlockOmmers},
BlockNumHash, ShardedKey,
},
}, },
DupSort,
}; };
use reth_primitives::{ use reth_primitives::{
Account, Address, BlockHash, BlockNumber, Header, IntegerList, Receipt, StorageEntry, Account, Address, BlockHash, BlockNumber, Header, IntegerList, Receipt, StorageEntry,
@ -57,7 +64,7 @@ macro_rules! table {
#[derive(Clone, Copy, Debug, Default)] #[derive(Clone, Copy, Debug, Default)]
pub struct $table_name; 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(); const NAME: &'static str = $table_name::const_name();
type Key = $key; type Key = $key;
type Value = $value; type Value = $value;
@ -171,10 +178,10 @@ table!(
/// ///
/// ``` /// ```
/// use reth_primitives::{Address, IntegerList}; /// use reth_primitives::{Address, IntegerList};
/// use reth_interfaces::db::{DbTx, DbTxMut, DbCursorRO, Database, models::ShardedKey, tables::AccountHistory}; /// use reth_db::{transaction::{DbTxMut,DbTx}, mdbx::{EnvKind, Env, test_utils,WriteMap}, cursor::DbCursorRO,database::Database, tables::{AccountHistory,models::ShardedKey}};
/// use reth_db::{kv::{EnvKind, Env, test_utils}, mdbx::WriteMap};
/// use std::{str::FromStr,sync::Arc}; /// use std::{str::FromStr,sync::Arc};
/// ///
///
/// fn main() { /// fn main() {
/// let db: Arc<Env<WriteMap>> = test_utils::create_test_db(EnvKind::RW); /// let db: Arc<Env<WriteMap>> = test_utils::create_test_db(EnvKind::RW);
/// let account = Address::from_str("0xa2c122be93b0074270ebee7f6b7292c7deb45047").unwrap(); /// let account = Address::from_str("0xa2c122be93b0074270ebee7f6b7292c7deb45047").unwrap();

View File

@ -1,11 +1,9 @@
//! Account related models and types. //! Account related models and types.
use crate::{ use crate::{
db::{
table::{Decode, Encode},
Error,
},
impl_fixed_arbitrary, impl_fixed_arbitrary,
table::{Decode, Encode},
Error,
}; };
use bytes::Bytes; use bytes::Bytes;
use reth_codecs::{main_codec, Compact}; use reth_codecs::{main_codec, Compact};

View File

@ -1,11 +1,9 @@
//! Block related models and types. //! Block related models and types.
use crate::{ use crate::{
db::{
table::{Decode, Encode},
Error,
},
impl_fixed_arbitrary, impl_fixed_arbitrary,
table::{Decode, Encode},
Error,
}; };
use bytes::Bytes; use bytes::Bytes;
use reth_codecs::{main_codec, Compact}; use reth_codecs::{main_codec, Compact};

View File

@ -1,8 +1,8 @@
//! Implements [`Compress`] and [`Decompress`] for [`IntegerList`] //! Implements [`Compress`] and [`Decompress`] for [`IntegerList`]
use crate::db::{ use crate::{
error::Error,
table::{Compress, Decompress}, table::{Compress, Decompress},
Error,
}; };
use bytes::Bytes; use bytes::Bytes;
use reth_primitives::IntegerList; use reth_primitives::IntegerList;

View File

@ -10,7 +10,7 @@ pub use blocks::*;
use reth_primitives::{Address, H256}; use reth_primitives::{Address, H256};
pub use sharded_key::ShardedKey; pub use sharded_key::ShardedKey;
use crate::db::{ use crate::{
table::{Decode, Encode}, table::{Decode, Encode},
Error, Error,
}; };

View File

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

View File

@ -1,22 +1,28 @@
//! Utils crate for `db`. //! Small database table utilities and helper functions
use crate::{
//suse crate::kv::Error; table::{Decode, Decompress, Table},
Error,
};
use bytes::Bytes; use bytes::Bytes;
use reth_interfaces::db::{Decode, Decompress, Error, Table};
use std::borrow::Cow; use std::borrow::Cow;
/// Returns the default page size that can be used in this OS. #[macro_export]
pub(crate) fn default_page_size() -> usize { /// Implements the [`arbitrary::Arbitrary`] trait for types with fixed array types.
let os_page_size = page_size::get(); 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 #[cfg(any(test, feature = "arbitrary"))]
let libmdbx_max_page_size = 0x10000; 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 Decode::decode(buffer).map_err(|_| arbitrary::Error::IncorrectFormat)
// data. }
let min_page_size = 4096; }
};
os_page_size.clamp(min_page_size, libmdbx_max_page_size)
} }
/// Helper function to decode a `(key, value)` pair. /// 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