Skip to content

Commit

Permalink
storage api
Browse files Browse the repository at this point in the history
  • Loading branch information
joshieDo committed Oct 29, 2024
1 parent 0c51609 commit daa9a18
Show file tree
Hide file tree
Showing 14 changed files with 216 additions and 37 deletions.
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion crates/ethereum/node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@ reth-node-api.workspace = true
reth-chainspec.workspace = true
reth-primitives.workspace = true
reth-revm = { workspace = true, features = ["std"] }

reth-db.workspace = true
# revm with required ethereum features
revm = { workspace = true, features = ["secp256k1", "blst", "c-kzg"] }

# misc
alloy-eips.workspace = true
eyre.workspace = true

[dev-dependencies]
Expand Down
65 changes: 63 additions & 2 deletions crates/ethereum/node/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
use std::sync::Arc;

use alloy_eips::BlockHashOrNumber;
use reth_auto_seal_consensus::AutoSealConsensus;
use reth_basic_payload_builder::{BasicPayloadJobGenerator, BasicPayloadJobGeneratorConfig};
use reth_beacon_consensus::EthBeaconConsensus;
use reth_chainspec::ChainSpec;
use reth_db::transaction::{DbTx, DbTxMut};
use reth_ethereum_engine_primitives::{
EthBuiltPayload, EthPayloadAttributes, EthPayloadBuilderAttributes, EthereumEngineValidator,
};
Expand All @@ -26,8 +28,11 @@ use reth_node_builder::{
BuilderContext, Node, NodeAdapter, NodeComponentsBuilder, PayloadBuilderConfig, PayloadTypes,
};
use reth_payload_builder::{PayloadBuilderHandle, PayloadBuilderService};
use reth_primitives::{Block, Header};
use reth_provider::CanonStateSubscriptions;
use reth_primitives::{Block, BlockBody, Header};
use reth_provider::{
BlockNumReader, BlockReader, CanonStateSubscriptions, ChainStorageReader, DBProvider,
HeaderProvider, ProviderResult, TransactionsProvider, WithdrawalsProvider,
};
use reth_rpc::EthApi;
use reth_tracing::tracing::{debug, info};
use reth_transaction_pool::{
Expand Down Expand Up @@ -81,6 +86,7 @@ impl EthereumNode {
impl NodeTypes for EthereumNode {
type Primitives = EthPrimitives;
type ChainSpec = ChainSpec;
type Storage = EthStorage;
}

impl NodeTypesWithEngine for EthereumNode {
Expand Down Expand Up @@ -126,6 +132,61 @@ where
}
}

/// Ethereum storage that implements [`ChainStorageReader`].
#[derive(Debug, Default)]
pub struct EthStorage;

impl ChainStorageReader for EthStorage {
type Primitives = EthPrimitives;

fn read_block<P>(
&self,
provider: &P,
id: BlockHashOrNumber,
) -> ProviderResult<Option<<Self::Primitives as NodePrimitives>::Block>>
where
P: DBProvider<Tx: DbTx>
+ TransactionsProvider
+ BlockReader
+ WithdrawalsProvider
+ HeaderProvider
+ BlockNumReader,
{
if let Some(number) = provider.convert_hash_or_number(id)? {
if let Some(header) = provider.header_by_number(number)? {
let withdrawals = provider.withdrawals_by_block(number.into(), header.timestamp)?;
let ommers = provider.ommers(number.into())?.unwrap_or_default();
// If the body indices are not found, this means that the transactions either do not
// exist in the database yet, or they do exit but are not indexed.
// If they exist but are not indexed, we don't have enough
// information to return the block anyways, so we return `None`.
let transactions = match provider.transactions_by_block(number.into())? {
Some(transactions) => transactions,
None => return Ok(None),
};

return Ok(Some(Block {
header,
body: BlockBody { transactions, ommers, withdrawals },
}))
}
}

Ok(None)
}

fn write_block<P>(
&self,
_provider: &P,
_block: &<Self::Primitives as NodePrimitives>::Block,
) -> ProviderResult<()>
where
P: DBProvider<Tx: DbTxMut>,
{
todo!()
}
}

/// A regular ethereum evm and executor builder.
#[derive(Debug, Default, Clone, Copy)]
#[non_exhaustive]
Expand Down
2 changes: 2 additions & 0 deletions crates/node/builder/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ where
type Primitives = <N::Types as NodeTypes>::Primitives;

type ChainSpec = <N::Types as NodeTypes>::ChainSpec;

type Storage = <N::Types as NodeTypes>::Storage;
}

impl<N, C, AO> NodeTypesWithEngine for AnyNode<N, C, AO>
Expand Down
2 changes: 1 addition & 1 deletion crates/node/types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ workspace = true
reth-chainspec.workspace = true
reth-db-api.workspace = true
reth-engine-primitives.workspace = true
reth-primitives.workspace = true
reth-primitives-traits.workspace = true
reth-storage-api.workspace =true
53 changes: 31 additions & 22 deletions crates/node/types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]

