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 5fa3508
Show file tree
Hide file tree
Showing 18 changed files with 315 additions and 39 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
1 change: 1 addition & 0 deletions crates/exex/test-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ pub struct TestNode;
impl NodeTypes for TestNode {
type Primitives = ();
type ChainSpec = ChainSpec;
type Storage = ();
}

impl NodeTypesWithEngine for TestNode {
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;
}
1 change: 1 addition & 0 deletions crates/optimism/node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ reth-network.workspace = true
reth-evm.workspace = true
reth-revm = { workspace = true, features = ["std"] }
reth-beacon-consensus.workspace = true
reth-db.workspace = true

# op-reth
reth-optimism-payload-builder.workspace = true
Expand Down
63 changes: 61 additions & 2 deletions crates/optimism/node/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
use std::sync::Arc;

use alloy_eips::BlockHashOrNumber;
use reth_basic_payload_builder::{BasicPayloadJobGenerator, BasicPayloadJobGeneratorConfig};
use reth_chainspec::{EthChainSpec, Hardforks};
use reth_db::transaction::{DbTx, DbTxMut};
use reth_evm::{execute::BasicBlockExecutorProvider, ConfigureEvm};
use reth_network::{NetworkConfig, NetworkHandle, NetworkManager, PeersInfo};
use reth_node_api::{
Expand All @@ -23,8 +25,8 @@ use reth_optimism_consensus::OptimismBeaconConsensus;
use reth_optimism_evm::{OpExecutionStrategyFactory, OptimismEvmConfig};
use reth_optimism_rpc::OpEthApi;
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_tracing::tracing::{debug, info};
use reth_transaction_pool::{
blobstore::DiskFileBlobStore, CoinbaseTipOrdering, TransactionPool,
Expand Down Expand Up @@ -122,12 +124,69 @@ where
impl NodeTypes for OptimismNode {
type Primitives = OpPrimitives;
type ChainSpec = OpChainSpec;
type Storage = OpStorage;
}

impl NodeTypesWithEngine for OptimismNode {
type Engine = OptimismEngineTypes;
}

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

impl ChainStorageReader for OpStorage {
type Primitives = OpPrimitives;

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


/// Add-ons w.r.t. optimism.
#[derive(Debug)]
pub struct OptimismAddOns<N: FullNodeComponents>(
Expand Down
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
Loading

0 comments on commit 5fa3508

Please sign in to comment.