Skip to content
This repository has been archived by the owner on Nov 19, 2024. It is now read-only.

Commit

Permalink
feat: make DatabaseProvider generic over chainspec (paradigmxyz#10978)
Browse files Browse the repository at this point in the history
  • Loading branch information
klkvr authored Sep 19, 2024
1 parent 161c2d2 commit 6cb26f7
Show file tree
Hide file tree
Showing 38 changed files with 290 additions and 190 deletions.
2 changes: 1 addition & 1 deletion crates/blockchain-tree/src/blockchain_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use reth_execution_errors::{BlockExecutionError, BlockValidationError};
use reth_execution_types::{Chain, ExecutionOutcome};
use reth_node_types::NodeTypesWithDB;
use reth_primitives::{
BlockNumHash, EthereumHardfork, ForkBlock, GotExpected, Receipt, SealedBlock,
BlockNumHash, EthereumHardfork, ForkBlock, GotExpected, Hardforks, Receipt, SealedBlock,
SealedBlockWithSenders, SealedHeader, StaticFileSegment,
};
use reth_provider::{
Expand Down
9 changes: 9 additions & 0 deletions crates/chainspec/src/api.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
use crate::ChainSpec;
use alloy_chains::Chain;
use alloy_eips::eip1559::BaseFeeParams;
use core::fmt::Debug;

/// Trait representing type configuring a chain spec.
#[auto_impl::auto_impl(&, Arc)]
pub trait EthChainSpec: Send + Sync + Unpin + Debug + 'static {
// todo: make chain spec type generic over hardfork
//type Hardfork: Clone + Copy + 'static;

/// Chain id.
fn chain(&self) -> Chain;

/// Get the [`BaseFeeParams`] for the chain at the given timestamp.
fn base_fee_params_at_timestamp(&self, timestamp: u64) -> BaseFeeParams;
}

impl EthChainSpec for ChainSpec {
fn chain(&self) -> Chain {
self.chain
}

fn base_fee_params_at_timestamp(&self, timestamp: u64) -> BaseFeeParams {
self.base_fee_params_at_timestamp(timestamp)
}
}
21 changes: 20 additions & 1 deletion crates/chainspec/src/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ use derive_more::From;
use once_cell::sync::{Lazy, OnceCell};
use reth_ethereum_forks::{
ChainHardforks, DisplayHardforks, EthereumHardfork, EthereumHardforks, ForkCondition,
ForkFilter, ForkFilterKey, ForkHash, ForkId, Hardfork, Head, DEV_HARDFORKS,
ForkFilter, ForkFilterKey, ForkHash, ForkId, Hardfork, Hardforks, Head, OptimismHardforks,
DEV_HARDFORKS,
};
use reth_network_peers::{
base_nodes, base_testnet_nodes, holesky_nodes, mainnet_nodes, op_nodes, op_testnet_nodes,
Expand Down Expand Up @@ -616,6 +617,24 @@ impl From<Genesis> for ChainSpec {
}
}

impl Hardforks for ChainSpec {
fn fork<H: Hardfork>(&self, fork: H) -> ForkCondition {
self.hardforks.fork(fork)
}

fn forks_iter(&self) -> impl Iterator<Item = (&dyn Hardfork, ForkCondition)> {
self.hardforks.forks_iter()
}
}

impl EthereumHardforks for ChainSpec {
fn final_paris_total_difficulty(&self, block_number: u64) -> Option<U256> {
self.final_paris_total_difficulty(block_number)
}
}

impl OptimismHardforks for ChainSpec {}

/// Convert the given [`Genesis`] into an Ethereum [`ChainSpec`].
#[cfg(not(feature = "optimism"))]
fn into_ethereum_chain_spec(genesis: Genesis) -> ChainSpec {
Expand Down
3 changes: 3 additions & 0 deletions crates/consensus/beacon/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ thiserror.workspace = true
schnellru.workspace = true
itertools.workspace = true

reth-chainspec = { workspace = true, optional = true }

[dev-dependencies]
# reth
reth-payload-builder = { workspace = true, features = ["test-utils"] }
Expand Down Expand Up @@ -79,4 +81,5 @@ optimism = [
"reth-primitives/optimism",
"reth-provider/optimism",
"reth-blockchain-tree/optimism",
"reth-chainspec"
]
5 changes: 3 additions & 2 deletions crates/consensus/beacon/src/engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ where
/// The payload store.
payload_builder: PayloadBuilderHandle<N::Engine>,
/// Validator for execution payloads
payload_validator: ExecutionPayloadValidator,
payload_validator: ExecutionPayloadValidator<N::ChainSpec>,
/// Current blockchain tree action.
blockchain_tree_action: Option<BlockchainTreeAction<N::Engine>>,
/// Pending forkchoice update.
Expand Down Expand Up @@ -462,7 +462,8 @@ where
) -> bool {
// On Optimism, the proposers are allowed to reorg their own chain at will.
#[cfg(feature = "optimism")]
if self.blockchain.chain_spec().is_optimism() {
if reth_chainspec::EthChainSpec::chain(self.blockchain.chain_spec().as_ref()).is_optimism()
{
debug!(
target: "consensus::engine",
fcu_head_num=?header.number,
Expand Down
2 changes: 1 addition & 1 deletion crates/consensus/beacon/src/engine/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ mod tests {
fn build<N>(
self,
pipeline: Pipeline<N>,
chain_spec: Arc<ChainSpec>,
chain_spec: Arc<N::ChainSpec>,
) -> EngineSyncController<N, Either<Client, TestFullBlockClient>>
where
N: ProviderNodeTypes,
Expand Down
8 changes: 4 additions & 4 deletions crates/consensus/common/src/validation.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Collection of methods for block validation.
use reth_chainspec::{ChainSpec, EthereumHardforks};
use reth_chainspec::{EthChainSpec, EthereumHardforks};
use reth_consensus::ConsensusError;
use reth_primitives::{
constants::{
Expand All @@ -25,7 +25,7 @@ pub const fn validate_header_gas(header: &Header) -> Result<(), ConsensusError>

/// Ensure the EIP-1559 base fee is set if the London hardfork is active.
#[inline]
pub fn validate_header_base_fee(
pub fn validate_header_base_fee<ChainSpec: EthereumHardforks>(
header: &Header,
chain_spec: &ChainSpec,
) -> Result<(), ConsensusError> {
Expand Down Expand Up @@ -101,7 +101,7 @@ pub fn validate_prague_request(block: &SealedBlock) -> Result<(), ConsensusError
/// - Compares the transactions root in the block header to the block body
/// - Pre-execution transaction validation
/// - (Optionally) Compares the receipts root in the block header to the block body
pub fn validate_block_pre_execution(
pub fn validate_block_pre_execution<ChainSpec: EthereumHardforks>(
block: &SealedBlock,
chain_spec: &ChainSpec,
) -> Result<(), ConsensusError> {
Expand Down Expand Up @@ -218,7 +218,7 @@ pub fn validate_against_parent_hash_number(

/// Validates the base fee against the parent and EIP-1559 rules.
#[inline]
pub fn validate_against_parent_eip1559_base_fee(
pub fn validate_against_parent_eip1559_base_fee<ChainSpec: EthChainSpec + EthereumHardforks>(
header: &Header,
parent: &Header,
chain_spec: &ChainSpec,
Expand Down
2 changes: 1 addition & 1 deletion crates/engine/invalid-block-hooks/src/witness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ where
// Apply pre-block system contract calls.
apply_beacon_root_contract_call(
&self.evm_config,
&self.provider.chain_spec(),
self.provider.chain_spec().as_ref(),
block.timestamp,
block.number,
block.parent_beacon_block_root,
Expand Down
5 changes: 2 additions & 3 deletions crates/engine/tree/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ reth-blockchain-tree.workspace = true
reth-blockchain-tree-api.workspace = true
reth-chain-state.workspace = true
reth-consensus.workspace = true
reth-chainspec.workspace = true
reth-engine-primitives.workspace = true
reth-errors.workspace = true
reth-evm.workspace = true
Expand Down Expand Up @@ -51,7 +52,6 @@ reth-prune-types = { workspace = true, optional = true }
reth-stages = { workspace = true, optional = true }
reth-static-file = { workspace = true, optional = true }
reth-tracing = { workspace = true, optional = true }
reth-chainspec = { workspace = true, optional = true }

[dev-dependencies]
# reth
Expand Down Expand Up @@ -82,6 +82,5 @@ test-utils = [
"reth-prune-types",
"reth-stages/test-utils",
"reth-static-file",
"reth-tracing",
"reth-chainspec"
"reth-tracing"
]
19 changes: 12 additions & 7 deletions crates/engine/tree/src/tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use reth_blockchain_tree::{
use reth_chain_state::{
CanonicalInMemoryState, ExecutedBlock, MemoryOverlayStateProvider, NewCanonicalChain,
};
use reth_chainspec::EthereumHardforks;
use reth_consensus::{Consensus, PostExecutionInput};
use reth_engine_primitives::EngineTypes;
use reth_errors::{ConsensusError, ProviderResult};
Expand Down Expand Up @@ -457,11 +458,11 @@ pub enum TreeAction {
///
/// This type is responsible for processing engine API requests, maintaining the canonical state and
/// emitting events.
pub struct EngineApiTreeHandler<P, E, T: EngineTypes> {
pub struct EngineApiTreeHandler<P, E, T: EngineTypes, Spec> {
provider: P,
executor_provider: E,
consensus: Arc<dyn Consensus>,
payload_validator: ExecutionPayloadValidator,
payload_validator: ExecutionPayloadValidator<Spec>,
/// Keeps track of internals such as executed and buffered blocks.
state: EngineApiTreeState,
/// The half for sending messages to the engine.
Expand Down Expand Up @@ -499,7 +500,9 @@ pub struct EngineApiTreeHandler<P, E, T: EngineTypes> {
metrics: EngineApiMetrics,
}

impl<P: Debug, E: Debug, T: EngineTypes + Debug> std::fmt::Debug for EngineApiTreeHandler<P, E, T> {
impl<P: Debug, E: Debug, T: EngineTypes + Debug, Spec: Debug> std::fmt::Debug
for EngineApiTreeHandler<P, E, T, Spec>
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EngineApiTreeHandler")
.field("provider", &self.provider)
Expand All @@ -521,20 +524,21 @@ impl<P: Debug, E: Debug, T: EngineTypes + Debug> std::fmt::Debug for EngineApiTr
}
}

impl<P, E, T> EngineApiTreeHandler<P, E, T>
impl<P, E, T, Spec> EngineApiTreeHandler<P, E, T, Spec>
where
P: DatabaseProviderFactory + BlockReader + StateProviderFactory + StateReader + Clone + 'static,
<P as DatabaseProviderFactory>::Provider: BlockReader,
E: BlockExecutorProvider,
T: EngineTypes,
Spec: Send + Sync + EthereumHardforks + 'static,
{
/// Creates a new [`EngineApiTreeHandler`].
#[allow(clippy::too_many_arguments)]
pub fn new(
provider: P,
executor_provider: E,
consensus: Arc<dyn Consensus>,
payload_validator: ExecutionPayloadValidator,
payload_validator: ExecutionPayloadValidator<Spec>,
outgoing: UnboundedSender<EngineApiEvent>,
state: EngineApiTreeState,
canonical_in_memory_state: CanonicalInMemoryState,
Expand Down Expand Up @@ -580,7 +584,7 @@ where
provider: P,
executor_provider: E,
consensus: Arc<dyn Consensus>,
payload_validator: ExecutionPayloadValidator,
payload_validator: ExecutionPayloadValidator<Spec>,
persistence: PersistenceHandle,
payload_builder: PayloadBuilderHandle<T>,
canonical_in_memory_state: CanonicalInMemoryState,
Expand Down Expand Up @@ -2655,7 +2659,8 @@ mod tests {
}

struct TestHarness {
tree: EngineApiTreeHandler<MockEthProvider, MockExecutorProvider, EthEngineTypes>,
tree:
EngineApiTreeHandler<MockEthProvider, MockExecutorProvider, EthEngineTypes, ChainSpec>,
to_tree_tx: Sender<FromEngine<EngineApiRequest<EthEngineTypes>>>,
from_tree_rx: UnboundedReceiver<EngineApiEvent>,
blocks: Vec<ExecutedBlock>,
Expand Down
12 changes: 6 additions & 6 deletions crates/engine/util/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,14 @@ pub trait EngineMessageStreamExt<Engine: EngineTypes>:
}

/// Creates reorgs with specified frequency.
fn reorg<Provider, Evm>(
fn reorg<Provider, Evm, Spec>(
self,
provider: Provider,
evm_config: Evm,
payload_validator: ExecutionPayloadValidator,
payload_validator: ExecutionPayloadValidator<Spec>,
frequency: usize,
depth: Option<usize>,
) -> EngineReorg<Self, Engine, Provider, Evm>
) -> EngineReorg<Self, Engine, Provider, Evm, Spec>
where
Self: Sized,
{
Expand All @@ -118,14 +118,14 @@ pub trait EngineMessageStreamExt<Engine: EngineTypes>:

/// If frequency is [Some], returns the stream that creates reorgs with
/// specified frequency. Otherwise, returns `Self`.
fn maybe_reorg<Provider, Evm>(
fn maybe_reorg<Provider, Evm, Spec>(
self,
provider: Provider,
evm_config: Evm,
payload_validator: ExecutionPayloadValidator,
payload_validator: ExecutionPayloadValidator<Spec>,
frequency: Option<usize>,
depth: Option<usize>,
) -> Either<EngineReorg<Self, Engine, Provider, Evm>, Self>
) -> Either<EngineReorg<Self, Engine, Provider, Evm, Spec>, Self>
where
Self: Sized,
{
Expand Down
16 changes: 9 additions & 7 deletions crates/engine/util/src/reorg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ type ReorgResponseFut = Pin<Box<dyn Future<Output = EngineReorgResponse> + Send
/// Engine API stream wrapper that simulates reorgs with specified frequency.
#[derive(Debug)]
#[pin_project::pin_project]
pub struct EngineReorg<S, Engine: EngineTypes, Provider, Evm> {
pub struct EngineReorg<S, Engine: EngineTypes, Provider, Evm, Spec> {
/// Underlying stream
#[pin]
stream: S,
Expand All @@ -59,7 +59,7 @@ pub struct EngineReorg<S, Engine: EngineTypes, Provider, Evm> {
/// Evm configuration.
evm_config: Evm,
/// Payload validator.
payload_validator: ExecutionPayloadValidator,
payload_validator: ExecutionPayloadValidator<Spec>,
/// The frequency of reorgs.
frequency: usize,
/// The depth of reorgs.
Expand All @@ -75,13 +75,13 @@ pub struct EngineReorg<S, Engine: EngineTypes, Provider, Evm> {
reorg_responses: FuturesUnordered<ReorgResponseFut>,
}

impl<S, Engine: EngineTypes, Provider, Evm> EngineReorg<S, Engine, Provider, Evm> {
impl<S, Engine: EngineTypes, Provider, Evm, Spec> EngineReorg<S, Engine, Provider, Evm, Spec> {
/// Creates new [`EngineReorg`] stream wrapper.
pub fn new(
stream: S,
provider: Provider,
evm_config: Evm,
payload_validator: ExecutionPayloadValidator,
payload_validator: ExecutionPayloadValidator<Spec>,
frequency: usize,
depth: usize,
) -> Self {
Expand All @@ -100,12 +100,13 @@ impl<S, Engine: EngineTypes, Provider, Evm> EngineReorg<S, Engine, Provider, Evm
}
}

impl<S, Engine, Provider, Evm> Stream for EngineReorg<S, Engine, Provider, Evm>
impl<S, Engine, Provider, Evm, Spec> Stream for EngineReorg<S, Engine, Provider, Evm, Spec>
where
S: Stream<Item = BeaconEngineMessage<Engine>>,
Engine: EngineTypes,
Provider: BlockReader + StateProviderFactory,
Evm: ConfigureEvm<Header = Header>,
Spec: EthereumHardforks,
{
type Item = S::Item;

Expand Down Expand Up @@ -227,17 +228,18 @@ where
}
}

fn create_reorg_head<Provider, Evm>(
fn create_reorg_head<Provider, Evm, Spec>(
provider: &Provider,
evm_config: &Evm,
payload_validator: &ExecutionPayloadValidator,
payload_validator: &ExecutionPayloadValidator<Spec>,
mut depth: usize,
next_payload: ExecutionPayload,
next_cancun_fields: Option<CancunPayloadFields>,
) -> RethResult<(ExecutionPayload, Option<CancunPayloadFields>)>
where
Provider: BlockReader + StateProviderFactory,
Evm: ConfigureEvm<Header = Header>,
Spec: EthereumHardforks,
{
let chain_spec = payload_validator.chain_spec();

Expand Down
16 changes: 10 additions & 6 deletions crates/ethereum-forks/src/hardforks/ethereum.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::{
hardforks::{ChainHardforks, Hardforks},
EthereumHardfork, ForkCondition,
};
use alloy_primitives::U256;

use crate::{hardforks::Hardforks, EthereumHardfork, ForkCondition};

/// Helper methods for Ethereum forks.
#[auto_impl::auto_impl(&, Arc)]
pub trait EthereumHardforks: Hardforks {
/// Convenience method to check if [`EthereumHardfork::Shanghai`] is active at a given
/// timestamp.
Expand Down Expand Up @@ -51,6 +51,10 @@ pub trait EthereumHardforks: Hardforks {
_ => None,
}
}
}

impl EthereumHardforks for ChainHardforks {}
/// Returns the final total difficulty if the given block number is after the Paris hardfork.
///
/// Note: technically this would also be valid for the block before the paris upgrade, but this
/// edge case is omitted here.
fn final_paris_total_difficulty(&self, block_number: u64) -> Option<U256>;
}
1 change: 1 addition & 0 deletions crates/ethereum-forks/src/hardforks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use alloc::collections::btree_map::Entry;
use alloc::{boxed::Box, vec::Vec};

/// Generic trait over a set of ordered hardforks
#[auto_impl::auto_impl(&, Arc)]
pub trait Hardforks: Default + Clone {
/// Retrieves [`ForkCondition`] from `fork`. If `fork` is not present, returns
/// [`ForkCondition::Never`].
Expand Down
Loading

0 comments on commit 6cb26f7

Please sign in to comment.