pub use reth_primitives_traits::{Block, BlockBody};
pub use reth_primitives_traits::{Block, BlockBody, NodePrimitives};
use reth_storage_api::ChainStorageReader;

use std::marker::PhantomData;

Expand All @@ -19,16 +20,6 @@ use reth_db_api::{
};
use reth_engine_primitives::EngineTypes;

/// Configures all the primitive types of the node.
pub trait NodePrimitives {
/// Block primitive.
type Block;
}

impl NodePrimitives for () {
type Block = reth_primitives::Block;
}

/// The type that configures the essential types of an Ethereum-like node.
///
/// This includes the primitive types of a node and chain specification.
Expand All @@ -39,6 +30,8 @@ pub trait NodeTypes: Send + Sync + Unpin + 'static {
type Primitives: NodePrimitives;
/// The type used for configuration of the EVM.
type ChainSpec: EthChainSpec;
/// The type used for reading chain specific types from storage.
type Storage: ChainStorageReader<Primitives = Self::Primitives>;
}

/// The type that configures an Ethereum-like node with an engine for consensus.
Expand Down Expand Up @@ -89,6 +82,7 @@ where
{
type Primitives = Types::Primitives;
type ChainSpec = Types::ChainSpec;
type Storage = Types::Storage;
}

impl<Types, DB> NodeTypesWithEngine for NodeTypesWithDBAdapter<Types, DB>
Expand All @@ -109,34 +103,41 @@ where

/// A [`NodeTypes`] type builder.
#[derive(Default, Debug)]
pub struct AnyNodeTypes<P = (), C = ()>(PhantomData<P>, PhantomData<C>);
pub struct AnyNodeTypes<P = (), C = (), S = ()>(PhantomData<P>, PhantomData<C>, PhantomData<S>);

