From 6cb26f72afa478ae72c0988383b62a924ebed521 Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Thu, 19 Sep 2024 17:23:06 +0300 Subject: [PATCH] feat: make `DatabaseProvider` generic over chainspec (#10978) --- crates/blockchain-tree/src/blockchain_tree.rs | 2 +- crates/chainspec/src/api.rs | 9 + crates/chainspec/src/spec.rs | 21 ++- crates/consensus/beacon/Cargo.toml | 3 + crates/consensus/beacon/src/engine/mod.rs | 5 +- crates/consensus/beacon/src/engine/sync.rs | 2 +- crates/consensus/common/src/validation.rs | 8 +- .../engine/invalid-block-hooks/src/witness.rs | 2 +- crates/engine/tree/Cargo.toml | 5 +- crates/engine/tree/src/tree/mod.rs | 19 +- crates/engine/util/src/lib.rs | 12 +- crates/engine/util/src/reorg.rs | 16 +- .../ethereum-forks/src/hardforks/ethereum.rs | 16 +- crates/ethereum-forks/src/hardforks/mod.rs | 1 + .../ethereum-forks/src/hardforks/optimism.rs | 7 +- crates/ethereum/cli/src/chainspec.rs | 6 +- crates/ethereum/consensus/src/lib.rs | 14 +- crates/ethereum/consensus/src/validation.rs | 4 +- crates/evm/src/system_calls/eip4788.rs | 5 +- .../cli/src/commands/init_state/bedrock.rs | 17 +- .../cli/src/commands/init_state/mod.rs | 7 +- crates/optimism/payload/src/builder.rs | 2 +- crates/optimism/rpc/src/eth/receipt.rs | 4 +- crates/payload/validator/src/lib.rs | 6 +- crates/revm/src/state_change.rs | 4 +- .../rpc-eth-api/src/helpers/pending_block.rs | 2 +- crates/stages/stages/benches/criterion.rs | 3 +- crates/stages/stages/benches/setup/mod.rs | 14 +- .../stages/src/stages/hashing_account.rs | 7 +- crates/stages/stages/src/test_utils/runner.rs | 4 +- .../src/providers/blockchain_provider.rs | 9 +- .../provider/src/providers/database/mod.rs | 10 +- .../src/providers/database/provider.rs | 173 +++++++++++------- crates/storage/provider/src/providers/mod.rs | 15 +- .../src/providers/static_file/manager.rs | 29 +-- .../storage/provider/src/test_utils/blocks.rs | 5 +- .../storage/provider/src/test_utils/mock.rs | 4 +- crates/trie/db/tests/trie.rs | 8 +- 38 files changed, 290 insertions(+), 190 deletions(-) diff --git a/crates/blockchain-tree/src/blockchain_tree.rs b/crates/blockchain-tree/src/blockchain_tree.rs index 398aa098b..71fb4314b 100644 --- a/crates/blockchain-tree/src/blockchain_tree.rs +++ b/crates/blockchain-tree/src/blockchain_tree.rs @@ -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::{ diff --git a/crates/chainspec/src/api.rs b/crates/chainspec/src/api.rs index dbf3a00be..c9d8cc98a 100644 --- a/crates/chainspec/src/api.rs +++ b/crates/chainspec/src/api.rs @@ -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) + } } diff --git a/crates/chainspec/src/spec.rs b/crates/chainspec/src/spec.rs index 280a0cb34..0a33db6b5 100644 --- a/crates/chainspec/src/spec.rs +++ b/crates/chainspec/src/spec.rs @@ -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, @@ -616,6 +617,24 @@ impl From for ChainSpec { } } +impl Hardforks for ChainSpec { + fn fork(&self, fork: H) -> ForkCondition { + self.hardforks.fork(fork) + } + + fn forks_iter(&self) -> impl Iterator { + self.hardforks.forks_iter() + } +} + +impl EthereumHardforks for ChainSpec { + fn final_paris_total_difficulty(&self, block_number: u64) -> Option { + 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 { diff --git a/crates/consensus/beacon/Cargo.toml b/crates/consensus/beacon/Cargo.toml index db9ed5a29..6d3fc798c 100644 --- a/crates/consensus/beacon/Cargo.toml +++ b/crates/consensus/beacon/Cargo.toml @@ -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"] } @@ -79,4 +81,5 @@ optimism = [ "reth-primitives/optimism", "reth-provider/optimism", "reth-blockchain-tree/optimism", + "reth-chainspec" ] diff --git a/crates/consensus/beacon/src/engine/mod.rs b/crates/consensus/beacon/src/engine/mod.rs index bd3530727..415b95c5a 100644 --- a/crates/consensus/beacon/src/engine/mod.rs +++ b/crates/consensus/beacon/src/engine/mod.rs @@ -197,7 +197,7 @@ where /// The payload store. payload_builder: PayloadBuilderHandle, /// Validator for execution payloads - payload_validator: ExecutionPayloadValidator, + payload_validator: ExecutionPayloadValidator, /// Current blockchain tree action. blockchain_tree_action: Option>, /// Pending forkchoice update. @@ -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, diff --git a/crates/consensus/beacon/src/engine/sync.rs b/crates/consensus/beacon/src/engine/sync.rs index bf80986e9..5f73c145e 100644 --- a/crates/consensus/beacon/src/engine/sync.rs +++ b/crates/consensus/beacon/src/engine/sync.rs @@ -517,7 +517,7 @@ mod tests { fn build( self, pipeline: Pipeline, - chain_spec: Arc, + chain_spec: Arc, ) -> EngineSyncController> where N: ProviderNodeTypes, diff --git a/crates/consensus/common/src/validation.rs b/crates/consensus/common/src/validation.rs index 848ab59ca..0eadb75a7 100644 --- a/crates/consensus/common/src/validation.rs +++ b/crates/consensus/common/src/validation.rs @@ -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::{ @@ -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( header: &Header, chain_spec: &ChainSpec, ) -> Result<(), ConsensusError> { @@ -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( block: &SealedBlock, chain_spec: &ChainSpec, ) -> Result<(), ConsensusError> { @@ -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( header: &Header, parent: &Header, chain_spec: &ChainSpec, diff --git a/crates/engine/invalid-block-hooks/src/witness.rs b/crates/engine/invalid-block-hooks/src/witness.rs index 6ce5513db..366965d6f 100644 --- a/crates/engine/invalid-block-hooks/src/witness.rs +++ b/crates/engine/invalid-block-hooks/src/witness.rs @@ -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, diff --git a/crates/engine/tree/Cargo.toml b/crates/engine/tree/Cargo.toml index 35d0dddc2..e6e9193d0 100644 --- a/crates/engine/tree/Cargo.toml +++ b/crates/engine/tree/Cargo.toml @@ -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 @@ -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 @@ -82,6 +82,5 @@ test-utils = [ "reth-prune-types", "reth-stages/test-utils", "reth-static-file", - "reth-tracing", - "reth-chainspec" + "reth-tracing" ] diff --git a/crates/engine/tree/src/tree/mod.rs b/crates/engine/tree/src/tree/mod.rs index 3bf2da19b..dd75557b2 100644 --- a/crates/engine/tree/src/tree/mod.rs +++ b/crates/engine/tree/src/tree/mod.rs @@ -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}; @@ -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 { +pub struct EngineApiTreeHandler { provider: P, executor_provider: E, consensus: Arc, - payload_validator: ExecutionPayloadValidator, + payload_validator: ExecutionPayloadValidator, /// Keeps track of internals such as executed and buffered blocks. state: EngineApiTreeState, /// The half for sending messages to the engine. @@ -499,7 +500,9 @@ pub struct EngineApiTreeHandler { metrics: EngineApiMetrics, } -impl std::fmt::Debug for EngineApiTreeHandler { +impl std::fmt::Debug + for EngineApiTreeHandler +{ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("EngineApiTreeHandler") .field("provider", &self.provider) @@ -521,12 +524,13 @@ impl std::fmt::Debug for EngineApiTr } } -impl EngineApiTreeHandler +impl EngineApiTreeHandler where P: DatabaseProviderFactory + BlockReader + StateProviderFactory + StateReader + Clone + 'static,

::Provider: BlockReader, E: BlockExecutorProvider, T: EngineTypes, + Spec: Send + Sync + EthereumHardforks + 'static, { /// Creates a new [`EngineApiTreeHandler`]. #[allow(clippy::too_many_arguments)] @@ -534,7 +538,7 @@ where provider: P, executor_provider: E, consensus: Arc, - payload_validator: ExecutionPayloadValidator, + payload_validator: ExecutionPayloadValidator, outgoing: UnboundedSender, state: EngineApiTreeState, canonical_in_memory_state: CanonicalInMemoryState, @@ -580,7 +584,7 @@ where provider: P, executor_provider: E, consensus: Arc, - payload_validator: ExecutionPayloadValidator, + payload_validator: ExecutionPayloadValidator, persistence: PersistenceHandle, payload_builder: PayloadBuilderHandle, canonical_in_memory_state: CanonicalInMemoryState, @@ -2655,7 +2659,8 @@ mod tests { } struct TestHarness { - tree: EngineApiTreeHandler, + tree: + EngineApiTreeHandler, to_tree_tx: Sender>>, from_tree_rx: UnboundedReceiver, blocks: Vec, diff --git a/crates/engine/util/src/lib.rs b/crates/engine/util/src/lib.rs index e8fab4b6b..26dc817fc 100644 --- a/crates/engine/util/src/lib.rs +++ b/crates/engine/util/src/lib.rs @@ -95,14 +95,14 @@ pub trait EngineMessageStreamExt: } /// Creates reorgs with specified frequency. - fn reorg( + fn reorg( self, provider: Provider, evm_config: Evm, - payload_validator: ExecutionPayloadValidator, + payload_validator: ExecutionPayloadValidator, frequency: usize, depth: Option, - ) -> EngineReorg + ) -> EngineReorg where Self: Sized, { @@ -118,14 +118,14 @@ pub trait EngineMessageStreamExt: /// If frequency is [Some], returns the stream that creates reorgs with /// specified frequency. Otherwise, returns `Self`. - fn maybe_reorg( + fn maybe_reorg( self, provider: Provider, evm_config: Evm, - payload_validator: ExecutionPayloadValidator, + payload_validator: ExecutionPayloadValidator, frequency: Option, depth: Option, - ) -> Either, Self> + ) -> Either, Self> where Self: Sized, { diff --git a/crates/engine/util/src/reorg.rs b/crates/engine/util/src/reorg.rs index 622e01847..bf6bb6c3a 100644 --- a/crates/engine/util/src/reorg.rs +++ b/crates/engine/util/src/reorg.rs @@ -50,7 +50,7 @@ type ReorgResponseFut = Pin + Send /// Engine API stream wrapper that simulates reorgs with specified frequency. #[derive(Debug)] #[pin_project::pin_project] -pub struct EngineReorg { +pub struct EngineReorg { /// Underlying stream #[pin] stream: S, @@ -59,7 +59,7 @@ pub struct EngineReorg { /// Evm configuration. evm_config: Evm, /// Payload validator. - payload_validator: ExecutionPayloadValidator, + payload_validator: ExecutionPayloadValidator, /// The frequency of reorgs. frequency: usize, /// The depth of reorgs. @@ -75,13 +75,13 @@ pub struct EngineReorg { reorg_responses: FuturesUnordered, } -impl EngineReorg { +impl EngineReorg { /// Creates new [`EngineReorg`] stream wrapper. pub fn new( stream: S, provider: Provider, evm_config: Evm, - payload_validator: ExecutionPayloadValidator, + payload_validator: ExecutionPayloadValidator, frequency: usize, depth: usize, ) -> Self { @@ -100,12 +100,13 @@ impl EngineReorg Stream for EngineReorg +impl Stream for EngineReorg where S: Stream>, Engine: EngineTypes, Provider: BlockReader + StateProviderFactory, Evm: ConfigureEvm

, + Spec: EthereumHardforks, { type Item = S::Item; @@ -227,10 +228,10 @@ where } } -fn create_reorg_head( +fn create_reorg_head( provider: &Provider, evm_config: &Evm, - payload_validator: &ExecutionPayloadValidator, + payload_validator: &ExecutionPayloadValidator, mut depth: usize, next_payload: ExecutionPayload, next_cancun_fields: Option, @@ -238,6 +239,7 @@ fn create_reorg_head( where Provider: BlockReader + StateProviderFactory, Evm: ConfigureEvm
, + Spec: EthereumHardforks, { let chain_spec = payload_validator.chain_spec(); diff --git a/crates/ethereum-forks/src/hardforks/ethereum.rs b/crates/ethereum-forks/src/hardforks/ethereum.rs index 3b4c860ad..c8240a83e 100644 --- a/crates/ethereum-forks/src/hardforks/ethereum.rs +++ b/crates/ethereum-forks/src/hardforks/ethereum.rs @@ -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. @@ -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; +} diff --git a/crates/ethereum-forks/src/hardforks/mod.rs b/crates/ethereum-forks/src/hardforks/mod.rs index 28a93c58a..b7e40bd50 100644 --- a/crates/ethereum-forks/src/hardforks/mod.rs +++ b/crates/ethereum-forks/src/hardforks/mod.rs @@ -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`]. diff --git a/crates/ethereum-forks/src/hardforks/optimism.rs b/crates/ethereum-forks/src/hardforks/optimism.rs index 267ce91cf..0e3e31f60 100644 --- a/crates/ethereum-forks/src/hardforks/optimism.rs +++ b/crates/ethereum-forks/src/hardforks/optimism.rs @@ -1,7 +1,8 @@ -use crate::{ChainHardforks, EthereumHardforks, OptimismHardfork}; +use super::Hardforks; +use crate::OptimismHardfork; /// Extends [`crate::EthereumHardforks`] with optimism helper methods. -pub trait OptimismHardforks: EthereumHardforks { +pub trait OptimismHardforks: Hardforks { /// Convenience method to check if [`OptimismHardfork::Bedrock`] is active at a given block /// number. fn is_bedrock_active_at_block(&self, block_number: u64) -> bool { @@ -23,5 +24,3 @@ pub trait OptimismHardforks: EthereumHardforks { self.fork(OptimismHardfork::Granite).active_at_timestamp(timestamp) } } - -impl OptimismHardforks for ChainHardforks {} diff --git a/crates/ethereum/cli/src/chainspec.rs b/crates/ethereum/cli/src/chainspec.rs index cbbafe490..05db177df 100644 --- a/crates/ethereum/cli/src/chainspec.rs +++ b/crates/ethereum/cli/src/chainspec.rs @@ -109,8 +109,8 @@ mod tests { }"#; let spec = ::parse(s).unwrap(); - assert!(spec.hardforks.is_shanghai_active_at_timestamp(0)); - assert!(spec.hardforks.is_cancun_active_at_timestamp(0)); - assert!(spec.hardforks.is_prague_active_at_timestamp(0)); + assert!(spec.is_shanghai_active_at_timestamp(0)); + assert!(spec.is_cancun_active_at_timestamp(0)); + assert!(spec.is_prague_active_at_timestamp(0)); } } diff --git a/crates/ethereum/consensus/src/lib.rs b/crates/ethereum/consensus/src/lib.rs index 2c93958e8..9fb07cca9 100644 --- a/crates/ethereum/consensus/src/lib.rs +++ b/crates/ethereum/consensus/src/lib.rs @@ -8,7 +8,7 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] -use reth_chainspec::{ChainSpec, EthereumHardfork, EthereumHardforks}; +use reth_chainspec::{EthChainSpec, EthereumHardfork, EthereumHardforks}; use reth_consensus::{Consensus, ConsensusError, PostExecutionInput}; use reth_consensus_common::validation::{ validate_4844_header_standalone, validate_against_parent_4844, @@ -20,7 +20,7 @@ use reth_primitives::{ constants::MINIMUM_GAS_LIMIT, BlockWithSenders, Header, SealedBlock, SealedHeader, EMPTY_OMMER_ROOT_HASH, U256, }; -use std::{sync::Arc, time::SystemTime}; +use std::{fmt::Debug, sync::Arc, time::SystemTime}; /// The bound divisor of the gas limit, used in update calculations. const GAS_LIMIT_BOUND_DIVISOR: u64 = 1024; @@ -32,12 +32,12 @@ pub use validation::validate_block_post_execution; /// /// This consensus engine does basic checks as outlined in the execution specs. #[derive(Debug)] -pub struct EthBeaconConsensus { +pub struct EthBeaconConsensus { /// Configuration chain_spec: Arc, } -impl EthBeaconConsensus { +impl EthBeaconConsensus { /// Create a new instance of [`EthBeaconConsensus`] pub const fn new(chain_spec: Arc) -> Self { Self { chain_spec } @@ -89,7 +89,9 @@ impl EthBeaconConsensus { } } -impl Consensus for EthBeaconConsensus { +impl Consensus + for EthBeaconConsensus +{ fn validate_header(&self, header: &SealedHeader) -> Result<(), ConsensusError> { validate_header_gas(header)?; validate_header_base_fee(header, &self.chain_spec)?; @@ -224,7 +226,7 @@ impl Consensus for EthBeaconConsensus { #[cfg(test)] mod tests { use super::*; - use reth_chainspec::ChainSpecBuilder; + use reth_chainspec::{ChainSpec, ChainSpecBuilder}; use reth_primitives::{proofs, B256}; fn header_with_gas_limit(gas_limit: u64) -> SealedHeader { diff --git a/crates/ethereum/consensus/src/validation.rs b/crates/ethereum/consensus/src/validation.rs index f3b782b8d..c8cdf3941 100644 --- a/crates/ethereum/consensus/src/validation.rs +++ b/crates/ethereum/consensus/src/validation.rs @@ -1,4 +1,4 @@ -use reth_chainspec::{ChainSpec, EthereumHardforks}; +use reth_chainspec::EthereumHardforks; use reth_consensus::ConsensusError; use reth_primitives::{ gas_spent_by_transactions, BlockWithSenders, Bloom, GotExpected, Receipt, Request, B256, @@ -8,7 +8,7 @@ use reth_primitives::{ /// /// - Compares the receipts root in the block header to the block body /// - Compares the gas used in the block header to the actual gas usage after execution -pub fn validate_block_post_execution( +pub fn validate_block_post_execution( block: &BlockWithSenders, chain_spec: &ChainSpec, receipts: &[Receipt], diff --git a/crates/evm/src/system_calls/eip4788.rs b/crates/evm/src/system_calls/eip4788.rs index b7087848c..79beaca69 100644 --- a/crates/evm/src/system_calls/eip4788.rs +++ b/crates/evm/src/system_calls/eip4788.rs @@ -58,9 +58,9 @@ where /// /// [EIP-4788]: https://eips.ethereum.org/EIPS/eip-4788 #[inline] -pub fn apply_beacon_root_contract_call( +pub fn apply_beacon_root_contract_call( evm_config: &EvmConfig, - chain_spec: &ChainSpec, + chain_spec: &Spec, block_timestamp: u64, block_number: u64, parent_beacon_block_root: Option, @@ -70,6 +70,7 @@ where DB: Database + DatabaseCommit, DB::Error: core::fmt::Display, EvmConfig: ConfigureEvm
, + Spec: EthereumHardforks, { if !chain_spec.is_cancun_active_at_timestamp(block_timestamp) { return Ok(()) diff --git a/crates/optimism/cli/src/commands/init_state/bedrock.rs b/crates/optimism/cli/src/commands/init_state/bedrock.rs index 1c77569f9..41cd467b2 100644 --- a/crates/optimism/cli/src/commands/init_state/bedrock.rs +++ b/crates/optimism/cli/src/commands/init_state/bedrock.rs @@ -1,23 +1,24 @@ use alloy_primitives::B256; -use reth_db::Database; use reth_optimism_primitives::bedrock::{BEDROCK_HEADER, BEDROCK_HEADER_HASH, BEDROCK_HEADER_TTD}; use reth_primitives::{ BlockBody, BlockNumber, Header, SealedBlock, SealedBlockWithSenders, SealedHeader, StaticFileSegment, U256, }; use reth_provider::{ - providers::StaticFileProvider, BlockWriter, DatabaseProviderRW, StageCheckpointWriter, - StaticFileWriter, + providers::StaticFileProvider, BlockWriter, StageCheckpointWriter, StaticFileWriter, }; use reth_stages::{StageCheckpoint, StageId}; use tracing::info; /// Creates a dummy chain (with no transactions) up to the last OVM block and appends the /// first valid Bedrock block. -pub(crate) fn setup_op_mainnet_without_ovm( - provider_rw: &DatabaseProviderRW, +pub(crate) fn setup_op_mainnet_without_ovm( + provider_rw: &Provider, static_file_provider: &StaticFileProvider, -) -> Result<(), eyre::Error> { +) -> Result<(), eyre::Error> +where + Provider: StageCheckpointWriter + BlockWriter, +{ info!(target: "reth::cli", "Setting up dummy OVM chain before importing state."); // Write OVM dummy data up to `BEDROCK_HEADER - 1` block @@ -40,8 +41,8 @@ pub(crate) fn setup_op_mainnet_without_ovm( /// /// By appending it, static file writer also verifies that all segments are at the same /// height. -fn append_bedrock_block( - provider_rw: &DatabaseProviderRW, +fn append_bedrock_block( + provider_rw: impl BlockWriter, sf_provider: &StaticFileProvider, ) -> Result<(), eyre::Error> { provider_rw.insert_block( diff --git a/crates/optimism/cli/src/commands/init_state/mod.rs b/crates/optimism/cli/src/commands/init_state/mod.rs index e62ec3d16..a021e509b 100644 --- a/crates/optimism/cli/src/commands/init_state/mod.rs +++ b/crates/optimism/cli/src/commands/init_state/mod.rs @@ -8,7 +8,8 @@ use reth_db_common::init::init_from_state_dump; use reth_node_builder::NodeTypesWithEngine; use reth_optimism_primitives::bedrock::BEDROCK_HEADER; use reth_provider::{ - BlockNumReader, ChainSpecProvider, StaticFileProviderFactory, StaticFileWriter, + BlockNumReader, ChainSpecProvider, DatabaseProviderFactory, StaticFileProviderFactory, + StaticFileWriter, }; use std::{fs::File, io::BufReader}; use tracing::info; @@ -45,7 +46,7 @@ impl> InitStateCommandOp { self.init_state.env.init::(AccessRights::RW)?; let static_file_provider = provider_factory.static_file_provider(); - let provider_rw = provider_factory.provider_rw()?; + let provider_rw = provider_factory.database_provider_rw()?; // OP-Mainnet may want to bootstrap a chain without OVM historical data if provider_factory.chain_spec().is_optimism_mainnet() && self.without_ovm { @@ -70,7 +71,7 @@ impl> InitStateCommandOp { info!(target: "reth::cli", "Initiating state dump"); let reader = BufReader::new(File::open(self.init_state.state)?); - let hash = init_from_state_dump(reader, &provider_rw.0, config.stages.etl)?; + let hash = init_from_state_dump(reader, &provider_rw, config.stages.etl)?; provider_rw.commit()?; diff --git a/crates/optimism/payload/src/builder.rs b/crates/optimism/payload/src/builder.rs index 92bd56c21..1d779107f 100644 --- a/crates/optimism/payload/src/builder.rs +++ b/crates/optimism/payload/src/builder.rs @@ -288,7 +288,7 @@ where let timestamp = op_block_attributes.payload_attributes.timestamp(); let receipts_root = execution_outcome - .optimism_receipts_root_slow(block_number, chain_spec.as_ref(), timestamp) + .optimism_receipts_root_slow(block_number, &chain_spec, timestamp) .expect("Number is in range"); let logs_bloom = diff --git a/crates/optimism/rpc/src/eth/receipt.rs b/crates/optimism/rpc/src/eth/receipt.rs index e7e8770cb..69723b1dc 100644 --- a/crates/optimism/rpc/src/eth/receipt.rs +++ b/crates/optimism/rpc/src/eth/receipt.rs @@ -139,7 +139,7 @@ impl OpReceiptFieldsBuilder { .saturating_to(), ); - self.l1_fee_scalar = (!chain_spec.hardforks.is_ecotone_active_at_timestamp(timestamp)) + self.l1_fee_scalar = (!chain_spec.is_ecotone_active_at_timestamp(timestamp)) .then_some(f64::from(l1_block_info.l1_base_fee_scalar) / 1_000_000.0); self.l1_base_fee = Some(l1_block_info.l1_base_fee.saturating_to()); @@ -358,7 +358,7 @@ mod test { reth_evm_optimism::extract_l1_info(&block).expect("should extract l1 info"); // test - assert!(OP_MAINNET.hardforks.is_fjord_active_at_timestamp(BLOCK_124665056_TIMESTAMP)); + assert!(OP_MAINNET.is_fjord_active_at_timestamp(BLOCK_124665056_TIMESTAMP)); let receipt_meta = OpReceiptFieldsBuilder::new(BLOCK_124665056_TIMESTAMP) .l1_block_info(&OP_MAINNET, &tx_1, l1_block_info) diff --git a/crates/payload/validator/src/lib.rs b/crates/payload/validator/src/lib.rs index 6e21111e6..4f83343f8 100644 --- a/crates/payload/validator/src/lib.rs +++ b/crates/payload/validator/src/lib.rs @@ -8,7 +8,7 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] -use reth_chainspec::{ChainSpec, EthereumHardforks}; +use reth_chainspec::EthereumHardforks; use reth_primitives::SealedBlock; use reth_rpc_types::{engine::MaybeCancunPayloadFields, ExecutionPayload, PayloadError}; use reth_rpc_types_compat::engine::payload::try_into_block; @@ -16,12 +16,12 @@ use std::sync::Arc; /// Execution payload validator. #[derive(Clone, Debug)] -pub struct ExecutionPayloadValidator { +pub struct ExecutionPayloadValidator { /// Chain spec to validate against. chain_spec: Arc, } -impl ExecutionPayloadValidator { +impl ExecutionPayloadValidator { /// Create a new validator. pub const fn new(chain_spec: Arc) -> Self { Self { chain_spec } diff --git a/crates/revm/src/state_change.rs b/crates/revm/src/state_change.rs index 5dddb9b86..6ac900186 100644 --- a/crates/revm/src/state_change.rs +++ b/crates/revm/src/state_change.rs @@ -46,7 +46,7 @@ pub fn post_block_balance_increments( /// /// Zero-valued withdrawals are filtered out. #[inline] -pub fn post_block_withdrawals_balance_increments( +pub fn post_block_withdrawals_balance_increments( chain_spec: &ChainSpec, block_timestamp: u64, withdrawals: &[Withdrawal], @@ -66,7 +66,7 @@ pub fn post_block_withdrawals_balance_increments( /// /// Zero-valued withdrawals are filtered out. #[inline] -pub fn insert_post_block_withdrawals_balance_increments( +pub fn insert_post_block_withdrawals_balance_increments( chain_spec: &ChainSpec, block_timestamp: u64, withdrawals: Option<&[Withdrawal]>, diff --git a/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs b/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs index 0f7000c01..d19adff6e 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs @@ -387,7 +387,7 @@ pub trait LoadPendingBlock: EthApiTypes { // executes the withdrawals and commits them to the Database and BundleState. let balance_increments = post_block_withdrawals_balance_increments( - &chain_spec, + chain_spec.as_ref(), block_env.timestamp.try_into().unwrap_or(u64::MAX), &withdrawals.clone().unwrap_or_default(), ); diff --git a/crates/stages/stages/benches/criterion.rs b/crates/stages/stages/benches/criterion.rs index 667caf2ab..3957ceac4 100644 --- a/crates/stages/stages/benches/criterion.rs +++ b/crates/stages/stages/benches/criterion.rs @@ -2,6 +2,7 @@ use criterion::{criterion_main, measurement::WallTime, BenchmarkGroup, Criterion}; #[cfg(not(target_os = "windows"))] use pprof::criterion::{Output, PProfProfiler}; +use reth_chainspec::ChainSpec; use reth_config::config::{EtlConfig, TransactionLookupConfig}; use reth_db::{test_utils::TempDatabase, Database, DatabaseEnv}; @@ -147,7 +148,7 @@ fn measure_stage( block_interval: RangeInclusive, label: String, ) where - S: Clone + Stage as Database>::TXMut>>, + S: Clone + Stage as Database>::TXMut, ChainSpec>>, F: Fn(S, &TestStageDB, StageRange), { let stage_range = ( diff --git a/crates/stages/stages/benches/setup/mod.rs b/crates/stages/stages/benches/setup/mod.rs index e0c4a960e..898dfdc8e 100644 --- a/crates/stages/stages/benches/setup/mod.rs +++ b/crates/stages/stages/benches/setup/mod.rs @@ -1,5 +1,6 @@ #![allow(unreachable_pub)] use itertools::concat; +use reth_chainspec::ChainSpec; use reth_db::{tables, test_utils::TempDatabase, Database, DatabaseEnv}; use reth_db_api::{ cursor::DbCursorRO, @@ -29,7 +30,7 @@ use reth_trie_db::DatabaseStateRoot; pub(crate) type StageRange = (ExecInput, UnwindInput); pub(crate) fn stage_unwind< - S: Clone + Stage as Database>::TXMut>>, + S: Clone + Stage as Database>::TXMut, ChainSpec>>, >( stage: S, db: &TestStageDB, @@ -59,13 +60,10 @@ pub(crate) fn stage_unwind< }); } -pub(crate) fn unwind_hashes< - S: Clone + Stage as Database>::TXMut>>, ->( - stage: S, - db: &TestStageDB, - range: StageRange, -) { +pub(crate) fn unwind_hashes(stage: S, db: &TestStageDB, range: StageRange) +where + S: Clone + Stage as Database>::TXMut, ChainSpec>>, +{ let (input, unwind) = range; let mut stage = stage; diff --git a/crates/stages/stages/src/stages/hashing_account.rs b/crates/stages/stages/src/stages/hashing_account.rs index 16510ac88..2e109f755 100644 --- a/crates/stages/stages/src/stages/hashing_account.rs +++ b/crates/stages/stages/src/stages/hashing_account.rs @@ -57,8 +57,11 @@ impl AccountHashingStage { /// /// Proceeds to go to the `BlockTransitionIndex` end, go back `transitions` and change the /// account state in the `AccountChangeSets` table. - pub fn seed( - provider: &reth_provider::DatabaseProvider, + pub fn seed< + Tx: DbTx + DbTxMut + 'static, + Spec: Send + Sync + 'static + reth_chainspec::EthereumHardforks, + >( + provider: &reth_provider::DatabaseProvider, opts: SeedOpts, ) -> Result, StageError> { use reth_db_api::models::AccountBeforeTx; diff --git a/crates/stages/stages/src/test_utils/runner.rs b/crates/stages/stages/src/test_utils/runner.rs index 7b36bb2e8..d2c4e68be 100644 --- a/crates/stages/stages/src/test_utils/runner.rs +++ b/crates/stages/stages/src/test_utils/runner.rs @@ -1,4 +1,5 @@ use super::TestStageDB; +use reth_chainspec::ChainSpec; use reth_db::{test_utils::TempDatabase, Database, DatabaseEnv}; use reth_provider::{DatabaseProvider, ProviderError}; use reth_stages_api::{ @@ -19,7 +20,8 @@ pub(crate) enum TestRunnerError { /// A generic test runner for stages. pub(crate) trait StageTestRunner { - type S: Stage as Database>::TXMut>> + 'static; + type S: Stage as Database>::TXMut, ChainSpec>> + + 'static; /// Return a reference to the database. fn db(&self) -> &TestStageDB; diff --git a/crates/storage/provider/src/providers/blockchain_provider.rs b/crates/storage/provider/src/providers/blockchain_provider.rs index b592e1b5c..65fe31dd0 100644 --- a/crates/storage/provider/src/providers/blockchain_provider.rs +++ b/crates/storage/provider/src/providers/blockchain_provider.rs @@ -15,7 +15,6 @@ use reth_chain_state::{ MemoryOverlayStateProvider, }; use reth_chainspec::ChainInfo; -use reth_db::Database; use reth_db_api::models::{AccountBeforeTx, StoredBlockBodyIndices}; use reth_evm::ConfigureEvmEnv; use reth_execution_types::ExecutionOutcome; @@ -36,7 +35,7 @@ use std::{ }; use tracing::trace; -use super::{DatabaseProvider, ProviderNodeTypes}; +use super::ProviderNodeTypes; /// The main type for interacting with the blockchain. /// @@ -187,7 +186,7 @@ impl BlockchainProvider2 { /// 2. The in-block transaction index. fn block_state_by_tx_id( &self, - provider: &DatabaseProviderRO, + provider: &DatabaseProviderRO, id: TxNumber, ) -> ProviderResult>, usize)>> { // Get the last block number stored in the database @@ -265,8 +264,8 @@ impl BlockchainProvider2 { impl DatabaseProviderFactory for BlockchainProvider2 { type DB = N::DB; - type Provider = DatabaseProvider<::TX>; - type ProviderRW = DatabaseProvider<::TXMut>; + type Provider = as DatabaseProviderFactory>::Provider; + type ProviderRW = as DatabaseProviderFactory>::ProviderRW; fn database_provider_ro(&self) -> ProviderResult { self.database.database_provider_ro() diff --git a/crates/storage/provider/src/providers/database/mod.rs b/crates/storage/provider/src/providers/database/mod.rs index 8cc07a854..ab1a008bb 100644 --- a/crates/storage/provider/src/providers/database/mod.rs +++ b/crates/storage/provider/src/providers/database/mod.rs @@ -10,7 +10,7 @@ use crate::{ use alloy_eips::BlockHashOrNumber; use alloy_primitives::{Address, BlockHash, BlockNumber, TxHash, TxNumber, B256, U256}; use core::fmt; -use reth_chainspec::ChainInfo; +use reth_chainspec::{ChainInfo, EthereumHardforks}; use reth_db::{init_db, mdbx::DatabaseArguments, DatabaseEnv}; use reth_db_api::{database::Database, models::StoredBlockBodyIndices}; use reth_errors::{RethError, RethResult}; @@ -130,7 +130,7 @@ impl ProviderFactory { /// This sets the [`PruneModes`] to [`None`], because they should only be relevant for writing /// data. #[track_caller] - pub fn provider(&self) -> ProviderResult> { + pub fn provider(&self) -> ProviderResult> { Ok(DatabaseProvider::new( self.db.tx()?, self.chain_spec.clone(), @@ -144,7 +144,7 @@ impl ProviderFactory { /// [`BlockHashReader`]. This may fail if the inner read/write database transaction fails to /// open. #[track_caller] - pub fn provider_rw(&self) -> ProviderResult> { + pub fn provider_rw(&self) -> ProviderResult> { Ok(DatabaseProviderRW(DatabaseProvider::new_rw( self.db.tx_mut()?, self.chain_spec.clone(), @@ -186,8 +186,8 @@ impl ProviderFactory { impl DatabaseProviderFactory for ProviderFactory { type DB = N::DB; - type Provider = DatabaseProviderRO; - type ProviderRW = DatabaseProvider<::TXMut>; + type Provider = DatabaseProvider<::TX, N::ChainSpec>; + type ProviderRW = DatabaseProvider<::TXMut, N::ChainSpec>; fn database_provider_ro(&self) -> ProviderResult { self.provider() diff --git a/crates/storage/provider/src/providers/database/provider.rs b/crates/storage/provider/src/providers/database/provider.rs index db3a879a0..de6d65ad4 100644 --- a/crates/storage/provider/src/providers/database/provider.rs +++ b/crates/storage/provider/src/providers/database/provider.rs @@ -19,7 +19,7 @@ use alloy_eips::BlockHashOrNumber; use alloy_primitives::{keccak256, Address, BlockHash, BlockNumber, TxHash, TxNumber, B256, U256}; use itertools::{izip, Itertools}; use rayon::slice::ParallelSliceMut; -use reth_chainspec::{ChainInfo, ChainSpec, ChainSpecProvider, EthereumHardforks}; +use reth_chainspec::{ChainInfo, ChainSpecProvider, EthChainSpec, EthereumHardforks}; use reth_db::{ cursor::DbDupCursorRW, tables, BlockNumberList, PlainAccountState, PlainStorageState, }; @@ -70,36 +70,40 @@ use tokio::sync::watch; use tracing::{debug, error, warn}; /// A [`DatabaseProvider`] that holds a read-only database transaction. -pub type DatabaseProviderRO = DatabaseProvider<::TX>; +pub type DatabaseProviderRO = DatabaseProvider<::TX, Spec>; /// A [`DatabaseProvider`] that holds a read-write database transaction. /// /// Ideally this would be an alias type. However, there's some weird compiler error (), that forces us to wrap this in a struct instead. /// Once that issue is solved, we can probably revert back to being an alias type. #[derive(Debug)] -pub struct DatabaseProviderRW(pub DatabaseProvider<::TXMut>); +pub struct DatabaseProviderRW( + pub DatabaseProvider<::TXMut, Spec>, +); -impl Deref for DatabaseProviderRW { - type Target = DatabaseProvider<::TXMut>; +impl Deref for DatabaseProviderRW { + type Target = DatabaseProvider<::TXMut, Spec>; fn deref(&self) -> &Self::Target { &self.0 } } -impl DerefMut for DatabaseProviderRW { +impl DerefMut for DatabaseProviderRW { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } -impl AsRef::TXMut>> for DatabaseProviderRW { - fn as_ref(&self) -> &DatabaseProvider<::TXMut> { +impl AsRef::TXMut, Spec>> + for DatabaseProviderRW +{ + fn as_ref(&self) -> &DatabaseProvider<::TXMut, Spec> { &self.0 } } -impl DatabaseProviderRW { +impl DatabaseProviderRW { /// Commit database transaction and static file if it exists. pub fn commit(self) -> ProviderResult { self.0.commit() @@ -111,8 +115,10 @@ impl DatabaseProviderRW { } } -impl From> for DatabaseProvider<::TXMut> { - fn from(provider: DatabaseProviderRW) -> Self { +impl From> + for DatabaseProvider<::TXMut, Spec> +{ + fn from(provider: DatabaseProviderRW) -> Self { provider.0 } } @@ -120,36 +126,44 @@ impl From> for DatabaseProvider< { +pub struct DatabaseProvider { /// Database transaction. tx: TX, /// Chain spec - chain_spec: Arc, + chain_spec: Arc, /// Static File provider static_file_provider: StaticFileProvider, /// Pruning configuration prune_modes: PruneModes, } -impl DatabaseProvider { +impl DatabaseProvider { /// Returns reference to prune modes. pub const fn prune_modes_ref(&self) -> &PruneModes { &self.prune_modes } } -impl StaticFileProviderFactory for DatabaseProvider { +impl StaticFileProviderFactory for DatabaseProvider { /// Returns a static file provider fn static_file_provider(&self) -> StaticFileProvider { self.static_file_provider.clone() } } -impl DatabaseProvider { +impl ChainSpecProvider for DatabaseProvider { + type ChainSpec = Spec; + + fn chain_spec(&self) -> Arc { + self.chain_spec.clone() + } +} + +impl DatabaseProvider { /// Creates a provider with an inner read-write transaction. pub const fn new_rw( tx: TX, - chain_spec: Arc, + chain_spec: Arc, static_file_provider: StaticFileProvider, prune_modes: PruneModes, ) -> Self { @@ -157,13 +171,15 @@ impl DatabaseProvider { } } -impl AsRef for DatabaseProvider { +impl AsRef for DatabaseProvider { fn as_ref(&self) -> &Self { self } } -impl TryIntoHistoricalStateProvider for DatabaseProvider { +impl TryIntoHistoricalStateProvider + for DatabaseProvider +{ fn try_into_history_at_block( self, mut block_number: BlockNumber, @@ -206,7 +222,9 @@ impl TryIntoHistoricalStateProvider for DatabaseProvider } } -impl DatabaseProvider { +impl + DatabaseProvider +{ // TODO: uncomment below, once `reth debug_cmd` has been feature gated with dev. // #[cfg(any(test, feature = "test-utils"))] /// Inserts an historical block. **Used for setting up test environments** @@ -287,11 +305,11 @@ where Ok(Vec::new()) } -impl DatabaseProvider { +impl DatabaseProvider { /// Creates a provider with an inner read-only transaction. pub const fn new( tx: TX, - chain_spec: Arc, + chain_spec: Arc, static_file_provider: StaticFileProvider, prune_modes: PruneModes, ) -> Self { @@ -313,8 +331,8 @@ impl DatabaseProvider { &self.tx } - /// Returns a reference to the [`ChainSpec`]. - pub fn chain_spec(&self) -> &ChainSpec { + /// Returns a reference to the chain specification. + pub fn chain_spec(&self) -> &Spec { &self.chain_spec } @@ -412,6 +430,7 @@ impl DatabaseProvider { construct_block: BF, ) -> ProviderResult> where + Spec: EthereumHardforks, H: AsRef
, HF: FnOnce(BlockNumber) -> ProviderResult>, BF: FnOnce( @@ -480,6 +499,7 @@ impl DatabaseProvider { mut assemble_block: F, ) -> ProviderResult> where + Spec: EthereumHardforks, H: AsRef
, HF: FnOnce(RangeInclusive) -> ProviderResult>, F: FnMut( @@ -571,6 +591,7 @@ impl DatabaseProvider { assemble_block: BF, ) -> ProviderResult> where + Spec: EthereumHardforks, H: AsRef
, HF: Fn(RangeInclusive) -> ProviderResult>, BF: Fn( @@ -689,7 +710,10 @@ impl DatabaseProvider { pub fn get_block_range( &self, range: impl RangeBounds + Clone, - ) -> ProviderResult> { + ) -> ProviderResult> + where + Spec: EthereumHardforks, + { // For blocks we need: // // - Headers @@ -949,7 +973,7 @@ impl DatabaseProvider { } } -impl DatabaseProvider { +impl DatabaseProvider { /// Commit database transaction. pub fn commit(self) -> ProviderResult { Ok(self.tx.commit()?) @@ -1176,7 +1200,10 @@ impl DatabaseProvider { pub fn take_block_range( &self, range: impl RangeBounds + Clone, - ) -> ProviderResult> { + ) -> ProviderResult> + where + Spec: EthereumHardforks, + { // For blocks we need: // // - Headers @@ -1329,21 +1356,13 @@ impl DatabaseProvider { } } -impl ChainSpecProvider for DatabaseProvider { - type ChainSpec = ChainSpec; - - fn chain_spec(&self) -> Arc { - self.chain_spec.clone() - } -} - -impl AccountReader for DatabaseProvider { +impl AccountReader for DatabaseProvider { fn basic_account(&self, address: Address) -> ProviderResult> { Ok(self.tx.get::(address)?) } } -impl AccountExtReader for DatabaseProvider { +impl AccountExtReader for DatabaseProvider { fn changed_accounts_with_range( &self, range: impl RangeBounds, @@ -1387,7 +1406,7 @@ impl AccountExtReader for DatabaseProvider { } } -impl ChangeSetReader for DatabaseProvider { +impl ChangeSetReader for DatabaseProvider { fn account_block_changeset( &self, block_number: BlockNumber, @@ -1404,7 +1423,7 @@ impl ChangeSetReader for DatabaseProvider { } } -impl HeaderSyncGapProvider for DatabaseProvider { +impl HeaderSyncGapProvider for DatabaseProvider { fn sync_gap( &self, tip: watch::Receiver, @@ -1448,7 +1467,9 @@ impl HeaderSyncGapProvider for DatabaseProvider { } } -impl HeaderProvider for DatabaseProvider { +impl HeaderProvider + for DatabaseProvider +{ fn header(&self, block_hash: &BlockHash) -> ProviderResult> { if let Some(num) = self.block_number(*block_hash)? { Ok(self.header_by_number(num)?) @@ -1546,7 +1567,7 @@ impl HeaderProvider for DatabaseProvider { } } -impl BlockHashReader for DatabaseProvider { +impl BlockHashReader for DatabaseProvider { fn block_hash(&self, number: u64) -> ProviderResult> { self.static_file_provider.get_with_static_file_or_database( StaticFileSegment::Headers, @@ -1573,7 +1594,7 @@ impl BlockHashReader for DatabaseProvider { } } -impl BlockNumReader for DatabaseProvider { +impl BlockNumReader for DatabaseProvider { fn chain_info(&self) -> ProviderResult { let best_number = self.best_block_number()?; let best_hash = self.block_hash(best_number)?.unwrap_or_default(); @@ -1604,7 +1625,7 @@ impl BlockNumReader for DatabaseProvider { } } -impl BlockReader for DatabaseProvider { +impl BlockReader for DatabaseProvider { fn find_block_by_hash(&self, hash: B256, source: BlockSource) -> ProviderResult> { if source.is_canonical() { self.block(hash.into()) @@ -1777,7 +1798,9 @@ impl BlockReader for DatabaseProvider { } } -impl TransactionsProviderExt for DatabaseProvider { +impl TransactionsProviderExt + for DatabaseProvider +{ /// Recovers transaction hashes by walking through `Transactions` table and /// calculating them in a parallel manner. Returned unsorted. fn transaction_hashes_by_range( @@ -1845,7 +1868,9 @@ impl TransactionsProviderExt for DatabaseProvider { } // Calculates the hash of the given transaction -impl TransactionsProvider for DatabaseProvider { +impl TransactionsProvider + for DatabaseProvider +{ fn transaction_id(&self, tx_hash: TxHash) -> ProviderResult> { Ok(self.tx.get::(tx_hash)?) } @@ -2003,7 +2028,9 @@ impl TransactionsProvider for DatabaseProvider { } } -impl ReceiptProvider for DatabaseProvider { +impl ReceiptProvider + for DatabaseProvider +{ fn receipt(&self, id: TxNumber) -> ProviderResult> { self.static_file_provider.get_with_static_file_or_database( StaticFileSegment::Receipts, @@ -2049,7 +2076,9 @@ impl ReceiptProvider for DatabaseProvider { } } -impl WithdrawalsProvider for DatabaseProvider { +impl WithdrawalsProvider + for DatabaseProvider +{ fn withdrawals_by_block( &self, id: BlockHashOrNumber, @@ -2077,7 +2106,9 @@ impl WithdrawalsProvider for DatabaseProvider { } } -impl RequestsProvider for DatabaseProvider { +impl RequestsProvider + for DatabaseProvider +{ fn requests_by_block( &self, id: BlockHashOrNumber, @@ -2095,7 +2126,9 @@ impl RequestsProvider for DatabaseProvider { } } -impl EvmEnvProvider for DatabaseProvider { +impl EvmEnvProvider + for DatabaseProvider +{ fn fill_env_at( &self, cfg: &mut CfgEnvWithHandlerCfg, @@ -2159,7 +2192,7 @@ impl EvmEnvProvider for DatabaseProvider { } } -impl StageCheckpointReader for DatabaseProvider { +impl StageCheckpointReader for DatabaseProvider { fn get_stage_checkpoint(&self, id: StageId) -> ProviderResult> { Ok(self.tx.get::(id.to_string())?) } @@ -2178,7 +2211,7 @@ impl StageCheckpointReader for DatabaseProvider { } } -impl StageCheckpointWriter for DatabaseProvider { +impl StageCheckpointWriter for DatabaseProvider { /// Save stage checkpoint. fn save_stage_checkpoint( &self, @@ -2219,7 +2252,7 @@ impl StageCheckpointWriter for DatabaseProvider { } } -impl StorageReader for DatabaseProvider { +impl StorageReader for DatabaseProvider { fn plain_state_storages( &self, addresses_with_keys: impl IntoIterator)>, @@ -2282,7 +2315,7 @@ impl StorageReader for DatabaseProvider { } } -impl StateChangeWriter for DatabaseProvider { +impl StateChangeWriter for DatabaseProvider { fn write_state_reverts( &self, reverts: PlainStateReverts, @@ -2659,7 +2692,7 @@ impl StateChangeWriter for DatabaseProvider { } } -impl TrieWriter for DatabaseProvider { +impl TrieWriter for DatabaseProvider { /// Writes trie updates. Returns the number of entries modified. fn write_trie_updates(&self, trie_updates: &TrieUpdates) -> ProviderResult { if trie_updates.is_empty() { @@ -2709,7 +2742,7 @@ impl TrieWriter for DatabaseProvider { } } -impl StorageTrieWriter for DatabaseProvider { +impl StorageTrieWriter for DatabaseProvider { /// Writes storage trie updates from the given storage trie map. First sorts the storage trie /// updates by the hashed address, writing in sorted order. fn write_storage_trie_updates( @@ -2746,7 +2779,7 @@ impl StorageTrieWriter for DatabaseProvider { } } -impl HashingWriter for DatabaseProvider { +impl HashingWriter for DatabaseProvider { fn unwind_account_hashing( &self, range: RangeInclusive, @@ -2951,7 +2984,7 @@ impl HashingWriter for DatabaseProvider { } } -impl HistoryWriter for DatabaseProvider { +impl HistoryWriter for DatabaseProvider { fn unwind_account_history_indices( &self, range: RangeInclusive, @@ -3067,7 +3100,9 @@ impl HistoryWriter for DatabaseProvider { } } -impl BlockExecutionReader for DatabaseProvider { +impl BlockExecutionReader + for DatabaseProvider +{ fn get_block_and_execution_range( &self, range: RangeInclusive, @@ -3082,13 +3117,15 @@ impl BlockExecutionReader for DatabaseProvider { } } -impl StateReader for DatabaseProvider { +impl StateReader for DatabaseProvider { fn get_state(&self, block: BlockNumber) -> ProviderResult> { self.get_state(block..=block) } } -impl BlockExecutionWriter for DatabaseProvider { +impl + BlockExecutionWriter for DatabaseProvider +{ fn take_block_and_execution_range( &self, range: RangeInclusive, @@ -3266,7 +3303,9 @@ impl BlockExecutionWriter for DatabaseProvider } } -impl BlockWriter for DatabaseProvider { +impl BlockWriter + for DatabaseProvider +{ /// Inserts the block into the database, always modifying the following tables: /// * [`CanonicalHeaders`](tables::CanonicalHeaders) /// * [`Headers`](tables::Headers) @@ -3483,7 +3522,7 @@ impl BlockWriter for DatabaseProvider { } } -impl PruneCheckpointReader for DatabaseProvider { +impl PruneCheckpointReader for DatabaseProvider { fn get_prune_checkpoint( &self, segment: PruneSegment, @@ -3500,7 +3539,7 @@ impl PruneCheckpointReader for DatabaseProvider { } } -impl PruneCheckpointWriter for DatabaseProvider { +impl PruneCheckpointWriter for DatabaseProvider { fn save_prune_checkpoint( &self, segment: PruneSegment, @@ -3510,7 +3549,7 @@ impl PruneCheckpointWriter for DatabaseProvider { } } -impl StatsReader for DatabaseProvider { +impl StatsReader for DatabaseProvider { fn count_entries(&self) -> ProviderResult { let db_entries = self.tx.entries::()?; let static_file_entries = match self.static_file_provider.count_entries::() { @@ -3523,7 +3562,7 @@ impl StatsReader for DatabaseProvider { } } -impl FinalizedBlockReader for DatabaseProvider { +impl FinalizedBlockReader for DatabaseProvider { fn last_finalized_block_number(&self) -> ProviderResult> { let mut finalized_blocks = self .tx @@ -3537,7 +3576,7 @@ impl FinalizedBlockReader for DatabaseProvider { } } -impl FinalizedBlockWriter for DatabaseProvider { +impl FinalizedBlockWriter for DatabaseProvider { fn save_finalized_block_number(&self, block_number: BlockNumber) -> ProviderResult<()> { Ok(self .tx @@ -3545,7 +3584,7 @@ impl FinalizedBlockWriter for DatabaseProvider { } } -impl DBProvider for DatabaseProvider { +impl DBProvider for DatabaseProvider { type Tx = TX; fn tx_ref(&self) -> &Self::Tx { diff --git a/crates/storage/provider/src/providers/mod.rs b/crates/storage/provider/src/providers/mod.rs index 2a0413525..35b808030 100644 --- a/crates/storage/provider/src/providers/mod.rs +++ b/crates/storage/provider/src/providers/mod.rs @@ -15,8 +15,7 @@ use reth_blockchain_tree_api::{ InsertPayloadOk, }; use reth_chain_state::{ChainInfoTracker, ForkChoiceNotifications, ForkChoiceSubscriptions}; -use reth_chainspec::{ChainInfo, ChainSpec}; -use reth_db::Database; +use reth_chainspec::{ChainInfo, EthereumHardforks}; use reth_db_api::models::{AccountBeforeTx, StoredBlockBodyIndices}; use reth_evm::ConfigureEvmEnv; use reth_node_types::NodeTypesWithDB; @@ -63,9 +62,9 @@ mod blockchain_provider; pub use blockchain_provider::BlockchainProvider2; /// Helper trait keeping common requirements of providers for [`NodeTypesWithDB`]. -pub trait ProviderNodeTypes: NodeTypesWithDB {} +pub trait ProviderNodeTypes: NodeTypesWithDB {} -impl ProviderNodeTypes for T where T: NodeTypesWithDB {} +impl ProviderNodeTypes for T where T: NodeTypesWithDB {} /// The main type for interacting with the blockchain. /// @@ -173,15 +172,15 @@ where impl DatabaseProviderFactory for BlockchainProvider { type DB = N::DB; - type Provider = DatabaseProvider<::TX>; - type ProviderRW = DatabaseProvider<::TXMut>; + type Provider = as DatabaseProviderFactory>::Provider; + type ProviderRW = as DatabaseProviderFactory>::ProviderRW; fn database_provider_ro(&self) -> ProviderResult { - self.database.provider() + self.database.database_provider_ro() } fn database_provider_rw(&self) -> ProviderResult { - self.database.provider_rw().map(|p| p.0) + self.database.database_provider_rw() } } diff --git a/crates/storage/provider/src/providers/static_file/manager.rs b/crates/storage/provider/src/providers/static_file/manager.rs index 074d109c3..261c682fb 100644 --- a/crates/storage/provider/src/providers/static_file/manager.rs +++ b/crates/storage/provider/src/providers/static_file/manager.rs @@ -4,16 +4,16 @@ use super::{ BLOCKS_PER_STATIC_FILE, }; use crate::{ - to_range, BlockHashReader, BlockNumReader, BlockReader, BlockSource, DatabaseProvider, - HeaderProvider, ReceiptProvider, RequestsProvider, StageCheckpointReader, StatsReader, - TransactionVariant, TransactionsProvider, TransactionsProviderExt, WithdrawalsProvider, + to_range, BlockHashReader, BlockNumReader, BlockReader, BlockSource, HeaderProvider, + ReceiptProvider, RequestsProvider, StageCheckpointReader, StatsReader, TransactionVariant, + TransactionsProvider, TransactionsProviderExt, WithdrawalsProvider, }; use alloy_eips::BlockHashOrNumber; use alloy_primitives::{keccak256, Address, BlockHash, BlockNumber, TxHash, TxNumber, B256, U256}; use dashmap::DashMap; use notify::{RecommendedWatcher, RecursiveMode, Watcher}; use parking_lot::RwLock; -use reth_chainspec::ChainInfo; +use reth_chainspec::{Chain, ChainInfo, ChainSpecProvider, EthChainSpec}; use reth_db::{ lockfile::StorageLock, static_file::{iter_static_files, HeaderMask, ReceiptMask, StaticFileCursor, TransactionMask}, @@ -33,6 +33,7 @@ use reth_primitives::{ Withdrawals, }; use reth_stages_types::{PipelineTarget, StageId}; +use reth_storage_api::DBProvider; use reth_storage_errors::provider::{ProviderError, ProviderResult}; use std::{ collections::{hash_map::Entry, BTreeMap, HashMap}, @@ -606,15 +607,18 @@ impl StaticFileProvider { /// WARNING: No static file writer should be held before calling this function, otherwise it /// will deadlock. #[allow(clippy::while_let_loop)] - pub fn check_consistency( + pub fn check_consistency( &self, - provider: &DatabaseProvider, + provider: &Provider, has_receipt_pruning: bool, - ) -> ProviderResult> { + ) -> ProviderResult> + where + Provider: DBProvider + BlockReader + StageCheckpointReader + ChainSpecProvider, + { // OVM chain contains duplicate transactions, so is inconsistent by default since reth db // not designed for duplicate transactions (see ). Undefined behaviour for queries // to OVM chain is also in op-erigon. - if provider.chain_spec().is_optimism_mainnet() { + if provider.chain_spec().chain() == Chain::optimism_mainnet() { info!(target: "reth::cli", "Skipping storage verification for OP mainnet, expected inconsistency in OVM chain" ); @@ -766,13 +770,16 @@ impl StaticFileProvider { /// /// * If the database tables overlap with static files and have contiguous keys, or the /// checkpoint block matches the highest static files block, then [`None`] will be returned. - fn ensure_invariants>( + fn ensure_invariants>( &self, - provider: &DatabaseProvider, + provider: &Provider, segment: StaticFileSegment, highest_static_file_entry: Option, highest_static_file_block: Option, - ) -> ProviderResult> { + ) -> ProviderResult> + where + Provider: DBProvider + BlockReader + StageCheckpointReader, + { let highest_static_file_entry = highest_static_file_entry.unwrap_or_default(); let highest_static_file_block = highest_static_file_block.unwrap_or_default(); let mut db_cursor = provider.tx_ref().cursor_read::()?; diff --git a/crates/storage/provider/src/test_utils/blocks.rs b/crates/storage/provider/src/test_utils/blocks.rs index 439a4b955..a9d69755b 100644 --- a/crates/storage/provider/src/test_utils/blocks.rs +++ b/crates/storage/provider/src/test_utils/blocks.rs @@ -18,7 +18,10 @@ use revm::{ use std::str::FromStr; /// Assert genesis block -pub fn assert_genesis_block(provider: &DatabaseProviderRW, g: SealedBlock) { +pub fn assert_genesis_block( + provider: &DatabaseProviderRW, + g: SealedBlock, +) { let n = g.number; let h = B256::ZERO; let tx = provider; diff --git a/crates/storage/provider/src/test_utils/mock.rs b/crates/storage/provider/src/test_utils/mock.rs index 09c967948..2a380fb74 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -148,8 +148,8 @@ impl MockEthProvider { impl DatabaseProviderFactory for MockEthProvider { type DB = DatabaseMock; - type Provider = DatabaseProvider; - type ProviderRW = DatabaseProvider; + type Provider = DatabaseProvider; + type ProviderRW = DatabaseProvider; fn database_provider_ro(&self) -> ProviderResult { Err(ConsistentViewError::Syncing { best_block: GotExpected::new(0, 0) }.into()) diff --git a/crates/trie/db/tests/trie.rs b/crates/trie/db/tests/trie.rs index acbcb119c..f7413c645 100644 --- a/crates/trie/db/tests/trie.rs +++ b/crates/trie/db/tests/trie.rs @@ -692,8 +692,8 @@ fn storage_trie_around_extension_node() { assert_trie_updates(updates.storage_nodes_ref()); } -fn extension_node_storage_trie( - tx: &DatabaseProviderRW>>, +fn extension_node_storage_trie( + tx: &DatabaseProviderRW>, Spec>, hashed_address: B256, ) -> (B256, StorageTrieUpdates) { let value = U256::from(1); @@ -720,7 +720,9 @@ fn extension_node_storage_trie( (root, trie_updates) } -fn extension_node_trie(tx: &DatabaseProviderRW>>) -> B256 { +fn extension_node_trie( + tx: &DatabaseProviderRW>, Spec>, +) -> B256 { let a = Account { nonce: 0, balance: U256::from(1u64), bytecode_hash: Some(B256::random()) }; let val = encode_account(a, None);