diff --git a/Cargo.lock b/Cargo.lock index 24c2e8db9..14cf9085a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7767,6 +7767,7 @@ dependencies = [ "reth-auto-seal-consensus", "reth-basic-payload-builder", "reth-beacon-consensus", + "reth-blockchain-tree", "reth-chainspec", "reth-consensus", "reth-db", diff --git a/crates/ethereum/engine/src/service.rs b/crates/ethereum/engine/src/service.rs index e5a974992..e9be329ba 100644 --- a/crates/ethereum/engine/src/service.rs +++ b/crates/ethereum/engine/src/service.rs @@ -19,7 +19,7 @@ use reth_evm_ethereum::execute::EthExecutorProvider; use reth_network_p2p::{bodies::client::BodiesClient, headers::client::HeadersClient}; use reth_payload_builder::PayloadBuilderHandle; use reth_payload_validator::ExecutionPayloadValidator; -use reth_provider::{providers::BlockchainProvider, ProviderFactory}; +use reth_provider::{providers::BlockchainProvider2, ProviderFactory}; use reth_prune::Pruner; use reth_stages_api::Pipeline; use reth_tasks::TaskSpawner; @@ -65,7 +65,7 @@ where pipeline: Pipeline, pipeline_task_spawner: Box, provider: ProviderFactory, - blockchain_db: BlockchainProvider, + blockchain_db: BlockchainProvider2, pruner: Pruner>, payload_builder: PayloadBuilderHandle, ) -> Self { @@ -123,18 +123,13 @@ pub struct EthServiceError {} #[cfg(test)] mod tests { use super::*; - use reth_blockchain_tree::{ - BlockchainTree, BlockchainTreeConfig, ShareableBlockchainTree, TreeExternals, - }; use reth_chainspec::{ChainSpecBuilder, MAINNET}; - use reth_consensus::test_utils::TestConsensus; use reth_engine_tree::test_utils::TestPipelineBuilder; use reth_ethereum_engine_primitives::EthEngineTypes; use reth_exex_types::FinishedExExHeight; use reth_network_p2p::test_utils::TestFullBlockClient; use reth_primitives::SealedHeader; use reth_provider::test_utils::create_test_provider_factory_with_chain_spec; - use reth_prune::PruneModes; use reth_tasks::TokioTaskExecutor; use std::sync::Arc; use tokio::sync::{mpsc::unbounded_channel, watch}; @@ -157,23 +152,9 @@ mod tests { let pipeline = TestPipelineBuilder::new().build(chain_spec.clone()); let pipeline_task_spawner = Box::::default(); let provider_factory = create_test_provider_factory_with_chain_spec(chain_spec.clone()); - let consensus = Arc::new(TestConsensus::default()); - let executor_factory = EthExecutorProvider::ethereum(chain_spec.clone()); - let externals = TreeExternals::new(provider_factory.clone(), consensus, executor_factory); - let tree = Arc::new(ShareableBlockchainTree::new( - BlockchainTree::new( - externals, - BlockchainTreeConfig::new(1, 2, 3, 2), - PruneModes::default(), - ) - .expect("failed to create tree"), - )); - let blockchain_db = BlockchainProvider::with_latest( - provider_factory.clone(), - tree, - SealedHeader::default(), - ); + let blockchain_db = + BlockchainProvider2::with_latest(provider_factory.clone(), SealedHeader::default()); let (_tx, rx) = watch::channel(FinishedExExHeight::NoExExs); let pruner = diff --git a/crates/ethereum/node/Cargo.toml b/crates/ethereum/node/Cargo.toml index 2cce8650d..f22490859 100644 --- a/crates/ethereum/node/Cargo.toml +++ b/crates/ethereum/node/Cargo.toml @@ -35,6 +35,7 @@ reth-tokio-util.workspace = true reth-node-events.workspace = true reth-node-core.workspace = true reth-exex.workspace = true +reth-blockchain-tree.workspace = true # misc eyre.workspace = true diff --git a/crates/ethereum/node/src/launch.rs b/crates/ethereum/node/src/launch.rs index c99f62714..c0b811862 100644 --- a/crates/ethereum/node/src/launch.rs +++ b/crates/ethereum/node/src/launch.rs @@ -5,6 +5,7 @@ use reth_beacon_consensus::{ hooks::{EngineHooks, StaticFileHook}, BeaconConsensusEngineHandle, }; +use reth_blockchain_tree::BlockchainTreeConfig; use reth_ethereum_engine::service::{ChainEvent, EthService}; use reth_ethereum_engine_primitives::EthEngineTypes; use reth_exex::ExExManagerHandle; @@ -23,7 +24,7 @@ use reth_node_core::{ version::{CARGO_PKG_VERSION, CLIENT_CODE, NAME_CLIENT, VERGEN_GIT_SHA}, }; use reth_node_events::{cl::ConsensusLayerHealthEvents, node}; -use reth_provider::providers::BlockchainProvider; +use reth_provider::providers::BlockchainProvider2; use reth_rpc_engine_api::{capabilities::EngineCapabilities, EngineApi}; use reth_rpc_types::engine::ClientVersionV1; use reth_tasks::TaskExecutor; @@ -49,7 +50,7 @@ impl EthNodeLauncher { impl LaunchNode> for EthNodeLauncher where T: FullNodeTypes< - Provider = BlockchainProvider<::DB>, + Provider = BlockchainProvider2<::DB>, Engine = EthEngineTypes, >, CB: NodeComponentsBuilder, @@ -72,6 +73,15 @@ where } = target; let NodeHooks { on_component_initialized, on_node_started, .. } = hooks; + // TODO: move tree_config and canon_state_notification_sender + // initialization to with_blockchain_db once the engine revamp is done + // https://github.com/paradigmxyz/reth/issues/8742 + let tree_config = BlockchainTreeConfig::default(); + + // NOTE: This is a temporary workaround to provide the canon state notification sender to the components builder because there's a cyclic dependency between the blockchain provider and the tree component. This will be removed once the Blockchain provider no longer depends on an instance of the tree: + let (canon_state_notification_sender, _receiver) = + tokio::sync::broadcast::channel(tree_config.max_reorg_depth() as usize * 2); + // setup the launch context let ctx = ctx .with_configured_globals() @@ -99,7 +109,9 @@ where .with_metrics_task() // passing FullNodeTypes as type parameter here so that we can build // later the components. - .with_blockchain_db::()? + .with_blockchain_db::(move |provider_factory| { + Ok(BlockchainProvider2::new(provider_factory)?) + }, tree_config, canon_state_notification_sender)? .with_components(components_builder, on_component_initialized).await?; // spawn exexs diff --git a/crates/ethereum/node/tests/it/builder.rs b/crates/ethereum/node/tests/it/builder.rs index 32ebf2d22..fe2ff7eff 100644 --- a/crates/ethereum/node/tests/it/builder.rs +++ b/crates/ethereum/node/tests/it/builder.rs @@ -1,11 +1,17 @@ //! Node builder setup tests. -use reth_db::test_utils::create_test_rw_db; +use std::sync::Arc; + +use reth_db::{ + test_utils::{create_test_rw_db, TempDatabase}, + DatabaseEnv, +}; use reth_node_builder::{FullNodeComponents, NodeBuilder, NodeConfig}; use reth_node_ethereum::{ launch::EthNodeLauncher, node::{EthereumAddOns, EthereumNode}, }; +use reth_provider::providers::BlockchainProvider2; use reth_tasks::TaskManager; #[test] @@ -45,7 +51,7 @@ async fn test_eth_launcher() { let db = create_test_rw_db(); let _builder = NodeBuilder::new(config) .with_database(db) - .with_types::() + .with_types_and_provider::>>>() .with_components(EthereumNode::components()) .with_add_ons::() .launch_with_fn(|builder| { diff --git a/crates/node/builder/src/launch/common.rs b/crates/node/builder/src/launch/common.rs index bfa75a8cf..fb575aac1 100644 --- a/crates/node/builder/src/launch/common.rs +++ b/crates/node/builder/src/launch/common.rs @@ -11,8 +11,7 @@ use rayon::ThreadPoolBuilder; use reth_auto_seal_consensus::MiningMode; use reth_beacon_consensus::EthBeaconConsensus; use reth_blockchain_tree::{ - noop::NoopBlockchainTree, BlockchainTree, BlockchainTreeConfig, ShareableBlockchainTree, - TreeExternals, + BlockchainTree, BlockchainTreeConfig, ShareableBlockchainTree, TreeExternals, }; use reth_chainspec::{Chain, ChainSpec}; use reth_config::{config::EtlConfig, PruneConfig}; @@ -29,8 +28,9 @@ use reth_node_core::{ }; use reth_primitives::{BlockNumber, Head, B256}; use reth_provider::{ - providers::{BlockchainProvider, StaticFileProvider}, - CanonStateNotificationSender, ProviderFactory, StaticFileProviderFactory, + providers::{BlockchainProvider, BlockchainProvider2, StaticFileProvider}, + CanonStateNotificationSender, FullProvider, ProviderFactory, StaticFileProviderFactory, + TreeViewer, }; use reth_prune::{PruneModes, PrunerBuilder}; use reth_rpc_builder::config::RethRpcServerConfig; @@ -45,6 +45,27 @@ use tokio::sync::{ oneshot, watch, }; +/// Allows to set a tree viewer for a configured blockchain provider. +// TODO: remove this helper trait once the engine revamp is done, the new +// blockchain provider won't require a TreeViewer. +// https://github.com/paradigmxyz/reth/issues/8742 +pub trait WithTree { + /// Setter for tree viewer. + fn set_tree(self, tree: Arc) -> Self; +} + +impl WithTree for BlockchainProvider { + fn set_tree(self, tree: Arc) -> Self { + self.with_tree(tree) + } +} + +impl WithTree for BlockchainProvider2 { + fn set_tree(self, _tree: Arc) -> Self { + self + } +} + /// Reusable setup for launching a node. /// /// This provides commonly used boilerplate for launching a node. @@ -523,24 +544,18 @@ where } /// Creates a `BlockchainProvider` and attaches it to the launch context. - pub fn with_blockchain_db( + pub fn with_blockchain_db( self, + create_blockchain_provider: F, + tree_config: BlockchainTreeConfig, + canon_state_notification_sender: CanonStateNotificationSender, ) -> eyre::Result>>> where - T: FullNodeTypes::DB>>, + T: FullNodeTypes, + T::Provider: FullProvider, + F: FnOnce(ProviderFactory) -> eyre::Result, { - let tree_config = BlockchainTreeConfig::default(); - - // NOTE: This is a temporary workaround to provide the canon state notification sender to the components builder because there's a cyclic dependency between the blockchain provider and the tree component. This will be removed once the Blockchain provider no longer depends on an instance of the tree: - let (canon_state_notification_sender, _receiver) = - tokio::sync::broadcast::channel(tree_config.max_reorg_depth() as usize * 2); - - let blockchain_db = BlockchainProvider::new( - self.provider_factory().clone(), - Arc::new(NoopBlockchainTree::with_canon_state_notifications( - canon_state_notification_sender.clone(), - )), - )?; + let blockchain_db = create_blockchain_provider(self.provider_factory().clone())?; let metered_providers = WithMeteredProviders { db_provider_container: WithMeteredProvider { @@ -566,7 +581,8 @@ where impl LaunchContextWith>> where DB: Database + DatabaseMetrics + Send + Sync + Clone + 'static, - T: FullNodeTypes>, + T: FullNodeTypes, + T::Provider: FullProvider + WithTree, { /// Returns access to the underlying database. pub fn database(&self) -> &DB { @@ -592,8 +608,8 @@ where self.right().db_provider_container.metrics_sender.clone() } - /// Returns a reference to the `BlockchainProvider`. - pub const fn blockchain_db(&self) -> &BlockchainProvider { + /// Returns a reference to the blockchain provider. + pub const fn blockchain_db(&self) -> &T::Provider { &self.right().blockchain_db } @@ -648,7 +664,7 @@ where let blockchain_tree = Arc::new(ShareableBlockchainTree::new(tree)); // Replace the tree component with the actual tree - let blockchain_db = self.blockchain_db().clone().with_tree(blockchain_tree); + let blockchain_db = self.blockchain_db().clone().set_tree(blockchain_tree); debug!(target: "reth::cli", "configured blockchain tree"); @@ -685,7 +701,8 @@ where impl LaunchContextWith>> where DB: Database + DatabaseMetrics + Send + Sync + Clone + 'static, - T: FullNodeTypes>, + T: FullNodeTypes, + T::Provider: FullProvider + WithTree, CB: NodeComponentsBuilder, { /// Returns the configured `ProviderFactory`. @@ -722,8 +739,8 @@ where &self.right().node_adapter } - /// Returns a reference to the `BlockchainProvider`. - pub const fn blockchain_db(&self) -> &BlockchainProvider { + /// Returns a reference to the blockchain provider. + pub const fn blockchain_db(&self) -> &T::Provider { &self.right().blockchain_db } @@ -819,9 +836,14 @@ pub struct WithMeteredProvider { /// Helper container to bundle the [`ProviderFactory`], [`BlockchainProvider`] /// and a metrics sender. #[allow(missing_debug_implementations)] -pub struct WithMeteredProviders { +pub struct WithMeteredProviders +where + DB: Database, + T: FullNodeTypes, + T::Provider: FullProvider, +{ db_provider_container: WithMeteredProvider, - blockchain_db: BlockchainProvider, + blockchain_db: T::Provider, canon_state_notification_sender: CanonStateNotificationSender, tree_config: BlockchainTreeConfig, // this field is used to store a reference to the FullNodeTypes so that we @@ -833,12 +855,14 @@ pub struct WithMeteredProviders { #[allow(missing_debug_implementations)] pub struct WithComponents where - T: FullNodeTypes>, + DB: Database, + T: FullNodeTypes, + T::Provider: FullProvider, CB: NodeComponentsBuilder, { db_provider_container: WithMeteredProvider, tree_config: BlockchainTreeConfig, - blockchain_db: BlockchainProvider, + blockchain_db: T::Provider, node_adapter: NodeAdapter, head: Head, consensus: Arc, diff --git a/crates/node/builder/src/launch/mod.rs b/crates/node/builder/src/launch/mod.rs index c18381a2d..99fc1ddf8 100644 --- a/crates/node/builder/src/launch/mod.rs +++ b/crates/node/builder/src/launch/mod.rs @@ -13,6 +13,7 @@ use reth_beacon_consensus::{ hooks::{EngineHooks, PruneHook, StaticFileHook}, BeaconConsensusEngine, }; +use reth_blockchain_tree::{noop::NoopBlockchainTree, BlockchainTreeConfig}; use reth_consensus_debug_client::{DebugConsensusClient, EtherscanBlockProvider, RpcBlockProvider}; use reth_engine_util::EngineMessageStreamExt; use reth_exex::ExExManagerHandle; @@ -119,6 +120,19 @@ where } = target; let NodeHooks { on_component_initialized, on_node_started, .. } = hooks; + // TODO: remove tree and move tree_config and canon_state_notification_sender + // initialization to with_blockchain_db once the engine revamp is done + // https://github.com/paradigmxyz/reth/issues/8742 + let tree_config = BlockchainTreeConfig::default(); + + // NOTE: This is a temporary workaround to provide the canon state notification sender to the components builder because there's a cyclic dependency between the blockchain provider and the tree component. This will be removed once the Blockchain provider no longer depends on an instance of the tree: + let (canon_state_notification_sender, _receiver) = + tokio::sync::broadcast::channel(tree_config.max_reorg_depth() as usize * 2); + + let tree = Arc::new(NoopBlockchainTree::with_canon_state_notifications( + canon_state_notification_sender.clone(), + )); + // setup the launch context let ctx = ctx .with_configured_globals() @@ -146,7 +160,9 @@ where .with_metrics_task() // passing FullNodeTypes as type parameter here so that we can build // later the components. - .with_blockchain_db::()? + .with_blockchain_db::(move |provider_factory| { + Ok(BlockchainProvider::new(provider_factory, tree)?) + }, tree_config, canon_state_notification_sender)? .with_components(components_builder, on_component_initialized).await?; // spawn exexs