impl<P, C> AnyNodeTypes<P, C> {
impl<P, C, S> AnyNodeTypes<P, C, S> {
/// Sets the `Primitives` associated type.
pub const fn primitives<T>(self) -> AnyNodeTypes<T, C> {
AnyNodeTypes::<T, C>(PhantomData::<T>, PhantomData::<C>)
pub const fn primitives<T>(self) -> AnyNodeTypes<T, C, S> {
AnyNodeTypes::<T, C, S>(PhantomData::<T>, PhantomData::<C>, PhantomData::<S>)
}

/// Sets the `ChainSpec` associated type.
pub const fn chain_spec<T>(self) -> AnyNodeTypes<P, T> {
AnyNodeTypes::<P, T>(PhantomData::<P>, PhantomData::<T>)
pub const fn chain_spec<T>(self) -> AnyNodeTypes<P, T, S> {
AnyNodeTypes::<P, T, S>(PhantomData::<P>, PhantomData::<T>, PhantomData::<S>)
}

/// Sets the `Storage` associated type.
pub const fn storage<T>(self) -> AnyNodeTypes<P, C, T> {
AnyNodeTypes::<P, C, T>(PhantomData::<P>, PhantomData::<C>, PhantomData::<T>)
}
}

impl<P, C> NodeTypes for AnyNodeTypes<P, C>
impl<P, C, S> NodeTypes for AnyNodeTypes<P, C, S>
where
P: NodePrimitives + Send + Sync + Unpin + 'static,
C: EthChainSpec + 'static,
S: ChainStorageReader<Primitives = P> + 'static,
{
type Primitives = P;
type ChainSpec = C;
type Storage = S;
}

/// A [`NodeTypesWithEngine`] type builder.
#[derive(Default, Debug)]
pub struct AnyNodeTypesWithEngine<P = (), E = (), C = ()> {
pub struct AnyNodeTypesWithEngine<P = (), E = (), C = (), S = ()> {
/// Embedding the basic node types.
base: AnyNodeTypes<P, C>,
base: AnyNodeTypes<P, C, S>,
/// Phantom data for the engine.
_engine: PhantomData<E>,
}
Expand All @@ -156,23 +157,31 @@ impl<P, E, C> AnyNodeTypesWithEngine<P, E, C> {
pub const fn chain_spec<T>(self) -> AnyNodeTypesWithEngine<P, E, T> {
AnyNodeTypesWithEngine { base: self.base.chain_spec::<T>(), _engine: PhantomData }
}

/// Sets the `Storage` associated type.
pub const fn storage<T>(self) -> AnyNodeTypesWithEngine<P, E, C, T> {
AnyNodeTypesWithEngine { base: self.base.storage::<T>(), _engine: PhantomData }
}
}

impl<P, E, C> NodeTypes for AnyNodeTypesWithEngine<P, E, C>
impl<P, E, C, S> NodeTypes for AnyNodeTypesWithEngine<P, E, C, S>
where
P: NodePrimitives + Send + Sync + Unpin + 'static,
E: EngineTypes + Send + Sync + Unpin,
C: EthChainSpec + 'static,
S: ChainStorageReader<Primitives = P> + 'static,
{
type Primitives = P;
type ChainSpec = C;
type Storage = S;
}

impl<P, E, C> NodeTypesWithEngine for AnyNodeTypesWithEngine<P, E, C>
impl<P, E, C, S> NodeTypesWithEngine for AnyNodeTypesWithEngine<P, E, C, S>
where
P: NodePrimitives + Send + Sync + Unpin + 'static,
E: EngineTypes + Send + Sync + Unpin,
C: EthChainSpec + 'static,
S: ChainStorageReader<Primitives = P> + 'static,
{
type Engine = E;
}
3 changes: 3 additions & 0 deletions crates/primitives-traits/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ pub use alloy_primitives::{logs_bloom, Log, LogData};
mod storage;
pub use storage::StorageEntry;

mod node;
pub use node::NodePrimitives;

/// Common header types
pub mod header;
#[cfg(any(test, feature = "arbitrary", feature = "test-utils"))]
Expand Down
5 changes: 5 additions & 0 deletions crates/primitives-traits/src/node.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// Configures all the primitive types of the node.
pub trait NodePrimitives {
/// Block primitive.
type Block;
}
34 changes: 25 additions & 9 deletions crates/storage/provider/src/providers/database/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::{
use alloy_eips::BlockHashOrNumber;
use alloy_primitives::{Address, BlockHash, BlockNumber, TxHash, TxNumber, B256, U256};
use core::fmt;
use provider::DatabaseProvider2;
use reth_chainspec::{ChainInfo, EthereumHardforks};
use reth_db::{init_db, mdbx::DatabaseArguments, DatabaseEnv};
use reth_db_api::{database::Database, models::StoredBlockBodyIndices};
Expand Down Expand Up @@ -53,19 +54,22 @@ pub struct ProviderFactory<N: NodeTypesWithDB> {
static_file_provider: StaticFileProvider,
/// Optional pruning configuration
prune_modes: PruneModes,
/// Chain storage reader
chain_storage: Arc<N::Storage>,
}

impl<N> fmt::Debug for ProviderFactory<N>
where
N: NodeTypesWithDB<DB: fmt::Debug, ChainSpec: fmt::Debug>,
N: NodeTypesWithDB<DB: fmt::Debug, ChainSpec: fmt::Debug, Storage: fmt::Debug>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { db, chain_spec, static_file_provider, prune_modes } = self;
let Self { db, chain_spec, static_file_provider, prune_modes, chain_storage } = self;
f.debug_struct("ProviderFactory")
.field("db", &db)
.field("chain_spec", &chain_spec)
.field("static_file_provider", &static_file_provider)
.field("prune_modes", &prune_modes)
.field("chain_storage", &chain_storage)
.finish()
}
}
Expand All @@ -77,7 +81,13 @@ impl<N: NodeTypesWithDB> ProviderFactory<N> {
chain_spec: Arc<N::ChainSpec>,
static_file_provider: StaticFileProvider,
) -> Self {
Self { db, chain_spec, static_file_provider, prune_modes: PruneModes::none() }
Self {
db,
chain_spec,
static_file_provider,
prune_modes: PruneModes::none(),
chain_storage: Default::default(),
}
}

/// Enables metrics on the static file provider.
Expand Down Expand Up @@ -118,6 +128,7 @@ impl<N: NodeTypesWithDB<DB = Arc<DatabaseEnv>>> ProviderFactory<N> {
chain_spec,
static_file_provider,
prune_modes: PruneModes::none(),
chain_storage: Default::default(),
})
}
}
Expand All @@ -131,12 +142,15 @@ impl<N: ProviderNodeTypes> ProviderFactory<N> {
/// data.
#[track_caller]
pub fn provider(&self) -> ProviderResult<DatabaseProviderRO<N::DB, N::ChainSpec>> {
Ok(DatabaseProvider::new(
self.db.tx()?,
self.chain_spec.clone(),
self.static_file_provider.clone(),
self.prune_modes.clone(),
))
let provider2: DatabaseProvider2<<<N as NodeTypesWithDB>::DB as Database>::TX, N> =
DatabaseProvider2::new(
self.db.tx()?,
self.chain_spec.clone(),
self.static_file_provider.clone(),
self.prune_modes.clone(),
self.chain_storage.clone(),
);
Ok(provider2.into_provider())
}

/// Returns a provider with a created `DbTxMut` inside, which allows fetching and updating
Expand Down Expand Up @@ -339,6 +353,7 @@ impl<N: ProviderNodeTypes> BlockReader for ProviderFactory<N> {

fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Block>> {
self.provider()?.block(id)
// self.chain_storage.block(&self.provider()?, id)
}

fn pending_block(&self) -> ProviderResult<Option<SealedBlock>> {
Expand Down Expand Up @@ -612,6 +627,7 @@ impl<N: NodeTypesWithDB> Clone for ProviderFactory<N> {
chain_spec: self.chain_spec.clone(),
static_file_provider: self.static_file_provider.clone(),
prune_modes: self.prune_modes.clone(),
chain_storage: self.chain_storage.clone(),
}
}
}
Expand Down
Loading

0 comments on commit daa9a18

Please sign in to comment.