diff --git a/Cargo.lock b/Cargo.lock index a24fdf011..397e687c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2850,6 +2850,8 @@ dependencies = [ "eyre", "reth-chainspec", "reth-db", + "reth-node-ethereum", + "reth-node-types", "reth-primitives", "reth-provider", "reth-rpc-types", @@ -6177,6 +6179,7 @@ dependencies = [ "reth-exex-types", "reth-metrics", "reth-network-p2p", + "reth-node-types", "reth-payload-builder", "reth-payload-primitives", "reth-payload-validator", @@ -6262,6 +6265,7 @@ dependencies = [ "reth-execution-types", "reth-metrics", "reth-network", + "reth-node-types", "reth-primitives", "reth-provider", "reth-prune-types", @@ -6595,6 +6599,7 @@ dependencies = [ "reth-db-api", "reth-etl", "reth-fs-util", + "reth-node-types", "reth-primitives", "reth-primitives-traits", "reth-provider", @@ -6819,14 +6824,13 @@ dependencies = [ "reth-blockchain-tree", "reth-chainspec", "reth-consensus", - "reth-db-api", - "reth-engine-primitives", "reth-engine-tree", "reth-ethereum-engine-primitives", "reth-evm", "reth-evm-ethereum", "reth-exex-types", "reth-network-p2p", + "reth-node-types", "reth-payload-builder", "reth-payload-validator", "reth-primitives", @@ -6856,7 +6860,6 @@ dependencies = [ "reth-chainspec", "reth-consensus", "reth-db", - "reth-db-api", "reth-engine-primitives", "reth-errors", "reth-ethereum-engine-primitives", @@ -6864,6 +6867,7 @@ dependencies = [ "reth-exex-types", "reth-metrics", "reth-network-p2p", + "reth-node-types", "reth-payload-builder", "reth-payload-primitives", "reth-payload-validator", @@ -7488,8 +7492,6 @@ dependencies = [ name = "reth-node-api" version = "1.0.6" dependencies = [ - "reth-chainspec", - "reth-db-api", "reth-engine-primitives", "reth-evm", "reth-network-api", @@ -7590,6 +7592,7 @@ dependencies = [ "reth-network", "reth-network-p2p", "reth-network-peers", + "reth-node-types", "reth-optimism-chainspec", "reth-primitives", "reth-provider", @@ -7686,7 +7689,6 @@ dependencies = [ "procfs", "reqwest", "reth-chainspec", - "reth-db", "reth-db-api", "reth-metrics", "reth-provider", @@ -7799,6 +7801,7 @@ dependencies = [ "reth-node-builder", "reth-node-core", "reth-node-events", + "reth-node-optimism", "reth-optimism-chainspec", "reth-optimism-primitives", "reth-primitives", @@ -8028,6 +8031,7 @@ dependencies = [ "reth-db", "reth-db-api", "reth-errors", + "reth-ethereum-engine-primitives", "reth-evm", "reth-execution-types", "reth-fs-util", @@ -8066,6 +8070,7 @@ dependencies = [ "reth-errors", "reth-exex-types", "reth-metrics", + "reth-node-types", "reth-provider", "reth-prune-types", "reth-stages", @@ -8483,6 +8488,7 @@ dependencies = [ "reth-errors", "reth-metrics", "reth-network-p2p", + "reth-node-types", "reth-primitives-traits", "reth-provider", "reth-prune", @@ -8522,9 +8528,11 @@ dependencies = [ "assert_matches", "parking_lot 0.12.3", "rayon", + "reth-chainspec", "reth-db", "reth-db-api", "reth-nippy-jar", + "reth-node-types", "reth-provider", "reth-prune-types", "reth-stages", @@ -8741,6 +8749,7 @@ dependencies = [ "reth-db-api", "reth-execution-errors", "reth-metrics", + "reth-node-types", "reth-primitives", "reth-provider", "reth-stages-types", diff --git a/bin/reth/src/cli/mod.rs b/bin/reth/src/cli/mod.rs index 4c7442b64..8c1f5c246 100644 --- a/bin/reth/src/cli/mod.rs +++ b/bin/reth/src/cli/mod.rs @@ -17,7 +17,7 @@ use reth_cli_runner::CliRunner; use reth_db::DatabaseEnv; use reth_node_builder::{NodeBuilder, WithLaunchContext}; use reth_node_core::args::utils::DefaultChainSpecParser; -use reth_node_ethereum::EthExecutorProvider; +use reth_node_ethereum::{EthExecutorProvider, EthereumNode}; use reth_tracing::FileWorkerGuard; use std::{ffi::OsString, fmt, future::Future, sync::Arc}; use tracing::info; @@ -148,22 +148,33 @@ impl, Ext: clap::Args + fmt::Debug> Cl Commands::Node(command) => { runner.run_command_until_exit(|ctx| command.execute(ctx, launcher)) } - Commands::Init(command) => runner.run_blocking_until_ctrl_c(command.execute()), - Commands::InitState(command) => runner.run_blocking_until_ctrl_c(command.execute()), - Commands::Import(command) => { - runner.run_blocking_until_ctrl_c(command.execute(EthExecutorProvider::ethereum)) + Commands::Init(command) => { + runner.run_blocking_until_ctrl_c(command.execute::()) } + Commands::InitState(command) => { + runner.run_blocking_until_ctrl_c(command.execute::()) + } + Commands::Import(command) => runner.run_blocking_until_ctrl_c( + command.execute::(EthExecutorProvider::ethereum), + ), Commands::DumpGenesis(command) => runner.run_blocking_until_ctrl_c(command.execute()), - Commands::Db(command) => runner.run_blocking_until_ctrl_c(command.execute()), - Commands::Stage(command) => runner - .run_command_until_exit(|ctx| command.execute(ctx, EthExecutorProvider::ethereum)), + Commands::Db(command) => { + runner.run_blocking_until_ctrl_c(command.execute::()) + } + Commands::Stage(command) => runner.run_command_until_exit(|ctx| { + command.execute::(ctx, EthExecutorProvider::ethereum) + }), Commands::P2P(command) => runner.run_until_ctrl_c(command.execute()), #[cfg(feature = "dev")] Commands::TestVectors(command) => runner.run_until_ctrl_c(command.execute()), Commands::Config(command) => runner.run_until_ctrl_c(command.execute()), - Commands::Debug(command) => runner.run_command_until_exit(|ctx| command.execute(ctx)), - Commands::Recover(command) => runner.run_command_until_exit(|ctx| command.execute(ctx)), - Commands::Prune(command) => runner.run_until_ctrl_c(command.execute()), + Commands::Debug(command) => { + runner.run_command_until_exit(|ctx| command.execute::(ctx)) + } + Commands::Recover(command) => { + runner.run_command_until_exit(|ctx| command.execute::(ctx)) + } + Commands::Prune(command) => runner.run_until_ctrl_c(command.execute::()), } } diff --git a/bin/reth/src/commands/debug_cmd/build_block.rs b/bin/reth/src/commands/debug_cmd/build_block.rs index c6a8bf38e..ca82449ff 100644 --- a/bin/reth/src/commands/debug_cmd/build_block.rs +++ b/bin/reth/src/commands/debug_cmd/build_block.rs @@ -14,12 +14,11 @@ use reth_cli::chainspec::ChainSpecParser; use reth_cli_commands::common::{AccessRights, Environment, EnvironmentArgs}; use reth_cli_runner::CliContext; use reth_consensus::Consensus; -use reth_db::DatabaseEnv; use reth_errors::RethResult; use reth_evm::execute::{BlockExecutorProvider, Executor}; use reth_execution_types::ExecutionOutcome; use reth_fs_util as fs; -use reth_node_api::PayloadBuilderAttributes; +use reth_node_api::{NodeTypesWithDB, NodeTypesWithEngine, PayloadBuilderAttributes}; use reth_node_ethereum::EthExecutorProvider; use reth_payload_builder::database::CachedReads; use reth_primitives::{ @@ -83,9 +82,9 @@ impl> Command { /// Fetches the best block block from the database. /// /// If the database is empty, returns the genesis block. - fn lookup_best_block( + fn lookup_best_block>( &self, - factory: ProviderFactory>, + factory: ProviderFactory, ) -> RethResult> { let provider = factory.provider()?; @@ -116,8 +115,11 @@ impl> Command { } /// Execute `debug in-memory-merkle` command - pub async fn execute(self, ctx: CliContext) -> eyre::Result<()> { - let Environment { provider_factory, .. } = self.env.init(AccessRights::RW)?; + pub async fn execute>( + self, + ctx: CliContext, + ) -> eyre::Result<()> { + let Environment { provider_factory, .. } = self.env.init::(AccessRights::RW)?; let consensus: Arc = Arc::new(EthBeaconConsensus::new(provider_factory.chain_spec())); diff --git a/bin/reth/src/commands/debug_cmd/execution.rs b/bin/reth/src/commands/debug_cmd/execution.rs index 6eeaec273..c216c3c66 100644 --- a/bin/reth/src/commands/debug_cmd/execution.rs +++ b/bin/reth/src/commands/debug_cmd/execution.rs @@ -12,7 +12,6 @@ use reth_cli_util::get_secret_key; use reth_config::Config; use reth_consensus::Consensus; use reth_db::DatabaseEnv; -use reth_db_api::database::Database; use reth_downloaders::{ bodies::bodies::BodiesDownloaderBuilder, headers::reverse_headers::ReverseHeadersDownloaderBuilder, @@ -21,6 +20,7 @@ use reth_exex::ExExManagerHandle; use reth_network::{BlockDownloaderProvider, NetworkEventListenerProvider, NetworkHandle}; use reth_network_api::NetworkInfo; use reth_network_p2p::{headers::client::HeadersClient, BlockClient}; +use reth_node_api::{NodeTypesWithDB, NodeTypesWithDBAdapter, NodeTypesWithEngine}; use reth_node_ethereum::EthExecutorProvider; use reth_primitives::{BlockHashOrNumber, BlockNumber, B256}; use reth_provider::{ @@ -57,17 +57,16 @@ pub struct Command { } impl> Command { - fn build_pipeline( + fn build_pipeline, Client>( &self, config: &Config, client: Client, consensus: Arc, - provider_factory: ProviderFactory, + provider_factory: ProviderFactory, task_executor: &TaskExecutor, - static_file_producer: StaticFileProducer, - ) -> eyre::Result> + static_file_producer: StaticFileProducer, + ) -> eyre::Result> where - DB: Database + Unpin + Clone + 'static, Client: BlockClient + 'static, { // building network downloaders using the fetch client @@ -85,7 +84,7 @@ impl> Command { let (tip_tx, tip_rx) = watch::channel(B256::ZERO); let executor = EthExecutorProvider::ethereum(provider_factory.chain_spec()); - let pipeline = Pipeline::builder() + let pipeline = Pipeline::::builder() .with_tip_sender(tip_tx) .add_stages( DefaultStages::new( @@ -116,11 +115,11 @@ impl> Command { Ok(pipeline) } - async fn build_network( + async fn build_network>( &self, config: &Config, task_executor: TaskExecutor, - provider_factory: ProviderFactory>, + provider_factory: ProviderFactory>>, network_secret_path: PathBuf, default_peers_path: PathBuf, ) -> eyre::Result { @@ -157,8 +156,12 @@ impl> Command { } /// Execute `execution-debug` command - pub async fn execute(self, ctx: CliContext) -> eyre::Result<()> { - let Environment { provider_factory, config, data_dir } = self.env.init(AccessRights::RW)?; + pub async fn execute>( + self, + ctx: CliContext, + ) -> eyre::Result<()> { + let Environment { provider_factory, config, data_dir } = + self.env.init::(AccessRights::RW)?; let consensus: Arc = Arc::new(EthBeaconConsensus::new(provider_factory.chain_spec())); diff --git a/bin/reth/src/commands/debug_cmd/in_memory_merkle.rs b/bin/reth/src/commands/debug_cmd/in_memory_merkle.rs index 6bbb78d7d..8c6b3f443 100644 --- a/bin/reth/src/commands/debug_cmd/in_memory_merkle.rs +++ b/bin/reth/src/commands/debug_cmd/in_memory_merkle.rs @@ -12,12 +12,12 @@ use reth_cli_commands::common::{AccessRights, Environment, EnvironmentArgs}; use reth_cli_runner::CliContext; use reth_cli_util::get_secret_key; use reth_config::Config; -use reth_db::DatabaseEnv; use reth_errors::BlockValidationError; use reth_evm::execute::{BlockExecutorProvider, Executor}; use reth_execution_types::ExecutionOutcome; use reth_network::{BlockDownloaderProvider, NetworkHandle}; use reth_network_api::NetworkInfo; +use reth_node_api::{NodeTypesWithDB, NodeTypesWithEngine}; use reth_node_ethereum::EthExecutorProvider; use reth_primitives::BlockHashOrNumber; use reth_provider::{ @@ -55,11 +55,11 @@ pub struct Command { } impl> Command { - async fn build_network( + async fn build_network>( &self, config: &Config, task_executor: TaskExecutor, - provider_factory: ProviderFactory>, + provider_factory: ProviderFactory, network_secret_path: PathBuf, default_peers_path: PathBuf, ) -> eyre::Result { @@ -77,8 +77,12 @@ impl> Command { } /// Execute `debug in-memory-merkle` command - pub async fn execute(self, ctx: CliContext) -> eyre::Result<()> { - let Environment { provider_factory, config, data_dir } = self.env.init(AccessRights::RW)?; + pub async fn execute>( + self, + ctx: CliContext, + ) -> eyre::Result<()> { + let Environment { provider_factory, config, data_dir } = + self.env.init::(AccessRights::RW)?; let provider = provider_factory.provider()?; diff --git a/bin/reth/src/commands/debug_cmd/merkle.rs b/bin/reth/src/commands/debug_cmd/merkle.rs index 1822a87ab..654d82cff 100644 --- a/bin/reth/src/commands/debug_cmd/merkle.rs +++ b/bin/reth/src/commands/debug_cmd/merkle.rs @@ -10,12 +10,13 @@ use reth_cli_runner::CliContext; use reth_cli_util::get_secret_key; use reth_config::Config; use reth_consensus::Consensus; -use reth_db::{tables, DatabaseEnv}; +use reth_db::tables; use reth_db_api::{cursor::DbCursorRO, transaction::DbTx}; use reth_evm::execute::{BatchExecutor, BlockExecutorProvider}; use reth_network::{BlockDownloaderProvider, NetworkHandle}; use reth_network_api::NetworkInfo; use reth_network_p2p::full_block::FullBlockClient; +use reth_node_api::{NodeTypesWithDB, NodeTypesWithEngine}; use reth_node_ethereum::EthExecutorProvider; use reth_primitives::BlockHashOrNumber; use reth_provider::{ @@ -54,11 +55,11 @@ pub struct Command { } impl> Command { - async fn build_network( + async fn build_network>( &self, config: &Config, task_executor: TaskExecutor, - provider_factory: ProviderFactory>, + provider_factory: ProviderFactory, network_secret_path: PathBuf, default_peers_path: PathBuf, ) -> eyre::Result { @@ -76,8 +77,12 @@ impl> Command { } /// Execute `merkle-debug` command - pub async fn execute(self, ctx: CliContext) -> eyre::Result<()> { - let Environment { provider_factory, config, data_dir } = self.env.init(AccessRights::RW)?; + pub async fn execute>( + self, + ctx: CliContext, + ) -> eyre::Result<()> { + let Environment { provider_factory, config, data_dir } = + self.env.init::(AccessRights::RW)?; let provider_rw = provider_factory.provider_rw()?; diff --git a/bin/reth/src/commands/debug_cmd/mod.rs b/bin/reth/src/commands/debug_cmd/mod.rs index b9c5f39ac..51681e8c5 100644 --- a/bin/reth/src/commands/debug_cmd/mod.rs +++ b/bin/reth/src/commands/debug_cmd/mod.rs @@ -4,6 +4,8 @@ use clap::{Parser, Subcommand}; use reth_chainspec::ChainSpec; use reth_cli::chainspec::ChainSpecParser; use reth_cli_runner::CliContext; +use reth_node_api::NodeTypesWithEngine; +use reth_node_ethereum::EthEngineTypes; mod build_block; mod execution; @@ -35,13 +37,18 @@ pub enum Subcommands { impl> Command { /// Execute `debug` command - pub async fn execute(self, ctx: CliContext) -> eyre::Result<()> { + pub async fn execute< + N: NodeTypesWithEngine, + >( + self, + ctx: CliContext, + ) -> eyre::Result<()> { match self.command { - Subcommands::Execution(command) => command.execute(ctx).await, - Subcommands::Merkle(command) => command.execute(ctx).await, - Subcommands::InMemoryMerkle(command) => command.execute(ctx).await, - Subcommands::BuildBlock(command) => command.execute(ctx).await, - Subcommands::ReplayEngine(command) => command.execute(ctx).await, + Subcommands::Execution(command) => command.execute::(ctx).await, + Subcommands::Merkle(command) => command.execute::(ctx).await, + Subcommands::InMemoryMerkle(command) => command.execute::(ctx).await, + Subcommands::BuildBlock(command) => command.execute::(ctx).await, + Subcommands::ReplayEngine(command) => command.execute::(ctx).await, } } } diff --git a/bin/reth/src/commands/debug_cmd/replay_engine.rs b/bin/reth/src/commands/debug_cmd/replay_engine.rs index 04d1c01b8..fa2cc18fe 100644 --- a/bin/reth/src/commands/debug_cmd/replay_engine.rs +++ b/bin/reth/src/commands/debug_cmd/replay_engine.rs @@ -18,7 +18,8 @@ use reth_engine_util::engine_store::{EngineMessageStore, StoredEngineApiMessage} use reth_fs_util as fs; use reth_network::{BlockDownloaderProvider, NetworkHandle}; use reth_network_api::NetworkInfo; -use reth_node_ethereum::EthExecutorProvider; +use reth_node_api::{NodeTypesWithDB, NodeTypesWithDBAdapter, NodeTypesWithEngine}; +use reth_node_ethereum::{EthEngineTypes, EthExecutorProvider}; use reth_payload_builder::{PayloadBuilderHandle, PayloadBuilderService}; use reth_provider::{ providers::BlockchainProvider, CanonStateSubscriptions, ChainSpecProvider, ProviderFactory, @@ -53,11 +54,11 @@ pub struct Command { } impl> Command { - async fn build_network( + async fn build_network>( &self, config: &Config, task_executor: TaskExecutor, - provider_factory: ProviderFactory>, + provider_factory: ProviderFactory, network_secret_path: PathBuf, default_peers_path: PathBuf, ) -> eyre::Result { @@ -75,8 +76,14 @@ impl> Command { } /// Execute `debug replay-engine` command - pub async fn execute(self, ctx: CliContext) -> eyre::Result<()> { - let Environment { provider_factory, config, data_dir } = self.env.init(AccessRights::RW)?; + pub async fn execute< + N: NodeTypesWithEngine, + >( + self, + ctx: CliContext, + ) -> eyre::Result<()> { + let Environment { provider_factory, config, data_dir } = + self.env.init::(AccessRights::RW)?; let consensus: Arc = Arc::new(EthBeaconConsensus::new(provider_factory.chain_spec())); @@ -121,10 +128,8 @@ impl> Command { payload_builder, ); - let (payload_service, payload_builder): ( - _, - PayloadBuilderHandle, - ) = PayloadBuilderService::new(payload_generator, blockchain_db.canonical_state_stream()); + let (payload_service, payload_builder): (_, PayloadBuilderHandle) = + PayloadBuilderService::new(payload_generator, blockchain_db.canonical_state_stream()); ctx.task_executor.spawn_critical("payload builder service", payload_service); @@ -132,7 +137,7 @@ impl> Command { let network_client = network.fetch_client().await?; let (beacon_consensus_engine, beacon_engine_handle) = BeaconConsensusEngine::new( network_client, - Pipeline::builder().build( + Pipeline::>>::builder().build( provider_factory.clone(), StaticFileProducer::new(provider_factory.clone(), PruneModes::none()), ), diff --git a/crates/blockchain-tree/Cargo.toml b/crates/blockchain-tree/Cargo.toml index 988bb54e8..aa44282ae 100644 --- a/crates/blockchain-tree/Cargo.toml +++ b/crates/blockchain-tree/Cargo.toml @@ -29,6 +29,7 @@ reth-trie-db = { workspace = true, features = ["metrics"] } reth-trie-parallel = { workspace = true, features = ["parallel"] } reth-network.workspace = true reth-consensus.workspace = true +reth-node-types.workspace = true # common parking_lot.workspace = true diff --git a/crates/blockchain-tree/src/blockchain_tree.rs b/crates/blockchain-tree/src/blockchain_tree.rs index 1da0d8023..a48d03a98 100644 --- a/crates/blockchain-tree/src/blockchain_tree.rs +++ b/crates/blockchain-tree/src/blockchain_tree.rs @@ -10,18 +10,19 @@ use reth_blockchain_tree_api::{ BlockAttachment, BlockStatus, BlockValidationKind, CanonicalOutcome, InsertPayloadOk, }; use reth_consensus::{Consensus, ConsensusError}; -use reth_db_api::database::Database; use reth_evm::execute::BlockExecutorProvider; use reth_execution_errors::{BlockExecutionError, BlockValidationError}; use reth_execution_types::{Chain, ExecutionOutcome}; +use reth_node_types::NodeTypesWithDB; use reth_primitives::{ BlockHash, BlockNumHash, BlockNumber, EthereumHardfork, ForkBlock, GotExpected, Receipt, SealedBlock, SealedBlockWithSenders, SealedHeader, StaticFileSegment, B256, U256, }; use reth_provider::{ - BlockExecutionWriter, BlockNumReader, BlockWriter, CanonStateNotification, - CanonStateNotificationSender, CanonStateNotifications, ChainSpecProvider, ChainSplit, - ChainSplitTarget, DisplayBlocksChain, HeaderProvider, ProviderError, StaticFileProviderFactory, + providers::ProviderNodeTypes, BlockExecutionWriter, BlockNumReader, BlockWriter, + CanonStateNotification, CanonStateNotificationSender, CanonStateNotifications, + ChainSpecProvider, ChainSplit, ChainSplitTarget, DisplayBlocksChain, HeaderProvider, + ProviderError, StaticFileProviderFactory, }; use reth_prune_types::PruneModes; use reth_stages_api::{MetricEvent, MetricEventsSender}; @@ -58,13 +59,13 @@ use tracing::{debug, error, info, instrument, trace, warn}; /// * [`BlockchainTree::make_canonical`]: Check if we have the hash of a block that is the current /// canonical head and commit it to db. #[derive(Debug)] -pub struct BlockchainTree { +pub struct BlockchainTree { /// The state of the tree /// /// Tracks all the chains, the block indices, and the block buffer. state: TreeState, /// External components (the database, consensus engine etc.) - externals: TreeExternals, + externals: TreeExternals, /// Tree configuration config: BlockchainTreeConfig, /// Broadcast channel for canon state changes notifications. @@ -75,7 +76,7 @@ pub struct BlockchainTree { metrics: TreeMetrics, } -impl BlockchainTree { +impl BlockchainTree { /// Subscribe to new blocks events. /// /// Note: Only canonical blocks are emitted by the tree. @@ -89,9 +90,9 @@ impl BlockchainTree { } } -impl BlockchainTree +impl BlockchainTree where - DB: Database + Clone, + N: ProviderNodeTypes, E: BlockExecutorProvider, { /// Builds the blockchain tree for the node. @@ -115,7 +116,7 @@ where /// storage space efficiently. It's important to validate this configuration to ensure it does /// not lead to unintended data loss. pub fn new( - mut externals: TreeExternals, + mut externals: TreeExternals, config: BlockchainTreeConfig, prune_modes: PruneModes, ) -> ProviderResult { @@ -1382,7 +1383,7 @@ mod tests { use linked_hash_set::LinkedHashSet; use reth_chainspec::{ChainSpecBuilder, MAINNET}; use reth_consensus::test_utils::TestConsensus; - use reth_db::{tables, test_utils::TempDatabase, DatabaseEnv}; + use reth_db::tables; use reth_db_api::transaction::DbTxMut; use reth_evm::test_utils::MockExecutorProvider; use reth_evm_ethereum::execute::EthExecutorProvider; @@ -1395,7 +1396,10 @@ mod tests { TransactionSignedEcRecovered, TxEip1559, Withdrawals, B256, }; use reth_provider::{ - test_utils::{blocks::BlockchainTestData, create_test_provider_factory_with_chain_spec}, + test_utils::{ + blocks::BlockchainTestData, create_test_provider_factory_with_chain_spec, + MockNodeTypesWithDB, + }, ProviderFactory, }; use reth_stages_api::StageCheckpoint; @@ -1404,7 +1408,7 @@ mod tests { fn setup_externals( exec_res: Vec, - ) -> TreeExternals>, MockExecutorProvider> { + ) -> TreeExternals { let chain_spec = Arc::new( ChainSpecBuilder::default() .chain(MAINNET.chain) @@ -1420,7 +1424,7 @@ mod tests { TreeExternals::new(provider_factory, consensus, executor_factory) } - fn setup_genesis(factory: &ProviderFactory, mut genesis: SealedBlock) { + fn setup_genesis(factory: &ProviderFactory, mut genesis: SealedBlock) { // insert genesis to db. genesis.header.set_block_number(10); @@ -1497,7 +1501,7 @@ mod tests { self } - fn assert(self, tree: &BlockchainTree) { + fn assert(self, tree: &BlockchainTree) { if let Some(chain_num) = self.chain_num { assert_eq!(tree.state.chains.len(), chain_num); } diff --git a/crates/blockchain-tree/src/chain.rs b/crates/blockchain-tree/src/chain.rs index b1cb6dbd4..df20a142a 100644 --- a/crates/blockchain-tree/src/chain.rs +++ b/crates/blockchain-tree/src/chain.rs @@ -10,7 +10,6 @@ use reth_blockchain_tree_api::{ BlockAttachment, BlockValidationKind, }; use reth_consensus::{Consensus, ConsensusError, PostExecutionInput}; -use reth_db_api::database::Database; use reth_evm::execute::{BlockExecutorProvider, Executor}; use reth_execution_errors::BlockExecutionError; use reth_execution_types::{Chain, ExecutionOutcome}; @@ -18,7 +17,7 @@ use reth_primitives::{ BlockHash, BlockNumber, ForkBlock, GotExpected, SealedBlockWithSenders, SealedHeader, U256, }; use reth_provider::{ - providers::{BundleStateProvider, ConsistentDbView}, + providers::{BundleStateProvider, ConsistentDbView, ProviderNodeTypes}, FullExecutionDataProvider, ProviderError, StateRootProvider, }; use reth_revm::database::StateProviderDatabase; @@ -66,17 +65,17 @@ impl AppendableChain { /// /// if [`BlockValidationKind::Exhaustive`] is specified, the method will verify the state root /// of the block. - pub fn new_canonical_fork( + pub fn new_canonical_fork( block: SealedBlockWithSenders, parent_header: &SealedHeader, canonical_block_hashes: &BTreeMap, canonical_fork: ForkBlock, - externals: &TreeExternals, + externals: &TreeExternals, block_attachment: BlockAttachment, block_validation_kind: BlockValidationKind, ) -> Result where - DB: Database + Clone, + N: ProviderNodeTypes, E: BlockExecutorProvider, { let execution_outcome = ExecutionOutcome::default(); @@ -104,17 +103,17 @@ impl AppendableChain { /// Create a new chain that forks off of an existing sidechain. /// /// This differs from [`AppendableChain::new_canonical_fork`] in that this starts a new fork. - pub(crate) fn new_chain_fork( + pub(crate) fn new_chain_fork( &self, block: SealedBlockWithSenders, side_chain_block_hashes: BTreeMap, canonical_block_hashes: &BTreeMap, canonical_fork: ForkBlock, - externals: &TreeExternals, + externals: &TreeExternals, block_validation_kind: BlockValidationKind, ) -> Result where - DB: Database + Clone, + N: ProviderNodeTypes, E: BlockExecutorProvider, { let parent_number = @@ -167,17 +166,17 @@ impl AppendableChain { /// - [`BlockAttachment`] represents if the block extends the canonical chain, and thus we can /// cache the trie state updates. /// - [`BlockValidationKind`] determines if the state root __should__ be validated. - fn validate_and_execute( + fn validate_and_execute( block: SealedBlockWithSenders, parent_block: &SealedHeader, bundle_state_data_provider: EDP, - externals: &TreeExternals, + externals: &TreeExternals, block_attachment: BlockAttachment, block_validation_kind: BlockValidationKind, ) -> Result<(ExecutionOutcome, Option), BlockExecutionError> where EDP: FullExecutionDataProvider, - DB: Database + Clone, + N: ProviderNodeTypes, E: BlockExecutorProvider, { // some checks are done before blocks comes here. @@ -271,18 +270,18 @@ impl AppendableChain { /// __not__ the canonical head. #[track_caller] #[allow(clippy::too_many_arguments)] - pub(crate) fn append_block( + pub(crate) fn append_block( &mut self, block: SealedBlockWithSenders, side_chain_block_hashes: BTreeMap, canonical_block_hashes: &BTreeMap, - externals: &TreeExternals, + externals: &TreeExternals, canonical_fork: ForkBlock, block_attachment: BlockAttachment, block_validation_kind: BlockValidationKind, ) -> Result<(), InsertBlockErrorKind> where - DB: Database + Clone, + N: ProviderNodeTypes, E: BlockExecutorProvider, { let parent_block = self.chain.tip(); diff --git a/crates/blockchain-tree/src/externals.rs b/crates/blockchain-tree/src/externals.rs index a903ae749..5991e5532 100644 --- a/crates/blockchain-tree/src/externals.rs +++ b/crates/blockchain-tree/src/externals.rs @@ -2,11 +2,12 @@ use reth_consensus::Consensus; use reth_db::{static_file::HeaderMask, tables}; -use reth_db_api::{cursor::DbCursorRO, database::Database, transaction::DbTx}; +use reth_db_api::{cursor::DbCursorRO, transaction::DbTx}; +use reth_node_types::NodeTypesWithDB; use reth_primitives::{BlockHash, BlockNumber, StaticFileSegment}; use reth_provider::{ - FinalizedBlockReader, FinalizedBlockWriter, ProviderFactory, StaticFileProviderFactory, - StatsReader, + providers::ProviderNodeTypes, FinalizedBlockReader, FinalizedBlockWriter, ProviderFactory, + StaticFileProviderFactory, StatsReader, }; use reth_storage_errors::provider::ProviderResult; use std::{collections::BTreeMap, sync::Arc}; @@ -21,19 +22,19 @@ use std::{collections::BTreeMap, sync::Arc}; /// - The executor factory to execute blocks with /// - The chain spec #[derive(Debug)] -pub struct TreeExternals { +pub struct TreeExternals { /// The provider factory, used to commit the canonical chain, or unwind it. - pub(crate) provider_factory: ProviderFactory, + pub(crate) provider_factory: ProviderFactory, /// The consensus engine. pub(crate) consensus: Arc, /// The executor factory to execute blocks with. pub(crate) executor_factory: E, } -impl TreeExternals { +impl TreeExternals { /// Create new tree externals. pub fn new( - provider_factory: ProviderFactory, + provider_factory: ProviderFactory, consensus: Arc, executor_factory: E, ) -> Self { @@ -41,7 +42,7 @@ impl TreeExternals { } } -impl TreeExternals { +impl TreeExternals { /// Fetches the latest canonical block hashes by walking backwards from the head. /// /// Returns the hashes sorted by increasing block numbers diff --git a/crates/blockchain-tree/src/shareable.rs b/crates/blockchain-tree/src/shareable.rs index 0f7903cf0..3cfabe1cd 100644 --- a/crates/blockchain-tree/src/shareable.rs +++ b/crates/blockchain-tree/src/shareable.rs @@ -7,15 +7,15 @@ use reth_blockchain_tree_api::{ BlockValidationKind, BlockchainTreeEngine, BlockchainTreeViewer, CanonicalOutcome, InsertPayloadOk, }; -use reth_db_api::database::Database; use reth_evm::execute::BlockExecutorProvider; +use reth_node_types::NodeTypesWithDB; use reth_primitives::{ BlockHash, BlockNumHash, BlockNumber, Receipt, SealedBlock, SealedBlockWithSenders, SealedHeader, }; use reth_provider::{ - BlockchainTreePendingStateProvider, CanonStateSubscriptions, FullExecutionDataProvider, - ProviderError, + providers::ProviderNodeTypes, BlockchainTreePendingStateProvider, CanonStateSubscriptions, + FullExecutionDataProvider, ProviderError, }; use reth_storage_errors::provider::ProviderResult; use std::{collections::BTreeMap, sync::Arc}; @@ -23,21 +23,21 @@ use tracing::trace; /// Shareable blockchain tree that is behind a `RwLock` #[derive(Clone, Debug)] -pub struct ShareableBlockchainTree { +pub struct ShareableBlockchainTree { /// `BlockchainTree` - pub tree: Arc>>, + pub tree: Arc>>, } -impl ShareableBlockchainTree { +impl ShareableBlockchainTree { /// Create a new shareable database. - pub fn new(tree: BlockchainTree) -> Self { + pub fn new(tree: BlockchainTree) -> Self { Self { tree: Arc::new(RwLock::new(tree)) } } } -impl BlockchainTreeEngine for ShareableBlockchainTree +impl BlockchainTreeEngine for ShareableBlockchainTree where - DB: Database + Clone, + N: ProviderNodeTypes, E: BlockExecutorProvider, { fn buffer_block(&self, block: SealedBlockWithSenders) -> Result<(), InsertBlockError> { @@ -106,9 +106,9 @@ where } } -impl BlockchainTreeViewer for ShareableBlockchainTree +impl BlockchainTreeViewer for ShareableBlockchainTree where - DB: Database + Clone, + N: ProviderNodeTypes, E: BlockExecutorProvider, { fn header_by_hash(&self, hash: BlockHash) -> Option { @@ -169,9 +169,9 @@ where } } -impl BlockchainTreePendingStateProvider for ShareableBlockchainTree +impl BlockchainTreePendingStateProvider for ShareableBlockchainTree where - DB: Database + Clone, + N: ProviderNodeTypes, E: BlockExecutorProvider, { fn find_pending_state_provider( @@ -184,9 +184,9 @@ where } } -impl CanonStateSubscriptions for ShareableBlockchainTree +impl CanonStateSubscriptions for ShareableBlockchainTree where - DB: Send + Sync, + N: ProviderNodeTypes, E: Send + Sync, { fn subscribe_to_canonical_state(&self) -> reth_provider::CanonStateNotifications { diff --git a/crates/chainspec/src/api.rs b/crates/chainspec/src/api.rs index f80dd702a..b8d260b59 100644 --- a/crates/chainspec/src/api.rs +++ b/crates/chainspec/src/api.rs @@ -1,8 +1,10 @@ +use core::fmt::Debug; + use crate::ChainSpec; use alloy_chains::Chain; /// Trait representing type configuring a chain spec. -pub trait EthChainSpec: Send + Sync + Unpin + 'static { +pub trait EthChainSpec: Send + Sync + Unpin + Debug + 'static { // todo: make chain spec type generic over hardfork //type Hardfork: Clone + Copy + 'static; diff --git a/crates/cli/commands/src/common.rs b/crates/cli/commands/src/common.rs index dad35938b..9470f2cfb 100644 --- a/crates/cli/commands/src/common.rs +++ b/crates/cli/commands/src/common.rs @@ -9,6 +9,7 @@ use reth_db::{init_db, open_db_read_only, DatabaseEnv}; use reth_db_common::init::init_genesis; use reth_downloaders::{bodies::noop::NoopBodiesDownloader, headers::noop::NoopHeaderDownloader}; use reth_evm::noop::NoopBlockExecutorProvider; +use reth_node_builder::{NodeTypesWithDBAdapter, NodeTypesWithEngine}; use reth_node_core::{ args::{DatabaseArgs, DatadirArgs}, dirs::{ChainPath, DataDirPath}, @@ -52,7 +53,10 @@ pub struct EnvironmentArgs { impl> EnvironmentArgs { /// Initializes environment according to [`AccessRights`] and returns an instance of /// [`Environment`]. - pub fn init(&self, access: AccessRights) -> eyre::Result { + pub fn init>( + &self, + access: AccessRights, + ) -> eyre::Result> { let data_dir = self.datadir.clone().resolve_datadir(self.chain.chain); let db_path = data_dir.db(); let sf_path = data_dir.static_files(); @@ -101,17 +105,21 @@ impl> EnvironmentArgs { /// If it's a read-write environment and an issue is found, it will attempt to heal (including a /// pipeline unwind). Otherwise, it will print out an warning, advising the user to restart the /// node to heal. - fn create_provider_factory( + fn create_provider_factory>( &self, config: &Config, db: Arc, static_file_provider: StaticFileProvider, - ) -> eyre::Result>> { + ) -> eyre::Result>>> { let has_receipt_pruning = config.prune.as_ref().map_or(false, |a| a.has_receipts_pruning()); let prune_modes = config.prune.as_ref().map(|prune| prune.segments.clone()).unwrap_or_default(); - let factory = ProviderFactory::new(db, self.chain.clone(), static_file_provider) - .with_prune_modes(prune_modes.clone()); + let factory = ProviderFactory::>>::new( + db, + self.chain.clone(), + static_file_provider, + ) + .with_prune_modes(prune_modes.clone()); // Check for consistency between database and static files. if let Some(unwind_target) = factory @@ -132,7 +140,7 @@ impl> EnvironmentArgs { let (_tip_tx, tip_rx) = watch::channel(B256::ZERO); // Builds and executes an unwind-only pipeline - let mut pipeline = Pipeline::builder() + let mut pipeline = Pipeline::>>::builder() .add_stages(DefaultStages::new( factory.clone(), tip_rx, @@ -156,11 +164,11 @@ impl> EnvironmentArgs { /// Environment built from [`EnvironmentArgs`]. #[derive(Debug)] -pub struct Environment { +pub struct Environment { /// Configuration for reth node pub config: Config, /// Provider factory. - pub provider_factory: ProviderFactory>, + pub provider_factory: ProviderFactory>>, /// Datadir path. pub data_dir: ChainPath, } diff --git a/crates/cli/commands/src/db/checksum.rs b/crates/cli/commands/src/db/checksum.rs index abc183da4..7aeed6dfe 100644 --- a/crates/cli/commands/src/db/checksum.rs +++ b/crates/cli/commands/src/db/checksum.rs @@ -1,9 +1,11 @@ use crate::db::get::{maybe_json_value_parser, table_key}; use ahash::RandomState; use clap::Parser; +use reth_chainspec::ChainSpec; use reth_db::{DatabaseEnv, RawKey, RawTable, RawValue, TableViewer, Tables}; -use reth_db_api::{cursor::DbCursorRO, database::Database, table::Table, transaction::DbTx}; +use reth_db_api::{cursor::DbCursorRO, table::Table, transaction::DbTx}; use reth_db_common::DbTool; +use reth_node_builder::{NodeTypesWithDB, NodeTypesWithDBAdapter, NodeTypesWithEngine}; use std::{ hash::{BuildHasher, Hasher}, sync::Arc, @@ -33,7 +35,10 @@ pub struct Command { impl Command { /// Execute `db checksum` command - pub fn execute(self, tool: &DbTool>) -> eyre::Result<()> { + pub fn execute>( + self, + tool: &DbTool>>, + ) -> eyre::Result<()> { warn!("This command should be run without the node running!"); self.table.view(&ChecksumViewer { tool, @@ -45,20 +50,22 @@ impl Command { } } -pub(crate) struct ChecksumViewer<'a, DB: Database> { - tool: &'a DbTool, +pub(crate) struct ChecksumViewer<'a, N: NodeTypesWithDB> { + tool: &'a DbTool, start_key: Option, end_key: Option, limit: Option, } -impl ChecksumViewer<'_, DB> { - pub(crate) const fn new(tool: &'_ DbTool) -> ChecksumViewer<'_, DB> { +impl ChecksumViewer<'_, N> { + pub(crate) const fn new(tool: &'_ DbTool) -> ChecksumViewer<'_, N> { ChecksumViewer { tool, start_key: None, end_key: None, limit: None } } } -impl TableViewer<(u64, Duration)> for ChecksumViewer<'_, DB> { +impl> TableViewer<(u64, Duration)> + for ChecksumViewer<'_, N> +{ type Error = eyre::Report; fn view(&self) -> Result<(u64, Duration), Self::Error> { diff --git a/crates/cli/commands/src/db/clear.rs b/crates/cli/commands/src/db/clear.rs index b9edf458d..de92c7dca 100644 --- a/crates/cli/commands/src/db/clear.rs +++ b/crates/cli/commands/src/db/clear.rs @@ -5,6 +5,7 @@ use reth_db_api::{ table::Table, transaction::{DbTx, DbTxMut}, }; +use reth_node_builder::NodeTypesWithDB; use reth_provider::{ProviderFactory, StaticFileProviderFactory}; use reth_static_file_types::{find_fixed_range, StaticFileSegment}; @@ -17,7 +18,10 @@ pub struct Command { impl Command { /// Execute `db clear` command - pub fn execute(self, provider_factory: ProviderFactory) -> eyre::Result<()> { + pub fn execute( + self, + provider_factory: ProviderFactory, + ) -> eyre::Result<()> { match self.subcommand { Subcommands::Mdbx { table } => { table.view(&ClearViewer { db: provider_factory.db_ref() })? diff --git a/crates/cli/commands/src/db/diff.rs b/crates/cli/commands/src/db/diff.rs index e025c4648..0b7b77907 100644 --- a/crates/cli/commands/src/db/diff.rs +++ b/crates/cli/commands/src/db/diff.rs @@ -2,6 +2,7 @@ use clap::Parser; use reth_db::{open_db_read_only, tables_to_generic, DatabaseEnv, Tables}; use reth_db_api::{cursor::DbCursorRO, database::Database, table::Table, transaction::DbTx}; use reth_db_common::DbTool; +use reth_node_builder::{NodeTypesWithDBAdapter, NodeTypesWithEngine}; use reth_node_core::{ args::DatabaseArgs, dirs::{DataDirPath, PlatformPath}, @@ -51,7 +52,10 @@ impl Command { /// /// The discrepancies and extra elements, along with a brief summary of the diff results are /// then written to a file in the output directory. - pub fn execute(self, tool: &DbTool>) -> eyre::Result<()> { + pub fn execute( + self, + tool: &DbTool>>, + ) -> eyre::Result<()> { warn!("Make sure the node is not running when running `reth db diff`!"); // open second db let second_db_path: PathBuf = self.secondary_datadir.join("db").into(); diff --git a/crates/cli/commands/src/db/get.rs b/crates/cli/commands/src/db/get.rs index cd721a1db..60faea012 100644 --- a/crates/cli/commands/src/db/get.rs +++ b/crates/cli/commands/src/db/get.rs @@ -1,13 +1,12 @@ use clap::Parser; +use reth_chainspec::ChainSpec; use reth_db::{ static_file::{ColumnSelectorOne, ColumnSelectorTwo, HeaderMask, ReceiptMask, TransactionMask}, tables, RawKey, RawTable, Receipts, TableViewer, Transactions, }; -use reth_db_api::{ - database::Database, - table::{Decompress, DupSort, Table}, -}; +use reth_db_api::table::{Decompress, DupSort, Table}; use reth_db_common::DbTool; +use reth_node_builder::NodeTypesWithDB; use reth_primitives::{BlockHash, Header}; use reth_provider::StaticFileProviderFactory; use reth_static_file_types::StaticFileSegment; @@ -54,7 +53,10 @@ enum Subcommand { impl Command { /// Execute `db get` command - pub fn execute(self, tool: &DbTool) -> eyre::Result<()> { + pub fn execute>( + self, + tool: &DbTool, + ) -> eyre::Result<()> { match self.subcommand { Subcommand::Mdbx { table, key, subkey, raw } => { table.view(&GetValueViewer { tool, key, subkey, raw })? @@ -138,14 +140,14 @@ fn table_subkey(subkey: &Option) -> Result { - tool: &'a DbTool, +struct GetValueViewer<'a, N: NodeTypesWithDB> { + tool: &'a DbTool, key: String, subkey: Option, raw: bool, } -impl TableViewer<()> for GetValueViewer<'_, DB> { +impl> TableViewer<()> for GetValueViewer<'_, N> { type Error = eyre::Report; fn view(&self) -> Result<(), Self::Error> { diff --git a/crates/cli/commands/src/db/list.rs b/crates/cli/commands/src/db/list.rs index ed337bdcf..4fcc6f3b6 100644 --- a/crates/cli/commands/src/db/list.rs +++ b/crates/cli/commands/src/db/list.rs @@ -1,9 +1,11 @@ use super::tui::DbListTUI; use clap::Parser; use eyre::WrapErr; +use reth_chainspec::ChainSpec; use reth_db::{DatabaseEnv, RawValue, TableViewer, Tables}; use reth_db_api::{database::Database, table::Table}; use reth_db_common::{DbTool, ListFilter}; +use reth_node_builder::{NodeTypesWithDBAdapter, NodeTypesWithEngine}; use reth_primitives::hex; use std::{cell::RefCell, sync::Arc}; use tracing::error; @@ -51,7 +53,10 @@ pub struct Command { impl Command { /// Execute `db list` command - pub fn execute(self, tool: &DbTool>) -> eyre::Result<()> { + pub fn execute>( + self, + tool: &DbTool>>, + ) -> eyre::Result<()> { self.table.view(&ListTableViewer { tool, args: &self }) } @@ -81,12 +86,12 @@ impl Command { } } -struct ListTableViewer<'a> { - tool: &'a DbTool>, +struct ListTableViewer<'a, N: NodeTypesWithEngine> { + tool: &'a DbTool>>, args: &'a Command, } -impl TableViewer<()> for ListTableViewer<'_> { +impl TableViewer<()> for ListTableViewer<'_, N> { type Error = eyre::Report; fn view(&self) -> Result<(), Self::Error> { diff --git a/crates/cli/commands/src/db/mod.rs b/crates/cli/commands/src/db/mod.rs index ab388b6e5..6d4825610 100644 --- a/crates/cli/commands/src/db/mod.rs +++ b/crates/cli/commands/src/db/mod.rs @@ -4,6 +4,7 @@ use reth_chainspec::ChainSpec; use reth_cli::chainspec::ChainSpecParser; use reth_db::version::{get_db_version, DatabaseVersionError, DB_VERSION}; use reth_db_common::DbTool; +use reth_node_builder::NodeTypesWithEngine; use std::io::{self, Write}; mod checksum; @@ -54,8 +55,8 @@ pub enum Subcommands { /// `db_ro_exec` opens a database in read-only mode, and then execute with the provided command macro_rules! db_ro_exec { - ($env:expr, $tool:ident, $command:block) => { - let Environment { provider_factory, .. } = $env.init(AccessRights::RO)?; + ($env:expr, $tool:ident, $N:ident, $command:block) => { + let Environment { provider_factory, .. } = $env.init::<$N>(AccessRights::RO)?; let $tool = DbTool::new(provider_factory.clone())?; $command; @@ -64,7 +65,9 @@ macro_rules! db_ro_exec { impl> Command { /// Execute `db` command - pub async fn execute(self) -> eyre::Result<()> { + pub async fn execute>( + self, + ) -> eyre::Result<()> { let data_dir = self.env.datadir.clone().resolve_datadir(self.env.chain.chain); let db_path = data_dir.db(); let static_files_path = data_dir.static_files(); @@ -82,27 +85,27 @@ impl> Command { match self.command { // TODO: We'll need to add this on the DB trait. Subcommands::Stats(command) => { - db_ro_exec!(self.env, tool, { + db_ro_exec!(self.env, tool, N, { command.execute(data_dir, &tool)?; }); } Subcommands::List(command) => { - db_ro_exec!(self.env, tool, { + db_ro_exec!(self.env, tool, N, { command.execute(&tool)?; }); } Subcommands::Checksum(command) => { - db_ro_exec!(self.env, tool, { + db_ro_exec!(self.env, tool, N, { command.execute(&tool)?; }); } Subcommands::Diff(command) => { - db_ro_exec!(self.env, tool, { + db_ro_exec!(self.env, tool, N, { command.execute(&tool)?; }); } Subcommands::Get(command) => { - db_ro_exec!(self.env, tool, { + db_ro_exec!(self.env, tool, N, { command.execute(&tool)?; }); } @@ -122,12 +125,12 @@ impl> Command { } } - let Environment { provider_factory, .. } = self.env.init(AccessRights::RW)?; + let Environment { provider_factory, .. } = self.env.init::(AccessRights::RW)?; let tool = DbTool::new(provider_factory)?; tool.drop(db_path, static_files_path)?; } Subcommands::Clear(command) => { - let Environment { provider_factory, .. } = self.env.init(AccessRights::RW)?; + let Environment { provider_factory, .. } = self.env.init::(AccessRights::RW)?; command.execute(provider_factory)?; } Subcommands::Version => { diff --git a/crates/cli/commands/src/db/stats.rs b/crates/cli/commands/src/db/stats.rs index 37f7d617b..1db42b87e 100644 --- a/crates/cli/commands/src/db/stats.rs +++ b/crates/cli/commands/src/db/stats.rs @@ -4,10 +4,12 @@ use comfy_table::{Cell, Row, Table as ComfyTable}; use eyre::WrapErr; use human_bytes::human_bytes; use itertools::Itertools; +use reth_chainspec::ChainSpec; use reth_db::{mdbx, static_file::iter_static_files, DatabaseEnv, TableViewer, Tables}; use reth_db_api::database::Database; use reth_db_common::DbTool; use reth_fs_util as fs; +use reth_node_builder::{NodeTypesWithDB, NodeTypesWithDBAdapter, NodeTypesWithEngine}; use reth_node_core::dirs::{ChainPath, DataDirPath}; use reth_provider::providers::StaticFileProvider; use reth_static_file_types::{find_fixed_range, SegmentRangeInclusive}; @@ -36,10 +38,10 @@ pub struct Command { impl Command { /// Execute `db stats` command - pub fn execute( + pub fn execute>( self, data_dir: ChainPath, - tool: &DbTool>, + tool: &DbTool>>, ) -> eyre::Result<()> { if self.checksum { let checksum_report = self.checksum_report(tool)?; @@ -58,7 +60,10 @@ impl Command { Ok(()) } - fn db_stats_table(&self, tool: &DbTool>) -> eyre::Result { + fn db_stats_table>>( + &self, + tool: &DbTool, + ) -> eyre::Result { let mut table = ComfyTable::new(); table.load_preset(comfy_table::presets::ASCII_MARKDOWN); table.set_header([ @@ -306,7 +311,10 @@ impl Command { Ok(table) } - fn checksum_report(&self, tool: &DbTool>) -> eyre::Result { + fn checksum_report>( + &self, + tool: &DbTool, + ) -> eyre::Result { let mut table = ComfyTable::new(); table.load_preset(comfy_table::presets::ASCII_MARKDOWN); table.set_header(vec![Cell::new("Table"), Cell::new("Checksum"), Cell::new("Elapsed")]); diff --git a/crates/cli/commands/src/import.rs b/crates/cli/commands/src/import.rs index ce8b1a627..b5fbee332 100644 --- a/crates/cli/commands/src/import.rs +++ b/crates/cli/commands/src/import.rs @@ -8,7 +8,7 @@ use reth_cli::chainspec::ChainSpecParser; use reth_config::Config; use reth_consensus::Consensus; use reth_db::tables; -use reth_db_api::{database::Database, transaction::DbTx}; +use reth_db_api::transaction::DbTx; use reth_downloaders::{ bodies::bodies::BodiesDownloaderBuilder, file_client::{ChunkedFileReader, FileClient, DEFAULT_BYTE_LEN_CHUNK_CHAIN_FILE}, @@ -19,6 +19,7 @@ use reth_network_p2p::{ bodies::downloader::BodyDownloader, headers::downloader::{HeaderDownloader, SyncTarget}, }; +use reth_node_builder::{NodeTypesWithDB, NodeTypesWithEngine}; use reth_node_core::version::SHORT_VERSION; use reth_node_events::node::NodeEvent; use reth_primitives::B256; @@ -57,10 +58,11 @@ pub struct ImportCommand { impl> ImportCommand { /// Execute `import` command - pub async fn execute(self, executor: F) -> eyre::Result<()> + pub async fn execute(self, executor: F) -> eyre::Result<()> where + N: NodeTypesWithEngine, E: BlockExecutorProvider, - F: FnOnce(Arc) -> E, + F: FnOnce(Arc) -> E, { info!(target: "reth::cli", "reth {} starting", SHORT_VERSION); @@ -73,7 +75,7 @@ impl> ImportCommand { "Chunking chain import" ); - let Environment { provider_factory, config, .. } = self.env.init(AccessRights::RW)?; + let Environment { provider_factory, config, .. } = self.env.init::(AccessRights::RW)?; let executor = executor(provider_factory.chain_spec()); let consensus = Arc::new(EthBeaconConsensus::new(self.env.chain.clone())); @@ -156,17 +158,17 @@ impl> ImportCommand { /// /// If configured to execute, all stages will run. Otherwise, only stages that don't require state /// will run. -pub fn build_import_pipeline( +pub fn build_import_pipeline( config: &Config, - provider_factory: ProviderFactory, + provider_factory: ProviderFactory, consensus: &Arc, file_client: Arc, - static_file_producer: StaticFileProducer, + static_file_producer: StaticFileProducer, disable_exec: bool, executor: E, -) -> eyre::Result<(Pipeline, impl Stream)> +) -> eyre::Result<(Pipeline, impl Stream)> where - DB: Database + Clone + Unpin + 'static, + N: NodeTypesWithDB, C: Consensus + 'static, E: BlockExecutorProvider, { @@ -201,7 +203,7 @@ where let max_block = file_client.max_block().unwrap_or(0); - let pipeline = Pipeline::builder() + let pipeline = Pipeline::::builder() .with_tip_sender(tip_tx) // we want to sync all blocks the file client provides or 0 if empty .with_max_block(max_block) diff --git a/crates/cli/commands/src/init_cmd.rs b/crates/cli/commands/src/init_cmd.rs index 525cb046f..63a8827eb 100644 --- a/crates/cli/commands/src/init_cmd.rs +++ b/crates/cli/commands/src/init_cmd.rs @@ -4,6 +4,7 @@ use crate::common::{AccessRights, Environment, EnvironmentArgs}; use clap::Parser; use reth_chainspec::ChainSpec; use reth_cli::chainspec::ChainSpecParser; +use reth_node_builder::NodeTypesWithEngine; use reth_provider::BlockHashReader; use tracing::info; @@ -16,10 +17,12 @@ pub struct InitCommand { impl> InitCommand { /// Execute the `init` command - pub async fn execute(self) -> eyre::Result<()> { + pub async fn execute>( + self, + ) -> eyre::Result<()> { info!(target: "reth::cli", "reth init starting"); - let Environment { provider_factory, .. } = self.env.init(AccessRights::RW)?; + let Environment { provider_factory, .. } = self.env.init::(AccessRights::RW)?; let hash = provider_factory .block_hash(0)? diff --git a/crates/cli/commands/src/init_state.rs b/crates/cli/commands/src/init_state.rs index c6765e77a..7c04b002c 100644 --- a/crates/cli/commands/src/init_state.rs +++ b/crates/cli/commands/src/init_state.rs @@ -5,8 +5,8 @@ use clap::Parser; use reth_chainspec::ChainSpec; use reth_cli::chainspec::ChainSpecParser; use reth_config::config::EtlConfig; -use reth_db_api::database::Database; use reth_db_common::init::init_from_state_dump; +use reth_node_builder::{NodeTypesWithDB, NodeTypesWithEngine}; use reth_primitives::B256; use reth_provider::ProviderFactory; @@ -42,10 +42,12 @@ pub struct InitStateCommand { impl> InitStateCommand { /// Execute the `init` command - pub async fn execute(self) -> eyre::Result<()> { + pub async fn execute>( + self, + ) -> eyre::Result<()> { info!(target: "reth::cli", "Reth init-state starting"); - let Environment { config, provider_factory, .. } = self.env.init(AccessRights::RW)?; + let Environment { config, provider_factory, .. } = self.env.init::(AccessRights::RW)?; info!(target: "reth::cli", "Initiating state dump"); @@ -57,9 +59,9 @@ impl> InitStateCommand { } /// Initialize chain with state at specific block, from a file with state dump. -pub fn init_at_state( +pub fn init_at_state>( state_dump_path: PathBuf, - factory: ProviderFactory, + factory: ProviderFactory, etl_config: EtlConfig, ) -> eyre::Result { info!(target: "reth::cli", diff --git a/crates/cli/commands/src/prune.rs b/crates/cli/commands/src/prune.rs index 2e6c0bc44..d19247e21 100644 --- a/crates/cli/commands/src/prune.rs +++ b/crates/cli/commands/src/prune.rs @@ -3,6 +3,7 @@ use crate::common::{AccessRights, Environment, EnvironmentArgs}; use clap::Parser; use reth_chainspec::ChainSpec; use reth_cli::chainspec::ChainSpecParser; +use reth_node_builder::NodeTypesWithEngine; use reth_prune::PrunerBuilder; use reth_static_file::StaticFileProducer; use tracing::info; @@ -16,8 +17,10 @@ pub struct PruneCommand { impl> PruneCommand { /// Execute the `prune` command - pub async fn execute(self) -> eyre::Result<()> { - let Environment { config, provider_factory, .. } = self.env.init(AccessRights::RW)?; + pub async fn execute>( + self, + ) -> eyre::Result<()> { + let Environment { config, provider_factory, .. } = self.env.init::(AccessRights::RW)?; let prune_config = config.prune.unwrap_or_default(); // Copy data from database to static files diff --git a/crates/cli/commands/src/recover/mod.rs b/crates/cli/commands/src/recover/mod.rs index 613bc5f23..9bf818174 100644 --- a/crates/cli/commands/src/recover/mod.rs +++ b/crates/cli/commands/src/recover/mod.rs @@ -4,6 +4,7 @@ use clap::{Parser, Subcommand}; use reth_chainspec::ChainSpec; use reth_cli::chainspec::ChainSpecParser; use reth_cli_runner::CliContext; +use reth_node_builder::NodeTypesWithEngine; mod storage_tries; @@ -23,9 +24,12 @@ pub enum Subcommands { impl> Command { /// Execute `recover` command - pub async fn execute(self, ctx: CliContext) -> eyre::Result<()> { + pub async fn execute>( + self, + ctx: CliContext, + ) -> eyre::Result<()> { match self.command { - Subcommands::StorageTries(command) => command.execute(ctx).await, + Subcommands::StorageTries(command) => command.execute::(ctx).await, } } } diff --git a/crates/cli/commands/src/recover/storage_tries.rs b/crates/cli/commands/src/recover/storage_tries.rs index c6ac277dd..65cb741f3 100644 --- a/crates/cli/commands/src/recover/storage_tries.rs +++ b/crates/cli/commands/src/recover/storage_tries.rs @@ -8,6 +8,7 @@ use reth_db_api::{ cursor::{DbCursorRO, DbDupCursorRW}, transaction::DbTx, }; +use reth_node_builder::NodeTypesWithEngine; use reth_provider::{BlockNumReader, HeaderProvider, ProviderError}; use reth_trie::StateRoot; use reth_trie_db::DatabaseStateRoot; @@ -22,8 +23,11 @@ pub struct Command { impl> Command { /// Execute `storage-tries` recovery command - pub async fn execute(self, _ctx: CliContext) -> eyre::Result<()> { - let Environment { provider_factory, .. } = self.env.init(AccessRights::RW)?; + pub async fn execute>( + self, + _ctx: CliContext, + ) -> eyre::Result<()> { + let Environment { provider_factory, .. } = self.env.init::(AccessRights::RW)?; let mut provider = provider_factory.provider_rw()?; let best_block = provider.best_block_number()?; diff --git a/crates/cli/commands/src/stage/drop.rs b/crates/cli/commands/src/stage/drop.rs index f7558ada7..ce1791506 100644 --- a/crates/cli/commands/src/stage/drop.rs +++ b/crates/cli/commands/src/stage/drop.rs @@ -10,6 +10,7 @@ use reth_db_common::{ init::{insert_genesis_header, insert_genesis_history, insert_genesis_state}, DbTool, }; +use reth_node_builder::NodeTypesWithEngine; use reth_node_core::args::StageEnum; use reth_provider::{writer::UnifiedStorageWriter, StaticFileProviderFactory}; use reth_stages::StageId; @@ -26,8 +27,10 @@ pub struct Command { impl> Command { /// Execute `db` command - pub async fn execute(self) -> eyre::Result<()> { - let Environment { provider_factory, .. } = self.env.init(AccessRights::RW)?; + pub async fn execute>( + self, + ) -> eyre::Result<()> { + let Environment { provider_factory, .. } = self.env.init::(AccessRights::RW)?; let static_file_provider = provider_factory.static_file_provider(); diff --git a/crates/cli/commands/src/stage/dump/execution.rs b/crates/cli/commands/src/stage/dump/execution.rs index 61fc5e41c..dfc320f15 100644 --- a/crates/cli/commands/src/stage/dump/execution.rs +++ b/crates/cli/commands/src/stage/dump/execution.rs @@ -1,17 +1,21 @@ +use std::sync::Arc; + use super::setup; +use reth_chainspec::ChainSpec; use reth_db::{tables, DatabaseEnv}; use reth_db_api::{ cursor::DbCursorRO, database::Database, table::TableImporter, transaction::DbTx, }; use reth_db_common::DbTool; use reth_evm::{execute::BlockExecutorProvider, noop::NoopBlockExecutorProvider}; +use reth_node_builder::{NodeTypesWithDB, NodeTypesWithDBAdapter}; use reth_node_core::dirs::{ChainPath, DataDirPath}; use reth_provider::{providers::StaticFileProvider, ProviderFactory}; use reth_stages::{stages::ExecutionStage, Stage, StageCheckpoint, UnwindInput}; use tracing::info; -pub(crate) async fn dump_execution_stage( - db_tool: &DbTool, +pub(crate) async fn dump_execution_stage( + db_tool: &DbTool, from: u64, to: u64, output_datadir: ChainPath, @@ -19,7 +23,7 @@ pub(crate) async fn dump_execution_stage( executor: E, ) -> eyre::Result<()> where - DB: Database, + N: NodeTypesWithDB, E: BlockExecutorProvider, { let (output_db, tip_block_number) = setup(from, to, &output_datadir.db(), db_tool)?; @@ -30,8 +34,8 @@ where if should_run { dry_run( - ProviderFactory::new( - output_db, + ProviderFactory::>>::new( + Arc::new(output_db), db_tool.chain(), StaticFileProvider::read_write(output_datadir.static_files())?, ), @@ -45,9 +49,9 @@ where } /// Imports all the tables that can be copied over a range. -fn import_tables_with_range( +fn import_tables_with_range( output_db: &DatabaseEnv, - db_tool: &DbTool, + db_tool: &DbTool, from: u64, to: u64, ) -> eyre::Result<()> { @@ -125,8 +129,8 @@ fn import_tables_with_range( /// Dry-run an unwind to FROM block, so we can get the `PlainStorageState` and /// `PlainAccountState` safely. There might be some state dependency from an address /// which hasn't been changed in the given range. -fn unwind_and_copy( - db_tool: &DbTool, +fn unwind_and_copy>( + db_tool: &DbTool, from: u64, tip_block_number: u64, output_db: &DatabaseEnv, @@ -155,14 +159,14 @@ fn unwind_and_copy( } /// Try to re-execute the stage without committing -fn dry_run( - output_provider_factory: ProviderFactory, +fn dry_run( + output_provider_factory: ProviderFactory, to: u64, from: u64, executor: E, ) -> eyre::Result<()> where - DB: Database, + N: NodeTypesWithDB, E: BlockExecutorProvider, { info!(target: "reth::cli", "Executing stage. [dry-run]"); diff --git a/crates/cli/commands/src/stage/dump/hashing_account.rs b/crates/cli/commands/src/stage/dump/hashing_account.rs index 025899231..b40c7a9d3 100644 --- a/crates/cli/commands/src/stage/dump/hashing_account.rs +++ b/crates/cli/commands/src/stage/dump/hashing_account.rs @@ -1,16 +1,20 @@ +use std::sync::Arc; + use super::setup; use eyre::Result; +use reth_chainspec::ChainSpec; use reth_db::{tables, DatabaseEnv}; use reth_db_api::{database::Database, table::TableImporter}; use reth_db_common::DbTool; +use reth_node_builder::{NodeTypesWithDB, NodeTypesWithDBAdapter}; use reth_node_core::dirs::{ChainPath, DataDirPath}; use reth_primitives::BlockNumber; use reth_provider::{providers::StaticFileProvider, ProviderFactory}; use reth_stages::{stages::AccountHashingStage, Stage, StageCheckpoint, UnwindInput}; use tracing::info; -pub(crate) async fn dump_hashing_account_stage( - db_tool: &DbTool, +pub(crate) async fn dump_hashing_account_stage>( + db_tool: &DbTool, from: BlockNumber, to: BlockNumber, output_datadir: ChainPath, @@ -31,8 +35,8 @@ pub(crate) async fn dump_hashing_account_stage( if should_run { dry_run( - ProviderFactory::new( - output_db, + ProviderFactory::>>::new( + Arc::new(output_db), db_tool.chain(), StaticFileProvider::read_write(output_datadir.static_files())?, ), @@ -45,8 +49,8 @@ pub(crate) async fn dump_hashing_account_stage( } /// Dry-run an unwind to FROM block and copy the necessary table data to the new database. -fn unwind_and_copy( - db_tool: &DbTool, +fn unwind_and_copy>( + db_tool: &DbTool, from: u64, tip_block_number: u64, output_db: &DatabaseEnv, @@ -70,8 +74,8 @@ fn unwind_and_copy( } /// Try to re-execute the stage straight away -fn dry_run( - output_provider_factory: ProviderFactory, +fn dry_run>( + output_provider_factory: ProviderFactory, to: u64, from: u64, ) -> eyre::Result<()> { diff --git a/crates/cli/commands/src/stage/dump/hashing_storage.rs b/crates/cli/commands/src/stage/dump/hashing_storage.rs index ad6298887..57f0ed53a 100644 --- a/crates/cli/commands/src/stage/dump/hashing_storage.rs +++ b/crates/cli/commands/src/stage/dump/hashing_storage.rs @@ -1,15 +1,19 @@ +use std::sync::Arc; + use super::setup; use eyre::Result; +use reth_chainspec::ChainSpec; use reth_db::{tables, DatabaseEnv}; use reth_db_api::{database::Database, table::TableImporter}; use reth_db_common::DbTool; +use reth_node_builder::{NodeTypesWithDB, NodeTypesWithDBAdapter}; use reth_node_core::dirs::{ChainPath, DataDirPath}; use reth_provider::{providers::StaticFileProvider, ProviderFactory}; use reth_stages::{stages::StorageHashingStage, Stage, StageCheckpoint, UnwindInput}; use tracing::info; -pub(crate) async fn dump_hashing_storage_stage( - db_tool: &DbTool, +pub(crate) async fn dump_hashing_storage_stage>( + db_tool: &DbTool, from: u64, to: u64, output_datadir: ChainPath, @@ -21,8 +25,8 @@ pub(crate) async fn dump_hashing_storage_stage( if should_run { dry_run( - ProviderFactory::new( - output_db, + ProviderFactory::>>::new( + Arc::new(output_db), db_tool.chain(), StaticFileProvider::read_write(output_datadir.static_files())?, ), @@ -35,8 +39,8 @@ pub(crate) async fn dump_hashing_storage_stage( } /// Dry-run an unwind to FROM block and copy the necessary table data to the new database. -fn unwind_and_copy( - db_tool: &DbTool, +fn unwind_and_copy>( + db_tool: &DbTool, from: u64, tip_block_number: u64, output_db: &DatabaseEnv, @@ -65,8 +69,8 @@ fn unwind_and_copy( } /// Try to re-execute the stage straight away -fn dry_run( - output_provider_factory: ProviderFactory, +fn dry_run>( + output_provider_factory: ProviderFactory, to: u64, from: u64, ) -> eyre::Result<()> { diff --git a/crates/cli/commands/src/stage/dump/merkle.rs b/crates/cli/commands/src/stage/dump/merkle.rs index 2d13c1515..3e6580c98 100644 --- a/crates/cli/commands/src/stage/dump/merkle.rs +++ b/crates/cli/commands/src/stage/dump/merkle.rs @@ -1,11 +1,15 @@ +use std::sync::Arc; + use super::setup; use eyre::Result; +use reth_chainspec::ChainSpec; use reth_config::config::EtlConfig; use reth_db::{tables, DatabaseEnv}; use reth_db_api::{database::Database, table::TableImporter}; use reth_db_common::DbTool; use reth_evm::noop::NoopBlockExecutorProvider; use reth_exex::ExExManagerHandle; +use reth_node_builder::{NodeTypesWithDB, NodeTypesWithDBAdapter}; use reth_node_core::dirs::{ChainPath, DataDirPath}; use reth_primitives::BlockNumber; use reth_provider::{providers::StaticFileProvider, ProviderFactory}; @@ -19,8 +23,8 @@ use reth_stages::{ }; use tracing::info; -pub(crate) async fn dump_merkle_stage( - db_tool: &DbTool, +pub(crate) async fn dump_merkle_stage>( + db_tool: &DbTool, from: BlockNumber, to: BlockNumber, output_datadir: ChainPath, @@ -48,8 +52,8 @@ pub(crate) async fn dump_merkle_stage( if should_run { dry_run( - ProviderFactory::new( - output_db, + ProviderFactory::>>::new( + Arc::new(output_db), db_tool.chain(), StaticFileProvider::read_write(output_datadir.static_files())?, ), @@ -62,8 +66,8 @@ pub(crate) async fn dump_merkle_stage( } /// Dry-run an unwind to FROM block and copy the necessary table data to the new database. -fn unwind_and_copy( - db_tool: &DbTool, +fn unwind_and_copy>( + db_tool: &DbTool, range: (u64, u64), tip_block_number: u64, output_db: &DatabaseEnv, @@ -140,8 +144,8 @@ fn unwind_and_copy( } /// Try to re-execute the stage straight away -fn dry_run( - output_provider_factory: ProviderFactory, +fn dry_run>( + output_provider_factory: ProviderFactory, to: u64, from: u64, ) -> eyre::Result<()> { diff --git a/crates/cli/commands/src/stage/dump/mod.rs b/crates/cli/commands/src/stage/dump/mod.rs index 1ead604c4..44161d9b3 100644 --- a/crates/cli/commands/src/stage/dump/mod.rs +++ b/crates/cli/commands/src/stage/dump/mod.rs @@ -10,6 +10,7 @@ use reth_db_api::{ }; use reth_db_common::DbTool; use reth_evm::execute::BlockExecutorProvider; +use reth_node_builder::{NodeTypesWithDB, NodeTypesWithEngine}; use reth_node_core::{ args::DatadirArgs, dirs::{DataDirPath, PlatformPath}, @@ -87,12 +88,13 @@ macro_rules! handle_stage { impl> Command { /// Execute `dump-stage` command - pub async fn execute(self, executor: F) -> eyre::Result<()> + pub async fn execute(self, executor: F) -> eyre::Result<()> where + N: NodeTypesWithEngine, E: BlockExecutorProvider, F: FnOnce(Arc) -> E, { - let Environment { provider_factory, .. } = self.env.init(AccessRights::RO)?; + let Environment { provider_factory, .. } = self.env.init::(AccessRights::RO)?; let tool = DbTool::new(provider_factory)?; match &self.command { @@ -111,11 +113,11 @@ impl> Command { /// Sets up the database and initial state on [`tables::BlockBodyIndices`]. Also returns the tip /// block number. -pub(crate) fn setup( +pub(crate) fn setup( from: u64, to: u64, output_db: &PathBuf, - db_tool: &DbTool, + db_tool: &DbTool, ) -> eyre::Result<(DatabaseEnv, u64)> { assert!(from < to, "FROM block should be bigger than TO block."); diff --git a/crates/cli/commands/src/stage/mod.rs b/crates/cli/commands/src/stage/mod.rs index 77d3014a4..a4e0d088a 100644 --- a/crates/cli/commands/src/stage/mod.rs +++ b/crates/cli/commands/src/stage/mod.rs @@ -7,6 +7,7 @@ use reth_chainspec::ChainSpec; use reth_cli::chainspec::ChainSpecParser; use reth_cli_runner::CliContext; use reth_evm::execute::BlockExecutorProvider; +use reth_node_builder::NodeTypesWithEngine; pub mod drop; pub mod dump; @@ -40,16 +41,17 @@ pub enum Subcommands { impl> Command { /// Execute `stage` command - pub async fn execute(self, ctx: CliContext, executor: F) -> eyre::Result<()> + pub async fn execute(self, ctx: CliContext, executor: F) -> eyre::Result<()> where + N: NodeTypesWithEngine, E: BlockExecutorProvider, F: FnOnce(Arc) -> E, { match self.command { - Subcommands::Run(command) => command.execute(ctx, executor).await, - Subcommands::Drop(command) => command.execute().await, - Subcommands::Dump(command) => command.execute(executor).await, - Subcommands::Unwind(command) => command.execute().await, + Subcommands::Run(command) => command.execute::(ctx, executor).await, + Subcommands::Drop(command) => command.execute::().await, + Subcommands::Dump(command) => command.execute::(executor).await, + Subcommands::Unwind(command) => command.execute::().await, } } } diff --git a/crates/cli/commands/src/stage/run.rs b/crates/cli/commands/src/stage/run.rs index 14beffe63..e0c2898ec 100644 --- a/crates/cli/commands/src/stage/run.rs +++ b/crates/cli/commands/src/stage/run.rs @@ -18,6 +18,7 @@ use reth_evm::execute::BlockExecutorProvider; use reth_exex::ExExManagerHandle; use reth_network::BlockDownloaderProvider; use reth_network_p2p::HeadersClient; +use reth_node_builder::NodeTypesWithEngine; use reth_node_core::{ args::{NetworkArgs, StageEnum}, primitives::BlockHashOrNumber, @@ -102,8 +103,9 @@ pub struct Command { impl> Command { /// Execute `stage` command - pub async fn execute(self, ctx: CliContext, executor: F) -> eyre::Result<()> + pub async fn execute(self, ctx: CliContext, executor: F) -> eyre::Result<()> where + N: NodeTypesWithEngine, E: BlockExecutorProvider, F: FnOnce(Arc) -> E, { @@ -111,7 +113,8 @@ impl> Command { // Does not do anything on windows. let _ = fdlimit::raise_fd_limit(); - let Environment { provider_factory, config, data_dir } = self.env.init(AccessRights::RW)?; + let Environment { provider_factory, config, data_dir } = + self.env.init::(AccessRights::RW)?; let mut provider_rw = provider_factory.provider_rw()?; diff --git a/crates/cli/commands/src/stage/unwind.rs b/crates/cli/commands/src/stage/unwind.rs index f41e732ba..ea5ad5745 100644 --- a/crates/cli/commands/src/stage/unwind.rs +++ b/crates/cli/commands/src/stage/unwind.rs @@ -7,10 +7,11 @@ use reth_chainspec::ChainSpec; use reth_cli::chainspec::ChainSpecParser; use reth_config::Config; use reth_consensus::Consensus; -use reth_db_api::database::Database; +use reth_db::DatabaseEnv; use reth_downloaders::{bodies::noop::NoopBodiesDownloader, headers::noop::NoopHeaderDownloader}; use reth_evm::noop::NoopBlockExecutorProvider; use reth_exex::ExExManagerHandle; +use reth_node_builder::{NodeTypesWithDB, NodeTypesWithEngine}; use reth_node_core::args::NetworkArgs; use reth_primitives::{BlockHashOrNumber, BlockNumber, B256}; use reth_provider::{ @@ -48,8 +49,10 @@ pub struct Command { impl> Command { /// Execute `db stage unwind` command - pub async fn execute(self) -> eyre::Result<()> { - let Environment { provider_factory, config, .. } = self.env.init(AccessRights::RW)?; + pub async fn execute>( + self, + ) -> eyre::Result<()> { + let Environment { provider_factory, config, .. } = self.env.init::(AccessRights::RW)?; let range = self.command.unwind_range(provider_factory.clone())?; if *range.start() == 0 { @@ -112,11 +115,11 @@ impl> Command { Ok(()) } - fn build_pipeline( + fn build_pipeline>( self, config: Config, - provider_factory: ProviderFactory>, - ) -> Result>, eyre::Error> { + provider_factory: ProviderFactory, + ) -> Result, eyre::Error> { let consensus: Arc = Arc::new(EthBeaconConsensus::new(provider_factory.chain_spec())); let stage_conf = &config.stages; @@ -128,13 +131,13 @@ impl> Command { let executor = NoopBlockExecutorProvider::default(); let builder = if self.offline { - Pipeline::builder().add_stages( + Pipeline::::builder().add_stages( OfflineStages::new(executor, config.stages, PruneModes::default()) .builder() .disable(reth_stages::StageId::SenderRecovery), ) } else { - Pipeline::builder().with_tip_sender(tip_tx).add_stages( + Pipeline::::builder().with_tip_sender(tip_tx).add_stages( DefaultStages::new( provider_factory.clone(), tip_rx, @@ -185,9 +188,9 @@ impl Subcommands { /// Returns the block range to unwind. /// /// This returns an inclusive range: [target..=latest] - fn unwind_range( + fn unwind_range>>( &self, - factory: ProviderFactory, + factory: ProviderFactory, ) -> eyre::Result> { let provider = factory.provider()?; let last = provider.last_block_number()?; diff --git a/crates/consensus/beacon/Cargo.toml b/crates/consensus/beacon/Cargo.toml index 483f4b702..1a56c5990 100644 --- a/crates/consensus/beacon/Cargo.toml +++ b/crates/consensus/beacon/Cargo.toml @@ -12,13 +12,11 @@ workspace = true [dependencies] # reth -reth-chainspec.workspace = true reth-ethereum-consensus.workspace = true reth-blockchain-tree-api.workspace = true reth-primitives.workspace = true reth-stages-api.workspace = true reth-errors.workspace = true -reth-db-api.workspace = true reth-provider.workspace = true reth-rpc-types.workspace = true reth-tasks.workspace = true @@ -30,7 +28,7 @@ reth-static-file.workspace = true reth-tokio-util.workspace = true reth-engine-primitives.workspace = true reth-network-p2p.workspace = true - +reth-node-types.workspace = true # async tokio = { workspace = true, features = ["sync"] } @@ -55,6 +53,7 @@ reth-consensus = { workspace = true, features = ["test-utils"] } reth-stages = { workspace = true, features = ["test-utils"] } reth-blockchain-tree = { workspace = true, features = ["test-utils"] } reth-db = { workspace = true, features = ["test-utils"] } +reth-db-api.workspace = true reth-provider = { workspace = true, features = ["test-utils"] } reth-evm = { workspace = true, features = ["test-utils"] } reth-network-p2p = { workspace = true, features = ["test-utils"] } @@ -67,6 +66,7 @@ reth-config.workspace = true reth-testing-utils.workspace = true reth-exex-types.workspace = true reth-prune-types.workspace = true +reth-chainspec.workspace = true alloy-genesis.workspace = true assert_matches.workspace = true diff --git a/crates/consensus/beacon/src/engine/hooks/prune.rs b/crates/consensus/beacon/src/engine/hooks/prune.rs index 16b796dd8..3aa787e4a 100644 --- a/crates/consensus/beacon/src/engine/hooks/prune.rs +++ b/crates/consensus/beacon/src/engine/hooks/prune.rs @@ -6,14 +6,14 @@ use crate::{ }; use futures::FutureExt; use metrics::Counter; -use reth_db_api::database::Database; use reth_errors::{RethError, RethResult}; +use reth_node_types::NodeTypesWithDB; use reth_primitives::BlockNumber; -use reth_provider::ProviderFactory; +use reth_provider::{providers::ProviderNodeTypes, ProviderFactory}; use reth_prune::{Pruner, PrunerError, PrunerWithResult}; use reth_tasks::TaskSpawner; use std::{ - fmt, + fmt::{self, Debug}, task::{ready, Context, Poll}, }; use tokio::sync::oneshot; @@ -21,15 +21,15 @@ use tokio::sync::oneshot; /// Manages pruning under the control of the engine. /// /// This type controls the [Pruner]. -pub struct PruneHook { +pub struct PruneHook { /// The current state of the pruner. - pruner_state: PrunerState, + pruner_state: PrunerState, /// The type that can spawn the pruner task. pruner_task_spawner: Box, metrics: Metrics, } -impl fmt::Debug for PruneHook { +impl fmt::Debug for PruneHook { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("PruneHook") .field("pruner_state", &self.pruner_state) @@ -38,10 +38,10 @@ impl fmt::Debug for PruneHook { } } -impl PruneHook { +impl PruneHook { /// Create a new instance pub fn new( - pruner: Pruner>, + pruner: Pruner>, pruner_task_spawner: Box, ) -> Self { Self { @@ -117,7 +117,7 @@ impl PruneHook { } } -impl EngineHook for PruneHook { +impl EngineHook for PruneHook { fn name(&self) -> &'static str { "Prune" } @@ -152,12 +152,23 @@ impl EngineHook for PruneHook { /// running, it acquires the write lock over the database. This means that we cannot forward to the /// blockchain tree any messages that would result in database writes, since it would result in a /// deadlock. -#[derive(Debug)] -enum PrunerState { +enum PrunerState { /// Pruner is idle. - Idle(Option>>), + Idle(Option>>), /// Pruner is running and waiting for a response - Running(oneshot::Receiver>>), + Running(oneshot::Receiver>>), +} + +impl fmt::Debug for PrunerState +where + N: NodeTypesWithDB, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Idle(f0) => f.debug_tuple("Idle").field(&f0).finish(), + Self::Running(f0) => f.debug_tuple("Running").field(&f0).finish(), + } + } } #[derive(reth_metrics::Metrics)] diff --git a/crates/consensus/beacon/src/engine/hooks/static_file.rs b/crates/consensus/beacon/src/engine/hooks/static_file.rs index 43c47ef41..356726d1d 100644 --- a/crates/consensus/beacon/src/engine/hooks/static_file.rs +++ b/crates/consensus/beacon/src/engine/hooks/static_file.rs @@ -5,9 +5,10 @@ use crate::{ hooks::EngineHookDBAccessLevel, }; use futures::FutureExt; -use reth_db_api::database::Database; use reth_errors::RethResult; +use reth_node_types::NodeTypesWithDB; use reth_primitives::{static_file::HighestStaticFiles, BlockNumber}; +use reth_provider::providers::ProviderNodeTypes; use reth_static_file::{StaticFileProducer, StaticFileProducerWithResult}; use reth_tasks::TaskSpawner; use std::task::{ready, Context, Poll}; @@ -18,17 +19,17 @@ use tracing::trace; /// /// This type controls the [`StaticFileProducer`]. #[derive(Debug)] -pub struct StaticFileHook { +pub struct StaticFileHook { /// The current state of the `static_file_producer`. - state: StaticFileProducerState, + state: StaticFileProducerState, /// The type that can spawn the `static_file_producer` task. task_spawner: Box, } -impl StaticFileHook { +impl StaticFileHook { /// Create a new instance pub fn new( - static_file_producer: StaticFileProducer, + static_file_producer: StaticFileProducer, task_spawner: Box, ) -> Self { Self { state: StaticFileProducerState::Idle(Some(static_file_producer)), task_spawner } @@ -126,7 +127,7 @@ impl StaticFileHook { } } -impl EngineHook for StaticFileHook { +impl EngineHook for StaticFileHook { fn name(&self) -> &'static str { "StaticFile" } @@ -162,9 +163,9 @@ impl EngineHook for StaticFileHook { /// [`StaticFileProducerState::Idle`] means that the static file producer is currently idle. /// [`StaticFileProducerState::Running`] means that the static file producer is currently running. #[derive(Debug)] -enum StaticFileProducerState { +enum StaticFileProducerState { /// [`StaticFileProducer`] is idle. - Idle(Option>), + Idle(Option>), /// [`StaticFileProducer`] is running and waiting for a response - Running(oneshot::Receiver>), + Running(oneshot::Receiver>), } diff --git a/crates/consensus/beacon/src/engine/mod.rs b/crates/consensus/beacon/src/engine/mod.rs index 50944891d..f3d67b7ab 100644 --- a/crates/consensus/beacon/src/engine/mod.rs +++ b/crates/consensus/beacon/src/engine/mod.rs @@ -4,14 +4,13 @@ use reth_blockchain_tree_api::{ error::{BlockchainTreeError, CanonicalError, InsertBlockError, InsertBlockErrorKind}, BlockStatus, BlockValidationKind, BlockchainTreeEngine, CanonicalOutcome, InsertPayloadOk, }; -use reth_chainspec::ChainSpec; -use reth_db_api::database::Database; -use reth_engine_primitives::EngineTypes; +use reth_engine_primitives::{EngineTypes, PayloadTypes}; use reth_errors::{BlockValidationError, ProviderResult, RethError, RethResult}; use reth_network_p2p::{ sync::{NetworkSyncUpdater, SyncState}, BlockClient, }; +use reth_node_types::NodeTypesWithDB; use reth_payload_builder::PayloadBuilderHandle; use reth_payload_primitives::{PayloadAttributes, PayloadBuilderAttributes}; use reth_payload_validator::ExecutionPayloadValidator; @@ -20,8 +19,8 @@ use reth_primitives::{ B256, }; use reth_provider::{ - BlockIdReader, BlockReader, BlockSource, CanonChainTracker, ChainSpecProvider, ProviderError, - StageCheckpointReader, + providers::ProviderNodeTypes, BlockIdReader, BlockReader, BlockSource, CanonChainTracker, + ChainSpecProvider, ProviderError, StageCheckpointReader, }; use reth_rpc_types::engine::{ CancunPayloadFields, ExecutionPayload, ForkchoiceState, PayloadStatus, PayloadStatusEnum, @@ -168,40 +167,40 @@ type PendingForkchoiceUpdate = /// If the future is polled more than once. Leads to undefined state. #[must_use = "Future does nothing unless polled"] #[allow(missing_debug_implementations)] -pub struct BeaconConsensusEngine +pub struct BeaconConsensusEngine where - DB: Database, + N: NodeTypesWithDB, Client: BlockClient, BT: BlockchainTreeEngine + BlockReader + BlockIdReader + CanonChainTracker + StageCheckpointReader, - EngineT: EngineTypes, { /// Controls syncing triggered by engine updates. - sync: EngineSyncController, + sync: EngineSyncController, /// The type we can use to query both the database and the blockchain tree. blockchain: BT, /// Used for emitting updates about whether the engine is syncing or not. sync_state_updater: Box, /// The Engine API message receiver. - engine_message_stream: BoxStream<'static, BeaconEngineMessage>, + engine_message_stream: BoxStream<'static, BeaconEngineMessage>, /// A clone of the handle - handle: BeaconConsensusEngineHandle, + handle: BeaconConsensusEngineHandle, /// Tracks the received forkchoice state updates received by the CL. forkchoice_state_tracker: ForkchoiceStateTracker, /// The payload store. - payload_builder: PayloadBuilderHandle, + payload_builder: PayloadBuilderHandle, /// Validator for execution payloads payload_validator: ExecutionPayloadValidator, /// Current blockchain tree action. - blockchain_tree_action: Option>, + blockchain_tree_action: Option>, /// Pending forkchoice update. /// It is recorded if we cannot process the forkchoice update because /// a hook with database read-write access is active. /// This is a temporary solution to always process missed FCUs. - pending_forkchoice_update: Option>, + pending_forkchoice_update: + Option::PayloadAttributes>>, /// Tracks the header of invalid payloads that were rejected by the engine because they're /// invalid. invalid_headers: InvalidHeaderCache, @@ -224,33 +223,32 @@ where metrics: EngineMetrics, } -impl BeaconConsensusEngine +impl BeaconConsensusEngine where - DB: Database + Unpin + 'static, + N: ProviderNodeTypes, BT: BlockchainTreeEngine + BlockReader + BlockIdReader + CanonChainTracker + StageCheckpointReader - + ChainSpecProvider + + ChainSpecProvider + 'static, Client: BlockClient + 'static, - EngineT: EngineTypes + Unpin, { /// Create a new instance of the [`BeaconConsensusEngine`]. #[allow(clippy::too_many_arguments)] pub fn new( client: Client, - pipeline: Pipeline, + pipeline: Pipeline, blockchain: BT, task_spawner: Box, sync_state_updater: Box, max_block: Option, - payload_builder: PayloadBuilderHandle, + payload_builder: PayloadBuilderHandle, target: Option, pipeline_run_threshold: u64, hooks: EngineHooks, - ) -> RethResult<(Self, BeaconConsensusEngineHandle)> { + ) -> RethResult<(Self, BeaconConsensusEngineHandle)> { let (to_engine, rx) = mpsc::unbounded_channel(); Self::with_channel( client, @@ -284,18 +282,18 @@ where #[allow(clippy::too_many_arguments)] pub fn with_channel( client: Client, - pipeline: Pipeline, + pipeline: Pipeline, blockchain: BT, task_spawner: Box, sync_state_updater: Box, max_block: Option, - payload_builder: PayloadBuilderHandle, + payload_builder: PayloadBuilderHandle, target: Option, pipeline_run_threshold: u64, - to_engine: UnboundedSender>, - engine_message_stream: BoxStream<'static, BeaconEngineMessage>, + to_engine: UnboundedSender>, + engine_message_stream: BoxStream<'static, BeaconEngineMessage>, hooks: EngineHooks, - ) -> RethResult<(Self, BeaconConsensusEngineHandle)> { + ) -> RethResult<(Self, BeaconConsensusEngineHandle)> { let event_sender = EventSender::default(); let handle = BeaconConsensusEngineHandle::new(to_engine, event_sender.clone()); let sync = EngineSyncController::new( @@ -349,7 +347,7 @@ where } /// Set the next blockchain tree action. - fn set_blockchain_tree_action(&mut self, action: BlockchainTreeAction) { + fn set_blockchain_tree_action(&mut self, action: BlockchainTreeAction) { let previous_action = self.blockchain_tree_action.replace(action); debug_assert!(previous_action.is_none(), "Pre-existing action found"); } @@ -391,7 +389,7 @@ where fn on_forkchoice_updated_make_canonical_result( &mut self, state: ForkchoiceState, - mut attrs: Option, + mut attrs: Option<::PayloadAttributes>, make_canonical_result: Result, elapsed: Duration, ) -> Result { @@ -455,7 +453,7 @@ where &self, head: &BlockNumHash, header: &SealedHeader, - attrs: &mut Option, + attrs: &mut Option<::PayloadAttributes>, ) -> bool { // On Optimism, the proposers are allowed to reorg their own chain at will. #[cfg(feature = "optimism")] @@ -499,7 +497,7 @@ where fn on_forkchoice_updated( &mut self, state: ForkchoiceState, - attrs: Option, + attrs: Option<::PayloadAttributes>, tx: oneshot::Sender>, ) { self.metrics.forkchoice_updated_messages.increment(1); @@ -621,7 +619,7 @@ where /// /// The [`BeaconConsensusEngineHandle`] can be used to interact with this /// [`BeaconConsensusEngine`] - pub fn handle(&self) -> BeaconConsensusEngineHandle { + pub fn handle(&self) -> BeaconConsensusEngineHandle { self.handle.clone() } @@ -1157,7 +1155,7 @@ where /// return an error if the payload attributes are invalid. fn process_payload_attributes( &self, - attrs: EngineT::PayloadAttributes, + attrs: ::PayloadAttributes, head: Header, state: ForkchoiceState, ) -> OnForkChoiceUpdated { @@ -1174,7 +1172,7 @@ where // forkchoiceState.headBlockHash and identified via buildProcessId value if // payloadAttributes is not null and the forkchoice state has been updated successfully. // The build process is specified in the Payload building section. - match ::try_new( + match <::PayloadBuilderAttributes as PayloadBuilderAttributes>::try_new( state.head_block_hash, attrs, ) { @@ -1596,7 +1594,7 @@ where /// so the state change should be handled accordingly. fn on_blockchain_tree_action( &mut self, - action: BlockchainTreeAction, + action: BlockchainTreeAction, ) -> RethResult { match action { BlockchainTreeAction::MakeForkchoiceHeadCanonical { state, attrs, tx } => { @@ -1789,19 +1787,18 @@ where /// local forkchoice state, it will launch the pipeline to sync to the head hash. /// While the pipeline is syncing, the consensus engine will keep processing messages from the /// receiver and forwarding them to the blockchain tree. -impl Future for BeaconConsensusEngine +impl Future for BeaconConsensusEngine where - DB: Database + Unpin + 'static, + N: ProviderNodeTypes, Client: BlockClient + 'static, BT: BlockchainTreeEngine + BlockReader + BlockIdReader + CanonChainTracker + StageCheckpointReader - + ChainSpecProvider + + ChainSpecProvider + Unpin + 'static, - EngineT: EngineTypes + Unpin, { type Output = Result<(), BeaconConsensusEngineError>; @@ -2156,8 +2153,8 @@ mod tests { assert_matches!(rx.await, Ok(Ok(()))); } - fn insert_blocks<'a, DB: Database>( - provider_factory: ProviderFactory, + fn insert_blocks<'a, N: ProviderNodeTypes>( + provider_factory: ProviderFactory, mut blocks: impl Iterator, ) { let provider = provider_factory.provider_rw().unwrap(); @@ -2176,10 +2173,10 @@ mod tests { mod fork_choice_updated { use super::*; use generators::BlockParams; - use reth_db::{tables, test_utils::create_test_static_files_dir}; + use reth_db::{tables, test_utils::create_test_static_files_dir, Database}; use reth_db_api::transaction::DbTxMut; use reth_primitives::U256; - use reth_provider::providers::StaticFileProvider; + use reth_provider::{providers::StaticFileProvider, test_utils::MockNodeTypesWithDB}; use reth_rpc_types::engine::ForkchoiceUpdateError; use reth_testing_utils::generators::random_block; @@ -2248,8 +2245,8 @@ mod tests { let (_static_dir, static_dir_path) = create_test_static_files_dir(); insert_blocks( - ProviderFactory::new( - env.db.as_ref(), + ProviderFactory::::new( + env.db.clone(), chain_spec.clone(), StaticFileProvider::read_write(static_dir_path).unwrap(), ), @@ -2316,8 +2313,8 @@ mod tests { let (_static_dir, static_dir_path) = create_test_static_files_dir(); insert_blocks( - ProviderFactory::new( - env.db.as_ref(), + ProviderFactory::::new( + env.db.clone(), chain_spec.clone(), StaticFileProvider::read_write(static_dir_path).unwrap(), ), @@ -2347,8 +2344,8 @@ mod tests { // Insert next head immediately after sending forkchoice update insert_blocks( - ProviderFactory::new( - env.db.as_ref(), + ProviderFactory::::new( + env.db.clone(), chain_spec.clone(), StaticFileProvider::read_write(static_dir_path).unwrap(), ), @@ -2403,8 +2400,8 @@ mod tests { let (_static_dir, static_dir_path) = create_test_static_files_dir(); insert_blocks( - ProviderFactory::new( - env.db.as_ref(), + ProviderFactory::::new( + env.db.clone(), chain_spec.clone(), StaticFileProvider::read_write(static_dir_path).unwrap(), ), @@ -2486,8 +2483,8 @@ mod tests { let (_static_dir, static_dir_path) = create_test_static_files_dir(); insert_blocks( - ProviderFactory::new( - env.db.as_ref(), + ProviderFactory::::new( + env.db.clone(), chain_spec.clone(), StaticFileProvider::read_write(static_dir_path).unwrap(), ), @@ -2547,8 +2544,8 @@ mod tests { let (_temp_dir, temp_dir_path) = create_test_static_files_dir(); insert_blocks( - ProviderFactory::new( - env.db.as_ref(), + ProviderFactory::::new( + env.db.clone(), chain_spec.clone(), StaticFileProvider::read_write(temp_dir_path).unwrap(), ), @@ -2580,7 +2577,8 @@ mod tests { use reth_db::test_utils::create_test_static_files_dir; use reth_primitives::{EthereumHardfork, U256}; use reth_provider::{ - providers::StaticFileProvider, test_utils::blocks::BlockchainTestData, + providers::StaticFileProvider, + test_utils::{blocks::BlockchainTestData, MockNodeTypesWithDB}, }; use reth_testing_utils::{generators::random_block, GenesisAllocator}; #[tokio::test] @@ -2680,8 +2678,8 @@ mod tests { let (_static_dir, static_dir_path) = create_test_static_files_dir(); insert_blocks( - ProviderFactory::new( - env.db.as_ref(), + ProviderFactory::::new( + env.db.clone(), chain_spec.clone(), StaticFileProvider::read_write(static_dir_path).unwrap(), ), @@ -2760,8 +2758,8 @@ mod tests { let (_static_dir, static_dir_path) = create_test_static_files_dir(); insert_blocks( - ProviderFactory::new( - env.db.as_ref(), + ProviderFactory::::new( + env.db.clone(), chain_spec.clone(), StaticFileProvider::read_write(static_dir_path).unwrap(), ), @@ -2810,8 +2808,8 @@ mod tests { let (_static_dir, static_dir_path) = create_test_static_files_dir(); insert_blocks( - ProviderFactory::new( - env.db.as_ref(), + ProviderFactory::::new( + env.db.clone(), chain_spec.clone(), StaticFileProvider::read_write(static_dir_path).unwrap(), ), @@ -2881,8 +2879,8 @@ mod tests { let (_static_dir, static_dir_path) = create_test_static_files_dir(); insert_blocks( - ProviderFactory::new( - env.db.as_ref(), + ProviderFactory::::new( + env.db.clone(), chain_spec.clone(), StaticFileProvider::read_write(static_dir_path).unwrap(), ), diff --git a/crates/consensus/beacon/src/engine/sync.rs b/crates/consensus/beacon/src/engine/sync.rs index 72c5cc2dd..007fb7027 100644 --- a/crates/consensus/beacon/src/engine/sync.rs +++ b/crates/consensus/beacon/src/engine/sync.rs @@ -5,13 +5,13 @@ use crate::{ ConsensusEngineLiveSyncProgress, EthBeaconConsensus, }; use futures::FutureExt; -use reth_chainspec::ChainSpec; -use reth_db_api::database::Database; use reth_network_p2p::{ full_block::{FetchFullBlockFuture, FetchFullBlockRangeFuture, FullBlockClient}, BlockClient, }; +use reth_node_types::NodeTypesWithDB; use reth_primitives::{BlockNumber, SealedBlock, B256}; +use reth_provider::providers::ProviderNodeTypes; use reth_stages_api::{ControlFlow, Pipeline, PipelineError, PipelineTarget, PipelineWithResult}; use reth_tasks::TaskSpawner; use reth_tokio_util::EventSender; @@ -31,9 +31,9 @@ use tracing::trace; /// Caution: If the pipeline is running, this type will not emit blocks downloaded from the network /// [`EngineSyncEvent::FetchedFullBlock`] until the pipeline is idle to prevent commits to the /// database while the pipeline is still active. -pub(crate) struct EngineSyncController +pub(crate) struct EngineSyncController where - DB: Database, + N: NodeTypesWithDB, Client: BlockClient, { /// A downloader that can download full blocks from the network. @@ -42,7 +42,7 @@ where pipeline_task_spawner: Box, /// The current state of the pipeline. /// The pipeline is used for large ranges. - pipeline_state: PipelineState, + pipeline_state: PipelineState, /// Pending target block for the pipeline to sync pending_pipeline_target: Option, /// In-flight full block requests in progress. @@ -61,18 +61,18 @@ where metrics: EngineSyncMetrics, } -impl EngineSyncController +impl EngineSyncController where - DB: Database + 'static, + N: ProviderNodeTypes, Client: BlockClient + 'static, { /// Create a new instance pub(crate) fn new( - pipeline: Pipeline, + pipeline: Pipeline, client: Client, pipeline_task_spawner: Box, max_block: Option, - chain_spec: Arc, + chain_spec: Arc, event_sender: EventSender, ) -> Self { Self { @@ -393,14 +393,14 @@ pub(crate) enum EngineSyncEvent { /// running, it acquires the write lock over the database. This means that we cannot forward to the /// blockchain tree any messages that would result in database writes, since it would result in a /// deadlock. -enum PipelineState { +enum PipelineState { /// Pipeline is idle. - Idle(Option>), + Idle(Option>), /// Pipeline is running and waiting for a response - Running(oneshot::Receiver>), + Running(oneshot::Receiver>), } -impl PipelineState { +impl PipelineState { /// Returns `true` if the state matches idle. const fn is_idle(&self) -> bool { matches!(self, Self::Idle(_)) @@ -412,12 +412,12 @@ mod tests { use super::*; use assert_matches::assert_matches; use futures::poll; - use reth_chainspec::{ChainSpecBuilder, MAINNET}; - use reth_db::{mdbx::DatabaseEnv, test_utils::TempDatabase}; + use reth_chainspec::{ChainSpec, ChainSpecBuilder, MAINNET}; use reth_network_p2p::{either::Either, test_utils::TestFullBlockClient}; use reth_primitives::{BlockBody, Header, SealedHeader}; use reth_provider::{ - test_utils::create_test_provider_factory_with_chain_spec, ExecutionOutcome, + test_utils::{create_test_provider_factory_with_chain_spec, MockNodeTypesWithDB}, + ExecutionOutcome, }; use reth_prune_types::PruneModes; use reth_stages::{test_utils::TestStages, ExecOutput, StageError}; @@ -467,12 +467,12 @@ mod tests { } /// Builds the pipeline. - fn build(self, chain_spec: Arc) -> Pipeline>> { + fn build(self, chain_spec: Arc) -> Pipeline { reth_tracing::init_test_tracing(); // Setup pipeline let (tip_tx, _tip_rx) = watch::channel(B256::default()); - let mut pipeline = Pipeline::builder() + let mut pipeline = Pipeline::::builder() .add_stages(TestStages::new(self.pipeline_exec_outputs, Default::default())) .with_tip_sender(tip_tx); @@ -514,13 +514,13 @@ mod tests { } /// Builds the sync controller. - fn build( + fn build( self, - pipeline: Pipeline, + pipeline: Pipeline, chain_spec: Arc, - ) -> EngineSyncController> + ) -> EngineSyncController> where - DB: Database + 'static, + N: ProviderNodeTypes, Client: BlockClient + 'static, { let client = self diff --git a/crates/consensus/beacon/src/engine/test_utils.rs b/crates/consensus/beacon/src/engine/test_utils.rs index 72bae2c26..33025bb9a 100644 --- a/crates/consensus/beacon/src/engine/test_utils.rs +++ b/crates/consensus/beacon/src/engine/test_utils.rs @@ -22,7 +22,8 @@ use reth_network_p2p::{sync::NoopSyncStateUpdater, test_utils::NoopFullBlockClie use reth_payload_builder::test_utils::spawn_test_payload_service; use reth_primitives::{BlockNumber, B256}; use reth_provider::{ - providers::BlockchainProvider, test_utils::create_test_provider_factory_with_chain_spec, + providers::BlockchainProvider, + test_utils::{create_test_provider_factory_with_chain_spec, MockNodeTypesWithDB}, ExecutionOutcome, ProviderFactory, }; use reth_prune::Pruner; @@ -39,10 +40,9 @@ use tokio::sync::{oneshot, watch}; type DatabaseEnv = TempDatabase; type TestBeaconConsensusEngine = BeaconConsensusEngine< - Arc, - BlockchainProvider>, + MockNodeTypesWithDB, + BlockchainProvider, Arc>, - EthEngineTypes, >; #[derive(Debug)] @@ -355,7 +355,7 @@ where // Setup pipeline let (tip_tx, tip_rx) = watch::channel(B256::default()); let mut pipeline = match self.base_config.pipeline_config { - TestPipelineConfig::Test(outputs) => Pipeline::builder() + TestPipelineConfig::Test(outputs) => Pipeline::::builder() .add_stages(TestStages::new(outputs, Default::default())) .with_tip_sender(tip_tx), TestPipelineConfig::Real => { @@ -367,7 +367,7 @@ where .build(client.clone(), consensus.clone(), provider_factory.clone()) .into_task(); - Pipeline::builder().add_stages(DefaultStages::new( + Pipeline::::builder().add_stages(DefaultStages::new( provider_factory.clone(), tip_rx.clone(), Arc::clone(&consensus), diff --git a/crates/e2e-test-utils/src/lib.rs b/crates/e2e-test-utils/src/lib.rs index 287114397..d11e39767 100644 --- a/crates/e2e-test-utils/src/lib.rs +++ b/crates/e2e-test-utils/src/lib.rs @@ -117,8 +117,10 @@ where // Type aliases type TmpDB = Arc>; -type TmpNodeAdapter = - FullNodeTypesAdapter, BlockchainProvider>; +type TmpNodeAdapter = FullNodeTypesAdapter< + NodeTypesWithDBAdapter, + BlockchainProvider>, +>; type Adapter = NodeAdapter< RethFullAdapter, diff --git a/crates/engine/service/Cargo.toml b/crates/engine/service/Cargo.toml index c5ace879d..1cee7506a 100644 --- a/crates/engine/service/Cargo.toml +++ b/crates/engine/service/Cargo.toml @@ -13,10 +13,7 @@ workspace = true [dependencies] # reth reth-beacon-consensus.workspace = true -reth-chainspec.workspace = true reth-consensus.workspace = true -reth-db-api.workspace = true -reth-engine-primitives.workspace = true reth-engine-tree.workspace = true reth-evm.workspace = true reth-network-p2p.workspace = true @@ -26,6 +23,7 @@ reth-provider.workspace = true reth-prune.workspace = true reth-stages-api.workspace = true reth-tasks.workspace = true +reth-node-types.workspace = true # async futures.workspace = true @@ -43,6 +41,7 @@ reth-evm-ethereum.workspace = true reth-exex-types.workspace = true reth-primitives.workspace = true reth-prune-types.workspace = true +reth-chainspec.workspace = true tokio = { workspace = true, features = ["sync"] } tokio-stream.workspace = true diff --git a/crates/engine/service/src/service.rs b/crates/engine/service/src/service.rs index 56e674fdf..b69eed9f5 100644 --- a/crates/engine/service/src/service.rs +++ b/crates/engine/service/src/service.rs @@ -1,10 +1,7 @@ use futures::{Stream, StreamExt}; use pin_project::pin_project; use reth_beacon_consensus::{BeaconConsensusEngineEvent, BeaconEngineMessage}; -use reth_chainspec::ChainSpec; use reth_consensus::Consensus; -use reth_db_api::database::Database; -use reth_engine_primitives::EngineTypes; use reth_engine_tree::{ backfill::PipelineSync, download::BasicBlockDownloader, @@ -18,9 +15,13 @@ pub use reth_engine_tree::{ }; use reth_evm::execute::BlockExecutorProvider; use reth_network_p2p::BlockClient; +use reth_node_types::NodeTypesWithEngine; use reth_payload_builder::PayloadBuilderHandle; use reth_payload_validator::ExecutionPayloadValidator; -use reth_provider::{providers::BlockchainProvider2, ProviderFactory}; +use reth_provider::{ + providers::{BlockchainProvider2, ProviderNodeTypes}, + ProviderFactory, +}; use reth_prune::Pruner; use reth_stages_api::Pipeline; use reth_tasks::TaskSpawner; @@ -35,50 +36,48 @@ use std::{ type EngineMessageStream = Pin> + Send + Sync>>; /// Alias for chain orchestrator. -type EngineServiceType = ChainOrchestrator< +type EngineServiceType = ChainOrchestrator< EngineHandler< - EngineApiRequestHandler>, - EngineMessageStream, + EngineApiRequestHandler::Engine>>, + EngineMessageStream<::Engine>, BasicBlockDownloader, >, - PipelineSync, + PipelineSync, >; /// The type that drives the chain forward and communicates progress. #[pin_project] #[allow(missing_debug_implementations)] -pub struct EngineService +pub struct EngineService where - DB: Database + 'static, + N: ProviderNodeTypes, Client: BlockClient + 'static, E: BlockExecutorProvider + 'static, - T: EngineTypes, { - orchestrator: EngineServiceType, + orchestrator: EngineServiceType, _marker: PhantomData, } -impl EngineService +impl EngineService where - DB: Database + 'static, + N: ProviderNodeTypes, Client: BlockClient + 'static, E: BlockExecutorProvider + 'static, - T: EngineTypes + 'static, { /// Constructor for `EngineService`. #[allow(clippy::too_many_arguments)] pub fn new( consensus: Arc, executor_factory: E, - chain_spec: Arc, + chain_spec: Arc, client: Client, - incoming_requests: EngineMessageStream, - pipeline: Pipeline, + incoming_requests: EngineMessageStream, + pipeline: Pipeline, pipeline_task_spawner: Box, - provider: ProviderFactory, - blockchain_db: BlockchainProvider2, - pruner: Pruner>, - payload_builder: PayloadBuilderHandle, + provider: ProviderFactory, + blockchain_db: BlockchainProvider2, + pruner: Pruner>, + payload_builder: PayloadBuilderHandle, tree_config: TreeConfig, invalid_block_hook: Box, ) -> Self { @@ -113,17 +112,16 @@ where } /// Returns a mutable reference to the orchestrator. - pub fn orchestrator_mut(&mut self) -> &mut EngineServiceType { + pub fn orchestrator_mut(&mut self) -> &mut EngineServiceType { &mut self.orchestrator } } -impl Stream for EngineService +impl Stream for EngineService where - DB: Database + 'static, + N: ProviderNodeTypes, Client: BlockClient + 'static, E: BlockExecutorProvider + 'static, - T: EngineTypes + 'static, { type Item = ChainEvent; diff --git a/crates/engine/tree/Cargo.toml b/crates/engine/tree/Cargo.toml index c978acc10..2d8aef52c 100644 --- a/crates/engine/tree/Cargo.toml +++ b/crates/engine/tree/Cargo.toml @@ -17,8 +17,6 @@ reth-blockchain-tree.workspace = true reth-blockchain-tree-api.workspace = true reth-chain-state.workspace = true reth-consensus.workspace = true -reth-db.workspace = true -reth-db-api.workspace = true reth-engine-primitives.workspace = true reth-errors.workspace = true reth-evm.workspace = true @@ -34,6 +32,7 @@ reth-rpc-types.workspace = true reth-stages-api.workspace = true reth-tasks.workspace = true reth-trie.workspace = true +reth-node-types.workspace = true # common futures.workspace = true @@ -48,16 +47,15 @@ reth-metrics = { workspace = true, features = ["common"] } tracing.workspace = true # optional deps for test-utils -reth-chainspec = { workspace = true, optional = true } 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 reth-db = { workspace = true, features = ["test-utils"] } -reth-chainspec.workspace = true reth-chain-state = { workspace = true, features = ["test-utils"] } reth-ethereum-engine-primitives.workspace = true reth-evm = { workspace = true, features = ["test-utils"] } @@ -69,6 +67,7 @@ reth-rpc-types-compat.workspace = true reth-stages = { workspace = true, features = ["test-utils"] } reth-static-file.workspace = true reth-tracing.workspace = true +reth-chainspec.workspace = true alloy-rlp.workspace = true @@ -79,10 +78,10 @@ rand.workspace = true test-utils = [ "reth-db/test-utils", "reth-chain-state/test-utils", - "reth-chainspec", "reth-network-p2p/test-utils", "reth-prune-types", "reth-stages/test-utils", "reth-static-file", "reth-tracing", + "reth-chainspec" ] diff --git a/crates/engine/tree/src/backfill.rs b/crates/engine/tree/src/backfill.rs index 5c4e56d29..9aee45f83 100644 --- a/crates/engine/tree/src/backfill.rs +++ b/crates/engine/tree/src/backfill.rs @@ -8,7 +8,8 @@ //! These modes are mutually exclusive and the node can only be in one mode at a time. use futures::FutureExt; -use reth_db_api::database::Database; +use reth_node_types::NodeTypesWithDB; +use reth_provider::providers::ProviderNodeTypes; use reth_stages_api::{ControlFlow, Pipeline, PipelineError, PipelineTarget, PipelineWithResult}; use reth_tasks::TaskSpawner; use std::task::{ready, Context, Poll}; @@ -78,25 +79,19 @@ pub enum BackfillEvent { /// Pipeline sync. #[derive(Debug)] -pub struct PipelineSync -where - DB: Database, -{ +pub struct PipelineSync { /// The type that can spawn the pipeline task. pipeline_task_spawner: Box, /// The current state of the pipeline. /// The pipeline is used for large ranges. - pipeline_state: PipelineState, + pipeline_state: PipelineState, /// Pending target block for the pipeline to sync pending_pipeline_target: Option, } -impl PipelineSync -where - DB: Database + 'static, -{ +impl PipelineSync { /// Create a new instance. - pub fn new(pipeline: Pipeline, pipeline_task_spawner: Box) -> Self { + pub fn new(pipeline: Pipeline, pipeline_task_spawner: Box) -> Self { Self { pipeline_task_spawner, pipeline_state: PipelineState::Idle(Some(pipeline)), @@ -183,10 +178,7 @@ where } } -impl BackfillSync for PipelineSync -where - DB: Database + 'static, -{ +impl BackfillSync for PipelineSync { fn on_action(&mut self, event: BackfillAction) { match event { BackfillAction::Start(target) => self.set_pipeline_sync_target(target), @@ -221,14 +213,14 @@ where /// blockchain tree any messages that would result in database writes, since it would result in a /// deadlock. #[derive(Debug)] -enum PipelineState { +enum PipelineState { /// Pipeline is idle. - Idle(Option>), + Idle(Option>), /// Pipeline is running and waiting for a response - Running(oneshot::Receiver>), + Running(oneshot::Receiver>), } -impl PipelineState { +impl PipelineState { /// Returns `true` if the state matches idle. const fn is_idle(&self) -> bool { matches!(self, Self::Idle(_)) @@ -242,16 +234,16 @@ mod tests { use assert_matches::assert_matches; use futures::poll; use reth_chainspec::{ChainSpecBuilder, MAINNET}; - use reth_db::{mdbx::DatabaseEnv, test_utils::TempDatabase}; use reth_network_p2p::test_utils::TestFullBlockClient; use reth_primitives::{BlockNumber, Header, B256}; + use reth_provider::test_utils::MockNodeTypesWithDB; use reth_stages::ExecOutput; use reth_stages_api::StageCheckpoint; use reth_tasks::TokioTaskExecutor; use std::{collections::VecDeque, future::poll_fn, sync::Arc}; struct TestHarness { - pipeline_sync: PipelineSync>>, + pipeline_sync: PipelineSync, tip: B256, } diff --git a/crates/engine/tree/src/persistence.rs b/crates/engine/tree/src/persistence.rs index 82c788389..de1703cd9 100644 --- a/crates/engine/tree/src/persistence.rs +++ b/crates/engine/tree/src/persistence.rs @@ -2,11 +2,12 @@ use crate::metrics::PersistenceMetrics; use reth_chain_state::ExecutedBlock; -use reth_db::Database; use reth_errors::ProviderError; +use reth_node_types::NodeTypesWithDB; use reth_primitives::B256; use reth_provider::{ - writer::UnifiedStorageWriter, BlockHashReader, ProviderFactory, StaticFileProviderFactory, + providers::ProviderNodeTypes, writer::UnifiedStorageWriter, BlockHashReader, ProviderFactory, + StaticFileProviderFactory, }; use reth_prune::{Pruner, PrunerError, PrunerOutput}; use std::{ @@ -25,23 +26,23 @@ use tracing::{debug, error}; /// This should be spawned in its own thread with [`std::thread::spawn`], since this performs /// blocking I/O operations in an endless loop. #[derive(Debug)] -pub struct PersistenceService { +pub struct PersistenceService { /// The provider factory to use - provider: ProviderFactory, + provider: ProviderFactory, /// Incoming requests incoming: Receiver, /// The pruner - pruner: Pruner>, + pruner: Pruner>, /// metrics metrics: PersistenceMetrics, } -impl PersistenceService { +impl PersistenceService { /// Create a new persistence service pub fn new( - provider: ProviderFactory, + provider: ProviderFactory, incoming: Receiver, - pruner: Pruner>, + pruner: Pruner>, ) -> Self { Self { provider, incoming, pruner, metrics: PersistenceMetrics::default() } } @@ -58,10 +59,7 @@ impl PersistenceService { } } -impl PersistenceService -where - DB: Database, -{ +impl PersistenceService { /// This is the main loop, that will listen to database events and perform the requested /// database actions pub fn run(mut self) -> Result<(), PersistenceError> { @@ -167,9 +165,9 @@ impl PersistenceHandle { } /// Create a new [`PersistenceHandle`], and spawn the persistence service. - pub fn spawn_service( - provider_factory: ProviderFactory, - pruner: Pruner>, + pub fn spawn_service( + provider_factory: ProviderFactory, + pruner: Pruner>, ) -> Self { // create the initial channels let (db_service_tx, db_service_rx) = std::sync::mpsc::channel(); diff --git a/crates/engine/tree/src/test_utils.rs b/crates/engine/tree/src/test_utils.rs index 5ace509d1..d76fabf43 100644 --- a/crates/engine/tree/src/test_utils.rs +++ b/crates/engine/tree/src/test_utils.rs @@ -1,8 +1,10 @@ use reth_chainspec::ChainSpec; -use reth_db::{mdbx::DatabaseEnv, test_utils::TempDatabase}; use reth_network_p2p::test_utils::TestFullBlockClient; use reth_primitives::{BlockBody, SealedHeader, B256}; -use reth_provider::{test_utils::create_test_provider_factory_with_chain_spec, ExecutionOutcome}; +use reth_provider::{ + test_utils::{create_test_provider_factory_with_chain_spec, MockNodeTypesWithDB}, + ExecutionOutcome, +}; use reth_prune_types::PruneModes; use reth_stages::{test_utils::TestStages, ExecOutput, StageError}; use reth_stages_api::Pipeline; @@ -40,12 +42,12 @@ impl TestPipelineBuilder { } /// Builds the pipeline. - pub fn build(self, chain_spec: Arc) -> Pipeline>> { + pub fn build(self, chain_spec: Arc) -> Pipeline { reth_tracing::init_test_tracing(); // Setup pipeline let (tip_tx, _tip_rx) = watch::channel(B256::default()); - let pipeline = Pipeline::builder() + let pipeline = Pipeline::::builder() .add_stages(TestStages::new(self.pipeline_exec_outputs, Default::default())) .with_tip_sender(tip_tx); diff --git a/crates/ethereum/node/tests/it/builder.rs b/crates/ethereum/node/tests/it/builder.rs index 6390dd854..4041c9766 100644 --- a/crates/ethereum/node/tests/it/builder.rs +++ b/crates/ethereum/node/tests/it/builder.rs @@ -6,6 +6,7 @@ use reth_db::{ test_utils::{create_test_rw_db, TempDatabase}, DatabaseEnv, }; +use reth_node_api::NodeTypesWithDBAdapter; use reth_node_builder::{EngineNodeLauncher, FullNodeComponents, NodeBuilder, NodeConfig}; use reth_node_ethereum::node::{EthereumAddOns, EthereumNode}; use reth_provider::providers::BlockchainProvider2; @@ -46,15 +47,18 @@ async fn test_eth_launcher() { let tasks = TaskManager::current(); let config = NodeConfig::test(); let db = create_test_rw_db(); - let _builder = NodeBuilder::new(config) - .with_database(db) - .with_types_and_provider::>>>() - .with_components(EthereumNode::components()) - .with_add_ons::() - .launch_with_fn(|builder| { - let launcher = EngineNodeLauncher::new(tasks.executor(), builder.config.datadir()); - builder.launch_with(launcher) - }); + let _builder = + NodeBuilder::new(config) + .with_database(db) + .with_types_and_provider::>>, + >>() + .with_components(EthereumNode::components()) + .with_add_ons::() + .launch_with_fn(|builder| { + let launcher = EngineNodeLauncher::new(tasks.executor(), builder.config.datadir()); + builder.launch_with(launcher) + }); } #[test] diff --git a/crates/exex/exex/src/backfill/test_utils.rs b/crates/exex/exex/src/backfill/test_utils.rs index 14377e520..26f92ea87 100644 --- a/crates/exex/exex/src/backfill/test_utils.rs +++ b/crates/exex/exex/src/backfill/test_utils.rs @@ -10,7 +10,10 @@ use reth_primitives::{ b256, constants::ETH_TO_WEI, Address, Block, BlockWithSenders, Genesis, GenesisAccount, Header, Receipt, Requests, SealedBlockWithSenders, Transaction, TxEip2930, TxKind, U256, }; -use reth_provider::{BlockWriter as _, ExecutionOutcome, LatestStateProviderRef, ProviderFactory}; +use reth_provider::{ + providers::ProviderNodeTypes, BlockWriter as _, ExecutionOutcome, LatestStateProviderRef, + ProviderFactory, +}; use reth_revm::database::StateProviderDatabase; use reth_testing_utils::generators::sign_tx_with_key_pair; use secp256k1::Keypair; @@ -46,13 +49,13 @@ pub(crate) fn chain_spec(address: Address) -> Arc { ) } -pub(crate) fn execute_block_and_commit_to_database( - provider_factory: &ProviderFactory, +pub(crate) fn execute_block_and_commit_to_database( + provider_factory: &ProviderFactory, chain_spec: Arc, block: &BlockWithSenders, ) -> eyre::Result> where - DB: reth_db_api::database::Database, + N: ProviderNodeTypes, { let provider = provider_factory.provider()?; @@ -149,13 +152,13 @@ fn blocks( Ok((block1, block2)) } -pub(crate) fn blocks_and_execution_outputs( - provider_factory: ProviderFactory, +pub(crate) fn blocks_and_execution_outputs( + provider_factory: ProviderFactory, chain_spec: Arc, key_pair: Keypair, ) -> eyre::Result)>> where - DB: reth_db_api::database::Database, + N: ProviderNodeTypes, { let (block1, block2) = blocks(chain_spec.clone(), key_pair)?; @@ -170,13 +173,13 @@ where Ok(vec![(block1, block_output1), (block2, block_output2)]) } -pub(crate) fn blocks_and_execution_outcome( - provider_factory: ProviderFactory, +pub(crate) fn blocks_and_execution_outcome( + provider_factory: ProviderFactory, chain_spec: Arc, key_pair: Keypair, ) -> eyre::Result<(Vec, ExecutionOutcome)> where - DB: reth_db_api::database::Database, + N: ProviderNodeTypes, { let (block1, block2) = blocks(chain_spec.clone(), key_pair)?; diff --git a/crates/exex/test-utils/src/lib.rs b/crates/exex/test-utils/src/lib.rs index 47e2f9be2..bfa18a454 100644 --- a/crates/exex/test-utils/src/lib.rs +++ b/crates/exex/test-utils/src/lib.rs @@ -12,7 +12,10 @@ use futures_util::FutureExt; use reth_blockchain_tree::noop::NoopBlockchainTree; use reth_chainspec::{ChainSpec, MAINNET}; use reth_consensus::test_utils::TestConsensus; -use reth_db::{test_utils::TempDatabase, DatabaseEnv}; +use reth_db::{ + test_utils::{create_test_rw_db, create_test_static_files_dir, TempDatabase}, + DatabaseEnv, +}; use reth_db_common::init::init_genesis; use reth_evm::test_utils::MockExecutorProvider; use reth_execution_types::Chain; @@ -36,7 +39,7 @@ use reth_node_ethereum::{ use reth_payload_builder::noop::NoopPayloadBuilderService; use reth_primitives::{Head, SealedBlockWithSenders}; use reth_provider::{ - providers::BlockchainProvider, test_utils::create_test_provider_factory_with_chain_spec, + providers::{BlockchainProvider, StaticFileProvider}, BlockReader, ProviderFactory, }; use reth_tasks::TaskManager; @@ -151,7 +154,10 @@ pub type TmpDB = Arc>; pub type Adapter = NodeAdapter< RethFullAdapter, <, BlockchainProvider>, + FullNodeTypesAdapter< + NodeTypesWithDBAdapter, + BlockchainProvider>, + >, >>::ComponentsBuilder as NodeComponentsBuilder>>::Components, >; /// An [`ExExContext`] using the [`Adapter`] type. @@ -163,7 +169,7 @@ pub struct TestExExHandle { /// Genesis block that was inserted into the storage pub genesis: SealedBlockWithSenders, /// Provider Factory for accessing the emphemeral storage of the host node - pub provider_factory: ProviderFactory, + pub provider_factory: ProviderFactory>, /// Channel for receiving events from the Execution Extension pub events_rx: UnboundedReceiver, /// Channel for sending notifications to the Execution Extension @@ -236,7 +242,14 @@ pub async fn test_exex_context_with_chain_spec( let executor = MockExecutorProvider::default(); let consensus = Arc::new(TestConsensus::default()); - let provider_factory = create_test_provider_factory_with_chain_spec(chain_spec); + let (static_dir, _) = create_test_static_files_dir(); + let db = create_test_rw_db(); + let provider_factory = ProviderFactory::new( + db, + chain_spec, + StaticFileProvider::read_write(static_dir.into_path()).expect("static file provider"), + ); + let genesis_hash = init_genesis(provider_factory.clone())?; let provider = BlockchainProvider::new(provider_factory.clone(), Arc::new(NoopBlockchainTree::default()))?; diff --git a/crates/net/downloaders/src/bodies/bodies.rs b/crates/net/downloaders/src/bodies/bodies.rs index ef1efff54..9bbf7a2f1 100644 --- a/crates/net/downloaders/src/bodies/bodies.rs +++ b/crates/net/downloaders/src/bodies/bodies.rs @@ -606,7 +606,9 @@ mod tests { use reth_consensus::test_utils::TestConsensus; use reth_db::test_utils::{create_test_rw_db, create_test_static_files_dir}; use reth_primitives::{BlockBody, B256}; - use reth_provider::{providers::StaticFileProvider, ProviderFactory}; + use reth_provider::{ + providers::StaticFileProvider, test_utils::MockNodeTypesWithDB, ProviderFactory, + }; use reth_testing_utils::generators::{self, random_block_range, BlockRangeParams}; use std::collections::HashMap; @@ -628,7 +630,7 @@ mod tests { let mut downloader = BodiesDownloaderBuilder::default().build( client.clone(), Arc::new(TestConsensus::default()), - ProviderFactory::new( + ProviderFactory::::new( db, MAINNET.clone(), StaticFileProvider::read_write(static_dir_path).unwrap(), @@ -682,7 +684,7 @@ mod tests { BodiesDownloaderBuilder::default().with_request_limit(request_limit).build( client.clone(), Arc::new(TestConsensus::default()), - ProviderFactory::new( + ProviderFactory::::new( db, MAINNET.clone(), StaticFileProvider::read_write(static_dir_path).unwrap(), @@ -716,7 +718,7 @@ mod tests { .build( client.clone(), Arc::new(TestConsensus::default()), - ProviderFactory::new( + ProviderFactory::::new( db, MAINNET.clone(), StaticFileProvider::read_write(static_dir_path).unwrap(), @@ -752,7 +754,7 @@ mod tests { let mut downloader = BodiesDownloaderBuilder::default().with_stream_batch_size(100).build( client.clone(), Arc::new(TestConsensus::default()), - ProviderFactory::new( + ProviderFactory::::new( db, MAINNET.clone(), StaticFileProvider::read_write(static_dir_path).unwrap(), @@ -798,7 +800,7 @@ mod tests { .build( client.clone(), Arc::new(TestConsensus::default()), - ProviderFactory::new( + ProviderFactory::::new( db, MAINNET.clone(), StaticFileProvider::read_write(static_dir_path).unwrap(), @@ -835,7 +837,7 @@ mod tests { .build( client.clone(), Arc::new(TestConsensus::default()), - ProviderFactory::new( + ProviderFactory::::new( db, MAINNET.clone(), StaticFileProvider::read_write(static_dir_path).unwrap(), diff --git a/crates/node/api/Cargo.toml b/crates/node/api/Cargo.toml index eaba88fee..82e863d5a 100644 --- a/crates/node/api/Cargo.toml +++ b/crates/node/api/Cargo.toml @@ -14,8 +14,6 @@ workspace = true # reth reth-evm.workspace = true reth-provider.workspace = true -reth-chainspec.workspace = true -reth-db-api.workspace = true reth-engine-primitives.workspace = true reth-transaction-pool.workspace = true reth-payload-builder.workspace = true diff --git a/crates/node/api/src/node.rs b/crates/node/api/src/node.rs index 227a170d3..faabda427 100644 --- a/crates/node/api/src/node.rs +++ b/crates/node/api/src/node.rs @@ -2,91 +2,16 @@ use std::marker::PhantomData; -use reth_chainspec::EthChainSpec; -use reth_db_api::{ - database::Database, - database_metrics::{DatabaseMetadata, DatabaseMetrics}, -}; use reth_evm::execute::BlockExecutorProvider; use reth_network_api::FullNetwork; -use reth_node_types::{NodePrimitives, NodeTypes, NodeTypesWithDB, NodeTypesWithEngine}; +use reth_node_types::{NodeTypesWithDB, NodeTypesWithEngine}; use reth_payload_builder::PayloadBuilderHandle; use reth_provider::FullProvider; use reth_rpc_eth_api::EthApiTypes; use reth_tasks::TaskExecutor; use reth_transaction_pool::TransactionPool; -use crate::{ConfigureEvm, EngineTypes}; - -/// A [`NodeTypes`] type builder. -#[derive(Default, Debug)] -pub struct AnyNodeTypes

(PhantomData

, PhantomData); - -impl AnyNodeTypes { - /// Sets the `Primitives` associated type. - pub const fn primitives(self) -> AnyNodeTypes { - AnyNodeTypes::(PhantomData::, PhantomData::) - } - - /// Sets the `ChainSpec` associated type. - pub const fn chain_spec(self) -> AnyNodeTypes { - AnyNodeTypes::(PhantomData::

, PhantomData::) - } -} - -impl NodeTypes for AnyNodeTypes -where - P: NodePrimitives + Send + Sync + Unpin + 'static, - C: EthChainSpec, -{ - type Primitives = P; - type ChainSpec = C; -} - -/// A [`NodeTypesWithEngine`] type builder. -#[derive(Default, Debug)] -pub struct AnyNodeTypesWithEngine

{ - /// Embedding the basic node types. - base: AnyNodeTypes, - /// Phantom data for the engine. - _engine: PhantomData, -} - -impl AnyNodeTypesWithEngine { - /// Sets the `Primitives` associated type. - pub const fn primitives(self) -> AnyNodeTypesWithEngine { - AnyNodeTypesWithEngine { base: self.base.primitives::(), _engine: PhantomData } - } - - /// Sets the `Engine` associated type. - pub const fn engine(self) -> AnyNodeTypesWithEngine { - AnyNodeTypesWithEngine { base: self.base, _engine: PhantomData:: } - } - - /// Sets the `ChainSpec` associated type. - pub const fn chain_spec(self) -> AnyNodeTypesWithEngine { - AnyNodeTypesWithEngine { base: self.base.chain_spec::(), _engine: PhantomData } - } -} - -impl NodeTypes for AnyNodeTypesWithEngine -where - P: NodePrimitives + Send + Sync + Unpin + 'static, - E: EngineTypes + Send + Sync + Unpin, - C: EthChainSpec, -{ - type Primitives = P; - type ChainSpec = C; -} - -impl NodeTypesWithEngine for AnyNodeTypesWithEngine -where - P: NodePrimitives + Send + Sync + Unpin + 'static, - E: EngineTypes + Send + Sync + Unpin, - C: EthChainSpec, -{ - type Engine = E; -} +use crate::ConfigureEvm; /// A helper trait that is downstream of the [`NodeTypesWithEngine`] trait and adds stateful /// components to the node. @@ -99,57 +24,6 @@ pub trait FullNodeTypes: Send + Sync + Unpin + 'static { type Provider: FullProvider; } -/// An adapter type combining [`NodeTypes`] and db into [`NodeTypesWithDB`]. -#[derive(Debug)] -pub struct NodeTypesWithDBAdapter { - types: PhantomData, - db: PhantomData, -} - -impl NodeTypesWithDBAdapter { - /// Create a new adapter with the configured types. - pub fn new() -> Self { - Self { types: Default::default(), db: Default::default() } - } -} - -impl Default for NodeTypesWithDBAdapter { - fn default() -> Self { - Self::new() - } -} - -impl Clone for NodeTypesWithDBAdapter { - fn clone(&self) -> Self { - Self { types: self.types, db: self.db } - } -} - -impl NodeTypes for NodeTypesWithDBAdapter -where - Types: NodeTypes, - DB: Send + Sync + Unpin + 'static, -{ - type Primitives = Types::Primitives; - type ChainSpec = Types::ChainSpec; -} - -impl NodeTypesWithEngine for NodeTypesWithDBAdapter -where - Types: NodeTypesWithEngine, - DB: Send + Sync + Unpin + 'static, -{ - type Engine = Types::Engine; -} - -impl NodeTypesWithDB for NodeTypesWithDBAdapter -where - Types: NodeTypesWithEngine, - DB: Database + DatabaseMetrics + DatabaseMetadata + Clone + Unpin + 'static, -{ - type DB = DB; -} - /// An adapter type that adds the builtin provider type to the user configured node types. #[derive(Debug)] pub struct FullNodeTypesAdapter { diff --git a/crates/node/builder/src/builder/mod.rs b/crates/node/builder/src/builder/mod.rs index f799d2b68..3c0bae025 100644 --- a/crates/node/builder/src/builder/mod.rs +++ b/crates/node/builder/src/builder/mod.rs @@ -49,8 +49,10 @@ use crate::{ /// The adapter type for a reth node with the builtin provider type // Note: we need to hardcode this because custom components might depend on it in associated types. -pub type RethFullAdapter = - FullNodeTypesAdapter, BlockchainProvider>; +pub type RethFullAdapter = FullNodeTypesAdapter< + NodeTypesWithDBAdapter, + BlockchainProvider>, +>; #[allow(clippy::doc_markdown)] #[cfg_attr(doc, aquamarine::aquamarine)] diff --git a/crates/node/builder/src/launch/common.rs b/crates/node/builder/src/launch/common.rs index eeb6fc4a4..d93d3bb0a 100644 --- a/crates/node/builder/src/launch/common.rs +++ b/crates/node/builder/src/launch/common.rs @@ -1,6 +1,6 @@ //! Helper types that can be used by launchers. -use std::{marker::PhantomData, sync::Arc, thread::available_parallelism}; +use std::{sync::Arc, thread::available_parallelism}; use eyre::Context; use rayon::ThreadPoolBuilder; @@ -12,13 +12,13 @@ use reth_blockchain_tree::{ use reth_chainspec::{Chain, ChainSpec}; use reth_config::{config::EtlConfig, PruneConfig}; use reth_consensus::Consensus; -use reth_db_api::{database::Database, database_metrics::DatabaseMetrics}; +use reth_db_api::database::Database; use reth_db_common::init::{init_genesis, InitDatabaseError}; use reth_downloaders::{bodies::noop::NoopBodiesDownloader, headers::noop::NoopHeaderDownloader}; use reth_engine_tree::tree::{InvalidBlockHook, InvalidBlockHooks, NoopInvalidBlockHook}; use reth_evm::noop::NoopBlockExecutorProvider; use reth_network_p2p::headers::client::HeadersClient; -use reth_node_api::FullNodeTypes; +use reth_node_api::{FullNodeTypes, NodeTypes, NodeTypesWithDB}; use reth_node_core::{ dirs::{ChainPath, DataDirPath}, node_config::NodeConfig, @@ -65,13 +65,13 @@ pub trait WithTree { fn set_tree(self, tree: Arc) -> Self; } -impl WithTree for BlockchainProvider { +impl WithTree for BlockchainProvider { fn set_tree(self, tree: Arc) -> Self { self.with_tree(tree) } } -impl WithTree for BlockchainProvider2 { +impl WithTree for BlockchainProvider2 { fn set_tree(self, _tree: Arc) -> Self { self } @@ -386,7 +386,9 @@ where /// Returns the [`ProviderFactory`] for the attached storage after executing a consistent check /// between the database and static files. **It may execute a pipeline unwind if it fails this /// check.** - pub async fn create_provider_factory(&self) -> eyre::Result> { + pub async fn create_provider_factory>( + &self, + ) -> eyre::Result> { let factory = ProviderFactory::new( self.right().clone(), self.chain_spec(), @@ -413,7 +415,7 @@ where let (_tip_tx, tip_rx) = watch::channel(B256::ZERO); // Builds an unwind-only pipeline - let pipeline = Pipeline::builder() + let pipeline = Pipeline::::builder() .add_stages(DefaultStages::new( factory.clone(), tip_rx, @@ -447,9 +449,9 @@ where } /// Creates a new [`ProviderFactory`] and attaches it to the launch context. - pub async fn with_provider_factory( + pub async fn with_provider_factory>( self, - ) -> eyre::Result>>> { + ) -> eyre::Result>>> { let factory = self.create_provider_factory().await?; let ctx = LaunchContextWith { inner: self.inner, @@ -460,17 +462,17 @@ where } } -impl LaunchContextWith>> +impl LaunchContextWith>> where - DB: Database + DatabaseMetrics + Send + Sync + Clone + 'static, + T: NodeTypesWithDB, { /// Returns access to the underlying database. - pub fn database(&self) -> &DB { + pub const fn database(&self) -> &T::DB { self.right().db_ref() } /// Returns the configured `ProviderFactory`. - pub const fn provider_factory(&self) -> &ProviderFactory { + pub const fn provider_factory(&self) -> &ProviderFactory { self.right() } @@ -530,7 +532,7 @@ where /// prometheus. pub fn with_metrics_task( self, - ) -> LaunchContextWith>> { + ) -> LaunchContextWith>> { let (metrics_sender, metrics_receiver) = unbounded_channel(); let with_metrics = @@ -547,12 +549,12 @@ where } } -impl LaunchContextWith>> +impl LaunchContextWith>> where - DB: Database + DatabaseMetrics + Send + Sync + Clone + 'static, + N: NodeTypesWithDB, { /// Returns the configured `ProviderFactory`. - const fn provider_factory(&self) -> &ProviderFactory { + const fn provider_factory(&self) -> &ProviderFactory { &self.right().provider_factory } @@ -567,10 +569,10 @@ where create_blockchain_provider: F, tree_config: BlockchainTreeConfig, canon_state_notification_sender: CanonStateNotificationSender, - ) -> eyre::Result>>> + ) -> eyre::Result>>> where - T: FullNodeTypes, - F: FnOnce(ProviderFactory) -> eyre::Result, + T: FullNodeTypes, + F: FnOnce(ProviderFactory) -> eyre::Result, { let blockchain_db = create_blockchain_provider(self.provider_factory().clone())?; @@ -582,8 +584,6 @@ where blockchain_db, tree_config, canon_state_notification_sender, - // we store here a reference to T. - phantom_data: PhantomData, }; let ctx = LaunchContextWith { @@ -595,18 +595,17 @@ where } } -impl LaunchContextWith>> +impl LaunchContextWith>> where - DB: Database + DatabaseMetrics + Send + Sync + Clone + 'static, - T: FullNodeTypes, + T: FullNodeTypes, Provider: WithTree>, { /// Returns access to the underlying database. - pub fn database(&self) -> &DB { + pub const fn database(&self) -> &::DB { self.provider_factory().db_ref() } /// Returns the configured `ProviderFactory`. - pub const fn provider_factory(&self) -> &ProviderFactory { + pub const fn provider_factory(&self) -> &ProviderFactory { &self.right().db_provider_container.provider_factory } @@ -646,7 +645,7 @@ where on_component_initialized: Box< dyn OnComponentInitializedHook>, >, - ) -> eyre::Result>>> + ) -> eyre::Result>>> where CB: NodeComponentsBuilder, { @@ -714,14 +713,13 @@ where } } -impl LaunchContextWith>> +impl LaunchContextWith>> where - DB: Database + DatabaseMetrics + Send + Sync + Clone + 'static, - T: FullNodeTypes, + T: FullNodeTypes>, CB: NodeComponentsBuilder, { /// Returns the configured `ProviderFactory`. - pub const fn provider_factory(&self) -> &ProviderFactory { + pub const fn provider_factory(&self) -> &ProviderFactory { &self.right().db_provider_container.provider_factory } @@ -740,7 +738,7 @@ where } /// Creates a new [`StaticFileProducer`] with the attached database. - pub fn static_file_producer(&self) -> StaticFileProducer { + pub fn static_file_producer(&self) -> StaticFileProducer { StaticFileProducer::new(self.provider_factory().clone(), self.prune_modes()) } @@ -929,37 +927,32 @@ pub struct WithConfigs { /// Helper container type to bundle the [`ProviderFactory`] and the metrics /// sender. #[derive(Debug, Clone)] -pub struct WithMeteredProvider { - provider_factory: ProviderFactory, +pub struct WithMeteredProvider { + provider_factory: ProviderFactory, metrics_sender: UnboundedSender, } /// 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, { - db_provider_container: WithMeteredProvider, + db_provider_container: WithMeteredProvider, 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 - // can build the components in `with_components` method. - phantom_data: PhantomData, } /// Helper container to bundle the metered providers container and [`NodeAdapter`]. #[allow(missing_debug_implementations)] -pub struct WithComponents +pub struct WithComponents where - DB: Database, T: FullNodeTypes, CB: NodeComponentsBuilder, { - db_provider_container: WithMeteredProvider, + db_provider_container: WithMeteredProvider, tree_config: BlockchainTreeConfig, blockchain_db: T::Provider, node_adapter: NodeAdapter, diff --git a/crates/node/builder/src/launch/engine.rs b/crates/node/builder/src/launch/engine.rs index f56c31cff..0bb0227a4 100644 --- a/crates/node/builder/src/launch/engine.rs +++ b/crates/node/builder/src/launch/engine.rs @@ -59,7 +59,7 @@ impl EngineNodeLauncher { impl LaunchNode> for EngineNodeLauncher where Types: NodeTypesWithDB, - T: FullNodeTypes>, + T: FullNodeTypes>, CB: NodeComponentsBuilder, AO: NodeAddOns< NodeAdapter, diff --git a/crates/node/builder/src/launch/mod.rs b/crates/node/builder/src/launch/mod.rs index b74e6debd..02f2a8896 100644 --- a/crates/node/builder/src/launch/mod.rs +++ b/crates/node/builder/src/launch/mod.rs @@ -103,7 +103,7 @@ impl DefaultNodeLauncher { impl LaunchNode> for DefaultNodeLauncher where Types: NodeTypesWithDB, - T: FullNodeTypes, Types = Types>, + T: FullNodeTypes, Types = Types>, CB: NodeComponentsBuilder, AO: NodeAddOns< NodeAdapter, diff --git a/crates/node/builder/src/setup.rs b/crates/node/builder/src/setup.rs index e4b26649e..69972a5a2 100644 --- a/crates/node/builder/src/setup.rs +++ b/crates/node/builder/src/setup.rs @@ -4,7 +4,6 @@ use std::sync::Arc; use reth_config::{config::StageConfig, PruneConfig}; use reth_consensus::Consensus; -use reth_db_api::database::Database; use reth_downloaders::{ bodies::bodies::BodiesDownloaderBuilder, headers::reverse_headers::ReverseHeadersDownloaderBuilder, @@ -15,7 +14,7 @@ use reth_network_p2p::{ bodies::downloader::BodyDownloader, headers::downloader::HeaderDownloader, BlockClient, }; use reth_node_core::primitives::{BlockNumber, B256}; -use reth_provider::ProviderFactory; +use reth_provider::{providers::ProviderNodeTypes, ProviderFactory}; use reth_stages::{prelude::DefaultStages, stages::ExecutionStage, Pipeline, StageSet}; use reth_static_file::StaticFileProducer; use reth_tasks::TaskExecutor; @@ -24,21 +23,21 @@ use tokio::sync::watch; /// Constructs a [Pipeline] that's wired to the network #[allow(clippy::too_many_arguments)] -pub fn build_networked_pipeline( +pub fn build_networked_pipeline( config: &StageConfig, client: Client, consensus: Arc, - provider_factory: ProviderFactory, + provider_factory: ProviderFactory, task_executor: &TaskExecutor, metrics_tx: reth_stages::MetricEventsSender, prune_config: Option, max_block: Option, - static_file_producer: StaticFileProducer, + static_file_producer: StaticFileProducer, executor: Executor, exex_manager_handle: ExExManagerHandle, -) -> eyre::Result> +) -> eyre::Result> where - DB: Database + Unpin + Clone + 'static, + N: ProviderNodeTypes, Client: BlockClient + 'static, Executor: BlockExecutorProvider, { @@ -70,8 +69,8 @@ where /// Builds the [Pipeline] with the given [`ProviderFactory`] and downloaders. #[allow(clippy::too_many_arguments)] -pub fn build_pipeline( - provider_factory: ProviderFactory, +pub fn build_pipeline( + provider_factory: ProviderFactory, stage_config: &StageConfig, header_downloader: H, body_downloader: B, @@ -79,17 +78,17 @@ pub fn build_pipeline( max_block: Option, metrics_tx: reth_stages::MetricEventsSender, prune_config: Option, - static_file_producer: StaticFileProducer, + static_file_producer: StaticFileProducer, executor: Executor, exex_manager_handle: ExExManagerHandle, -) -> eyre::Result> +) -> eyre::Result> where - DB: Database + Clone + 'static, + N: ProviderNodeTypes, H: HeaderDownloader + 'static, B: BodyDownloader + 'static, Executor: BlockExecutorProvider, { - let mut builder = Pipeline::builder(); + let mut builder = Pipeline::::builder(); if let Some(max_block) = max_block { debug!(target: "reth::cli", max_block, "Configuring builder to use max block"); diff --git a/crates/node/core/Cargo.toml b/crates/node/core/Cargo.toml index e688b1da3..8381a668f 100644 --- a/crates/node/core/Cargo.toml +++ b/crates/node/core/Cargo.toml @@ -40,6 +40,7 @@ reth-consensus-common.workspace = true reth-prune-types.workspace = true reth-stages-types.workspace = true reth-optimism-chainspec = { workspace = true, optional = true } +reth-node-types.workspace = true # ethereum alloy-genesis.workspace = true diff --git a/crates/node/core/src/node_config.rs b/crates/node/core/src/node_config.rs index 176d43e26..7a2856d07 100644 --- a/crates/node/core/src/node_config.rs +++ b/crates/node/core/src/node_config.rs @@ -11,11 +11,11 @@ use crate::{ use eyre::eyre; use reth_chainspec::{ChainSpec, MAINNET}; use reth_config::config::PruneConfig; -use reth_db_api::database::Database; use reth_network_p2p::headers::client::HeadersClient; use serde::{de::DeserializeOwned, Serialize}; use std::{fs, path::Path}; +use reth_node_types::NodeTypesWithDB; use reth_primitives::{ revm_primitives::EnvKzgSettings, BlockHashOrNumber, BlockNumber, Head, SealedHeader, B256, }; @@ -269,7 +269,10 @@ impl NodeConfig { /// Fetches the head block from the database. /// /// If the database is empty, returns the genesis block. - pub fn lookup_head(&self, factory: ProviderFactory) -> ProviderResult { + pub fn lookup_head>( + &self, + factory: ProviderFactory, + ) -> ProviderResult { let provider = factory.provider()?; let head = provider.get_stage_checkpoint(StageId::Finish)?.unwrap_or_default().block_number; diff --git a/crates/node/metrics/Cargo.toml b/crates/node/metrics/Cargo.toml index 74333cf4f..b43d40252 100644 --- a/crates/node/metrics/Cargo.toml +++ b/crates/node/metrics/Cargo.toml @@ -34,10 +34,10 @@ tikv-jemalloc-ctl = { version = "0.5.0", optional = true } procfs = "0.16.0" [dev-dependencies] -reth-db = { workspace = true, features = ["test-utils"] } reqwest.workspace = true reth-chainspec.workspace = true socket2 = { version = "0.4", default-features = false } +reth-provider = { workspace = true, features = ["test-utils"] } [lints] workspace = true diff --git a/crates/node/metrics/src/server.rs b/crates/node/metrics/src/server.rs index 5eadaaab5..d22df4eab 100644 --- a/crates/node/metrics/src/server.rs +++ b/crates/node/metrics/src/server.rs @@ -204,27 +204,11 @@ const fn describe_io_stats() {} mod tests { use super::*; use reqwest::Client; - use reth_chainspec::MAINNET; - use reth_db::{ - test_utils::{create_test_rw_db, create_test_static_files_dir, TempDatabase}, - DatabaseEnv, - }; - use reth_provider::{ - providers::StaticFileProvider, ProviderFactory, StaticFileProviderFactory, - }; + use reth_provider::{test_utils::create_test_provider_factory, StaticFileProviderFactory}; use reth_tasks::TaskManager; use socket2::{Domain, Socket, Type}; use std::net::{SocketAddr, TcpListener}; - fn create_test_db() -> ProviderFactory>> { - let (_, static_dir_path) = create_test_static_files_dir(); - ProviderFactory::new( - create_test_rw_db(), - MAINNET.clone(), - StaticFileProvider::read_write(static_dir_path).unwrap(), - ) - } - fn get_random_available_addr() -> SocketAddr { let addr = &"127.0.0.1:0".parse::().unwrap().into(); let socket = Socket::new(Domain::IPV4, Type::STREAM, None).unwrap(); @@ -249,7 +233,7 @@ mod tests { let tasks = TaskManager::current(); let executor = tasks.executor(); - let factory = create_test_db(); + let factory = create_test_provider_factory(); let hooks = Hooks::new(factory.db_ref().clone(), factory.static_file_provider()); let listen_addr = get_random_available_addr(); diff --git a/crates/node/types/src/lib.rs b/crates/node/types/src/lib.rs index a53a240a8..5abd31323 100644 --- a/crates/node/types/src/lib.rs +++ b/crates/node/types/src/lib.rs @@ -8,6 +8,8 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +use std::marker::PhantomData; + use reth_chainspec::EthChainSpec; use reth_db_api::{ database_metrics::{DatabaseMetadata, DatabaseMetrics}, @@ -48,3 +50,124 @@ pub trait NodeTypesWithDB: NodeTypesWithEngine { /// Underlying database type used by the node to store and retrieve data. type DB: Database + DatabaseMetrics + DatabaseMetadata + Clone + Unpin + 'static; } + +/// An adapter type combining [`NodeTypes`] and db into [`NodeTypesWithDB`]. +#[derive(Debug)] +pub struct NodeTypesWithDBAdapter { + types: PhantomData, + db: PhantomData, +} + +impl NodeTypesWithDBAdapter { + /// Create a new adapter with the configured types. + pub fn new() -> Self { + Self { types: Default::default(), db: Default::default() } + } +} + +impl Default for NodeTypesWithDBAdapter { + fn default() -> Self { + Self::new() + } +} + +impl Clone for NodeTypesWithDBAdapter { + fn clone(&self) -> Self { + Self { types: self.types, db: self.db } + } +} + +impl NodeTypes for NodeTypesWithDBAdapter +where + Types: NodeTypes, + DB: Send + Sync + Unpin + 'static, +{ + type Primitives = Types::Primitives; + type ChainSpec = Types::ChainSpec; +} + +impl NodeTypesWithEngine for NodeTypesWithDBAdapter +where + Types: NodeTypesWithEngine, + DB: Send + Sync + Unpin + 'static, +{ + type Engine = Types::Engine; +} + +impl NodeTypesWithDB for NodeTypesWithDBAdapter +where + Types: NodeTypesWithEngine, + DB: Database + DatabaseMetrics + DatabaseMetadata + Clone + Unpin + 'static, +{ + type DB = DB; +} + +/// A [`NodeTypes`] type builder. +#[derive(Default, Debug)] +pub struct AnyNodeTypes

(PhantomData

, PhantomData); + +impl AnyNodeTypes { + /// Sets the `Primitives` associated type. + pub const fn primitives(self) -> AnyNodeTypes { + AnyNodeTypes::(PhantomData::, PhantomData::) + } + + /// Sets the `ChainSpec` associated type. + pub const fn chain_spec(self) -> AnyNodeTypes { + AnyNodeTypes::(PhantomData::

, PhantomData::) + } +} + +impl NodeTypes for AnyNodeTypes +where + P: NodePrimitives + Send + Sync + Unpin + 'static, + C: EthChainSpec, +{ + type Primitives = P; + type ChainSpec = C; +} + +/// A [`NodeTypesWithEngine`] type builder. +#[derive(Default, Debug)] +pub struct AnyNodeTypesWithEngine

{ + /// Embedding the basic node types. + base: AnyNodeTypes, + /// Phantom data for the engine. + _engine: PhantomData, +} + +impl AnyNodeTypesWithEngine { + /// Sets the `Primitives` associated type. + pub const fn primitives(self) -> AnyNodeTypesWithEngine { + AnyNodeTypesWithEngine { base: self.base.primitives::(), _engine: PhantomData } + } + + /// Sets the `Engine` associated type. + pub const fn engine(self) -> AnyNodeTypesWithEngine { + AnyNodeTypesWithEngine { base: self.base, _engine: PhantomData:: } + } + + /// Sets the `ChainSpec` associated type. + pub const fn chain_spec(self) -> AnyNodeTypesWithEngine { + AnyNodeTypesWithEngine { base: self.base.chain_spec::(), _engine: PhantomData } + } +} + +impl NodeTypes for AnyNodeTypesWithEngine +where + P: NodePrimitives + Send + Sync + Unpin + 'static, + E: EngineTypes + Send + Sync + Unpin, + C: EthChainSpec, +{ + type Primitives = P; + type ChainSpec = C; +} + +impl NodeTypesWithEngine for AnyNodeTypesWithEngine +where + P: NodePrimitives + Send + Sync + Unpin + 'static, + E: EngineTypes + Send + Sync + Unpin, + C: EthChainSpec, +{ + type Engine = E; +} diff --git a/crates/optimism/cli/Cargo.toml b/crates/optimism/cli/Cargo.toml index 6eb896edd..41135d4a2 100644 --- a/crates/optimism/cli/Cargo.toml +++ b/crates/optimism/cli/Cargo.toml @@ -23,6 +23,7 @@ reth-stages.workspace = true reth-static-file.workspace = true reth-execution-types.workspace = true reth-node-core.workspace = true +reth-node-optimism.workspace = true reth-primitives.workspace = true ## optimisim @@ -72,4 +73,5 @@ reth-db-common.workspace = true "reth-primitives/optimism", "reth-evm-optimism/optimism", "reth-provider/optimism", + "reth-node-optimism/optimism", ] diff --git a/crates/optimism/cli/src/commands/build_pipeline.rs b/crates/optimism/cli/src/commands/build_pipeline.rs index e770a1e8b..20f01cc17 100644 --- a/crates/optimism/cli/src/commands/build_pipeline.rs +++ b/crates/optimism/cli/src/commands/build_pipeline.rs @@ -1,8 +1,8 @@ use alloy_primitives::B256; use futures_util::{Stream, StreamExt}; +use reth_chainspec::ChainSpec; use reth_config::Config; use reth_consensus::Consensus; -use reth_db_api::database::Database; use reth_downloaders::{ bodies::bodies::BodiesDownloaderBuilder, file_client::FileClient, headers::reverse_headers::ReverseHeadersDownloaderBuilder, @@ -13,6 +13,7 @@ use reth_network_p2p::{ bodies::downloader::BodyDownloader, headers::downloader::{HeaderDownloader, SyncTarget}, }; +use reth_node_builder::NodeTypesWithDB; use reth_node_events::node::NodeEvent; use reth_provider::{BlockNumReader, ChainSpecProvider, HeaderProvider, ProviderFactory}; use reth_prune::PruneModes; @@ -26,16 +27,16 @@ use tokio::sync::watch; /// /// If configured to execute, all stages will run. Otherwise, only stages that don't require state /// will run. -pub(crate) async fn build_import_pipeline( +pub(crate) async fn build_import_pipeline( config: &Config, - provider_factory: ProviderFactory, + provider_factory: ProviderFactory, consensus: &Arc, file_client: Arc, - static_file_producer: StaticFileProducer, + static_file_producer: StaticFileProducer, disable_exec: bool, -) -> eyre::Result<(Pipeline, impl Stream)> +) -> eyre::Result<(Pipeline, impl Stream)> where - DB: Database + Clone + Unpin + 'static, + N: NodeTypesWithDB, C: Consensus + 'static, { if !file_client.has_canonical_blocks() { @@ -70,7 +71,7 @@ where let max_block = file_client.max_block().unwrap_or(0); - let pipeline = Pipeline::builder() + let pipeline = Pipeline::::builder() .with_tip_sender(tip_tx) // we want to sync all blocks the file client provides or 0 if empty .with_max_block(max_block) diff --git a/crates/optimism/cli/src/commands/import.rs b/crates/optimism/cli/src/commands/import.rs index 5028efb80..c4823fdf4 100644 --- a/crates/optimism/cli/src/commands/import.rs +++ b/crates/optimism/cli/src/commands/import.rs @@ -10,6 +10,7 @@ use reth_db_api::transaction::DbTx; use reth_downloaders::file_client::{ ChunkedFileReader, FileClient, DEFAULT_BYTE_LEN_CHUNK_CHAIN_FILE, }; +use reth_node_builder::NodeTypesWithEngine; use reth_node_core::version::SHORT_VERSION; use reth_optimism_primitives::bedrock_import::is_dup_tx; use reth_provider::StageCheckpointReader; @@ -41,7 +42,9 @@ pub struct ImportOpCommand { impl> ImportOpCommand { /// Execute `import` command - pub async fn execute(self) -> eyre::Result<()> { + pub async fn execute>( + self, + ) -> eyre::Result<()> { info!(target: "reth::cli", "reth {} starting", SHORT_VERSION); info!(target: "reth::cli", @@ -53,7 +56,7 @@ impl> ImportOpCommand { "Chunking chain import" ); - let Environment { provider_factory, config, .. } = self.env.init(AccessRights::RW)?; + let Environment { provider_factory, config, .. } = self.env.init::(AccessRights::RW)?; // we use noop here because we expect the inputs to be valid let consensus = Arc::new(NoopConsensus::default()); diff --git a/crates/optimism/cli/src/commands/import_receipts.rs b/crates/optimism/cli/src/commands/import_receipts.rs index bebc35c08..efc815dc4 100644 --- a/crates/optimism/cli/src/commands/import_receipts.rs +++ b/crates/optimism/cli/src/commands/import_receipts.rs @@ -8,12 +8,12 @@ use reth_chainspec::ChainSpec; use reth_cli::chainspec::ChainSpecParser; use reth_cli_commands::common::{AccessRights, Environment, EnvironmentArgs}; use reth_db::tables; -use reth_db_api::database::Database; use reth_downloaders::{ file_client::{ChunkedFileReader, DEFAULT_BYTE_LEN_CHUNK_CHAIN_FILE}, receipt_file_client::ReceiptFileClient, }; use reth_execution_types::ExecutionOutcome; +use reth_node_builder::{NodeTypesWithDB, NodeTypesWithEngine}; use reth_node_core::version::SHORT_VERSION; use reth_optimism_primitives::bedrock_import::is_dup_tx; use reth_primitives::Receipts; @@ -47,7 +47,9 @@ pub struct ImportReceiptsOpCommand { impl> ImportReceiptsOpCommand { /// Execute `import` command - pub async fn execute(self) -> eyre::Result<()> { + pub async fn execute>( + self, + ) -> eyre::Result<()> { info!(target: "reth::cli", "reth {} starting", SHORT_VERSION); debug!(target: "reth::cli", @@ -55,7 +57,7 @@ impl> ImportReceiptsOpCommand { "Chunking receipts import" ); - let Environment { provider_factory, .. } = self.env.init(AccessRights::RW)?; + let Environment { provider_factory, .. } = self.env.init::(AccessRights::RW)?; import_receipts_from_file( provider_factory, @@ -78,14 +80,14 @@ impl> ImportReceiptsOpCommand { } /// Imports receipts to static files from file in chunks. See [`import_receipts_from_reader`]. -pub async fn import_receipts_from_file( - provider_factory: ProviderFactory, +pub async fn import_receipts_from_file( + provider_factory: ProviderFactory, path: P, chunk_len: Option, filter: F, ) -> eyre::Result<()> where - DB: Database, + N: NodeTypesWithDB, P: AsRef, F: FnMut(u64, &mut Receipts) -> usize, { @@ -170,13 +172,13 @@ where /// Caution! Filter callback must replace completely filtered out receipts for a block, with empty /// vectors, rather than `vec!(None)`. This is since the code for writing to static files, expects /// indices in the [`Receipts`] list, to map to sequential block numbers. -pub async fn import_receipts_from_reader( - provider_factory: &ProviderFactory, +pub async fn import_receipts_from_reader( + provider_factory: &ProviderFactory, mut reader: ChunkedFileReader, mut filter: F, ) -> eyre::Result where - DB: Database, + N: NodeTypesWithDB, F: FnMut(u64, &mut Receipts) -> usize, { let mut total_decoded_receipts = 0; diff --git a/crates/optimism/cli/src/lib.rs b/crates/optimism/cli/src/lib.rs index 4af95a88a..b83d08db5 100644 --- a/crates/optimism/cli/src/lib.rs +++ b/crates/optimism/cli/src/lib.rs @@ -46,6 +46,7 @@ use reth_node_core::{ args::LogArgs, version::{LONG_VERSION, SHORT_VERSION}, }; +use reth_node_optimism::OptimismNode; use reth_tracing::FileWorkerGuard; use tracing::info; @@ -130,20 +131,31 @@ impl Cli { Commands::Node(command) => { runner.run_command_until_exit(|ctx| command.execute(ctx, launcher)) } - Commands::Init(command) => runner.run_blocking_until_ctrl_c(command.execute()), - Commands::InitState(command) => runner.run_blocking_until_ctrl_c(command.execute()), - Commands::ImportOp(command) => runner.run_blocking_until_ctrl_c(command.execute()), + Commands::Init(command) => { + runner.run_blocking_until_ctrl_c(command.execute::()) + } + Commands::InitState(command) => { + runner.run_blocking_until_ctrl_c(command.execute::()) + } + Commands::ImportOp(command) => { + runner.run_blocking_until_ctrl_c(command.execute::()) + } Commands::ImportReceiptsOp(command) => { - runner.run_blocking_until_ctrl_c(command.execute()) + runner.run_blocking_until_ctrl_c(command.execute::()) } Commands::DumpGenesis(command) => runner.run_blocking_until_ctrl_c(command.execute()), - Commands::Db(command) => runner.run_blocking_until_ctrl_c(command.execute()), - Commands::Stage(command) => runner - .run_command_until_exit(|ctx| command.execute(ctx, OpExecutorProvider::optimism)), + Commands::Db(command) => { + runner.run_blocking_until_ctrl_c(command.execute::()) + } + Commands::Stage(command) => runner.run_command_until_exit(|ctx| { + command.execute::(ctx, OpExecutorProvider::optimism) + }), Commands::P2P(command) => runner.run_until_ctrl_c(command.execute()), Commands::Config(command) => runner.run_until_ctrl_c(command.execute()), - Commands::Recover(command) => runner.run_command_until_exit(|ctx| command.execute(ctx)), - Commands::Prune(command) => runner.run_until_ctrl_c(command.execute()), + Commands::Recover(command) => { + runner.run_command_until_exit(|ctx| command.execute::(ctx)) + } + Commands::Prune(command) => runner.run_until_ctrl_c(command.execute::()), } } diff --git a/crates/prune/prune/Cargo.toml b/crates/prune/prune/Cargo.toml index 2f2a37d5b..091ecf424 100644 --- a/crates/prune/prune/Cargo.toml +++ b/crates/prune/prune/Cargo.toml @@ -23,6 +23,7 @@ reth-tokio-util.workspace = true reth-config.workspace = true reth-prune-types.workspace = true reth-static-file-types.workspace = true +reth-node-types.workspace = true # metrics reth-metrics.workspace = true diff --git a/crates/prune/prune/src/builder.rs b/crates/prune/prune/src/builder.rs index af426a898..7bd699ce4 100644 --- a/crates/prune/prune/src/builder.rs +++ b/crates/prune/prune/src/builder.rs @@ -3,6 +3,7 @@ use reth_chainspec::MAINNET; use reth_config::PruneConfig; use reth_db_api::database::Database; use reth_exex_types::FinishedExExHeight; +use reth_node_types::NodeTypesWithDB; use reth_provider::{providers::StaticFileProvider, ProviderFactory, StaticFileProviderFactory}; use reth_prune_types::PruneModes; use std::time::Duration; @@ -71,16 +72,14 @@ impl PrunerBuilder { } /// Builds a [Pruner] from the current configuration with the given provider factory. - pub fn build_with_provider_factory( + pub fn build_with_provider_factory( self, - provider_factory: ProviderFactory, - ) -> Pruner> { - let segments = SegmentSet::::from_components( - provider_factory.static_file_provider(), - self.segments, - ); + provider_factory: ProviderFactory, + ) -> Pruner> { + let segments = + SegmentSet::from_components(provider_factory.static_file_provider(), self.segments); - Pruner::<_, ProviderFactory>::new( + Pruner::<_, ProviderFactory>::new( provider_factory, segments.into_vec(), self.block_interval, diff --git a/crates/prune/prune/src/pruner.rs b/crates/prune/prune/src/pruner.rs index dea50406a..f47705211 100644 --- a/crates/prune/prune/src/pruner.rs +++ b/crates/prune/prune/src/pruner.rs @@ -7,7 +7,10 @@ use crate::{ use alloy_primitives::BlockNumber; use reth_db_api::database::Database; use reth_exex_types::FinishedExExHeight; -use reth_provider::{DatabaseProviderRW, ProviderFactory, PruneCheckpointReader}; +use reth_node_types::NodeTypesWithDB; +use reth_provider::{ + providers::ProviderNodeTypes, DatabaseProviderRW, ProviderFactory, PruneCheckpointReader, +}; use reth_prune_types::{PruneLimiter, PruneProgress, PruneSegment, PrunerOutput}; use reth_tokio_util::{EventSender, EventStream}; use std::time::{Duration, Instant}; @@ -69,11 +72,11 @@ impl Pruner { } } -impl Pruner> { +impl Pruner> { /// Crates a new pruner with the given provider factory. pub fn new( - provider_factory: ProviderFactory, - segments: Vec>>, + provider_factory: ProviderFactory, + segments: Vec>>, min_block_interval: usize, delete_limit: usize, timeout: Option, @@ -312,7 +315,7 @@ impl Pruner { } } -impl Pruner> { +impl Pruner> { /// Run the pruner. This will only prune data up to the highest finished ExEx height, if there /// are no ExExes. /// diff --git a/crates/stages/api/Cargo.toml b/crates/stages/api/Cargo.toml index a5db5b9fb..8b74b8c5a 100644 --- a/crates/stages/api/Cargo.toml +++ b/crates/stages/api/Cargo.toml @@ -23,6 +23,7 @@ reth-prune.workspace = true reth-errors.workspace = true reth-stages-types.workspace = true reth-static-file-types.workspace = true +reth-node-types.workspace = true alloy-primitives.workspace = true diff --git a/crates/stages/api/src/pipeline/builder.rs b/crates/stages/api/src/pipeline/builder.rs index 1e83af4c3..c5c585cfc 100644 --- a/crates/stages/api/src/pipeline/builder.rs +++ b/crates/stages/api/src/pipeline/builder.rs @@ -1,6 +1,7 @@ use crate::{pipeline::BoxedStage, MetricEventsSender, Pipeline, Stage, StageId, StageSet}; use alloy_primitives::{BlockNumber, B256}; use reth_db_api::database::Database; +use reth_node_types::NodeTypesWithDB; use reth_provider::ProviderFactory; use reth_static_file::StaticFileProducer; use tokio::sync::watch; @@ -68,11 +69,11 @@ where } /// Builds the final [`Pipeline`] using the given database. - pub fn build( + pub fn build>( self, - provider_factory: ProviderFactory, - static_file_producer: StaticFileProducer, - ) -> Pipeline { + provider_factory: ProviderFactory, + static_file_producer: StaticFileProducer, + ) -> Pipeline { let Self { stages, max_block, tip_tx, metrics_tx } = self; Pipeline { provider_factory, diff --git a/crates/stages/api/src/pipeline/mod.rs b/crates/stages/api/src/pipeline/mod.rs index b2cdbfa1a..470adf228 100644 --- a/crates/stages/api/src/pipeline/mod.rs +++ b/crates/stages/api/src/pipeline/mod.rs @@ -5,11 +5,12 @@ use crate::{PipelineTarget, StageCheckpoint, StageId}; use alloy_primitives::{BlockNumber, B256}; pub use event::*; use futures_util::Future; -use reth_db_api::database::Database; +use reth_node_types::NodeTypesWithDB; use reth_primitives_traits::constants::BEACON_CONSENSUS_REORG_UNWIND_DEPTH; use reth_provider::{ - writer::UnifiedStorageWriter, FinalizedBlockReader, FinalizedBlockWriter, ProviderFactory, - StageCheckpointReader, StageCheckpointWriter, StaticFileProviderFactory, + providers::ProviderNodeTypes, writer::UnifiedStorageWriter, FinalizedBlockReader, + FinalizedBlockWriter, ProviderFactory, StageCheckpointReader, StageCheckpointWriter, + StaticFileProviderFactory, }; use reth_prune::PrunerBuilder; use reth_static_file::StaticFileProducer; @@ -36,10 +37,10 @@ pub(crate) type BoxedStage = Box>; /// The future that returns the owned pipeline and the result of the pipeline run. See /// [`Pipeline::run_as_fut`]. -pub type PipelineFut = Pin> + Send>>; +pub type PipelineFut = Pin> + Send>>; /// The pipeline type itself with the result of [`Pipeline::run_as_fut`] -pub type PipelineWithResult = (Pipeline, Result); +pub type PipelineWithResult = (Pipeline, Result); #[cfg_attr(doc, aquamarine::aquamarine)] /// A staged sync pipeline. @@ -63,14 +64,14 @@ pub type PipelineWithResult = (Pipeline, Result { +pub struct Pipeline { /// Provider factory. - provider_factory: ProviderFactory, + provider_factory: ProviderFactory, /// All configured stages in the order they will be executed. - stages: Vec>, + stages: Vec>, /// The maximum block number to sync to. max_block: Option, - static_file_producer: StaticFileProducer, + static_file_producer: StaticFileProducer, /// Sender for events the pipeline emits. event_sender: EventSender, /// Keeps track of the progress of the pipeline. @@ -80,12 +81,9 @@ pub struct Pipeline { metrics_tx: Option, } -impl Pipeline -where - DB: Database + 'static, -{ +impl Pipeline { /// Construct a pipeline using a [`PipelineBuilder`]. - pub fn builder() -> PipelineBuilder { + pub fn builder() -> PipelineBuilder { PipelineBuilder::default() } @@ -107,7 +105,9 @@ where pub fn events(&self) -> EventStream { self.event_sender.new_listener() } +} +impl Pipeline { /// Registers progress metrics for each registered stage pub fn register_metrics(&mut self) -> Result<(), PipelineError> { let Some(metrics_tx) = &mut self.metrics_tx else { return Ok(()) }; @@ -127,7 +127,7 @@ where /// Consume the pipeline and run it until it reaches the provided tip, if set. Return the /// pipeline and its result as a future. #[track_caller] - pub fn run_as_fut(mut self, target: Option) -> PipelineFut { + pub fn run_as_fut(mut self, target: Option) -> PipelineFut { // TODO: fix this in a follow up PR. ideally, consensus engine would be responsible for // updating metrics. let _ = self.register_metrics(); // ignore error @@ -487,8 +487,8 @@ where } } -fn on_stage_error( - factory: &ProviderFactory, +fn on_stage_error( + factory: &ProviderFactory, stage_id: StageId, prev_checkpoint: Option, err: StageError, @@ -574,7 +574,7 @@ fn on_stage_error( } } -impl std::fmt::Debug for Pipeline { +impl std::fmt::Debug for Pipeline { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Pipeline") .field("stages", &self.stages.iter().map(|stage| stage.id()).collect::>()) @@ -591,7 +591,7 @@ mod tests { use assert_matches::assert_matches; use reth_consensus::ConsensusError; use reth_errors::ProviderError; - use reth_provider::test_utils::create_test_provider_factory; + use reth_provider::test_utils::{create_test_provider_factory, MockNodeTypesWithDB}; use reth_prune::PruneModes; use reth_testing_utils::{generators, generators::random_header}; use tokio_stream::StreamExt; @@ -628,7 +628,7 @@ mod tests { async fn run_pipeline() { let provider_factory = create_test_provider_factory(); - let mut pipeline = Pipeline::builder() + let mut pipeline = Pipeline::::builder() .add_stage( TestStage::new(StageId::Other("A")) .add_exec(Ok(ExecOutput { checkpoint: StageCheckpoint::new(20), done: true })), @@ -696,7 +696,7 @@ mod tests { async fn unwind_pipeline() { let provider_factory = create_test_provider_factory(); - let mut pipeline = Pipeline::builder() + let mut pipeline = Pipeline::::builder() .add_stage( TestStage::new(StageId::Other("A")) .add_exec(Ok(ExecOutput { checkpoint: StageCheckpoint::new(100), done: true })) @@ -830,7 +830,7 @@ mod tests { async fn unwind_pipeline_with_intermediate_progress() { let provider_factory = create_test_provider_factory(); - let mut pipeline = Pipeline::builder() + let mut pipeline = Pipeline::::builder() .add_stage( TestStage::new(StageId::Other("A")) .add_exec(Ok(ExecOutput { checkpoint: StageCheckpoint::new(100), done: true })) @@ -930,7 +930,7 @@ mod tests { async fn run_pipeline_with_unwind() { let provider_factory = create_test_provider_factory(); - let mut pipeline = Pipeline::builder() + let mut pipeline = Pipeline::::builder() .add_stage( TestStage::new(StageId::Other("A")) .add_exec(Ok(ExecOutput { checkpoint: StageCheckpoint::new(10), done: true })) @@ -1051,7 +1051,7 @@ mod tests { async fn pipeline_error_handling() { // Non-fatal let provider_factory = create_test_provider_factory(); - let mut pipeline = Pipeline::builder() + let mut pipeline = Pipeline::::builder() .add_stage( TestStage::new(StageId::Other("NonFatal")) .add_exec(Err(StageError::Recoverable(Box::new(std::fmt::Error)))) @@ -1067,7 +1067,7 @@ mod tests { // Fatal let provider_factory = create_test_provider_factory(); - let mut pipeline = Pipeline::builder() + let mut pipeline = Pipeline::::builder() .add_stage(TestStage::new(StageId::Other("Fatal")).add_exec(Err( StageError::DatabaseIntegrity(ProviderError::BlockBodyIndicesNotFound(5)), ))) diff --git a/crates/stages/stages/src/lib.rs b/crates/stages/stages/src/lib.rs index 10b2e1976..e33b6e7c0 100644 --- a/crates/stages/stages/src/lib.rs +++ b/crates/stages/stages/src/lib.rs @@ -27,7 +27,7 @@ //! # use reth_evm_ethereum::EthEvmConfig; //! # use reth_provider::ProviderFactory; //! # use reth_provider::StaticFileProviderFactory; -//! # use reth_provider::test_utils::create_test_provider_factory; +//! # use reth_provider::test_utils::{create_test_provider_factory, MockNodeTypesWithDB}; //! # use reth_static_file::StaticFileProducer; //! # use reth_config::config::StageConfig; //! # use reth_consensus::Consensus; @@ -53,7 +53,7 @@ //! # ); //! // Create a pipeline that can fully sync //! # let pipeline = -//! Pipeline::builder() +//! Pipeline::::builder() //! .with_tip_sender(tip_tx) //! .add_stages(DefaultStages::new( //! provider_factory.clone(), diff --git a/crates/stages/stages/src/sets.rs b/crates/stages/stages/src/sets.rs index 3945bb039..d97b31e06 100644 --- a/crates/stages/stages/src/sets.rs +++ b/crates/stages/stages/src/sets.rs @@ -16,7 +16,7 @@ //! # use reth_prune_types::PruneModes; //! # use reth_evm_ethereum::EthEvmConfig; //! # use reth_provider::StaticFileProviderFactory; -//! # use reth_provider::test_utils::create_test_provider_factory; +//! # use reth_provider::test_utils::{create_test_provider_factory, MockNodeTypesWithDB}; //! # use reth_static_file::StaticFileProducer; //! # use reth_config::config::StageConfig; //! # use reth_evm::execute::BlockExecutorProvider; @@ -27,7 +27,7 @@ //! let static_file_producer = //! StaticFileProducer::new(provider_factory.clone(), PruneModes::default()); //! // Build a pipeline with all offline stages. -//! let pipeline = Pipeline::builder() +//! let pipeline = Pipeline::::builder() //! .add_stages(OfflineStages::new(exec, StageConfig::default(), PruneModes::default())) //! .build(provider_factory, static_file_producer); //! diff --git a/crates/stages/stages/src/stages/bodies.rs b/crates/stages/stages/src/stages/bodies.rs index d292ed66e..175154738 100644 --- a/crates/stages/stages/src/stages/bodies.rs +++ b/crates/stages/stages/src/stages/bodies.rs @@ -618,7 +618,7 @@ mod tests { }, }; use futures_util::Stream; - use reth_db::{static_file::HeaderMask, tables, test_utils::TempDatabase, DatabaseEnv}; + use reth_db::{static_file::HeaderMask, tables}; use reth_db_api::{ cursor::DbCursorRO, models::{StoredBlockBodyIndices, StoredBlockOmmers}, @@ -636,8 +636,8 @@ mod tests { StaticFileSegment, TxNumber, B256, }; use reth_provider::{ - providers::StaticFileWriter, HeaderProvider, ProviderFactory, - StaticFileProviderFactory, TransactionsProvider, + providers::StaticFileWriter, test_utils::MockNodeTypesWithDB, HeaderProvider, + ProviderFactory, StaticFileProviderFactory, TransactionsProvider, }; use reth_stages_api::{ExecInput, ExecOutput, UnwindInput}; use reth_testing_utils::generators::{ @@ -647,7 +647,6 @@ mod tests { collections::{HashMap, VecDeque}, ops::RangeInclusive, pin::Pin, - sync::Arc, task::{Context, Poll}, }; @@ -892,7 +891,7 @@ mod tests { /// A [`BodyDownloader`] that is backed by an internal [`HashMap`] for testing. #[derive(Debug)] pub(crate) struct TestBodyDownloader { - provider_factory: ProviderFactory>>, + provider_factory: ProviderFactory, responses: HashMap, headers: VecDeque, batch_size: u64, @@ -900,7 +899,7 @@ mod tests { impl TestBodyDownloader { pub(crate) fn new( - provider_factory: ProviderFactory>>, + provider_factory: ProviderFactory, responses: HashMap, batch_size: u64, ) -> Self { diff --git a/crates/stages/stages/src/stages/headers.rs b/crates/stages/stages/src/stages/headers.rs index 3e376f672..d3329f56a 100644 --- a/crates/stages/stages/src/stages/headers.rs +++ b/crates/stages/stages/src/stages/headers.rs @@ -389,12 +389,11 @@ mod tests { use super::*; use crate::test_utils::{TestRunnerError, TestStageDB}; use reth_consensus::test_utils::TestConsensus; - use reth_db::{test_utils::TempDatabase, DatabaseEnv}; use reth_downloaders::headers::reverse_headers::{ ReverseHeadersDownloader, ReverseHeadersDownloaderBuilder, }; use reth_network_p2p::test_utils::{TestHeaderDownloader, TestHeadersClient}; - use reth_provider::BlockNumReader; + use reth_provider::{test_utils::MockNodeTypesWithDB, BlockNumReader}; use tokio::sync::watch; pub(crate) struct HeadersTestRunner { @@ -426,7 +425,7 @@ mod tests { } impl StageTestRunner for HeadersTestRunner { - type S = HeaderStage>>, D>; + type S = HeaderStage, D>; fn db(&self) -> &TestStageDB { &self.db diff --git a/crates/stages/stages/src/stages/mod.rs b/crates/stages/stages/src/stages/mod.rs index eca259585..694f3e472 100644 --- a/crates/stages/stages/src/stages/mod.rs +++ b/crates/stages/stages/src/stages/mod.rs @@ -46,9 +46,7 @@ mod tests { use reth_chainspec::ChainSpecBuilder; use reth_db::{ mdbx::{cursor::Cursor, RW}, - tables, - test_utils::TempDatabase, - AccountsHistory, DatabaseEnv, + tables, AccountsHistory, }; use reth_db_api::{ cursor::{DbCursorRO, DbCursorRW}, @@ -63,6 +61,7 @@ mod tests { }; use reth_provider::{ providers::{StaticFileProvider, StaticFileWriter}, + test_utils::MockNodeTypesWithDB, AccountExtReader, BlockReader, DatabaseProviderFactory, ProviderFactory, ProviderResult, ReceiptProvider, StageCheckpointWriter, StaticFileProviderFactory, StorageReader, }; @@ -140,7 +139,7 @@ mod tests { .unwrap(); provider_rw.commit().unwrap(); - let check_pruning = |factory: ProviderFactory>>, + let check_pruning = |factory: ProviderFactory, prune_modes: PruneModes, expect_num_receipts: usize, expect_num_acc_changesets: usize, diff --git a/crates/stages/stages/src/test_utils/test_db.rs b/crates/stages/stages/src/test_utils/test_db.rs index 43f3f0843..9a44d9bac 100644 --- a/crates/stages/stages/src/test_utils/test_db.rs +++ b/crates/stages/stages/src/test_utils/test_db.rs @@ -1,9 +1,7 @@ use reth_chainspec::MAINNET; use reth_db::{ tables, - test_utils::{ - create_test_rw_db, create_test_rw_db_with_path, create_test_static_files_dir, TempDatabase, - }, + test_utils::{create_test_rw_db, create_test_rw_db_with_path, create_test_static_files_dir}, DatabaseEnv, }; use reth_db_api::{ @@ -21,17 +19,18 @@ use reth_primitives::{ }; use reth_provider::{ providers::{StaticFileProvider, StaticFileProviderRWRefMut, StaticFileWriter}, + test_utils::MockNodeTypesWithDB, HistoryWriter, ProviderError, ProviderFactory, StaticFileProviderFactory, }; use reth_storage_errors::provider::ProviderResult; use reth_testing_utils::generators::ChangeSet; -use std::{collections::BTreeMap, path::Path, sync::Arc}; +use std::{collections::BTreeMap, path::Path}; use tempfile::TempDir; /// Test database that is used for testing stage implementations. #[derive(Debug)] pub struct TestStageDB { - pub factory: ProviderFactory>>, + pub factory: ProviderFactory, pub temp_static_files_dir: TempDir, } diff --git a/crates/static-file/static-file/Cargo.toml b/crates/static-file/static-file/Cargo.toml index 1a1921d58..8fa89e12e 100644 --- a/crates/static-file/static-file/Cargo.toml +++ b/crates/static-file/static-file/Cargo.toml @@ -13,6 +13,7 @@ workspace = true [dependencies] # reth +reth-chainspec.workspace = true reth-db.workspace = true reth-db-api.workspace = true reth-provider.workspace = true @@ -22,6 +23,7 @@ reth-tokio-util.workspace = true reth-prune-types.workspace = true reth-static-file-types.workspace = true reth-stages-types.workspace = true +reth-node-types.workspace = true alloy-primitives.workspace = true diff --git a/crates/static-file/static-file/src/static_file_producer.rs b/crates/static-file/static-file/src/static_file_producer.rs index 935e49a50..fd2c48bbf 100644 --- a/crates/static-file/static-file/src/static_file_producer.rs +++ b/crates/static-file/static-file/src/static_file_producer.rs @@ -4,7 +4,8 @@ use crate::{segments, segments::Segment, StaticFileProducerEvent}; use alloy_primitives::BlockNumber; use parking_lot::Mutex; use rayon::prelude::*; -use reth_db_api::database::Database; +use reth_chainspec::ChainSpec; +use reth_node_types::NodeTypesWithDB; use reth_provider::{ providers::StaticFileWriter, ProviderFactory, StageCheckpointReader as _, StaticFileProviderFactory, @@ -25,22 +26,28 @@ use tracing::{debug, trace}; pub type StaticFileProducerResult = ProviderResult; /// The [`StaticFileProducer`] instance itself with the result of [`StaticFileProducerInner::run`] -pub type StaticFileProducerWithResult = (StaticFileProducer, StaticFileProducerResult); +pub type StaticFileProducerWithResult = (StaticFileProducer, StaticFileProducerResult); /// Static File producer. It's a wrapper around [`StaticFileProducer`] that allows to share it /// between threads. -#[derive(Debug, Clone)] -pub struct StaticFileProducer(Arc>>); +#[derive(Debug)] +pub struct StaticFileProducer(Arc>>); -impl StaticFileProducer { +impl StaticFileProducer { /// Creates a new [`StaticFileProducer`]. - pub fn new(provider_factory: ProviderFactory, prune_modes: PruneModes) -> Self { + pub fn new(provider_factory: ProviderFactory, prune_modes: PruneModes) -> Self { Self(Arc::new(Mutex::new(StaticFileProducerInner::new(provider_factory, prune_modes)))) } } -impl Deref for StaticFileProducer { - type Target = Arc>>; +impl Clone for StaticFileProducer { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +impl Deref for StaticFileProducer { + type Target = Arc>>; fn deref(&self) -> &Self::Target { &self.0 @@ -50,9 +57,9 @@ impl Deref for StaticFileProducer { /// Static File producer routine. See [`StaticFileProducerInner::run`] for more detailed /// description. #[derive(Debug)] -pub struct StaticFileProducerInner { +pub struct StaticFileProducerInner { /// Provider factory - provider_factory: ProviderFactory, + provider_factory: ProviderFactory, /// Pruning configuration for every part of the data that can be pruned. Set by user, and /// needed in [`StaticFileProducerInner`] to prevent attempting to move prunable data to static /// files. See [`StaticFileProducerInner::get_static_file_targets`]. @@ -94,11 +101,13 @@ impl StaticFileTargets { } } -impl StaticFileProducerInner { - fn new(provider_factory: ProviderFactory, prune_modes: PruneModes) -> Self { +impl StaticFileProducerInner { + fn new(provider_factory: ProviderFactory, prune_modes: PruneModes) -> Self { Self { provider_factory, prune_modes, event_sender: Default::default() } } +} +impl> StaticFileProducerInner { /// Listen for events on the `static_file_producer`. pub fn events(&self) -> EventStream { self.event_sender.new_listener() @@ -128,7 +137,7 @@ impl StaticFileProducerInner { debug!(target: "static_file", ?targets, "StaticFileProducer started"); let start = Instant::now(); - let mut segments = Vec::<(Box>, RangeInclusive)>::new(); + let mut segments = Vec::<(Box>, RangeInclusive)>::new(); if let Some(block_range) = targets.transactions.clone() { segments.push((Box::new(segments::Transactions), block_range)); @@ -257,10 +266,10 @@ mod tests { }; use alloy_primitives::{B256, U256}; use assert_matches::assert_matches; - use reth_db::{test_utils::TempDatabase, DatabaseEnv}; use reth_db_api::{database::Database, transaction::DbTx}; use reth_provider::{ - providers::StaticFileWriter, ProviderError, ProviderFactory, StaticFileProviderFactory, + providers::StaticFileWriter, test_utils::MockNodeTypesWithDB, ProviderError, + ProviderFactory, StaticFileProviderFactory, }; use reth_prune_types::PruneModes; use reth_stages::test_utils::{StorageKind, TestStageDB}; @@ -268,13 +277,10 @@ mod tests { use reth_testing_utils::generators::{ self, random_block_range, random_receipt, BlockRangeParams, }; - use std::{ - sync::{mpsc::channel, Arc}, - time::Duration, - }; + use std::{sync::mpsc::channel, time::Duration}; use tempfile::TempDir; - fn setup() -> (ProviderFactory>>, TempDir) { + fn setup() -> (ProviderFactory, TempDir) { let mut rng = generators::rng(); let db = TestStageDB::default(); diff --git a/crates/storage/db-api/src/database.rs b/crates/storage/db-api/src/database.rs index 22c61284b..df7c3a567 100644 --- a/crates/storage/db-api/src/database.rs +++ b/crates/storage/db-api/src/database.rs @@ -8,7 +8,7 @@ use std::{fmt::Debug, sync::Arc}; /// Main Database trait that can open read-only and read-write transactions. /// /// Sealed trait which cannot be implemented by 3rd parties, exposed only for consumption. -pub trait Database: Send + Sync { +pub trait Database: Send + Sync + Debug { /// Read-Only database transaction type TX: DbTx + Send + Sync + Debug + 'static; /// Read-Write database transaction diff --git a/crates/storage/db-common/Cargo.toml b/crates/storage/db-common/Cargo.toml index 5c453df1c..f977d176a 100644 --- a/crates/storage/db-common/Cargo.toml +++ b/crates/storage/db-common/Cargo.toml @@ -21,6 +21,7 @@ reth-etl.workspace = true reth-codecs.workspace = true reth-stages-types.workspace = true reth-fs-util.workspace = true +reth-node-types.workspace = true # eth alloy-genesis.workspace = true @@ -39,6 +40,7 @@ tracing.workspace = true [dev-dependencies] reth-primitives-traits.workspace = true +reth-provider = { workspace = true, features = ["test-utils"] } [lints] workspace = true diff --git a/crates/storage/db-common/src/db_tool/mod.rs b/crates/storage/db-common/src/db_tool/mod.rs index 3884089b4..483e6c301 100644 --- a/crates/storage/db-common/src/db_tool/mod.rs +++ b/crates/storage/db-common/src/db_tool/mod.rs @@ -12,28 +12,21 @@ use reth_db_api::{ DatabaseError, }; use reth_fs_util as fs; +use reth_node_types::NodeTypesWithDB; use reth_provider::{ChainSpecProvider, ProviderFactory}; use std::{path::Path, rc::Rc, sync::Arc}; use tracing::info; /// Wrapper over DB that implements many useful DB queries. #[derive(Debug)] -pub struct DbTool { +pub struct DbTool { /// The provider factory that the db tool will use. - pub provider_factory: ProviderFactory, + pub provider_factory: ProviderFactory, } -impl DbTool { - /// Takes a DB where the tables have already been created. - pub fn new(provider_factory: ProviderFactory) -> eyre::Result { - // Disable timeout because we are entering a TUI which might read for a long time. We - // disable on the [`DbTool`] level since it's only used in the CLI. - provider_factory.provider()?.disable_long_read_transaction_safety(); - Ok(Self { provider_factory }) - } - +impl DbTool { /// Get an [`Arc`] to the [`ChainSpec`]. - pub fn chain(&self) -> Arc { + pub fn chain(&self) -> Arc { self.provider_factory.chain_spec() } @@ -115,6 +108,16 @@ impl DbTool { Ok((data.map_err(|e: DatabaseError| eyre::eyre!(e))?, hits)) } +} + +impl> DbTool { + /// Takes a DB where the tables have already been created. + pub fn new(provider_factory: ProviderFactory) -> eyre::Result { + // Disable timeout because we are entering a TUI which might read for a long time. We + // disable on the [`DbTool`] level since it's only used in the CLI. + provider_factory.provider()?.disable_long_read_transaction_safety(); + Ok(Self { provider_factory }) + } /// Grabs the content of the table for the given key pub fn get(&self, key: T::Key) -> Result> { diff --git a/crates/storage/db-common/src/init.rs b/crates/storage/db-common/src/init.rs index 3ceb62d68..c40249561 100644 --- a/crates/storage/db-common/src/init.rs +++ b/crates/storage/db-common/src/init.rs @@ -7,6 +7,7 @@ use reth_config::config::EtlConfig; use reth_db::tables; use reth_db_api::{database::Database, transaction::DbTxMut, DatabaseError}; use reth_etl::Collector; +use reth_node_types::NodeTypesWithDB; use reth_primitives::{ Account, Address, Bytecode, Receipts, StaticFileSegment, StorageEntry, B256, U256, }; @@ -81,7 +82,9 @@ impl From for InitDatabaseError { } /// Write the genesis block if it has not already been written -pub fn init_genesis(factory: ProviderFactory) -> Result { +pub fn init_genesis>( + factory: ProviderFactory, +) -> Result { let chain = factory.chain_spec(); let genesis = chain.genesis(); @@ -317,9 +320,9 @@ pub fn insert_genesis_header( /// It's similar to [`init_genesis`] but supports importing state too big to fit in memory, and can /// be set to the highest block present. One practical usecase is to import OP mainnet state at /// bedrock transition block. -pub fn init_from_state_dump( +pub fn init_from_state_dump>( mut reader: impl BufRead, - factory: ProviderFactory, + factory: ProviderFactory, etl_config: EtlConfig, ) -> eyre::Result { let block = factory.last_block_number()?; @@ -545,7 +548,9 @@ mod tests { }; use reth_primitives::{HOLESKY_GENESIS_HASH, MAINNET_GENESIS_HASH, SEPOLIA_GENESIS_HASH}; use reth_primitives_traits::IntegerList; - use reth_provider::test_utils::create_test_provider_factory_with_chain_spec; + use reth_provider::test_utils::{ + create_test_provider_factory_with_chain_spec, MockNodeTypesWithDB, + }; fn collect_table_entries( tx: &::TX, @@ -591,7 +596,7 @@ mod tests { init_genesis(factory.clone()).unwrap(); // Try to init db with a different genesis block - let genesis_hash = init_genesis(ProviderFactory::new( + let genesis_hash = init_genesis(ProviderFactory::::new( factory.into_db(), MAINNET.clone(), static_file_provider, diff --git a/crates/storage/provider/Cargo.toml b/crates/storage/provider/Cargo.toml index 2d8208141..57f01fd51 100644 --- a/crates/storage/provider/Cargo.toml +++ b/crates/storage/provider/Cargo.toml @@ -57,6 +57,7 @@ strum.workspace = true # test-utils once_cell = { workspace = true, optional = true } +reth-ethereum-engine-primitives = { workspace = true, optional = true } # parallel utils rayon.workspace = true @@ -83,4 +84,5 @@ test-utils = [ "reth-trie/test-utils", "reth-chain-state/test-utils", "once_cell", + "reth-ethereum-engine-primitives", ] diff --git a/crates/storage/provider/src/providers/blockchain_provider.rs b/crates/storage/provider/src/providers/blockchain_provider.rs index 52b244715..72890f7ea 100644 --- a/crates/storage/provider/src/providers/blockchain_provider.rs +++ b/crates/storage/provider/src/providers/blockchain_provider.rs @@ -12,13 +12,11 @@ use reth_chain_state::{ BlockState, CanonicalInMemoryState, ForkChoiceNotifications, ForkChoiceSubscriptions, MemoryOverlayStateProvider, }; -use reth_chainspec::{ChainInfo, ChainSpec}; -use reth_db_api::{ - database::Database, - models::{AccountBeforeTx, StoredBlockBodyIndices}, -}; +use reth_chainspec::ChainInfo; +use reth_db_api::models::{AccountBeforeTx, StoredBlockBodyIndices}; use reth_evm::ConfigureEvmEnv; use reth_execution_types::ExecutionOutcome; +use reth_node_types::NodeTypesWithDB; use reth_primitives::{ Account, Address, Block, BlockHash, BlockHashOrNumber, BlockId, BlockNumHash, BlockNumber, BlockNumberOrTag, BlockWithSenders, EthereumHardforks, Header, Receipt, SealedBlock, @@ -36,21 +34,23 @@ use std::{ }; use tracing::trace; +use super::ProviderNodeTypes; + /// The main type for interacting with the blockchain. /// /// This type serves as the main entry point for interacting with the blockchain and provides data /// from database storage and from the blockchain tree (pending state etc.) It is a simple wrapper /// type that holds an instance of the database and the blockchain tree. #[derive(Debug)] -pub struct BlockchainProvider2 { +pub struct BlockchainProvider2 { /// Provider type used to access the database. - database: ProviderFactory, + database: ProviderFactory, /// Tracks the chain info wrt forkchoice updates and in memory canonical /// state. pub(super) canonical_in_memory_state: CanonicalInMemoryState, } -impl Clone for BlockchainProvider2 { +impl Clone for BlockchainProvider2 { fn clone(&self) -> Self { Self { database: self.database.clone(), @@ -59,13 +59,10 @@ impl Clone for BlockchainProvider2 { } } -impl BlockchainProvider2 -where - DB: Database, -{ +impl BlockchainProvider2 { /// Create a new provider using only the database, fetching the latest header from /// the database to initialize the provider. - pub fn new(database: ProviderFactory) -> ProviderResult { + pub fn new(database: ProviderFactory) -> ProviderResult { let provider = database.provider()?; let best: ChainInfo = provider.chain_info()?; match provider.header_by_number(best.best_number)? { @@ -82,10 +79,7 @@ where /// /// This returns a `ProviderResult` since it tries the retrieve the last finalized header from /// `database`. - pub fn with_latest( - database: ProviderFactory, - latest: SealedHeader, - ) -> ProviderResult { + pub fn with_latest(database: ProviderFactory, latest: SealedHeader) -> ProviderResult { let provider = database.provider()?; let finalized_header = provider .last_finalized_block_number()? @@ -191,7 +185,7 @@ where /// 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 @@ -247,10 +241,7 @@ where } } -impl BlockchainProvider2 -where - DB: Database, -{ +impl BlockchainProvider2 { /// Ensures that the given block number is canonical (synced) /// /// This is a helper for guarding the `HistoricalStateProvider` against block numbers that are @@ -270,25 +261,19 @@ where } } -impl DatabaseProviderFactory for BlockchainProvider2 -where - DB: Database, -{ - fn database_provider_ro(&self) -> ProviderResult> { +impl DatabaseProviderFactory for BlockchainProvider2 { + fn database_provider_ro(&self) -> ProviderResult> { self.database.provider() } } -impl StaticFileProviderFactory for BlockchainProvider2 { +impl StaticFileProviderFactory for BlockchainProvider2 { fn static_file_provider(&self) -> StaticFileProvider { self.database.static_file_provider() } } -impl HeaderProvider for BlockchainProvider2 -where - DB: Database, -{ +impl HeaderProvider for BlockchainProvider2 { fn header(&self, block_hash: &BlockHash) -> ProviderResult> { if let Some(block_state) = self.canonical_in_memory_state.state_by_hash(*block_hash) { return Ok(Some(block_state.block().block().header.header().clone())); @@ -388,10 +373,7 @@ where } } -impl BlockHashReader for BlockchainProvider2 -where - DB: Database, -{ +impl BlockHashReader for BlockchainProvider2 { fn block_hash(&self, number: u64) -> ProviderResult> { if let Some(block_state) = self.canonical_in_memory_state.state_by_number(number) { return Ok(Some(block_state.hash())); @@ -418,10 +400,7 @@ where } } -impl BlockNumReader for BlockchainProvider2 -where - DB: Database, -{ +impl BlockNumReader for BlockchainProvider2 { fn chain_info(&self) -> ProviderResult { Ok(self.canonical_in_memory_state.chain_info()) } @@ -443,10 +422,7 @@ where } } -impl BlockIdReader for BlockchainProvider2 -where - DB: Database, -{ +impl BlockIdReader for BlockchainProvider2 { fn pending_block_num_hash(&self) -> ProviderResult> { Ok(self.canonical_in_memory_state.pending_block_num_hash()) } @@ -460,10 +436,7 @@ where } } -impl BlockReader for BlockchainProvider2 -where - DB: Database, -{ +impl BlockReader for BlockchainProvider2 { fn find_block_by_hash(&self, hash: B256, source: BlockSource) -> ProviderResult> { match source { BlockSource::Any | BlockSource::Canonical => { @@ -662,10 +635,7 @@ where } } -impl TransactionsProvider for BlockchainProvider2 -where - DB: Database, -{ +impl TransactionsProvider for BlockchainProvider2 { fn transaction_id(&self, tx_hash: TxHash) -> ProviderResult> { // First, check the database if let Some(id) = self.database.transaction_id(tx_hash)? { @@ -855,10 +825,7 @@ where } } -impl ReceiptProvider for BlockchainProvider2 -where - DB: Database, -{ +impl ReceiptProvider for BlockchainProvider2 { fn receipt(&self, id: TxNumber) -> ProviderResult> { let provider = self.database.provider()?; let Some((block_state, tx_index)) = self.block_state_by_tx_id(&provider, id)? else { @@ -920,10 +887,7 @@ where } } -impl ReceiptProviderIdExt for BlockchainProvider2 -where - DB: Database, -{ +impl ReceiptProviderIdExt for BlockchainProvider2 { fn receipts_by_block_id(&self, block: BlockId) -> ProviderResult>> { match block { BlockId::Hash(rpc_block_hash) => { @@ -954,10 +918,7 @@ where } } -impl WithdrawalsProvider for BlockchainProvider2 -where - DB: Database, -{ +impl WithdrawalsProvider for BlockchainProvider2 { fn withdrawals_by_block( &self, id: BlockHashOrNumber, @@ -989,10 +950,7 @@ where } } -impl RequestsProvider for BlockchainProvider2 -where - DB: Database, -{ +impl RequestsProvider for BlockchainProvider2 { fn requests_by_block( &self, id: BlockHashOrNumber, @@ -1010,10 +968,7 @@ where } } -impl StageCheckpointReader for BlockchainProvider2 -where - DB: Database, -{ +impl StageCheckpointReader for BlockchainProvider2 { fn get_stage_checkpoint(&self, id: StageId) -> ProviderResult> { self.database.provider()?.get_stage_checkpoint(id) } @@ -1027,10 +982,7 @@ where } } -impl EvmEnvProvider for BlockchainProvider2 -where - DB: Database, -{ +impl EvmEnvProvider for BlockchainProvider2 { fn fill_env_at( &self, cfg: &mut CfgEnvWithHandlerCfg, @@ -1100,10 +1052,7 @@ where } } -impl PruneCheckpointReader for BlockchainProvider2 -where - DB: Database, -{ +impl PruneCheckpointReader for BlockchainProvider2 { fn get_prune_checkpoint( &self, segment: PruneSegment, @@ -1116,21 +1065,15 @@ where } } -impl ChainSpecProvider for BlockchainProvider2 -where - DB: Send + Sync, -{ - type ChainSpec = ChainSpec; +impl ChainSpecProvider for BlockchainProvider2 { + type ChainSpec = N::ChainSpec; - fn chain_spec(&self) -> Arc { + fn chain_spec(&self) -> Arc { self.database.chain_spec() } } -impl StateProviderFactory for BlockchainProvider2 -where - DB: Database, -{ +impl StateProviderFactory for BlockchainProvider2 { /// Storage provider for latest block fn latest(&self) -> ProviderResult { trace!(target: "providers::blockchain", "Getting latest block state provider"); @@ -1247,9 +1190,8 @@ where } } -impl CanonChainTracker for BlockchainProvider2 +impl CanonChainTracker for BlockchainProvider2 where - DB: Send + Sync, Self: BlockReader, { fn on_forkchoice_update_received(&self, _update: &ForkchoiceState) { @@ -1282,7 +1224,7 @@ where } } -impl BlockReaderIdExt for BlockchainProvider2 +impl BlockReaderIdExt for BlockchainProvider2 where Self: BlockReader + BlockIdReader + ReceiptProviderIdExt, { @@ -1370,19 +1312,13 @@ where } } -impl CanonStateSubscriptions for BlockchainProvider2 -where - DB: Send + Sync, -{ +impl CanonStateSubscriptions for BlockchainProvider2 { fn subscribe_to_canonical_state(&self) -> CanonStateNotifications { self.canonical_in_memory_state.subscribe_canon_state() } } -impl ForkChoiceSubscriptions for BlockchainProvider2 -where - DB: Send + Sync, -{ +impl ForkChoiceSubscriptions for BlockchainProvider2 { fn subscribe_safe_block(&self) -> ForkChoiceNotifications { let receiver = self.canonical_in_memory_state.subscribe_safe_block(); ForkChoiceNotifications(receiver) @@ -1394,10 +1330,7 @@ where } } -impl ChangeSetReader for BlockchainProvider2 -where - DB: Database, -{ +impl ChangeSetReader for BlockchainProvider2 { fn account_block_changeset( &self, block_number: BlockNumber, @@ -1422,10 +1355,7 @@ where } } -impl AccountReader for BlockchainProvider2 -where - DB: Database + Sync + Send, -{ +impl AccountReader for BlockchainProvider2 { /// Get basic account information. fn basic_account(&self, address: Address) -> ProviderResult> { // use latest state provider @@ -1434,10 +1364,7 @@ where } } -impl StateReader for BlockchainProvider2 -where - DB: Database + Sync + Send, -{ +impl StateReader for BlockchainProvider2 { fn get_state(&self, block: BlockNumber) -> ProviderResult> { if let Some(state) = self.canonical_in_memory_state.state_by_number(block) { let state = state.block().execution_outcome().clone(); @@ -1458,7 +1385,10 @@ mod tests { use crate::{ providers::BlockchainProvider2, - test_utils::{create_test_provider_factory, create_test_provider_factory_with_chain_spec}, + test_utils::{ + create_test_provider_factory, create_test_provider_factory_with_chain_spec, + MockNodeTypesWithDB, + }, writer::UnifiedStorageWriter, BlockWriter, CanonChainTracker, StaticFileProviderFactory, StaticFileWriter, }; @@ -1471,11 +1401,7 @@ mod tests { use reth_chainspec::{ ChainSpec, ChainSpecBuilder, ChainSpecProvider, EthereumHardfork, MAINNET, }; - use reth_db::{ - models::{AccountBeforeTx, StoredBlockBodyIndices}, - test_utils::TempDatabase, - DatabaseEnv, - }; + use reth_db::models::{AccountBeforeTx, StoredBlockBodyIndices}; use reth_execution_types::{Chain, ExecutionOutcome}; use reth_primitives::{ BlockHashOrNumber, BlockNumHash, BlockNumberOrTag, BlockWithSenders, Receipt, SealedBlock, @@ -1539,7 +1465,7 @@ mod tests { in_memory_blocks: usize, block_range_params: BlockRangeParams, ) -> eyre::Result<( - BlockchainProvider2>>, + BlockchainProvider2, Vec, Vec, Vec>, @@ -1630,7 +1556,7 @@ mod tests { in_memory_blocks: usize, block_range_params: BlockRangeParams, ) -> eyre::Result<( - BlockchainProvider2>>, + BlockchainProvider2, Vec, Vec, Vec>, diff --git a/crates/storage/provider/src/providers/database/mod.rs b/crates/storage/provider/src/providers/database/mod.rs index 40287c962..249d1f116 100644 --- a/crates/storage/provider/src/providers/database/mod.rs +++ b/crates/storage/provider/src/providers/database/mod.rs @@ -7,11 +7,13 @@ use crate::{ PruneCheckpointReader, RequestsProvider, StageCheckpointReader, StateProviderBox, StaticFileProviderFactory, TransactionVariant, TransactionsProvider, WithdrawalsProvider, }; -use reth_chainspec::{ChainInfo, ChainSpec, EthChainSpec}; +use core::fmt; +use reth_chainspec::ChainInfo; use reth_db::{init_db, mdbx::DatabaseArguments, DatabaseEnv}; use reth_db_api::{database::Database, models::StoredBlockBodyIndices}; use reth_errors::{RethError, RethResult}; use reth_evm::ConfigureEvmEnv; +use reth_node_types::NodeTypesWithDB; use reth_primitives::{ Address, Block, BlockHash, BlockHashOrNumber, BlockNumber, BlockWithSenders, Header, Receipt, SealedBlock, SealedBlockWithSenders, SealedHeader, StaticFileSegment, TransactionMeta, @@ -33,31 +35,47 @@ use tracing::trace; mod provider; pub use provider::{DatabaseProvider, DatabaseProviderRO, DatabaseProviderRW}; +use super::ProviderNodeTypes; + mod metrics; /// A common provider that fetches data from a database or static file. /// /// This provider implements most provider or provider factory traits. -#[derive(Debug)] -pub struct ProviderFactory { +pub struct ProviderFactory { /// Database - db: Arc, + db: N::DB, /// Chain spec - chain_spec: Arc, + chain_spec: Arc, /// Static File Provider static_file_provider: StaticFileProvider, /// Optional pruning configuration prune_modes: PruneModes, } -impl ProviderFactory { +impl fmt::Debug for ProviderFactory +where + N: NodeTypesWithDB, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { db, chain_spec, static_file_provider, prune_modes } = self; + f.debug_struct("ProviderFactory") + .field("db", &db) + .field("chain_spec", &chain_spec) + .field("static_file_provider", &static_file_provider) + .field("prune_modes", &prune_modes) + .finish() + } +} + +impl ProviderFactory { /// Create new database provider factory. pub fn new( - db: DB, - chain_spec: Arc, + db: N::DB, + chain_spec: Arc, static_file_provider: StaticFileProvider, ) -> Self { - Self { db: Arc::new(db), chain_spec, static_file_provider, prune_modes: PruneModes::none() } + Self { db, chain_spec, static_file_provider, prune_modes: PruneModes::none() } } /// Enables metrics on the static file provider. @@ -73,23 +91,23 @@ impl ProviderFactory { } /// Returns reference to the underlying database. - pub fn db_ref(&self) -> &DB { + pub const fn db_ref(&self) -> &N::DB { &self.db } #[cfg(any(test, feature = "test-utils"))] /// Consumes Self and returns DB - pub fn into_db(self) -> Arc { + pub fn into_db(self) -> N::DB { self.db } } -impl ProviderFactory { +impl>> ProviderFactory { /// Create new database provider by passing a path. [`ProviderFactory`] will own the database /// instance. pub fn new_with_database_path>( path: P, - chain_spec: Arc, + chain_spec: Arc, args: DatabaseArguments, static_file_provider: StaticFileProvider, ) -> RethResult { @@ -102,7 +120,7 @@ impl ProviderFactory { } } -impl ProviderFactory { +impl ProviderFactory { /// Returns a provider with a created `DbTx` inside, which allows fetching data from the /// database using different types of providers. Example: [`HeaderProvider`] /// [`BlockHashReader`]. This may fail if the inner read database transaction fails to open. @@ -110,7 +128,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(), @@ -124,7 +142,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(), @@ -164,20 +182,20 @@ impl ProviderFactory { } } -impl DatabaseProviderFactory for ProviderFactory { - fn database_provider_ro(&self) -> ProviderResult> { +impl DatabaseProviderFactory for ProviderFactory { + fn database_provider_ro(&self) -> ProviderResult> { self.provider() } } -impl StaticFileProviderFactory for ProviderFactory { +impl StaticFileProviderFactory for ProviderFactory { /// Returns static file provider fn static_file_provider(&self) -> StaticFileProvider { self.static_file_provider.clone() } } -impl HeaderSyncGapProvider for ProviderFactory { +impl HeaderSyncGapProvider for ProviderFactory { fn sync_gap( &self, tip: watch::Receiver, @@ -187,7 +205,7 @@ impl HeaderSyncGapProvider for ProviderFactory { } } -impl HeaderProvider for ProviderFactory { +impl HeaderProvider for ProviderFactory { fn header(&self, block_hash: &BlockHash) -> ProviderResult> { self.provider()?.header(block_hash) } @@ -261,7 +279,7 @@ impl HeaderProvider for ProviderFactory { } } -impl BlockHashReader for ProviderFactory { +impl BlockHashReader for ProviderFactory { fn block_hash(&self, number: u64) -> ProviderResult> { self.static_file_provider.get_with_static_file_or_database( StaticFileSegment::Headers, @@ -286,7 +304,7 @@ impl BlockHashReader for ProviderFactory { } } -impl BlockNumReader for ProviderFactory { +impl BlockNumReader for ProviderFactory { fn chain_info(&self) -> ProviderResult { self.provider()?.chain_info() } @@ -304,7 +322,7 @@ impl BlockNumReader for ProviderFactory { } } -impl BlockReader for ProviderFactory { +impl BlockReader for ProviderFactory { fn find_block_by_hash(&self, hash: B256, source: BlockSource) -> ProviderResult> { self.provider()?.find_block_by_hash(hash, source) } @@ -371,7 +389,7 @@ impl BlockReader for ProviderFactory { } } -impl TransactionsProvider for ProviderFactory { +impl TransactionsProvider for ProviderFactory { fn transaction_id(&self, tx_hash: TxHash) -> ProviderResult> { self.provider()?.transaction_id(tx_hash) } @@ -445,7 +463,7 @@ impl TransactionsProvider for ProviderFactory { } } -impl ReceiptProvider for ProviderFactory { +impl ReceiptProvider for ProviderFactory { fn receipt(&self, id: TxNumber) -> ProviderResult> { self.static_file_provider.get_with_static_file_or_database( StaticFileSegment::Receipts, @@ -477,7 +495,7 @@ impl ReceiptProvider for ProviderFactory { } } -impl WithdrawalsProvider for ProviderFactory { +impl WithdrawalsProvider for ProviderFactory { fn withdrawals_by_block( &self, id: BlockHashOrNumber, @@ -491,10 +509,7 @@ impl WithdrawalsProvider for ProviderFactory { } } -impl RequestsProvider for ProviderFactory -where - DB: Database, -{ +impl RequestsProvider for ProviderFactory { fn requests_by_block( &self, id: BlockHashOrNumber, @@ -504,7 +519,7 @@ where } } -impl StageCheckpointReader for ProviderFactory { +impl StageCheckpointReader for ProviderFactory { fn get_stage_checkpoint(&self, id: StageId) -> ProviderResult> { self.provider()?.get_stage_checkpoint(id) } @@ -517,7 +532,7 @@ impl StageCheckpointReader for ProviderFactory { } } -impl EvmEnvProvider for ProviderFactory { +impl EvmEnvProvider for ProviderFactory { fn fill_env_at( &self, cfg: &mut CfgEnvWithHandlerCfg, @@ -569,18 +584,15 @@ impl EvmEnvProvider for ProviderFactory { } } -impl ChainSpecProvider for ProviderFactory -where - DB: Send + Sync, - ChainSpec: EthChainSpec, -{ - type ChainSpec = ChainSpec; - fn chain_spec(&self) -> Arc { +impl ChainSpecProvider for ProviderFactory { + type ChainSpec = N::ChainSpec; + + fn chain_spec(&self) -> Arc { self.chain_spec.clone() } } -impl PruneCheckpointReader for ProviderFactory { +impl PruneCheckpointReader for ProviderFactory { fn get_prune_checkpoint( &self, segment: PruneSegment, @@ -593,10 +605,10 @@ impl PruneCheckpointReader for ProviderFactory { } } -impl Clone for ProviderFactory { +impl Clone for ProviderFactory { fn clone(&self) -> Self { Self { - db: Arc::clone(&self.db), + db: self.db.clone(), chain_spec: self.chain_spec.clone(), static_file_provider: self.static_file_provider.clone(), prune_modes: self.prune_modes.clone(), @@ -609,7 +621,7 @@ mod tests { use super::*; use crate::{ providers::{StaticFileProvider, StaticFileWriter}, - test_utils::{blocks::TEST_BLOCK, create_test_provider_factory}, + test_utils::{blocks::TEST_BLOCK, create_test_provider_factory, MockNodeTypesWithDB}, BlockHashReader, BlockNumReader, BlockWriter, HeaderSyncGapProvider, TransactionsProvider, }; use assert_matches::assert_matches; @@ -657,7 +669,7 @@ mod tests { fn provider_factory_with_database_path() { let chain_spec = ChainSpecBuilder::mainnet().build(); let (_static_dir, static_dir_path) = create_test_static_files_dir(); - let factory = ProviderFactory::new_with_database_path( + let factory = ProviderFactory::>::new_with_database_path( tempfile::TempDir::new().expect(ERROR_TEMPDIR).into_path(), Arc::new(chain_spec), DatabaseArguments::new(Default::default()), diff --git a/crates/storage/provider/src/providers/mod.rs b/crates/storage/provider/src/providers/mod.rs index 3b85a8086..246bd426f 100644 --- a/crates/storage/provider/src/providers/mod.rs +++ b/crates/storage/provider/src/providers/mod.rs @@ -13,12 +13,10 @@ use reth_blockchain_tree_api::{ InsertPayloadOk, }; use reth_chain_state::{ChainInfoTracker, ForkChoiceNotifications, ForkChoiceSubscriptions}; -use reth_chainspec::{ChainInfo, ChainSpec, EthChainSpec}; -use reth_db_api::{ - database::Database, - models::{AccountBeforeTx, StoredBlockBodyIndices}, -}; +use reth_chainspec::{ChainInfo, ChainSpec}; +use reth_db_api::models::{AccountBeforeTx, StoredBlockBodyIndices}; use reth_evm::ConfigureEvmEnv; +use reth_node_types::NodeTypesWithDB; use reth_primitives::{ Account, Address, Block, BlockHash, BlockHashOrNumber, BlockId, BlockNumHash, BlockNumber, BlockNumberOrTag, BlockWithSenders, Header, Receipt, SealedBlock, SealedBlockWithSenders, @@ -62,22 +60,27 @@ pub use consistent_view::{ConsistentDbView, ConsistentViewError}; mod blockchain_provider; pub use blockchain_provider::BlockchainProvider2; +/// Helper trait keeping common requirements of providers for [`NodeTypesWithDB`]. +pub trait ProviderNodeTypes: NodeTypesWithDB {} + +impl ProviderNodeTypes for T where T: NodeTypesWithDB {} + /// The main type for interacting with the blockchain. /// /// This type serves as the main entry point for interacting with the blockchain and provides data /// from database storage and from the blockchain tree (pending state etc.) It is a simple wrapper /// type that holds an instance of the database and the blockchain tree. #[allow(missing_debug_implementations)] -pub struct BlockchainProvider { +pub struct BlockchainProvider { /// Provider type used to access the database. - database: ProviderFactory, + database: ProviderFactory, /// The blockchain tree instance. tree: Arc, /// Tracks the chain info wrt forkchoice updates chain_info: ChainInfoTracker, } -impl Clone for BlockchainProvider { +impl Clone for BlockchainProvider { fn clone(&self) -> Self { Self { database: self.database.clone(), @@ -87,7 +90,7 @@ impl Clone for BlockchainProvider { } } -impl BlockchainProvider { +impl BlockchainProvider { /// Sets the treeviewer for the provider. #[doc(hidden)] pub fn with_tree(mut self, tree: Arc) -> Self { @@ -96,15 +99,12 @@ impl BlockchainProvider { } } -impl BlockchainProvider -where - DB: Database, -{ +impl BlockchainProvider { /// Create new provider instance that wraps the database and the blockchain tree, using the /// provided latest header to initialize the chain info tracker, alongside the finalized header /// if it exists. pub fn with_blocks( - database: ProviderFactory, + database: ProviderFactory, tree: Arc, latest: SealedHeader, finalized: Option, @@ -114,7 +114,7 @@ where /// Create a new provider using only the database and the tree, fetching the latest header from /// the database to initialize the provider. - pub fn new(database: ProviderFactory, tree: Arc) -> ProviderResult { + pub fn new(database: ProviderFactory, tree: Arc) -> ProviderResult { let provider = database.provider()?; let best: ChainInfo = provider.chain_info()?; let latest_header = provider @@ -149,10 +149,10 @@ where } } -impl BlockchainProvider +impl BlockchainProvider where Self: StateProviderFactory, - DB: Database, + N: NodeTypesWithDB, { /// Return a [`StateProviderBox`] that contains bundle state data provider. /// Used to inspect or execute transaction on the pending state. @@ -169,25 +169,19 @@ where } } -impl DatabaseProviderFactory for BlockchainProvider -where - DB: Database, -{ - fn database_provider_ro(&self) -> ProviderResult> { +impl DatabaseProviderFactory for BlockchainProvider { + fn database_provider_ro(&self) -> ProviderResult> { self.database.provider() } } -impl StaticFileProviderFactory for BlockchainProvider { +impl StaticFileProviderFactory for BlockchainProvider { fn static_file_provider(&self) -> StaticFileProvider { self.database.static_file_provider() } } -impl HeaderProvider for BlockchainProvider -where - DB: Database, -{ +impl HeaderProvider for BlockchainProvider { fn header(&self, block_hash: &BlockHash) -> ProviderResult> { self.database.header(block_hash) } @@ -228,10 +222,7 @@ where } } -impl BlockHashReader for BlockchainProvider -where - DB: Database, -{ +impl BlockHashReader for BlockchainProvider { fn block_hash(&self, number: u64) -> ProviderResult> { self.database.block_hash(number) } @@ -245,10 +236,7 @@ where } } -impl BlockNumReader for BlockchainProvider -where - DB: Database, -{ +impl BlockNumReader for BlockchainProvider { fn chain_info(&self) -> ProviderResult { Ok(self.chain_info.chain_info()) } @@ -266,10 +254,7 @@ where } } -impl BlockIdReader for BlockchainProvider -where - DB: Database, -{ +impl BlockIdReader for BlockchainProvider { fn pending_block_num_hash(&self) -> ProviderResult> { Ok(self.tree.pending_block_num_hash()) } @@ -283,10 +268,7 @@ where } } -impl BlockReader for BlockchainProvider -where - DB: Database, -{ +impl BlockReader for BlockchainProvider { fn find_block_by_hash(&self, hash: B256, source: BlockSource) -> ProviderResult> { let block = match source { BlockSource::Any => { @@ -377,10 +359,7 @@ where } } -impl TransactionsProvider for BlockchainProvider -where - DB: Database, -{ +impl TransactionsProvider for BlockchainProvider { fn transaction_id(&self, tx_hash: TxHash) -> ProviderResult> { self.database.transaction_id(tx_hash) } @@ -444,10 +423,7 @@ where } } -impl ReceiptProvider for BlockchainProvider -where - DB: Database, -{ +impl ReceiptProvider for BlockchainProvider { fn receipt(&self, id: TxNumber) -> ProviderResult> { self.database.receipt(id) } @@ -468,10 +444,7 @@ where } } -impl ReceiptProviderIdExt for BlockchainProvider -where - DB: Database, -{ +impl ReceiptProviderIdExt for BlockchainProvider { fn receipts_by_block_id(&self, block: BlockId) -> ProviderResult>> { match block { BlockId::Hash(rpc_block_hash) => { @@ -495,10 +468,7 @@ where } } -impl WithdrawalsProvider for BlockchainProvider -where - DB: Database, -{ +impl WithdrawalsProvider for BlockchainProvider { fn withdrawals_by_block( &self, id: BlockHashOrNumber, @@ -512,10 +482,7 @@ where } } -impl RequestsProvider for BlockchainProvider -where - DB: Database, -{ +impl RequestsProvider for BlockchainProvider { fn requests_by_block( &self, id: BlockHashOrNumber, @@ -525,10 +492,7 @@ where } } -impl StageCheckpointReader for BlockchainProvider -where - DB: Database, -{ +impl StageCheckpointReader for BlockchainProvider { fn get_stage_checkpoint(&self, id: StageId) -> ProviderResult> { self.database.provider()?.get_stage_checkpoint(id) } @@ -542,10 +506,7 @@ where } } -impl EvmEnvProvider for BlockchainProvider -where - DB: Database, -{ +impl EvmEnvProvider for BlockchainProvider { fn fill_env_at( &self, cfg: &mut CfgEnvWithHandlerCfg, @@ -597,10 +558,7 @@ where } } -impl PruneCheckpointReader for BlockchainProvider -where - DB: Database, -{ +impl PruneCheckpointReader for BlockchainProvider { fn get_prune_checkpoint( &self, segment: PruneSegment, @@ -613,22 +571,15 @@ where } } -impl ChainSpecProvider for BlockchainProvider -where - DB: Send + Sync, - ChainSpec: EthChainSpec, -{ - type ChainSpec = ChainSpec; +impl ChainSpecProvider for BlockchainProvider { + type ChainSpec = N::ChainSpec; fn chain_spec(&self) -> Arc { self.database.chain_spec() } } -impl StateProviderFactory for BlockchainProvider -where - DB: Database, -{ +impl StateProviderFactory for BlockchainProvider { /// Storage provider for latest block fn latest(&self) -> ProviderResult { trace!(target: "providers::blockchain", "Getting latest block state provider"); @@ -721,10 +672,7 @@ where } } -impl BlockchainTreeEngine for BlockchainProvider -where - DB: Send + Sync, -{ +impl BlockchainTreeEngine for BlockchainProvider { fn buffer_block(&self, block: SealedBlockWithSenders) -> Result<(), InsertBlockError> { self.tree.buffer_block(block) } @@ -763,10 +711,7 @@ where } } -impl BlockchainTreeViewer for BlockchainProvider -where - DB: Send + Sync, -{ +impl BlockchainTreeViewer for BlockchainProvider { fn header_by_hash(&self, hash: BlockHash) -> Option { self.tree.header_by_hash(hash) } @@ -808,9 +753,8 @@ where } } -impl CanonChainTracker for BlockchainProvider +impl CanonChainTracker for BlockchainProvider where - DB: Send + Sync, Self: BlockReader, { fn on_forkchoice_update_received(&self, _update: &ForkchoiceState) { @@ -843,7 +787,7 @@ where } } -impl BlockReaderIdExt for BlockchainProvider +impl BlockReaderIdExt for BlockchainProvider where Self: BlockReader + BlockIdReader + ReceiptProviderIdExt, { @@ -859,7 +803,7 @@ where // check the database, canonical blocks are only stored in the database self.find_block_by_hash(hash.block_hash, BlockSource::Canonical) } else { - self.block_by_hash(hash.block_hash) + BlockReader::block_by_hash(self, hash.block_hash) } } } @@ -922,10 +866,7 @@ where } } -impl BlockchainTreePendingStateProvider for BlockchainProvider -where - DB: Send + Sync, -{ +impl BlockchainTreePendingStateProvider for BlockchainProvider { fn find_pending_state_provider( &self, block_hash: BlockHash, @@ -934,19 +875,13 @@ where } } -impl CanonStateSubscriptions for BlockchainProvider -where - DB: Send + Sync, -{ +impl CanonStateSubscriptions for BlockchainProvider { fn subscribe_to_canonical_state(&self) -> CanonStateNotifications { self.tree.subscribe_to_canonical_state() } } -impl ForkChoiceSubscriptions for BlockchainProvider -where - DB: Send + Sync, -{ +impl ForkChoiceSubscriptions for BlockchainProvider { fn subscribe_safe_block(&self) -> ForkChoiceNotifications { let receiver = self.chain_info.subscribe_safe_block(); ForkChoiceNotifications(receiver) @@ -958,10 +893,7 @@ where } } -impl ChangeSetReader for BlockchainProvider -where - DB: Database, -{ +impl ChangeSetReader for BlockchainProvider { fn account_block_changeset( &self, block_number: BlockNumber, @@ -970,10 +902,7 @@ where } } -impl AccountReader for BlockchainProvider -where - DB: Database + Sync + Send, -{ +impl AccountReader for BlockchainProvider { /// Get basic account information. fn basic_account(&self, address: Address) -> ProviderResult> { self.database.provider()?.basic_account(address) diff --git a/crates/storage/provider/src/test_utils/mod.rs b/crates/storage/provider/src/test_utils/mod.rs index 8e3146633..e2d7e6d77 100644 --- a/crates/storage/provider/src/test_utils/mod.rs +++ b/crates/storage/provider/src/test_utils/mod.rs @@ -2,9 +2,10 @@ use crate::{providers::StaticFileProvider, HashingWriter, ProviderFactory, TrieW use reth_chainspec::{ChainSpec, MAINNET}; use reth_db::{ test_utils::{create_test_rw_db, create_test_static_files_dir, TempDatabase}, - Database, DatabaseEnv, + DatabaseEnv, }; use reth_errors::ProviderResult; +use reth_node_types::{NodeTypesWithDB, NodeTypesWithDBAdapter}; use reth_primitives::{Account, StorageEntry, B256}; use reth_trie::StateRoot; use reth_trie_db::DatabaseStateRoot; @@ -18,15 +19,26 @@ pub use mock::{ExtendedAccount, MockEthProvider}; pub use noop::NoopProvider; pub use reth_chain_state::test_utils::TestCanonStateSubscriptions; +/// Mock [`reth_node_types::NodeTypes`] for testing. +pub type MockNodeTypes = reth_node_types::AnyNodeTypesWithEngine< + (), + reth_ethereum_engine_primitives::EthEngineTypes, + reth_chainspec::ChainSpec, +>; + +/// Mock [`reth_node_types::NodeTypesWithDB`] for testing. +pub type MockNodeTypesWithDB> = + NodeTypesWithDBAdapter>; + /// Creates test provider factory with mainnet chain spec. -pub fn create_test_provider_factory() -> ProviderFactory>> { +pub fn create_test_provider_factory() -> ProviderFactory { create_test_provider_factory_with_chain_spec(MAINNET.clone()) } /// Creates test provider factory with provided chain spec. pub fn create_test_provider_factory_with_chain_spec( chain_spec: Arc, -) -> ProviderFactory>> { +) -> ProviderFactory { let (static_dir, _) = create_test_static_files_dir(); let db = create_test_rw_db(); ProviderFactory::new( @@ -37,9 +49,9 @@ pub fn create_test_provider_factory_with_chain_spec( } /// Inserts the genesis alloc from the provided chain spec into the trie. -pub fn insert_genesis( - provider_factory: &ProviderFactory, - chain_spec: Arc, +pub fn insert_genesis>( + provider_factory: &ProviderFactory, + chain_spec: Arc, ) -> ProviderResult { let provider = provider_factory.provider_rw()?; diff --git a/crates/trie/db/Cargo.toml b/crates/trie/db/Cargo.toml index 83ef66aab..f42046656 100644 --- a/crates/trie/db/Cargo.toml +++ b/crates/trie/db/Cargo.toml @@ -55,6 +55,7 @@ reth-provider = { workspace = true, features = ["test-utils"] } reth-storage-errors.workspace = true reth-trie-common = { workspace = true, features = ["test-utils", "arbitrary"] } reth-trie = { workspace = true, features = ["test-utils"] } +reth-node-types.workspace = true # trie triehash = "0.8" diff --git a/crates/trie/db/tests/proof.rs b/crates/trie/db/tests/proof.rs index 41d599571..db9d708d4 100644 --- a/crates/trie/db/tests/proof.rs +++ b/crates/trie/db/tests/proof.rs @@ -1,15 +1,9 @@ use reth_chainspec::{Chain, ChainSpec, HOLESKY, MAINNET}; -use reth_db_api::database::Database; -use reth_primitives::{ - constants::EMPTY_ROOT_HASH, keccak256, Account, Address, Bytes, StorageEntry, B256, U256, -}; -use reth_provider::{ - test_utils::create_test_provider_factory, HashingWriter, ProviderFactory, TrieWriter, -}; -use reth_storage_errors::provider::ProviderResult; -use reth_trie::{proof::Proof, Nibbles, StateRoot}; +use reth_primitives::{constants::EMPTY_ROOT_HASH, keccak256, Account, Address, Bytes, B256, U256}; +use reth_provider::test_utils::{create_test_provider_factory, insert_genesis}; +use reth_trie::{proof::Proof, Nibbles}; use reth_trie_common::{AccountProof, StorageProof}; -use reth_trie_db::{DatabaseProof, DatabaseStateRoot}; +use reth_trie_db::DatabaseProof; use std::{ str::FromStr, sync::{Arc, LazyLock}, @@ -40,39 +34,6 @@ fn convert_to_proof<'a>(path: impl IntoIterator) -> Vec { path.into_iter().map(Bytes::from_str).collect::, _>>().unwrap() } -fn insert_genesis( - provider_factory: &ProviderFactory, - chain_spec: Arc, -) -> ProviderResult { - let provider = provider_factory.provider_rw()?; - - // Hash accounts and insert them into hashing table. - let genesis = chain_spec.genesis(); - let alloc_accounts = - genesis.alloc.iter().map(|(addr, account)| (*addr, Some(Account::from(account)))); - provider.insert_account_for_hashing(alloc_accounts).unwrap(); - - let alloc_storage = genesis.alloc.clone().into_iter().filter_map(|(addr, account)| { - // Only return `Some` if there is storage. - account.storage.map(|storage| { - ( - addr, - storage.into_iter().map(|(key, value)| StorageEntry { key, value: value.into() }), - ) - }) - }); - provider.insert_storage_for_hashing(alloc_storage)?; - - let (root, updates) = StateRoot::from_tx(provider.tx_ref()) - .root_with_updates() - .map_err(Into::::into)?; - provider.write_trie_updates(&updates).unwrap(); - - provider.commit()?; - - Ok(root) -} - #[test] fn testspec_proofs() { // Create test database and insert genesis accounts. diff --git a/examples/db-access/Cargo.toml b/examples/db-access/Cargo.toml index 692a1175d..6ddfeb5e5 100644 --- a/examples/db-access/Cargo.toml +++ b/examples/db-access/Cargo.toml @@ -12,6 +12,8 @@ reth-db.workspace = true reth-primitives.workspace = true reth-provider.workspace = true reth-rpc-types.workspace = true +reth-node-ethereum.workspace = true +reth-node-types.workspace = true eyre.workspace = true diff --git a/examples/db-access/src/main.rs b/examples/db-access/src/main.rs index 0a8368801..9d11950fc 100644 --- a/examples/db-access/src/main.rs +++ b/examples/db-access/src/main.rs @@ -1,4 +1,6 @@ use reth_chainspec::ChainSpecBuilder; +use reth_node_ethereum::EthereumNode; +use reth_node_types::NodeTypesWithDBAdapter; use reth_primitives::{Address, B256}; use reth_provider::{ providers::StaticFileProvider, AccountReader, BlockReader, BlockSource, HeaderProvider, @@ -21,12 +23,13 @@ fn main() -> eyre::Result<()> { // Instantiate a provider factory for Ethereum mainnet using the provided DB. // TODO: Should the DB version include the spec so that you do not need to specify it here? let spec = ChainSpecBuilder::mainnet().build(); - let factory = ProviderFactory::new_with_database_path( - db_path, - spec.into(), - Default::default(), - StaticFileProvider::read_only(db_path.join("static_files"))?, - )?; + let factory = + ProviderFactory::>::new_with_database_path( + db_path, + spec.into(), + Default::default(), + StaticFileProvider::read_only(db_path.join("static_files"))?, + )?; // This call opens a RO transaction on the database. To write to the DB you'd need to call // the `provider_rw` function and look for the `Writer` variants of the traits. diff --git a/examples/rpc-db/src/main.rs b/examples/rpc-db/src/main.rs index 69f61fbd1..1b03f2e5b 100644 --- a/examples/rpc-db/src/main.rs +++ b/examples/rpc-db/src/main.rs @@ -15,6 +15,7 @@ use std::{path::Path, sync::Arc}; use reth::{ + api::NodeTypesWithDBAdapter, providers::{ providers::{BlockchainProvider, StaticFileProvider}, ProviderFactory, @@ -23,7 +24,7 @@ use reth::{ utils::open_db_read_only, }; use reth_chainspec::ChainSpecBuilder; -use reth_db::mdbx::DatabaseArguments; +use reth_db::{mdbx::DatabaseArguments, DatabaseEnv}; use reth_db_api::models::ClientVersion; // Bringing up the RPC @@ -33,7 +34,7 @@ use reth::rpc::builder::{ // Configuring the network parts, ideally also wouldn't need to think about this. use myrpc_ext::{MyRpcExt, MyRpcExtApiServer}; use reth::{blockchain_tree::noop::NoopBlockchainTree, tasks::TokioTaskExecutor}; -use reth_node_ethereum::EthEvmConfig; +use reth_node_ethereum::{EthEvmConfig, EthereumNode}; use reth_provider::test_utils::TestCanonStateSubscriptions; // Custom rpc extension @@ -49,7 +50,7 @@ async fn main() -> eyre::Result<()> { DatabaseArguments::new(ClientVersion::default()), )?); let spec = Arc::new(ChainSpecBuilder::mainnet().build()); - let factory = ProviderFactory::new( + let factory = ProviderFactory::>>::new( db.clone(), spec.clone(), StaticFileProvider::read_only(db_path.join("static_files"))?,