mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat(db): Refactor storage libraries (#371)
This commit is contained in:
42
Cargo.lock
generated
42
Cargo.lock
generated
@ -3094,6 +3094,7 @@ dependencies = [
|
|||||||
"eyre",
|
"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",
|
||||||
|
|||||||
@ -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"]
|
||||||
@ -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"}
|
||||||
|
|||||||
@ -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");
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -1,16 +0,0 @@
|
|||||||
//! Module that interacts with MDBX.
|
|
||||||
|
|
||||||
#![warn(missing_debug_implementations, missing_docs, unreachable_pub)]
|
|
||||||
#![deny(unused_must_use, rust_2018_idioms)]
|
|
||||||
#![doc(test(
|
|
||||||
no_crate_inject,
|
|
||||||
attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
|
|
||||||
))]
|
|
||||||
|
|
||||||
/// Rust bindings for [MDBX](https://libmdbx.dqdkfa.ru/).
|
|
||||||
pub mod mdbx {
|
|
||||||
pub use reth_libmdbx::*;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod kv;
|
|
||||||
mod utils;
|
|
||||||
@ -11,6 +11,8 @@ readme = "README.md"
|
|||||||
reth-primitives = { path = "../primitives" }
|
reth-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"] }
|
||||||
|
|||||||
@ -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::*;
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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"] }
|
||||||
|
|||||||
@ -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.
|
||||||
@ -1,289 +0,0 @@
|
|||||||
pub mod codecs;
|
|
||||||
mod error;
|
|
||||||
pub mod mock;
|
|
||||||
pub mod models;
|
|
||||||
mod table;
|
|
||||||
pub mod tables;
|
|
||||||
|
|
||||||
use std::marker::PhantomData;
|
|
||||||
|
|
||||||
pub use error::Error;
|
|
||||||
pub use table::*;
|
|
||||||
|
|
||||||
// Sealed trait helper to prevent misuse of the API.
|
|
||||||
mod sealed {
|
|
||||||
pub trait Sealed: Sized {}
|
|
||||||
pub struct Bounds<T>(T);
|
|
||||||
impl<T> Sealed for Bounds<T> {}
|
|
||||||
}
|
|
||||||
use sealed::{Bounds, Sealed};
|
|
||||||
|
|
||||||
/// Implements the GAT method from:
|
|
||||||
/// https://sabrinajewson.org/blog/the-better-alternative-to-lifetime-gats#the-better-gats.
|
|
||||||
///
|
|
||||||
/// Sealed trait which cannot be implemented by 3rd parties, exposed only for implementers
|
|
||||||
pub trait DatabaseGAT<'a, __ImplicitBounds: Sealed = Bounds<&'a Self>>: Send + Sync {
|
|
||||||
/// RO database transaction
|
|
||||||
type TX: DbTx<'a> + Send + Sync;
|
|
||||||
/// RW database transaction
|
|
||||||
type TXMut: DbTxMut<'a> + DbTx<'a> + Send + Sync;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Main Database trait that spawns transactions to be executed.
|
|
||||||
pub trait Database: for<'a> DatabaseGAT<'a> {
|
|
||||||
/// Create read only transaction.
|
|
||||||
fn tx(&self) -> Result<<Self as DatabaseGAT<'_>>::TX, Error>;
|
|
||||||
|
|
||||||
/// Create read write transaction only possible if database is open with write access.
|
|
||||||
fn tx_mut(&self) -> Result<<Self as DatabaseGAT<'_>>::TXMut, Error>;
|
|
||||||
|
|
||||||
/// Takes a function and passes a read-only transaction into it, making sure it's closed in the
|
|
||||||
/// end of the execution.
|
|
||||||
fn view<T, F>(&self, f: F) -> Result<T, Error>
|
|
||||||
where
|
|
||||||
F: Fn(&<Self as DatabaseGAT<'_>>::TX) -> T,
|
|
||||||
{
|
|
||||||
let tx = self.tx()?;
|
|
||||||
|
|
||||||
let res = f(&tx);
|
|
||||||
tx.commit()?;
|
|
||||||
|
|
||||||
Ok(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Takes a function and passes a write-read transaction into it, making sure it's committed in
|
|
||||||
/// the end of the execution.
|
|
||||||
fn update<T, F>(&self, f: F) -> Result<T, Error>
|
|
||||||
where
|
|
||||||
F: Fn(&<Self as DatabaseGAT<'_>>::TXMut) -> T,
|
|
||||||
{
|
|
||||||
let tx = self.tx_mut()?;
|
|
||||||
|
|
||||||
let res = f(&tx);
|
|
||||||
tx.commit()?;
|
|
||||||
|
|
||||||
Ok(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Implements the GAT method from:
|
|
||||||
/// https://sabrinajewson.org/blog/the-better-alternative-to-lifetime-gats#the-better-gats.
|
|
||||||
///
|
|
||||||
/// Sealed trait which cannot be implemented by 3rd parties, exposed only for implementers
|
|
||||||
pub trait DbTxGAT<'a, __ImplicitBounds: Sealed = Bounds<&'a Self>>: Send + Sync {
|
|
||||||
/// Cursor GAT
|
|
||||||
type Cursor<T: Table>: DbCursorRO<'a, T> + Send + Sync;
|
|
||||||
/// DupCursor GAT
|
|
||||||
type DupCursor<T: DupSort>: DbDupCursorRO<'a, T> + DbCursorRO<'a, T> + Send + Sync;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Implements the GAT method from:
|
|
||||||
/// https://sabrinajewson.org/blog/the-better-alternative-to-lifetime-gats#the-better-gats.
|
|
||||||
///
|
|
||||||
/// Sealed trait which cannot be implemented by 3rd parties, exposed only for implementers
|
|
||||||
pub trait DbTxMutGAT<'a, __ImplicitBounds: Sealed = Bounds<&'a Self>>: Send + Sync {
|
|
||||||
/// Cursor GAT
|
|
||||||
type CursorMut<T: Table>: DbCursorRW<'a, T> + DbCursorRO<'a, T> + Send + Sync;
|
|
||||||
/// DupCursor GAT
|
|
||||||
type DupCursorMut<T: DupSort>: DbDupCursorRW<'a, T>
|
|
||||||
+ DbCursorRW<'a, T>
|
|
||||||
+ DbDupCursorRO<'a, T>
|
|
||||||
+ DbCursorRO<'a, T>
|
|
||||||
+ Send
|
|
||||||
+ Sync;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Read only transaction
|
|
||||||
pub trait DbTx<'tx>: for<'a> DbTxGAT<'a> {
|
|
||||||
/// Get value
|
|
||||||
fn get<T: Table>(&self, key: T::Key) -> Result<Option<T::Value>, Error>;
|
|
||||||
/// Commit for read only transaction will consume and free transaction and allows
|
|
||||||
/// freeing of memory pages
|
|
||||||
fn commit(self) -> Result<bool, Error>;
|
|
||||||
/// Iterate over read only values in table.
|
|
||||||
fn cursor<T: Table>(&self) -> Result<<Self as DbTxGAT<'_>>::Cursor<T>, Error>;
|
|
||||||
/// Iterate over read only values in dup sorted table.
|
|
||||||
fn cursor_dup<T: DupSort>(&self) -> Result<<Self as DbTxGAT<'_>>::DupCursor<T>, Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Read write transaction that allows writing to database
|
|
||||||
pub trait DbTxMut<'tx>: for<'a> DbTxMutGAT<'a> {
|
|
||||||
/// Put value to database
|
|
||||||
fn put<T: Table>(&self, key: T::Key, value: T::Value) -> Result<(), Error>;
|
|
||||||
/// Delete value from database
|
|
||||||
fn delete<T: Table>(&self, key: T::Key, value: Option<T::Value>) -> Result<bool, Error>;
|
|
||||||
/// Clears database.
|
|
||||||
fn clear<T: Table>(&self) -> Result<(), Error>;
|
|
||||||
/// Cursor mut
|
|
||||||
fn cursor_mut<T: Table>(&self) -> Result<<Self as DbTxMutGAT<'_>>::CursorMut<T>, Error>;
|
|
||||||
/// DupCursor mut.
|
|
||||||
fn cursor_dup_mut<T: DupSort>(
|
|
||||||
&self,
|
|
||||||
) -> Result<<Self as DbTxMutGAT<'_>>::DupCursorMut<T>, Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Alias type for a `(key, value)` result coming from a cursor.
|
|
||||||
pub type PairResult<T> = Result<Option<(<T as Table>::Key, <T as Table>::Value)>, Error>;
|
|
||||||
/// Alias type for a `(key, value)` result coming from an iterator.
|
|
||||||
pub type IterPairResult<T> = Option<Result<(<T as Table>::Key, <T as Table>::Value), Error>>;
|
|
||||||
/// Alias type for a value result coming from a cursor without its key.
|
|
||||||
pub type ValueOnlyResult<T> = Result<Option<<T as Table>::Value>, Error>;
|
|
||||||
|
|
||||||
/// Read only cursor over table.
|
|
||||||
pub trait DbCursorRO<'tx, T: Table> {
|
|
||||||
/// First item in table
|
|
||||||
fn first(&mut self) -> PairResult<T>;
|
|
||||||
|
|
||||||
/// Seeks for the exact `(key, value)` pair with `key`.
|
|
||||||
fn seek_exact(&mut self, key: T::Key) -> PairResult<T>;
|
|
||||||
|
|
||||||
/// Returns the next `(key, value)` pair.
|
|
||||||
#[allow(clippy::should_implement_trait)]
|
|
||||||
fn next(&mut self) -> PairResult<T>;
|
|
||||||
|
|
||||||
/// Returns the previous `(key, value)` pair.
|
|
||||||
fn prev(&mut self) -> PairResult<T>;
|
|
||||||
|
|
||||||
/// Returns the last `(key, value)` pair.
|
|
||||||
fn last(&mut self) -> PairResult<T>;
|
|
||||||
|
|
||||||
/// Returns the current `(key, value)` pair of the cursor.
|
|
||||||
fn current(&mut self) -> PairResult<T>;
|
|
||||||
|
|
||||||
/// Returns an iterator starting at a key greater or equal than `start_key`.
|
|
||||||
fn walk<'cursor>(
|
|
||||||
&'cursor mut self,
|
|
||||||
start_key: T::Key,
|
|
||||||
) -> Result<Walker<'cursor, 'tx, T, Self>, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Read only curor over DupSort table.
|
|
||||||
pub trait DbDupCursorRO<'tx, T: DupSort> {
|
|
||||||
/// Seeks for a `(key, value)` pair greater or equal than `key`.
|
|
||||||
fn seek(&mut self, key: T::SubKey) -> PairResult<T>;
|
|
||||||
|
|
||||||
/// Returns the next `(key, value)` pair of a DUPSORT table.
|
|
||||||
fn next_dup(&mut self) -> PairResult<T>;
|
|
||||||
|
|
||||||
/// Returns the next `(key, value)` pair skipping the duplicates.
|
|
||||||
fn next_no_dup(&mut self) -> PairResult<T>;
|
|
||||||
|
|
||||||
/// Returns the next `value` of a duplicate `key`.
|
|
||||||
fn next_dup_val(&mut self) -> ValueOnlyResult<T>;
|
|
||||||
|
|
||||||
/// Returns an iterator starting at a key greater or equal than `start_key` of a DUPSORT
|
|
||||||
/// table.
|
|
||||||
fn walk_dup<'cursor>(
|
|
||||||
&'cursor mut self,
|
|
||||||
key: T::Key,
|
|
||||||
subkey: T::SubKey,
|
|
||||||
) -> Result<DupWalker<'cursor, 'tx, T, Self>, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Read write cursor over table.
|
|
||||||
pub trait DbCursorRW<'tx, T: Table> {
|
|
||||||
/// Database operation that will update an existing row if a specified value already
|
|
||||||
/// exists in a table, and insert a new row if the specified value doesn't already exist
|
|
||||||
fn upsert(&mut self, key: T::Key, value: T::Value) -> Result<(), Error>;
|
|
||||||
|
|
||||||
/// Database operation that will insert a row at a given key. If the key is already
|
|
||||||
/// present, the operation will result in an error.
|
|
||||||
fn insert(&mut self, key: T::Key, value: T::Value) -> Result<(), Error>;
|
|
||||||
|
|
||||||
/// Append value to next cursor item.
|
|
||||||
///
|
|
||||||
/// This is efficient for pre-sorted data. If the data is not pre-sorted, use [`insert`].
|
|
||||||
fn append(&mut self, key: T::Key, value: T::Value) -> Result<(), Error>;
|
|
||||||
|
|
||||||
/// Delete current value that cursor points to
|
|
||||||
fn delete_current(&mut self) -> Result<(), Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Read Write Cursor over DupSorted table.
|
|
||||||
pub trait DbDupCursorRW<'tx, T: DupSort> {
|
|
||||||
/// Append value to next cursor item
|
|
||||||
fn delete_current_duplicates(&mut self) -> Result<(), Error>;
|
|
||||||
|
|
||||||
/// Append duplicate value.
|
|
||||||
///
|
|
||||||
/// This is efficient for pre-sorted data. If the data is not pre-sorted, use [`insert`].
|
|
||||||
fn append_dup(&mut self, key: T::Key, value: T::Value) -> Result<(), Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Provides an iterator to `Cursor` when handling `Table`.
|
|
||||||
///
|
|
||||||
/// Reason why we have two lifetimes is to distinguish between `'cursor` lifetime
|
|
||||||
/// and inherited `'tx` lifetime. If there is only one, rust would short circle
|
|
||||||
/// the Cursor lifetime and it wouldn't be possible to use Walker.
|
|
||||||
pub struct Walker<'cursor, 'tx, T: Table, CURSOR: DbCursorRO<'tx, T>> {
|
|
||||||
/// Cursor to be used to walk through the table.
|
|
||||||
pub cursor: &'cursor mut CURSOR,
|
|
||||||
/// `(key, value)` where to start the walk.
|
|
||||||
pub start: IterPairResult<T>,
|
|
||||||
/// Phantom data for 'tx. As it is only used for `DbCursorRO`.
|
|
||||||
pub _tx_phantom: PhantomData<&'tx T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'cursor, 'tx, T: Table, CURSOR: DbCursorRO<'tx, T>> std::iter::Iterator
|
|
||||||
for Walker<'cursor, 'tx, T, CURSOR>
|
|
||||||
{
|
|
||||||
type Item = Result<(T::Key, T::Value), Error>;
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
let start = self.start.take();
|
|
||||||
if start.is_some() {
|
|
||||||
return start
|
|
||||||
}
|
|
||||||
|
|
||||||
self.cursor.next().transpose()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Provides an iterator to `Cursor` when handling a `DupSort` table.
|
|
||||||
///
|
|
||||||
/// Reason why we have two lifetimes is to distinguish between `'cursor` lifetime
|
|
||||||
/// and inherited `'tx` lifetime. If there is only one, rust would short circle
|
|
||||||
/// the Cursor lifetime and it wouldn't be possible to use Walker.
|
|
||||||
pub struct DupWalker<'cursor, 'tx, T: DupSort, CURSOR: DbDupCursorRO<'tx, T>> {
|
|
||||||
/// Cursor to be used to walk through the table.
|
|
||||||
pub cursor: &'cursor mut CURSOR,
|
|
||||||
/// Value where to start the walk.
|
|
||||||
pub start: IterPairResult<T>,
|
|
||||||
/// Phantom data for 'tx. As it is only used for `DbDupCursorRO`.
|
|
||||||
pub _tx_phantom: PhantomData<&'tx T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'cursor, 'tx, T: DupSort, CURSOR: DbDupCursorRO<'tx, T>> std::iter::Iterator
|
|
||||||
for DupWalker<'cursor, 'tx, T, CURSOR>
|
|
||||||
{
|
|
||||||
type Item = Result<(T::Key, T::Value), Error>;
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
let start = self.start.take();
|
|
||||||
if start.is_some() {
|
|
||||||
return start
|
|
||||||
}
|
|
||||||
self.cursor.next_dup().transpose()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
/// Implements the [`arbitrary::Arbitrary`] trait for types with fixed array types.
|
|
||||||
macro_rules! impl_fixed_arbitrary {
|
|
||||||
($name:tt, $size:tt) => {
|
|
||||||
#[cfg(any(test, feature = "arbitrary"))]
|
|
||||||
use arbitrary::{Arbitrary, Unstructured};
|
|
||||||
|
|
||||||
#[cfg(any(test, feature = "arbitrary"))]
|
|
||||||
impl<'a> Arbitrary<'a> for $name {
|
|
||||||
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self, arbitrary::Error> {
|
|
||||||
let mut buffer = vec![0; $size];
|
|
||||||
u.fill_buffer(buffer.as_mut_slice())?;
|
|
||||||
|
|
||||||
Decode::decode(buffer).map_err(|_| arbitrary::Error::IncorrectFormat)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -13,11 +13,12 @@ pub mod executor;
|
|||||||
/// Consensus traits.
|
/// 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;
|
||||||
|
|
||||||
|
|||||||
@ -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 },
|
||||||
}
|
}
|
||||||
@ -1,12 +0,0 @@
|
|||||||
mod block;
|
|
||||||
pub mod db_provider;
|
|
||||||
mod error;
|
|
||||||
mod state;
|
|
||||||
|
|
||||||
pub use block::{
|
|
||||||
get_cumulative_tx_count_by_hash, insert_canonical_block, BlockProvider, ChainInfo,
|
|
||||||
HeaderProvider,
|
|
||||||
};
|
|
||||||
pub use db_provider::{self as db, ProviderImpl};
|
|
||||||
pub use error::Error;
|
|
||||||
pub use state::{AccountProvider, StateProvider, StateProviderFactory};
|
|
||||||
@ -1,10 +1,8 @@
|
|||||||
mod api;
|
|
||||||
mod bodies;
|
mod 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::*;
|
||||||
|
|||||||
@ -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"
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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};
|
||||||
|
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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 }
|
||||||
|
|||||||
@ -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" }
|
||||||
|
|||||||
@ -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};
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
@ -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};
|
||||||
|
|||||||
@ -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].
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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]
|
||||||
|
|||||||
@ -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},
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
@ -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>,
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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
|
||||||
@ -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]]
|
||||||
@ -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 {
|
||||||
@ -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(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
16
crates/storage/db/src/abstraction/common.rs
Normal file
16
crates/storage/db/src/abstraction/common.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/// Alias type for a `(key, value)` result coming from a cursor.
|
||||||
|
pub type PairResult<T> = Result<Option<(<T as Table>::Key, <T as Table>::Value)>, Error>;
|
||||||
|
/// Alias type for a `(key, value)` result coming from an iterator.
|
||||||
|
pub type IterPairResult<T> = Option<Result<(<T as Table>::Key, <T as Table>::Value), Error>>;
|
||||||
|
/// Alias type for a value result coming from a cursor without its key.
|
||||||
|
pub type ValueOnlyResult<T> = Result<Option<<T as Table>::Value>, Error>;
|
||||||
|
|
||||||
|
use crate::{abstraction::table::*, Error};
|
||||||
|
|
||||||
|
// Sealed trait helper to prevent misuse of the API.
|
||||||
|
mod sealed {
|
||||||
|
pub trait Sealed: Sized {}
|
||||||
|
pub struct Bounds<T>(T);
|
||||||
|
impl<T> Sealed for Bounds<T> {}
|
||||||
|
}
|
||||||
|
pub(crate) use sealed::{Bounds, Sealed};
|
||||||
147
crates/storage/db/src/abstraction/cursor.rs
Normal file
147
crates/storage/db/src/abstraction/cursor.rs
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
common::{IterPairResult, PairResult, ValueOnlyResult},
|
||||||
|
table::{DupSort, Table},
|
||||||
|
Error,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Read only cursor over table.
|
||||||
|
pub trait DbCursorRO<'tx, T: Table> {
|
||||||
|
/// First item in table
|
||||||
|
fn first(&mut self) -> PairResult<T>;
|
||||||
|
|
||||||
|
/// Seeks for the exact `(key, value)` pair with `key`.
|
||||||
|
fn seek_exact(&mut self, key: T::Key) -> PairResult<T>;
|
||||||
|
|
||||||
|
/// Returns the next `(key, value)` pair.
|
||||||
|
#[allow(clippy::should_implement_trait)]
|
||||||
|
fn next(&mut self) -> PairResult<T>;
|
||||||
|
|
||||||
|
/// Returns the previous `(key, value)` pair.
|
||||||
|
fn prev(&mut self) -> PairResult<T>;
|
||||||
|
|
||||||
|
/// Returns the last `(key, value)` pair.
|
||||||
|
fn last(&mut self) -> PairResult<T>;
|
||||||
|
|
||||||
|
/// Returns the current `(key, value)` pair of the cursor.
|
||||||
|
fn current(&mut self) -> PairResult<T>;
|
||||||
|
|
||||||
|
/// Returns an iterator starting at a key greater or equal than `start_key`.
|
||||||
|
fn walk<'cursor>(
|
||||||
|
&'cursor mut self,
|
||||||
|
start_key: T::Key,
|
||||||
|
) -> Result<Walker<'cursor, 'tx, T, Self>, Error>
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read only curor over DupSort table.
|
||||||
|
pub trait DbDupCursorRO<'tx, T: DupSort> {
|
||||||
|
/// Seeks for a `(key, value)` pair greater or equal than `key`.
|
||||||
|
fn seek(&mut self, key: T::SubKey) -> PairResult<T>;
|
||||||
|
|
||||||
|
/// Returns the next `(key, value)` pair of a DUPSORT table.
|
||||||
|
fn next_dup(&mut self) -> PairResult<T>;
|
||||||
|
|
||||||
|
/// Returns the next `(key, value)` pair skipping the duplicates.
|
||||||
|
fn next_no_dup(&mut self) -> PairResult<T>;
|
||||||
|
|
||||||
|
/// Returns the next `value` of a duplicate `key`.
|
||||||
|
fn next_dup_val(&mut self) -> ValueOnlyResult<T>;
|
||||||
|
|
||||||
|
/// Returns an iterator starting at a key greater or equal than `start_key` of a DUPSORT
|
||||||
|
/// table.
|
||||||
|
fn walk_dup<'cursor>(
|
||||||
|
&'cursor mut self,
|
||||||
|
key: T::Key,
|
||||||
|
subkey: T::SubKey,
|
||||||
|
) -> Result<DupWalker<'cursor, 'tx, T, Self>, Error>
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read write cursor over table.
|
||||||
|
pub trait DbCursorRW<'tx, T: Table> {
|
||||||
|
/// Database operation that will update an existing row if a specified value already
|
||||||
|
/// exists in a table, and insert a new row if the specified value doesn't already exist
|
||||||
|
fn upsert(&mut self, key: T::Key, value: T::Value) -> Result<(), Error>;
|
||||||
|
|
||||||
|
/// Database operation that will insert a row at a given key. If the key is already
|
||||||
|
/// present, the operation will result in an error.
|
||||||
|
fn insert(&mut self, key: T::Key, value: T::Value) -> Result<(), Error>;
|
||||||
|
|
||||||
|
/// Append value to next cursor item.
|
||||||
|
///
|
||||||
|
/// This is efficient for pre-sorted data. If the data is not pre-sorted, use [`insert`].
|
||||||
|
fn append(&mut self, key: T::Key, value: T::Value) -> Result<(), Error>;
|
||||||
|
|
||||||
|
/// Delete current value that cursor points to
|
||||||
|
fn delete_current(&mut self) -> Result<(), Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read Write Cursor over DupSorted table.
|
||||||
|
pub trait DbDupCursorRW<'tx, T: DupSort> {
|
||||||
|
/// Append value to next cursor item
|
||||||
|
fn delete_current_duplicates(&mut self) -> Result<(), Error>;
|
||||||
|
|
||||||
|
/// Append duplicate value.
|
||||||
|
///
|
||||||
|
/// This is efficient for pre-sorted data. If the data is not pre-sorted, use [`insert`].
|
||||||
|
fn append_dup(&mut self, key: T::Key, value: T::Value) -> Result<(), Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Provides an iterator to `Cursor` when handling `Table`.
|
||||||
|
///
|
||||||
|
/// Reason why we have two lifetimes is to distinguish between `'cursor` lifetime
|
||||||
|
/// and inherited `'tx` lifetime. If there is only one, rust would short circle
|
||||||
|
/// the Cursor lifetime and it wouldn't be possible to use Walker.
|
||||||
|
pub struct Walker<'cursor, 'tx, T: Table, CURSOR: DbCursorRO<'tx, T>> {
|
||||||
|
/// Cursor to be used to walk through the table.
|
||||||
|
pub cursor: &'cursor mut CURSOR,
|
||||||
|
/// `(key, value)` where to start the walk.
|
||||||
|
pub start: IterPairResult<T>,
|
||||||
|
/// Phantom data for 'tx. As it is only used for `DbCursorRO`.
|
||||||
|
pub _tx_phantom: PhantomData<&'tx T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'cursor, 'tx, T: Table, CURSOR: DbCursorRO<'tx, T>> std::iter::Iterator
|
||||||
|
for Walker<'cursor, 'tx, T, CURSOR>
|
||||||
|
{
|
||||||
|
type Item = Result<(T::Key, T::Value), Error>;
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let start = self.start.take();
|
||||||
|
if start.is_some() {
|
||||||
|
return start
|
||||||
|
}
|
||||||
|
|
||||||
|
self.cursor.next().transpose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Provides an iterator to `Cursor` when handling a `DupSort` table.
|
||||||
|
///
|
||||||
|
/// Reason why we have two lifetimes is to distinguish between `'cursor` lifetime
|
||||||
|
/// and inherited `'tx` lifetime. If there is only one, rust would short circle
|
||||||
|
/// the Cursor lifetime and it wouldn't be possible to use Walker.
|
||||||
|
pub struct DupWalker<'cursor, 'tx, T: DupSort, CURSOR: DbDupCursorRO<'tx, T>> {
|
||||||
|
/// Cursor to be used to walk through the table.
|
||||||
|
pub cursor: &'cursor mut CURSOR,
|
||||||
|
/// Value where to start the walk.
|
||||||
|
pub start: IterPairResult<T>,
|
||||||
|
/// Phantom data for 'tx. As it is only used for `DbDupCursorRO`.
|
||||||
|
pub _tx_phantom: PhantomData<&'tx T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'cursor, 'tx, T: DupSort, CURSOR: DbDupCursorRO<'tx, T>> std::iter::Iterator
|
||||||
|
for DupWalker<'cursor, 'tx, T, CURSOR>
|
||||||
|
{
|
||||||
|
type Item = Result<(T::Key, T::Value), Error>;
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let start = self.start.take();
|
||||||
|
if start.is_some() {
|
||||||
|
return start
|
||||||
|
}
|
||||||
|
self.cursor.next_dup().transpose()
|
||||||
|
}
|
||||||
|
}
|
||||||
53
crates/storage/db/src/abstraction/database.rs
Normal file
53
crates/storage/db/src/abstraction/database.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
use crate::{
|
||||||
|
common::{Bounds, Sealed},
|
||||||
|
transaction::{DbTx, DbTxMut},
|
||||||
|
Error,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Implements the GAT method from:
|
||||||
|
/// https://sabrinajewson.org/blog/the-better-alternative-to-lifetime-gats#the-better-gats.
|
||||||
|
///
|
||||||
|
/// Sealed trait which cannot be implemented by 3rd parties, exposed only for implementers
|
||||||
|
pub trait DatabaseGAT<'a, __ImplicitBounds: Sealed = Bounds<&'a Self>>: Send + Sync {
|
||||||
|
/// RO database transaction
|
||||||
|
type TX: DbTx<'a> + Send + Sync;
|
||||||
|
/// RW database transaction
|
||||||
|
type TXMut: DbTxMut<'a> + DbTx<'a> + Send + Sync;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Main Database trait that spawns transactions to be executed.
|
||||||
|
pub trait Database: for<'a> DatabaseGAT<'a> {
|
||||||
|
/// Create read only transaction.
|
||||||
|
fn tx(&self) -> Result<<Self as DatabaseGAT<'_>>::TX, Error>;
|
||||||
|
|
||||||
|
/// Create read write transaction only possible if database is open with write access.
|
||||||
|
fn tx_mut(&self) -> Result<<Self as DatabaseGAT<'_>>::TXMut, Error>;
|
||||||
|
|
||||||
|
/// Takes a function and passes a read-only transaction into it, making sure it's closed in the
|
||||||
|
/// end of the execution.
|
||||||
|
fn view<T, F>(&self, f: F) -> Result<T, Error>
|
||||||
|
where
|
||||||
|
F: Fn(&<Self as DatabaseGAT<'_>>::TX) -> T,
|
||||||
|
{
|
||||||
|
let tx = self.tx()?;
|
||||||
|
|
||||||
|
let res = f(&tx);
|
||||||
|
tx.commit()?;
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes a function and passes a write-read transaction into it, making sure it's committed in
|
||||||
|
/// the end of the execution.
|
||||||
|
fn update<T, F>(&self, f: F) -> Result<T, Error>
|
||||||
|
where
|
||||||
|
F: Fn(&<Self as DatabaseGAT<'_>>::TXMut) -> T,
|
||||||
|
{
|
||||||
|
let tx = self.tx_mut()?;
|
||||||
|
|
||||||
|
let res = f(&tx);
|
||||||
|
tx.commit()?;
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,9 +1,13 @@
|
|||||||
//! Mock database
|
//! 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!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
12
crates/storage/db/src/abstraction/mod.rs
Normal file
12
crates/storage/db/src/abstraction/mod.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/// Commont return types
|
||||||
|
pub mod common;
|
||||||
|
/// Cursor database traits.
|
||||||
|
pub mod cursor;
|
||||||
|
/// Database traits.
|
||||||
|
pub mod database;
|
||||||
|
/// mock
|
||||||
|
pub mod mock;
|
||||||
|
/// Table traits
|
||||||
|
pub mod table;
|
||||||
|
/// Transaction database traits.
|
||||||
|
pub mod transaction;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
use super::Error;
|
use crate::Error;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use std::{
|
use std::{
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
62
crates/storage/db/src/abstraction/transaction.rs
Normal file
62
crates/storage/db/src/abstraction/transaction.rs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
use crate::{
|
||||||
|
common::{Bounds, Sealed},
|
||||||
|
cursor::{DbCursorRO, DbCursorRW, DbDupCursorRO, DbDupCursorRW},
|
||||||
|
table::{DupSort, Table},
|
||||||
|
Error,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Implements the GAT method from:
|
||||||
|
/// https://sabrinajewson.org/blog/the-better-alternative-to-lifetime-gats#the-better-gats.
|
||||||
|
///
|
||||||
|
/// Sealed trait which cannot be implemented by 3rd parties, exposed only for implementers
|
||||||
|
pub trait DbTxGAT<'a, __ImplicitBounds: Sealed = Bounds<&'a Self>>: Send + Sync {
|
||||||
|
/// Cursor GAT
|
||||||
|
type Cursor<T: Table>: DbCursorRO<'a, T> + Send + Sync;
|
||||||
|
/// DupCursor GAT
|
||||||
|
type DupCursor<T: DupSort>: DbDupCursorRO<'a, T> + DbCursorRO<'a, T> + Send + Sync;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implements the GAT method from:
|
||||||
|
/// https://sabrinajewson.org/blog/the-better-alternative-to-lifetime-gats#the-better-gats.
|
||||||
|
///
|
||||||
|
/// Sealed trait which cannot be implemented by 3rd parties, exposed only for implementers
|
||||||
|
pub trait DbTxMutGAT<'a, __ImplicitBounds: Sealed = Bounds<&'a Self>>: Send + Sync {
|
||||||
|
/// Cursor GAT
|
||||||
|
type CursorMut<T: Table>: DbCursorRW<'a, T> + DbCursorRO<'a, T> + Send + Sync;
|
||||||
|
/// DupCursor GAT
|
||||||
|
type DupCursorMut<T: DupSort>: DbDupCursorRW<'a, T>
|
||||||
|
+ DbCursorRW<'a, T>
|
||||||
|
+ DbDupCursorRO<'a, T>
|
||||||
|
+ DbCursorRO<'a, T>
|
||||||
|
+ Send
|
||||||
|
+ Sync;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read only transaction
|
||||||
|
pub trait DbTx<'tx>: for<'a> DbTxGAT<'a> {
|
||||||
|
/// Get value
|
||||||
|
fn get<T: Table>(&self, key: T::Key) -> Result<Option<T::Value>, Error>;
|
||||||
|
/// Commit for read only transaction will consume and free transaction and allows
|
||||||
|
/// freeing of memory pages
|
||||||
|
fn commit(self) -> Result<bool, Error>;
|
||||||
|
/// Iterate over read only values in table.
|
||||||
|
fn cursor<T: Table>(&self) -> Result<<Self as DbTxGAT<'_>>::Cursor<T>, Error>;
|
||||||
|
/// Iterate over read only values in dup sorted table.
|
||||||
|
fn cursor_dup<T: DupSort>(&self) -> Result<<Self as DbTxGAT<'_>>::DupCursor<T>, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read write transaction that allows writing to database
|
||||||
|
pub trait DbTxMut<'tx>: for<'a> DbTxMutGAT<'a> {
|
||||||
|
/// Put value to database
|
||||||
|
fn put<T: Table>(&self, key: T::Key, value: T::Value) -> Result<(), Error>;
|
||||||
|
/// Delete value from database
|
||||||
|
fn delete<T: Table>(&self, key: T::Key, value: Option<T::Value>) -> Result<bool, Error>;
|
||||||
|
/// Clears database.
|
||||||
|
fn clear<T: Table>(&self) -> Result<(), Error>;
|
||||||
|
/// Cursor mut
|
||||||
|
fn cursor_mut<T: Table>(&self) -> Result<<Self as DbTxMutGAT<'_>>::CursorMut<T>, Error>;
|
||||||
|
/// DupCursor mut.
|
||||||
|
fn cursor_dup_mut<T: DupSort>(
|
||||||
|
&self,
|
||||||
|
) -> Result<<Self as DbTxMutGAT<'_>>::DupCursorMut<T>, Error>;
|
||||||
|
}
|
||||||
@ -2,10 +2,11 @@
|
|||||||
|
|
||||||
use std::{borrow::Cow, marker::PhantomData};
|
use 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()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -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;
|
||||||
2
crates/storage/db/src/implementation/mod.rs
Normal file
2
crates/storage/db/src/implementation/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#[cfg(feature = "mdbx")]
|
||||||
|
pub(crate) mod mdbx;
|
||||||
26
crates/storage/db/src/lib.rs
Normal file
26
crates/storage/db/src/lib.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
//! Rust database abstraction and concrete database implementations.
|
||||||
|
|
||||||
|
#![warn(missing_docs, unreachable_pub)]
|
||||||
|
#![deny(unused_must_use, rust_2018_idioms)]
|
||||||
|
#![doc(test(
|
||||||
|
no_crate_inject,
|
||||||
|
attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
|
||||||
|
))]
|
||||||
|
|
||||||
|
/// Abstracted part of database, containing traits for transactions and cursors.
|
||||||
|
pub mod abstraction;
|
||||||
|
|
||||||
|
mod implementation;
|
||||||
|
pub mod tables;
|
||||||
|
mod utils;
|
||||||
|
|
||||||
|
#[cfg(feature = "mdbx")]
|
||||||
|
/// Bindings for [MDBX](https://libmdbx.dqdkfa.ru/).
|
||||||
|
pub mod mdbx {
|
||||||
|
pub use crate::implementation::mdbx::*;
|
||||||
|
pub use reth_libmdbx::*;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use abstraction::*;
|
||||||
|
pub use reth_interfaces::db::Error;
|
||||||
|
pub use tables::*;
|
||||||
@ -1,6 +1,7 @@
|
|||||||
use crate::db::{
|
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::*;
|
||||||
@ -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.
|
||||||
@ -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;
|
||||||
@ -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);
|
||||||
@ -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::*;
|
||||||
|
|
||||||
@ -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();
|
||||||
@ -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};
|
||||||
@ -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};
|
||||||
@ -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;
|
||||||
@ -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,
|
||||||
};
|
};
|
||||||
@ -1,6 +1,6 @@
|
|||||||
//! Sharded key
|
//! Sharded key
|
||||||
|
|
||||||
use crate::db::{
|
use crate::{
|
||||||
table::{Decode, Encode},
|
table::{Decode, Encode},
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
@ -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.
|
||||||
15
crates/storage/db/src/utils.rs
Normal file
15
crates/storage/db/src/utils.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//! Utils crate for `db`.
|
||||||
|
|
||||||
|
/// Returns the default page size that can be used in this OS.
|
||||||
|
pub(crate) fn default_page_size() -> usize {
|
||||||
|
let os_page_size = page_size::get();
|
||||||
|
|
||||||
|
// source: https://gitflic.ru/project/erthink/libmdbx/blob?file=mdbx.h#line-num-821
|
||||||
|
let libmdbx_max_page_size = 0x10000;
|
||||||
|
|
||||||
|
// May lead to errors if it's reduced further because of the potential size of the
|
||||||
|
// data.
|
||||||
|
let min_page_size = 4096;
|
||||||
|
|
||||||
|
os_page_size.clamp(min_page_size, libmdbx_max_page_size)
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user