diff --git a/Cargo.lock b/Cargo.lock index f1ba11884..24ceb8f7d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7558,6 +7558,7 @@ version = "1.0.3" dependencies = [ "alloy-primitives", "alloy-rpc-types-admin", + "auto_impl", "enr", "reth-eth-wire", "reth-network-peers", @@ -7980,13 +7981,14 @@ name = "reth-optimism-rpc" version = "1.0.3" dependencies = [ "alloy-primitives", + "derive_more", "jsonrpsee", "jsonrpsee-types", "parking_lot 0.12.3", - "reth-chainspec", - "reth-errors", "reth-evm", "reth-evm-optimism", + "reth-network", + "reth-network-api", "reth-node-api", "reth-primitives", "reth-provider", @@ -8407,6 +8409,7 @@ dependencies = [ "reth-errors", "reth-evm", "reth-execution-types", + "reth-network-api", "reth-primitives", "reth-provider", "reth-revm", diff --git a/crates/net/network-api/Cargo.toml b/crates/net/network-api/Cargo.toml index bedaf2c29..682298309 100644 --- a/crates/net/network-api/Cargo.toml +++ b/crates/net/network-api/Cargo.toml @@ -27,6 +27,7 @@ enr = { workspace = true, default-features = false, features = ["rust-secp256k1" thiserror.workspace = true serde = { workspace = true, features = ["derive"], optional = true } tokio = { workspace = true, features = ["sync"] } +auto_impl.workspace = true [features] default = ["serde"] diff --git a/crates/net/network-api/src/lib.rs b/crates/net/network-api/src/lib.rs index 1e23390fd..c053e4698 100644 --- a/crates/net/network-api/src/lib.rs +++ b/crates/net/network-api/src/lib.rs @@ -32,6 +32,7 @@ pub mod reputation; pub mod noop; /// Provides general purpose information about the network. +#[auto_impl::auto_impl(&, Arc)] pub trait NetworkInfo: Send + Sync { /// Returns the [`SocketAddr`] that listens for incoming connections. fn local_addr(&self) -> SocketAddr; diff --git a/crates/optimism/node/src/node.rs b/crates/optimism/node/src/node.rs index 01531130b..067d1945f 100644 --- a/crates/optimism/node/src/node.rs +++ b/crates/optimism/node/src/node.rs @@ -19,7 +19,6 @@ use reth_optimism_consensus::OptimismBeaconConsensus; use reth_optimism_rpc::OpEthApi; use reth_payload_builder::{PayloadBuilderHandle, PayloadBuilderService}; use reth_provider::CanonStateSubscriptions; -use reth_rpc::EthApi; use reth_tracing::tracing::{debug, info}; use reth_transaction_pool::{ blobstore::DiskFileBlobStore, CoinbaseTipOrdering, TransactionPool, @@ -105,7 +104,7 @@ impl NodeTypes for OptimismNode { pub struct OptimismAddOns; impl NodeAddOns for OptimismAddOns { - type EthApi = OpEthApi>; + type EthApi = OpEthApi; } /// A regular optimism evm and executor builder. diff --git a/crates/optimism/rpc/Cargo.toml b/crates/optimism/rpc/Cargo.toml index 1f0b15b6e..b8bfd6db6 100644 --- a/crates/optimism/rpc/Cargo.toml +++ b/crates/optimism/rpc/Cargo.toml @@ -13,8 +13,6 @@ workspace = true [dependencies] # reth -reth-chainspec.workspace = true -reth-errors.workspace = true reth-evm-optimism.workspace = true reth-evm.workspace = true reth-primitives.workspace = true @@ -27,6 +25,8 @@ reth-tasks = { workspace = true, features = ["rayon"] } reth-transaction-pool.workspace = true reth-rpc.workspace = true reth-node-api.workspace = true +reth-network-api.workspace = true +reth-network.workspace = true # ethereum alloy-primitives.workspace = true @@ -43,6 +43,7 @@ jsonrpsee-types.workspace = true # misc thiserror.workspace = true serde = { workspace = true, features = ["derive"] } +derive_more.workspace = true [dev-dependencies] serde_json.workspace = true @@ -55,7 +56,6 @@ client = [ ] optimism = [ - "reth-chainspec/optimism", "reth-evm-optimism/optimism", "reth-primitives/optimism", "reth-provider/optimism", diff --git a/crates/optimism/rpc/src/eth/block.rs b/crates/optimism/rpc/src/eth/block.rs index c1bdc6098..c7a7b45ab 100644 --- a/crates/optimism/rpc/src/eth/block.rs +++ b/crates/optimism/rpc/src/eth/block.rs @@ -1,22 +1,29 @@ //! Loads and formats OP block RPC response. +use reth_node_api::FullNodeComponents; use reth_primitives::TransactionMeta; use reth_provider::{BlockReaderIdExt, HeaderProvider}; use reth_rpc_eth_api::{ - helpers::{EthApiSpec, EthBlocks, LoadBlock, LoadReceipt, LoadTransaction}, + helpers::{ + EthApiSpec, EthBlocks, LoadBlock, LoadPendingBlock, LoadReceipt, LoadTransaction, + SpawnBlocking, + }, FromEthApiError, }; use reth_rpc_eth_types::{EthStateCache, ReceiptBuilder}; use reth_rpc_types::{AnyTransactionReceipt, BlockId}; -use crate::{op_receipt_fields, OpEthApi}; +use crate::{op_receipt_fields, OpEthApi, OpEthApiError}; -impl EthBlocks for OpEthApi +impl EthBlocks for OpEthApi where - Eth: EthBlocks + EthApiSpec + LoadTransaction, + Self: LoadBlock + EthApiSpec + LoadTransaction, + Self::Error: From, + N: FullNodeComponents, { + #[inline] fn provider(&self) -> impl HeaderProvider { - EthBlocks::provider(&self.inner) + self.inner.provider() } async fn block_receipts( @@ -69,11 +76,17 @@ where } } -impl LoadBlock for OpEthApi { +impl LoadBlock for OpEthApi +where + Self: LoadPendingBlock + SpawnBlocking, + N: FullNodeComponents, +{ + #[inline] fn provider(&self) -> impl BlockReaderIdExt { - LoadBlock::provider(&self.inner) + self.inner.provider() } + #[inline] fn cache(&self) -> &EthStateCache { self.inner.cache() } diff --git a/crates/optimism/rpc/src/eth/call.rs b/crates/optimism/rpc/src/eth/call.rs index d3bea8dec..3f25b0182 100644 --- a/crates/optimism/rpc/src/eth/call.rs +++ b/crates/optimism/rpc/src/eth/call.rs @@ -1,28 +1,37 @@ use reth_evm::ConfigureEvm; +use reth_node_api::FullNodeComponents; use reth_primitives::{ revm_primitives::{BlockEnv, OptimismFields, TxEnv}, - Bytes, + Bytes, TxKind, U256, }; use reth_rpc_eth_api::{ - helpers::{Call, EthCall}, - EthApiTypes, FromEthApiError, + helpers::{Call, EthCall, LoadState, SpawnBlocking}, + FromEthApiError, IntoEthApiError, }; -use reth_rpc_eth_types::EthApiError; +use reth_rpc_eth_types::{revm_utils::CallFees, RpcInvalidTransactionError}; use reth_rpc_types::TransactionRequest; -use crate::OpEthApi; +use crate::{OpEthApi, OpEthApiError}; -impl EthCall for OpEthApi where EthApiError: From {} - -impl Call for OpEthApi +impl EthCall for OpEthApi where - Eth: Call + EthApiTypes, - EthApiError: From, + Self: Call, + N: FullNodeComponents, { +} + +impl Call for OpEthApi +where + Self: LoadState + SpawnBlocking, + Self::Error: From, + N: FullNodeComponents, +{ + #[inline] fn call_gas_limit(&self) -> u64 { - self.inner.call_gas_limit() + self.inner.gas_cap() } + #[inline] fn evm_config(&self) -> &impl ConfigureEvm { self.inner.evm_config() } @@ -32,10 +41,68 @@ where block_env: &BlockEnv, request: TransactionRequest, ) -> Result { - let mut env = - self.inner.create_txn_env(block_env, request).map_err(Self::Error::from_eth_err)?; + // Ensure that if versioned hashes are set, they're not empty + if request.blob_versioned_hashes.as_ref().map_or(false, |hashes| hashes.is_empty()) { + return Err(RpcInvalidTransactionError::BlobTransactionMissingBlobHashes.into_eth_err()) + } - env.optimism = OptimismFields { enveloped_tx: Some(Bytes::new()), ..Default::default() }; + let TransactionRequest { + from, + to, + gas_price, + max_fee_per_gas, + max_priority_fee_per_gas, + gas, + value, + input, + nonce, + access_list, + chain_id, + blob_versioned_hashes, + max_fee_per_blob_gas, + // authorization_list, + .. + } = request; + + let CallFees { max_priority_fee_per_gas, gas_price, max_fee_per_blob_gas } = + CallFees::ensure_fees( + gas_price.map(U256::from), + max_fee_per_gas.map(U256::from), + max_priority_fee_per_gas.map(U256::from), + block_env.basefee, + blob_versioned_hashes.as_deref(), + max_fee_per_blob_gas.map(U256::from), + block_env.get_blob_gasprice().map(U256::from), + )?; + + let gas_limit = gas.unwrap_or_else(|| block_env.gas_limit.min(U256::from(u64::MAX)).to()); + + #[allow(clippy::needless_update)] + let env = TxEnv { + gas_limit: gas_limit + .try_into() + .map_err(|_| RpcInvalidTransactionError::GasUintOverflow) + .map_err(Self::Error::from_eth_err)?, + nonce, + caller: from.unwrap_or_default(), + gas_price, + gas_priority_fee: max_priority_fee_per_gas, + transact_to: to.unwrap_or(TxKind::Create), + value: value.unwrap_or_default(), + data: input + .try_into_unique_input() + .map_err(Self::Error::from_eth_err)? + .unwrap_or_default(), + chain_id, + access_list: access_list.unwrap_or_default().into(), + // EIP-4844 fields + blob_hashes: blob_versioned_hashes.unwrap_or_default(), + max_fee_per_blob_gas, + // EIP-7702 fields + // authorization_list: TODO + authorization_list: Default::default(), + optimism: OptimismFields { enveloped_tx: Some(Bytes::new()), ..Default::default() }, + }; Ok(env) } diff --git a/crates/optimism/rpc/src/eth/mod.rs b/crates/optimism/rpc/src/eth/mod.rs index 1f2b27c86..08a90eda3 100644 --- a/crates/optimism/rpc/src/eth/mod.rs +++ b/crates/optimism/rpc/src/eth/mod.rs @@ -7,30 +7,53 @@ mod block; mod call; mod pending_block; -use std::{future::Future, sync::Arc}; +use std::{fmt, sync::Arc}; -use alloy_primitives::{Address, U64}; -use reth_chainspec::{ChainInfo, ChainSpec}; -use reth_errors::RethResult; +use alloy_primitives::U256; +use derive_more::Deref; use reth_evm::ConfigureEvm; -use reth_node_api::{BuilderProvider, FullNodeComponents}; -use reth_provider::{BlockReaderIdExt, ChainSpecProvider, HeaderProvider, StateProviderFactory}; -use reth_rpc::eth::DevSigner; +use reth_network::NetworkHandle; +use reth_network_api::NetworkInfo; +use reth_node_api::{BuilderProvider, FullNodeComponents, FullNodeTypes}; +use reth_provider::{ + BlockIdReader, BlockNumReader, BlockReaderIdExt, ChainSpecProvider, HeaderProvider, + StateProviderFactory, +}; +use reth_rpc::eth::{core::EthApiInner, DevSigner}; use reth_rpc_eth_api::{ helpers::{ - AddDevSigners, EthApiSpec, EthFees, EthSigner, EthState, LoadFee, LoadState, SpawnBlocking, - Trace, UpdateRawTxForwarder, + AddDevSigners, EthApiSpec, EthFees, EthState, LoadBlock, LoadFee, LoadState, SpawnBlocking, + Trace, }, - EthApiTypes, RawTransactionForwarder, + EthApiTypes, +}; +use reth_rpc_eth_types::{EthStateCache, FeeHistoryCache, GasPriceOracle}; +use reth_tasks::{ + pool::{BlockingTaskGuard, BlockingTaskPool}, + TaskExecutor, TaskSpawner, }; -use reth_rpc_eth_types::EthStateCache; -use reth_rpc_types::SyncStatus; -use reth_tasks::{pool::BlockingTaskPool, TaskSpawner}; use reth_transaction_pool::TransactionPool; -use tokio::sync::{AcquireError, OwnedSemaphorePermit}; use crate::OpEthApiError; +/// Adapter for [`EthApiInner`], which holds all the data required to serve core `eth_` API. +pub type EthApiNodeBackend = EthApiInner< + ::Provider, + ::Pool, + NetworkHandle, + ::Evm, +>; + +/// Adapter for [`EthApiBuilderCtx`]. +pub type EthApiBuilderCtx = reth_rpc_eth_types::EthApiBuilderCtx< + ::Provider, + ::Pool, + ::Evm, + NetworkHandle, + TaskExecutor, + ::Provider, +>; + /// OP-Reth `Eth` API implementation. /// /// This type provides the functionality for handling `eth_` related requests. @@ -41,148 +64,187 @@ use crate::OpEthApiError; /// /// This type implements the [`FullEthApi`](reth_rpc_eth_api::helpers::FullEthApi) by implemented /// all the `Eth` helper traits and prerequisite traits. -#[derive(Debug, Clone)] -pub struct OpEthApi { - inner: Eth, +#[derive(Clone, Deref)] +pub struct OpEthApi { + inner: Arc>, } -impl OpEthApi { - /// Creates a new `OpEthApi` from the provided `Eth` implementation. - pub const fn new(inner: Eth) -> Self { - Self { inner } +impl OpEthApi { + /// Creates a new instance for given context. + #[allow(clippy::type_complexity)] + pub fn with_spawner(ctx: &EthApiBuilderCtx) -> Self { + let blocking_task_pool = + BlockingTaskPool::build().expect("failed to build blocking task pool"); + + let inner = EthApiInner::new( + ctx.provider.clone(), + ctx.pool.clone(), + ctx.network.clone(), + ctx.cache.clone(), + ctx.new_gas_price_oracle(), + ctx.config.rpc_gas_cap, + ctx.config.eth_proof_window, + blocking_task_pool, + ctx.new_fee_history_cache(), + ctx.evm_config.clone(), + ctx.executor.clone(), + None, + ctx.config.proof_permits, + ); + + Self { inner: Arc::new(inner) } } } -impl EthApiTypes for OpEthApi +impl EthApiTypes for OpEthApi where - Eth: Send + Sync, + Self: Send + Sync, + N: FullNodeComponents, { type Error = OpEthApiError; } -impl EthApiSpec for OpEthApi { - fn protocol_version(&self) -> impl Future> + Send { - self.inner.protocol_version() +impl EthApiSpec for OpEthApi +where + N: FullNodeComponents, +{ + #[inline] + fn provider(&self) -> impl ChainSpecProvider + BlockNumReader { + self.inner.provider() } - fn chain_id(&self) -> U64 { - self.inner.chain_id() + #[inline] + fn network(&self) -> impl NetworkInfo { + self.inner.network() } - fn chain_info(&self) -> RethResult { - self.inner.chain_info() + #[inline] + fn starting_block(&self) -> U256 { + self.inner.starting_block() } - fn accounts(&self) -> Vec
{ - self.inner.accounts() - } - - fn is_syncing(&self) -> bool { - self.inner.is_syncing() - } - - fn sync_status(&self) -> RethResult { - self.inner.sync_status() - } - - fn chain_spec(&self) -> Arc { - self.inner.chain_spec() + #[inline] + fn signers(&self) -> &parking_lot::RwLock>> { + self.inner.signers() } } -impl SpawnBlocking for OpEthApi { +impl SpawnBlocking for OpEthApi +where + Self: Send + Sync + Clone + 'static, + N: FullNodeComponents, +{ + #[inline] fn io_task_spawner(&self) -> impl TaskSpawner { - self.inner.io_task_spawner() + self.inner.task_spawner() } + #[inline] fn tracing_task_pool(&self) -> &BlockingTaskPool { - self.inner.tracing_task_pool() + self.inner.blocking_task_pool() } - fn acquire_owned( - &self, - ) -> impl Future> + Send { - self.inner.acquire_owned() - } - - fn acquire_many_owned( - &self, - n: u32, - ) -> impl Future> + Send { - self.inner.acquire_many_owned(n) + #[inline] + fn tracing_task_guard(&self) -> &BlockingTaskGuard { + self.inner.blocking_task_guard() } } -impl LoadFee for OpEthApi { - fn provider(&self) -> impl reth_provider::BlockIdReader + HeaderProvider + ChainSpecProvider { - LoadFee::provider(&self.inner) +impl LoadFee for OpEthApi +where + Self: LoadBlock, + N: FullNodeComponents, +{ + #[inline] + fn provider(&self) -> impl BlockIdReader + HeaderProvider + ChainSpecProvider { + self.inner.provider() } + #[inline] fn cache(&self) -> &EthStateCache { - LoadFee::cache(&self.inner) + self.inner.cache() } - fn gas_oracle(&self) -> &reth_rpc_eth_types::GasPriceOracle { + #[inline] + fn gas_oracle(&self) -> &GasPriceOracle { self.inner.gas_oracle() } - fn fee_history_cache(&self) -> &reth_rpc_eth_types::FeeHistoryCache { + #[inline] + fn fee_history_cache(&self) -> &FeeHistoryCache { self.inner.fee_history_cache() } } -impl LoadState for OpEthApi { +impl LoadState for OpEthApi +where + Self: Send + Sync, + N: FullNodeComponents, +{ + #[inline] fn provider(&self) -> impl StateProviderFactory + ChainSpecProvider { - LoadState::provider(&self.inner) + self.inner.provider() } + #[inline] fn cache(&self) -> &EthStateCache { - LoadState::cache(&self.inner) + self.inner.cache() } + #[inline] fn pool(&self) -> impl TransactionPool { - LoadState::pool(&self.inner) + self.inner.pool() } } -impl EthState for OpEthApi { +impl EthState for OpEthApi +where + Self: LoadState + SpawnBlocking, + N: FullNodeComponents, +{ + #[inline] fn max_proof_window(&self) -> u64 { - self.inner.max_proof_window() + self.inner.eth_proof_window() } } -impl EthFees for OpEthApi {} +impl EthFees for OpEthApi +where + Self: LoadFee, + N: FullNodeComponents, +{ +} -impl Trace for OpEthApi { +impl Trace for OpEthApi +where + Self: LoadState, + N: FullNodeComponents, +{ + #[inline] fn evm_config(&self) -> &impl ConfigureEvm { self.inner.evm_config() } } -impl AddDevSigners for OpEthApi { - fn signers(&self) -> &parking_lot::RwLock>> { - self.inner.signers() - } - +impl AddDevSigners for OpEthApi { fn with_dev_accounts(&self) { *self.signers().write() = DevSigner::random_signers(20) } } -impl UpdateRawTxForwarder for OpEthApi { - fn set_eth_raw_transaction_forwarder(&self, forwarder: Arc) { - self.inner.set_eth_raw_transaction_forwarder(forwarder); - } -} - -impl BuilderProvider for OpEthApi +impl BuilderProvider for OpEthApi where - Eth: BuilderProvider, N: FullNodeComponents, { - type Ctx<'a> = >::Ctx<'a>; + type Ctx<'a> = &'a EthApiBuilderCtx; fn builder() -> Box Fn(Self::Ctx<'a>) -> Self + Send> { - Box::new(|ctx| Self { inner: Eth::builder()(ctx) }) + Box::new(|ctx| Self::with_spawner(ctx)) + } +} + +impl fmt::Debug for OpEthApi { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("OpEthApi").finish_non_exhaustive() } } diff --git a/crates/optimism/rpc/src/eth/pending_block.rs b/crates/optimism/rpc/src/eth/pending_block.rs index 3215f32a8..c64c83cc0 100644 --- a/crates/optimism/rpc/src/eth/pending_block.rs +++ b/crates/optimism/rpc/src/eth/pending_block.rs @@ -1,19 +1,21 @@ //! Loads OP pending block for a RPC response. use reth_evm::ConfigureEvm; +use reth_node_api::FullNodeComponents; use reth_primitives::{revm_primitives::BlockEnv, BlockNumber, B256}; use reth_provider::{ BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, ExecutionOutcome, StateProviderFactory, }; -use reth_rpc_eth_api::helpers::LoadPendingBlock; +use reth_rpc_eth_api::helpers::{LoadPendingBlock, SpawnBlocking}; use reth_rpc_eth_types::PendingBlock; use reth_transaction_pool::TransactionPool; use crate::OpEthApi; -impl LoadPendingBlock for OpEthApi +impl LoadPendingBlock for OpEthApi where - Eth: LoadPendingBlock, + Self: SpawnBlocking, + N: FullNodeComponents, { #[inline] fn provider( diff --git a/crates/optimism/rpc/src/eth/receipt.rs b/crates/optimism/rpc/src/eth/receipt.rs index bef18a716..5aa1b172a 100644 --- a/crates/optimism/rpc/src/eth/receipt.rs +++ b/crates/optimism/rpc/src/eth/receipt.rs @@ -1,5 +1,6 @@ //! Loads and formats OP receipt RPC response. +use reth_node_api::FullNodeComponents; use reth_primitives::{Receipt, TransactionMeta, TransactionSigned}; use reth_rpc_eth_api::{ helpers::{EthApiSpec, LoadReceipt, LoadTransaction}, @@ -8,15 +9,17 @@ use reth_rpc_eth_api::{ use reth_rpc_eth_types::{EthApiError, EthStateCache, ReceiptBuilder}; use reth_rpc_types::{AnyTransactionReceipt, OptimismTransactionReceiptFields}; -use crate::{OpEthApi, OptimismTxMeta}; +use crate::{OpEthApi, OpEthApiError, OptimismTxMeta}; -impl LoadReceipt for OpEthApi +impl LoadReceipt for OpEthApi where - Eth: LoadReceipt + EthApiSpec + LoadTransaction, + Self: EthApiSpec + LoadTransaction, + Self::Error: From, + N: FullNodeComponents, { #[inline] fn cache(&self) -> &EthStateCache { - LoadReceipt::cache(&self.inner) + self.inner.cache() } async fn build_transaction_receipt( diff --git a/crates/optimism/rpc/src/eth/transaction.rs b/crates/optimism/rpc/src/eth/transaction.rs index 6689e230f..523fb326f 100644 --- a/crates/optimism/rpc/src/eth/transaction.rs +++ b/crates/optimism/rpc/src/eth/transaction.rs @@ -3,10 +3,11 @@ use std::sync::Arc; use reth_evm_optimism::RethL1BlockInfo; +use reth_node_api::FullNodeComponents; use reth_primitives::TransactionSigned; use reth_provider::{BlockReaderIdExt, TransactionsProvider}; use reth_rpc_eth_api::{ - helpers::{EthApiSpec, EthSigner, EthTransactions, LoadTransaction}, + helpers::{EthApiSpec, EthSigner, EthTransactions, LoadTransaction, SpawnBlocking}, EthApiTypes, RawTransactionForwarder, }; use reth_rpc_eth_types::EthStateCache; @@ -14,9 +15,13 @@ use revm::L1BlockInfo; use crate::{OpEthApi, OpEthApiError}; -impl EthTransactions for OpEthApi { +impl EthTransactions for OpEthApi +where + Self: LoadTransaction, + N: FullNodeComponents, +{ fn provider(&self) -> impl BlockReaderIdExt { - EthTransactions::provider(&self.inner) + self.inner.provider() } fn raw_tx_forwarder(&self) -> Option> { @@ -28,19 +33,23 @@ impl EthTransactions for OpEthApi { } } -impl LoadTransaction for OpEthApi { - type Pool = Eth::Pool; +impl LoadTransaction for OpEthApi +where + Self: SpawnBlocking, + N: FullNodeComponents, +{ + type Pool = N::Pool; fn provider(&self) -> impl TransactionsProvider { - LoadTransaction::provider(&self.inner) + self.inner.provider() } fn cache(&self) -> &EthStateCache { - LoadTransaction::cache(&self.inner) + self.inner.cache() } fn pool(&self) -> &Self::Pool { - LoadTransaction::pool(&self.inner) + self.inner.pool() } } @@ -66,9 +75,11 @@ impl OptimismTxMeta { } } -impl OpEthApi +impl OpEthApi where - Eth: EthApiSpec + LoadTransaction, + Self: EthApiSpec + LoadTransaction, + ::Error: From, + N: FullNodeComponents, { /// Builds [`OptimismTxMeta`] object using the provided [`TransactionSigned`], L1 block /// info and block timestamp. The [`L1BlockInfo`] is used to calculate the l1 fee and l1 data @@ -86,15 +97,10 @@ where let envelope_buf = tx.envelope_encoded(); let inner_l1_fee = l1_block_info - .l1_tx_data_fee( - &self.inner.chain_spec(), - block_timestamp, - &envelope_buf, - tx.is_deposit(), - ) + .l1_tx_data_fee(&self.chain_spec(), block_timestamp, &envelope_buf, tx.is_deposit()) .map_err(|_| OpEthApiError::L1BlockFeeError)?; let inner_l1_data_gas = l1_block_info - .l1_data_gas(&self.inner.chain_spec(), block_timestamp, &envelope_buf) + .l1_data_gas(&self.chain_spec(), block_timestamp, &envelope_buf) .map_err(|_| OpEthApiError::L1BlockGasError)?; ( Some(inner_l1_fee.saturating_to::()), diff --git a/crates/rpc/rpc-eth-api/Cargo.toml b/crates/rpc/rpc-eth-api/Cargo.toml index 20e73908b..06b193cf5 100644 --- a/crates/rpc/rpc-eth-api/Cargo.toml +++ b/crates/rpc/rpc-eth-api/Cargo.toml @@ -29,6 +29,7 @@ reth-chainspec.workspace = true reth-execution-types.workspace = true reth-rpc-eth-types.workspace = true reth-rpc-server-types.workspace = true +reth-network-api.workspace = true # ethereum alloy-dyn-abi = { workspace = true, features = ["eip712"] } diff --git a/crates/rpc/rpc-eth-api/src/helpers/blocking_task.rs b/crates/rpc/rpc-eth-api/src/helpers/blocking_task.rs index d23453b5e..c3a0a43ff 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/blocking_task.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/blocking_task.rs @@ -3,7 +3,10 @@ use futures::Future; use reth_rpc_eth_types::EthApiError; -use reth_tasks::{pool::BlockingTaskPool, TaskSpawner}; +use reth_tasks::{ + pool::{BlockingTaskGuard, BlockingTaskPool}, + TaskSpawner, +}; use tokio::sync::{oneshot, AcquireError, OwnedSemaphorePermit}; use crate::EthApiTypes; @@ -20,16 +23,23 @@ pub trait SpawnBlocking: EthApiTypes + Clone + Send + Sync + 'static { /// Thread pool access in default trait method implementations. fn tracing_task_pool(&self) -> &BlockingTaskPool; + /// Returns handle to semaphore for pool of CPU heavy blocking tasks. + fn tracing_task_guard(&self) -> &BlockingTaskGuard; + /// See also [`Semaphore::acquire_owned`](`tokio::sync::Semaphore::acquire_owned`). fn acquire_owned( &self, - ) -> impl Future> + Send; + ) -> impl Future> + Send { + self.tracing_task_guard().clone().acquire_owned() + } /// See also [`Semaphore::acquire_many_owned`](`tokio::sync::Semaphore::acquire_many_owned`). fn acquire_many_owned( &self, n: u32, - ) -> impl Future> + Send; + ) -> impl Future> + Send { + self.tracing_task_guard().clone().acquire_many_owned(n) + } /// Executes the future on a new blocking task. /// diff --git a/crates/rpc/rpc-eth-api/src/helpers/signer.rs b/crates/rpc/rpc-eth-api/src/helpers/signer.rs index d7aecfe25..5b7176143 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/signer.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/signer.rs @@ -41,9 +41,6 @@ dyn_clone::clone_trait_object!(EthSigner); /// Adds 20 random dev signers for access via the API. Used in dev mode. #[auto_impl::auto_impl(&)] pub trait AddDevSigners { - /// Returns a handle to the signers. - fn signers(&self) -> &parking_lot::RwLock>>; - /// Generates 20 random developer accounts. /// Used in DEV mode. fn with_dev_accounts(&self); diff --git a/crates/rpc/rpc-eth-api/src/helpers/spec.rs b/crates/rpc/rpc-eth-api/src/helpers/spec.rs index a36868e52..96b9bdeb3 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/spec.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/spec.rs @@ -4,33 +4,80 @@ use std::sync::Arc; use futures::Future; use reth_chainspec::{ChainInfo, ChainSpec}; -use reth_errors::RethResult; -use reth_primitives::{Address, U64}; -use reth_rpc_types::SyncStatus; +use reth_errors::{RethError, RethResult}; +use reth_network_api::NetworkInfo; +use reth_primitives::{Address, U256, U64}; +use reth_provider::{BlockNumReader, ChainSpecProvider}; +use reth_rpc_types::{SyncInfo, SyncStatus}; + +use super::EthSigner; /// `Eth` API trait. /// /// Defines core functionality of the `eth` API implementation. #[auto_impl::auto_impl(&, Arc)] pub trait EthApiSpec: Send + Sync { + /// Returns a handle for reading data from disk. + fn provider(&self) -> impl ChainSpecProvider + BlockNumReader; + + /// Returns a handle for reading network data summary. + fn network(&self) -> impl NetworkInfo; + + /// Returns the block node is started on. + fn starting_block(&self) -> U256; + + /// Returns a handle to the signers owned by provider. + fn signers(&self) -> &parking_lot::RwLock>>; + /// Returns the current ethereum protocol version. - fn protocol_version(&self) -> impl Future> + Send; + fn protocol_version(&self) -> impl Future> + Send { + async move { + let status = self.network().network_status().await.map_err(RethError::other)?; + Ok(U64::from(status.protocol_version)) + } + } /// Returns the chain id - fn chain_id(&self) -> U64; + fn chain_id(&self) -> U64 { + U64::from(self.network().chain_id()) + } /// Returns provider chain info - fn chain_info(&self) -> RethResult; + fn chain_info(&self) -> RethResult { + Ok(self.provider().chain_info()?) + } /// Returns a list of addresses owned by provider. - fn accounts(&self) -> Vec
; + fn accounts(&self) -> Vec
{ + self.signers().read().iter().flat_map(|s| s.accounts()).collect() + } /// Returns `true` if the network is undergoing sync. - fn is_syncing(&self) -> bool; + fn is_syncing(&self) -> bool { + self.network().is_syncing() + } /// Returns the [`SyncStatus`] of the network - fn sync_status(&self) -> RethResult; + fn sync_status(&self) -> RethResult { + let status = if self.is_syncing() { + let current_block = U256::from( + self.provider().chain_info().map(|info| info.best_number).unwrap_or_default(), + ); + SyncStatus::Info(SyncInfo { + starting_block: self.starting_block(), + current_block, + highest_block: current_block, + warp_chunks_amount: None, + warp_chunks_processed: None, + }) + } else { + SyncStatus::None + }; + Ok(status) + } /// Returns the configured [`ChainSpec`]. - fn chain_spec(&self) -> Arc; + fn chain_spec(&self) -> Arc { + self.provider().chain_spec() + } } diff --git a/crates/rpc/rpc-eth-api/src/helpers/state.rs b/crates/rpc/rpc-eth-api/src/helpers/state.rs index 48d350e0e..b59e524c4 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/state.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/state.rs @@ -102,8 +102,7 @@ pub trait EthState: LoadState + SpawnBlocking { let block_id = block_id.unwrap_or_default(); // Check whether the distance to the block exceeds the maximum configured window. - let block_number = self - .provider() + let block_number = LoadState::provider(self) .block_number_for_id(block_id) .map_err(Self::Error::from_eth_err)? .ok_or(EthApiError::UnknownBlockNumber)?; diff --git a/crates/rpc/rpc/src/eth/core.rs b/crates/rpc/rpc/src/eth/core.rs index 590d73f7f..231b6a72d 100644 --- a/crates/rpc/rpc/src/eth/core.rs +++ b/crates/rpc/rpc/src/eth/core.rs @@ -4,7 +4,6 @@ use std::sync::Arc; use derive_more::Deref; -use futures::Future; use reth_node_api::{BuilderProvider, FullNodeComponents}; use reth_primitives::{BlockNumberOrTag, U256}; use reth_provider::{BlockReaderIdExt, CanonStateSubscriptions, ChainSpecProvider}; @@ -20,7 +19,7 @@ use reth_tasks::{ pool::{BlockingTaskGuard, BlockingTaskPool}, TaskExecutor, TaskSpawner, TokioTaskExecutor, }; -use tokio::sync::{AcquireError, Mutex, OwnedSemaphorePermit}; +use tokio::sync::Mutex; /// `Eth` API implementation. /// @@ -139,29 +138,21 @@ impl Clone for EthApi SpawnBlocking for EthApi where - Self: EthApiTypes + Clone + Send + Sync + 'static, + Self: Clone + Send + Sync + 'static, { #[inline] - fn io_task_spawner(&self) -> impl reth_tasks::TaskSpawner { + fn io_task_spawner(&self) -> impl TaskSpawner { self.inner.task_spawner() } #[inline] - fn tracing_task_pool(&self) -> &reth_tasks::pool::BlockingTaskPool { + fn tracing_task_pool(&self) -> &BlockingTaskPool { self.inner.blocking_task_pool() } - fn acquire_owned( - &self, - ) -> impl Future> + Send { - self.blocking_task_guard.clone().acquire_owned() - } - - fn acquire_many_owned( - &self, - n: u32, - ) -> impl Future> + Send { - self.blocking_task_guard.clone().acquire_many_owned(n) + #[inline] + fn tracing_task_guard(&self) -> &BlockingTaskGuard { + self.inner.blocking_task_guard() } } @@ -358,6 +349,12 @@ impl EthApiInner u64 { self.eth_proof_window } + + /// Returns reference to [`BlockingTaskGuard`]. + #[inline] + pub const fn blocking_task_guard(&self) -> &BlockingTaskGuard { + &self.blocking_task_guard + } } impl UpdateRawTxForwarder diff --git a/crates/rpc/rpc/src/eth/helpers/pending_block.rs b/crates/rpc/rpc/src/eth/helpers/pending_block.rs index d1a47da75..02b092b4b 100644 --- a/crates/rpc/rpc/src/eth/helpers/pending_block.rs +++ b/crates/rpc/rpc/src/eth/helpers/pending_block.rs @@ -14,7 +14,7 @@ where Self: SpawnBlocking, Provider: BlockReaderIdExt + EvmEnvProvider + ChainSpecProvider + StateProviderFactory, Pool: TransactionPool, - EvmConfig: reth_evm::ConfigureEvm, + EvmConfig: ConfigureEvm, { #[inline] fn provider( diff --git a/crates/rpc/rpc/src/eth/helpers/receipt.rs b/crates/rpc/rpc/src/eth/helpers/receipt.rs index eb4483705..db1fee781 100644 --- a/crates/rpc/rpc/src/eth/helpers/receipt.rs +++ b/crates/rpc/rpc/src/eth/helpers/receipt.rs @@ -1,13 +1,13 @@ //! Builds an RPC receipt response w.r.t. data layout of network. -use reth_rpc_eth_api::{helpers::LoadReceipt, EthApiTypes}; +use reth_rpc_eth_api::helpers::LoadReceipt; use reth_rpc_eth_types::EthStateCache; use crate::EthApi; impl LoadReceipt for EthApi where - Self: EthApiTypes, + Self: Send + Sync, { #[inline] fn cache(&self) -> &EthStateCache { diff --git a/crates/rpc/rpc/src/eth/helpers/signer.rs b/crates/rpc/rpc/src/eth/helpers/signer.rs index d29b0cc07..d7e075d33 100644 --- a/crates/rpc/rpc/src/eth/helpers/signer.rs +++ b/crates/rpc/rpc/src/eth/helpers/signer.rs @@ -17,12 +17,8 @@ use crate::EthApi; impl AddDevSigners for EthApi { - fn signers(&self) -> &parking_lot::RwLock>> { - self.inner.signers() - } - fn with_dev_accounts(&self) { - *self.signers().write() = DevSigner::random_signers(20) + *self.inner.signers().write() = DevSigner::random_signers(20) } } diff --git a/crates/rpc/rpc/src/eth/helpers/spec.rs b/crates/rpc/rpc/src/eth/helpers/spec.rs index 58ac1c64d..34616b735 100644 --- a/crates/rpc/rpc/src/eth/helpers/spec.rs +++ b/crates/rpc/rpc/src/eth/helpers/spec.rs @@ -1,13 +1,7 @@ -use std::sync::Arc; - -use reth_chainspec::{ChainInfo, ChainSpec}; -use reth_errors::{RethError, RethResult}; -use reth_evm::ConfigureEvm; use reth_network_api::NetworkInfo; -use reth_primitives::{Address, U256, U64}; -use reth_provider::{BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, StateProviderFactory}; +use reth_primitives::U256; +use reth_provider::{BlockNumReader, ChainSpecProvider}; use reth_rpc_eth_api::helpers::EthApiSpec; -use reth_rpc_types::{SyncInfo, SyncStatus}; use reth_transaction_pool::TransactionPool; use crate::EthApi; @@ -15,57 +9,23 @@ use crate::EthApi; impl EthApiSpec for EthApi where Pool: TransactionPool + 'static, - Provider: - BlockReaderIdExt + ChainSpecProvider + StateProviderFactory + EvmEnvProvider + 'static, + Provider: BlockNumReader + ChainSpecProvider + 'static, Network: NetworkInfo + 'static, - EvmConfig: ConfigureEvm, + EvmConfig: Send + Sync, { - /// Returns the current ethereum protocol version. - /// - /// Note: This returns an [`U64`], since this should return as hex string. - async fn protocol_version(&self) -> RethResult { - let status = self.network().network_status().await.map_err(RethError::other)?; - Ok(U64::from(status.protocol_version)) + fn provider(&self) -> impl ChainSpecProvider + BlockNumReader { + self.inner.provider() } - /// Returns the chain id - fn chain_id(&self) -> U64 { - U64::from(self.network().chain_id()) + fn network(&self) -> impl NetworkInfo { + self.inner.network() } - /// Returns the current info for the chain - fn chain_info(&self) -> RethResult { - Ok(self.provider().chain_info()?) + fn starting_block(&self) -> U256 { + self.inner.starting_block() } - fn accounts(&self) -> Vec
{ - self.inner.signers().read().iter().flat_map(|s| s.accounts()).collect() - } - - fn is_syncing(&self) -> bool { - self.network().is_syncing() - } - - /// Returns the [`SyncStatus`] of the network - fn sync_status(&self) -> RethResult { - let status = if self.is_syncing() { - let current_block = U256::from( - self.provider().chain_info().map(|info| info.best_number).unwrap_or_default(), - ); - SyncStatus::Info(SyncInfo { - starting_block: self.inner.starting_block(), - current_block, - highest_block: current_block, - warp_chunks_amount: None, - warp_chunks_processed: None, - }) - } else { - SyncStatus::None - }; - Ok(status) - } - - fn chain_spec(&self) -> Arc { - self.inner.provider().chain_spec() + fn signers(&self) -> &parking_lot::RwLock>> { + self.inner.signers() } } diff --git a/crates/rpc/rpc/src/eth/helpers/state.rs b/crates/rpc/rpc/src/eth/helpers/state.rs index f76be9d88..7974fc114 100644 --- a/crates/rpc/rpc/src/eth/helpers/state.rs +++ b/crates/rpc/rpc/src/eth/helpers/state.rs @@ -3,10 +3,7 @@ use reth_provider::{ChainSpecProvider, StateProviderFactory}; use reth_transaction_pool::TransactionPool; -use reth_rpc_eth_api::{ - helpers::{EthState, LoadState, SpawnBlocking}, - EthApiTypes, -}; +use reth_rpc_eth_api::helpers::{EthState, LoadState, SpawnBlocking}; use reth_rpc_eth_types::EthStateCache; use crate::EthApi; @@ -16,13 +13,13 @@ where Self: LoadState + SpawnBlocking, { fn max_proof_window(&self) -> u64 { - self.eth_proof_window() + self.inner.eth_proof_window() } } impl LoadState for EthApi where - Self: EthApiTypes, + Self: Send + Sync, Provider: StateProviderFactory + ChainSpecProvider, Pool: TransactionPool, {