From 7d8196e29ca8427f48f18516963a6a5c3356ef44 Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Thu, 22 Aug 2024 16:36:38 +0200 Subject: [PATCH] chore(rpc): config network specific transaction type in node builder (#10417) --- Cargo.lock | 28 ++- Cargo.toml | 1 + crates/e2e-test-utils/Cargo.toml | 4 + crates/e2e-test-utils/src/lib.rs | 15 +- crates/e2e-test-utils/src/node.rs | 8 +- crates/e2e-test-utils/src/rpc.rs | 13 +- crates/e2e-test-utils/src/transaction.rs | 23 ++- crates/ethereum/node/src/node.rs | 10 +- crates/node/api/Cargo.toml | 1 + crates/node/api/src/lib.rs | 2 + crates/node/api/src/node.rs | 9 +- crates/node/builder/Cargo.toml | 3 + crates/node/builder/src/builder/add_ons.rs | 4 +- crates/node/builder/src/builder/mod.rs | 11 +- crates/node/builder/src/launch/engine.rs | 11 +- crates/node/builder/src/launch/mod.rs | 5 +- crates/node/builder/src/rpc.rs | 75 ++++++-- crates/optimism/node/Cargo.toml | 1 + crates/optimism/node/src/node.rs | 8 +- crates/optimism/primitives/Cargo.toml | 2 +- crates/optimism/rpc/Cargo.toml | 4 +- crates/optimism/rpc/src/eth/call.rs | 3 +- crates/optimism/rpc/src/eth/mod.rs | 36 ++-- crates/optimism/rpc/src/eth/pending_block.rs | 5 +- crates/rpc/rpc-api/Cargo.toml | 3 + crates/rpc/rpc-api/src/engine.rs | 15 +- crates/rpc/rpc-builder/Cargo.toml | 1 + crates/rpc/rpc-builder/src/lib.rs | 6 +- crates/rpc/rpc-builder/tests/it/http.rs | 177 +++++++++++++----- crates/rpc/rpc-builder/tests/it/middleware.rs | 3 +- crates/rpc/rpc-eth-api/Cargo.toml | 2 + crates/rpc/rpc-eth-api/src/core.rs | 82 ++++---- crates/rpc/rpc-eth-api/src/filter.rs | 5 +- crates/rpc/rpc-eth-api/src/helpers/block.rs | 20 +- crates/rpc/rpc-eth-api/src/helpers/mod.rs | 1 - .../rpc-eth-api/src/helpers/transaction.rs | 8 +- crates/rpc/rpc-eth-api/src/helpers/types.rs | 17 -- crates/rpc/rpc-eth-api/src/lib.rs | 6 +- crates/rpc/rpc-eth-api/src/pubsub.rs | 3 +- crates/rpc/rpc-eth-api/src/types.rs | 35 ++++ crates/rpc/rpc-testing-util/Cargo.toml | 1 + crates/rpc/rpc-testing-util/src/debug.rs | 15 +- crates/rpc/rpc-testing-util/tests/it/trace.rs | 16 +- crates/rpc/rpc/Cargo.toml | 1 + crates/rpc/rpc/src/engine.rs | 23 ++- crates/rpc/rpc/src/eth/core.rs | 22 ++- crates/rpc/rpc/src/eth/filter.rs | 2 +- crates/rpc/rpc/src/eth/helpers/block.rs | 2 +- crates/rpc/rpc/src/eth/pubsub.rs | 2 +- crates/rpc/rpc/src/otterscan.rs | 31 ++- examples/custom-evm/src/main.rs | 2 +- examples/custom-node-components/Cargo.toml | 2 - examples/custom-node-components/src/main.rs | 3 +- examples/stateful-precompile/src/main.rs | 2 +- 54 files changed, 518 insertions(+), 272 deletions(-) delete mode 100644 crates/rpc/rpc-eth-api/src/helpers/types.rs create mode 100644 crates/rpc/rpc-eth-api/src/types.rs diff --git a/Cargo.lock b/Cargo.lock index b5a47a8dc983..873cd2c815b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2856,7 +2856,6 @@ version = "0.0.0" dependencies = [ "eyre", "reth", - "reth-chainspec", "reth-node-ethereum", "reth-tracing", "reth-transaction-pool", @@ -5242,6 +5241,20 @@ dependencies = [ "serde", ] +[[package]] +name = "op-alloy-network" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3cbfa664a74fe4577a78d1c4bce18fa93be56756730782283df8ff3241c7118" +dependencies = [ + "alloy-consensus", + "alloy-network", + "alloy-primitives", + "alloy-rpc-types-eth", + "op-alloy-consensus", + "op-alloy-rpc-types", +] + [[package]] name = "op-alloy-rpc-types" version = "0.1.5" @@ -6948,6 +6961,7 @@ dependencies = [ "eyre", "futures-util", "jsonrpsee", + "jsonrpsee-types", "reth", "reth-chainspec", "reth-db", @@ -6959,6 +6973,8 @@ dependencies = [ "reth-provider", "reth-rpc", "reth-rpc-layer", + "reth-rpc-types", + "reth-rpc-types-compat", "reth-stages-types", "reth-tokio-util", "reth-tracing", @@ -7684,6 +7700,7 @@ dependencies = [ "reth-payload-builder", "reth-payload-primitives", "reth-provider", + "reth-rpc-eth-api", "reth-tasks", "reth-transaction-pool", ] @@ -7692,6 +7709,7 @@ dependencies = [ name = "reth-node-builder" version = "1.0.5" dependencies = [ + "alloy-network", "aquamarine", "eyre", "fdlimit", @@ -7914,6 +7932,7 @@ dependencies = [ "reth-primitives", "reth-provider", "reth-revm", + "reth-rpc", "reth-rpc-eth-api", "reth-rpc-eth-types", "reth-rpc-types", @@ -8017,12 +8036,14 @@ dependencies = [ "derive_more 1.0.0", "jsonrpsee", "jsonrpsee-types", + "op-alloy-network", "parking_lot 0.12.3", "reth-chainspec", "reth-evm", "reth-evm-optimism", "reth-network-api", "reth-node-api", + "reth-node-builder", "reth-primitives", "reth-provider", "reth-rpc", @@ -8266,6 +8287,7 @@ version = "1.0.5" dependencies = [ "alloy-dyn-abi", "alloy-genesis", + "alloy-network", "alloy-primitives", "alloy-rlp", "async-trait", @@ -8321,6 +8343,7 @@ dependencies = [ name = "reth-rpc-api" version = "1.0.5" dependencies = [ + "alloy-json-rpc", "jsonrpsee", "reth-engine-primitives", "reth-network-peers", @@ -8336,6 +8359,7 @@ version = "1.0.5" dependencies = [ "futures", "jsonrpsee", + "jsonrpsee-http-client", "reth-primitives", "reth-rpc-api", "reth-rpc-eth-api", @@ -8429,6 +8453,8 @@ name = "reth-rpc-eth-api" version = "1.0.5" dependencies = [ "alloy-dyn-abi", + "alloy-json-rpc", + "alloy-network", "async-trait", "auto_impl", "dyn-clone", diff --git a/Cargo.toml b/Cargo.toml index 0278ae35ccc7..9b525ff4e4aa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -428,6 +428,7 @@ alloy-transport-ws = { version = "0.2.1", default-features = false } # op op-alloy-rpc-types = "0.1" +op-alloy-network = "0.1" # misc aquamarine = "0.5" diff --git a/crates/e2e-test-utils/Cargo.toml b/crates/e2e-test-utils/Cargo.toml index 7bdbfd885e55..1111d44d7067 100644 --- a/crates/e2e-test-utils/Cargo.toml +++ b/crates/e2e-test-utils/Cargo.toml @@ -25,7 +25,11 @@ reth-tokio-util.workspace = true reth-stages-types.workspace = true reth-network-peers.workspace = true reth-node-ethereum.workspace = true +reth-rpc-types.workspace = true +reth-rpc-types-compat.workspace = true +# rpc +jsonrpsee-types.workspace = true jsonrpsee.workspace = true futures-util.workspace = true diff --git a/crates/e2e-test-utils/src/lib.rs b/crates/e2e-test-utils/src/lib.rs index c7f464fa7423..032acaccb09f 100644 --- a/crates/e2e-test-utils/src/lib.rs +++ b/crates/e2e-test-utils/src/lib.rs @@ -2,6 +2,7 @@ use std::sync::Arc; +use alloy_network::Network; use node::NodeTestContext; use reth::{ args::{DiscoveryArgs, NetworkArgs, RpcServerArgs}, @@ -51,9 +52,17 @@ pub async fn setup( ) -> eyre::Result<(Vec>, TaskManager, Wallet)> where N: Default + Node> + NodeTypes, - <>>::Components as NodeComponents>>::Network: PeersHandleProvider, - >>::EthApi: - FullEthApiServer + AddDevSigners + EthApiBuilderProvider>, + N::ComponentsBuilder: NodeComponentsBuilder< + TmpNodeAdapter, + Components: NodeComponents, Network: PeersHandleProvider>, + >, + N::AddOns: NodeAddOns< + Adapter, + EthApi: FullEthApiServer< + NetworkTypes: Network, + > + AddDevSigners + + EthApiBuilderProvider>, + >, { let tasks = TaskManager::current(); let exec = tasks.executor(); diff --git a/crates/e2e-test-utils/src/node.rs b/crates/e2e-test-utils/src/node.rs index 350eb6ca0d85..681a3bbd176a 100644 --- a/crates/e2e-test-utils/src/node.rs +++ b/crates/e2e-test-utils/src/node.rs @@ -1,5 +1,6 @@ use std::{marker::PhantomData, pin::Pin}; +use alloy_network::Network; use alloy_rpc_types::BlockNumberOrTag; use eyre::Ok; use futures_util::Future; @@ -14,8 +15,7 @@ use reth::{ types::engine::PayloadStatusEnum, }, }; -use reth_chainspec::ChainSpec; -use reth_node_builder::{NodeAddOns, NodeTypes}; +use reth_node_builder::{EthApiTypes, NodeAddOns, NodeTypes}; use reth_primitives::{BlockHash, BlockNumber, Bytes, B256}; use reth_stages_types::StageId; use tokio_stream::StreamExt; @@ -46,7 +46,7 @@ where impl NodeTestContext where - Node: FullNodeComponents, + Node: FullNodeComponents, Node::Network: PeersHandleProvider, AddOns: NodeAddOns, { @@ -93,6 +93,8 @@ where ::ExecutionPayloadV3: From<::BuiltPayload> + PayloadEnvelopeExt, AddOns::EthApi: EthApiSpec + EthTransactions + TraceExt, + ::NetworkTypes: + Network, { let mut chain = Vec::with_capacity(length as usize); for i in 0..length { diff --git a/crates/e2e-test-utils/src/rpc.rs b/crates/e2e-test-utils/src/rpc.rs index 1714ffb7a29e..4688e435a654 100644 --- a/crates/e2e-test-utils/src/rpc.rs +++ b/crates/e2e-test-utils/src/rpc.rs @@ -1,5 +1,5 @@ use alloy_consensus::TxEnvelope; -use alloy_network::eip2718::Decodable2718; +use alloy_network::{eip2718::Decodable2718, Network}; use reth::{ builder::{rpc::RpcRegistry, FullNodeComponents}, rpc::api::{ @@ -7,17 +7,20 @@ use reth::{ DebugApiServer, }, }; -use reth_chainspec::ChainSpec; +use reth_node_builder::EthApiTypes; use reth_primitives::{Bytes, B256}; #[allow(missing_debug_implementations)] -pub struct RpcTestContext { +pub struct RpcTestContext { pub inner: RpcRegistry, } -impl, EthApi> RpcTestContext +impl RpcTestContext where - EthApi: EthApiSpec + EthTransactions + TraceExt, + Node: FullNodeComponents, + EthApi: EthApiSpec + + EthTransactions> + + TraceExt, { /// Injects a raw transaction into the node tx pool via RPC server pub async fn inject_tx(&self, raw_tx: Bytes) -> Result { diff --git a/crates/e2e-test-utils/src/transaction.rs b/crates/e2e-test-utils/src/transaction.rs index e2c6a019b3ac..041ba40d6eb2 100644 --- a/crates/e2e-test-utils/src/transaction.rs +++ b/crates/e2e-test-utils/src/transaction.rs @@ -2,13 +2,11 @@ use alloy_consensus::{ BlobTransactionSidecar, EnvKzgSettings, SidecarBuilder, SimpleCoder, TxEip4844Variant, TxEnvelope, }; -use alloy_network::{eip2718::Encodable2718, EthereumWallet, TransactionBuilder}; +use alloy_network::{eip2718::Encodable2718, Ethereum, EthereumWallet, TransactionBuilder}; use alloy_rpc_types::{TransactionInput, TransactionRequest}; use alloy_signer_local::PrivateKeySigner; use eyre::Ok; -use reth_primitives::{hex, Address, Bytes, U256}; - -use reth_primitives::B256; +use reth_primitives::{hex, Address, Bytes, TxKind, B256, U256}; /// Helper for transaction operations #[derive(Debug)] @@ -38,8 +36,11 @@ impl TransactionTestContext { builder.ingest(b"dummy blob"); let sidecar: BlobTransactionSidecar = builder.build()?; - tx.set_blob_sidecar(sidecar); - tx.set_max_fee_per_blob_gas(15e9 as u128); + >::set_blob_sidecar(&mut tx, sidecar); + >::set_max_fee_per_blob_gas( + &mut tx, + 15e9 as u128, + ); let signed = Self::sign_tx(wallet, tx).await; Ok(signed) @@ -48,7 +49,7 @@ impl TransactionTestContext { /// Signs an arbitrary [`TransactionRequest`] using the provided wallet pub async fn sign_tx(wallet: PrivateKeySigner, tx: TransactionRequest) -> TxEnvelope { let signer = EthereumWallet::from(wallet); - tx.build(&signer).await.unwrap() + >::build(tx, &signer).await.unwrap() } /// Creates a tx with blob sidecar and sign it, returning bytes @@ -70,7 +71,11 @@ impl TransactionTestContext { let l1_block_info = Bytes::from_static(&hex!("7ef9015aa044bae9d41b8380d781187b426c6fe43df5fb2fb57bd4466ef6a701e1f01e015694deaddeaddeaddeaddeaddeaddeaddeaddead000194420000000000000000000000000000000000001580808408f0d18001b90104015d8eb900000000000000000000000000000000000000000000000000000000008057650000000000000000000000000000000000000000000000000000000063d96d10000000000000000000000000000000000000000000000000000000000009f35273d89754a1e0387b89520d989d3be9c37c1f32495a88faf1ea05c61121ab0d1900000000000000000000000000000000000000000000000000000000000000010000000000000000000000002d679b567db6187c0c8323fa982cfb88b74dbcc7000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240")); let tx = tx(chain_id, Some(l1_block_info), nonce); let signer = EthereumWallet::from(wallet); - tx.build(&signer).await.unwrap().encoded_2718().into() + >::build(tx, &signer) + .await + .unwrap() + .encoded_2718() + .into() } /// Validates the sidecar of a given tx envelope and returns the versioned hashes @@ -95,7 +100,7 @@ fn tx(chain_id: u64, data: Option, nonce: u64) -> TransactionRequest { TransactionRequest { nonce: Some(nonce), value: Some(U256::from(100)), - to: Some(reth_primitives::TxKind::Call(Address::random())), + to: Some(TxKind::Call(Address::random())), gas: Some(210000), max_fee_per_gas: Some(20e9 as u128), max_priority_fee_per_gas: Some(20e9 as u128), diff --git a/crates/ethereum/node/src/node.rs b/crates/ethereum/node/src/node.rs index c6142d88aa53..ce1498a15f33 100644 --- a/crates/ethereum/node/src/node.rs +++ b/crates/ethereum/node/src/node.rs @@ -47,7 +47,7 @@ impl EthereumNode { EthereumConsensusBuilder, > where - Node: FullNodeTypes, + Node: FullNodeTypes, ::Engine: PayloadTypes< BuiltPayload = EthBuiltPayload, PayloadAttributes = EthPayloadAttributes, @@ -105,7 +105,7 @@ pub struct EthereumExecutorBuilder; impl ExecutorBuilder for EthereumExecutorBuilder where - Node: FullNodeTypes, + Node: FullNodeTypes, { type EVM = EthEvmConfig; type Executor = EthExecutorProvider; @@ -134,7 +134,7 @@ pub struct EthereumPoolBuilder { impl PoolBuilder for EthereumPoolBuilder where - Node: FullNodeTypes, + Node: FullNodeTypes, { type Pool = EthTransactionPool; @@ -212,7 +212,7 @@ impl EthereumPayloadBuilder { impl PayloadServiceBuilder for EthereumPayloadBuilder where - Node: FullNodeTypes, + Node: FullNodeTypes, Evm: ConfigureEvm, Pool: TransactionPool + Unpin + 'static, ::Engine: PayloadTypes< @@ -284,7 +284,7 @@ pub struct EthereumConsensusBuilder { impl ConsensusBuilder for EthereumConsensusBuilder where - Node: FullNodeTypes, + Node: FullNodeTypes, { type Consensus = Arc; diff --git a/crates/node/api/Cargo.toml b/crates/node/api/Cargo.toml index db5eb6b2de5e..e9f297fc44d1 100644 --- a/crates/node/api/Cargo.toml +++ b/crates/node/api/Cargo.toml @@ -21,4 +21,5 @@ reth-transaction-pool.workspace = true reth-payload-builder.workspace = true reth-payload-primitives.workspace = true reth-tasks.workspace = true +reth-rpc-eth-api.workspace = true reth-network-api.workspace = true diff --git a/crates/node/api/src/lib.rs b/crates/node/api/src/lib.rs index b01a2def0bde..8748fc79d94e 100644 --- a/crates/node/api/src/lib.rs +++ b/crates/node/api/src/lib.rs @@ -26,3 +26,5 @@ pub use node::*; // re-export for convenience pub use reth_provider::FullProvider; + +pub use reth_rpc_eth_api::EthApiTypes; diff --git a/crates/node/api/src/node.rs b/crates/node/api/src/node.rs index b7bfdd804183..50e87f98b7c3 100644 --- a/crates/node/api/src/node.rs +++ b/crates/node/api/src/node.rs @@ -2,7 +2,7 @@ use std::marker::PhantomData; -use reth_chainspec::EthChainSpec; +use reth_chainspec::{ChainSpec, EthChainSpec}; use reth_db_api::{ database::Database, database_metrics::{DatabaseMetadata, DatabaseMetrics}, @@ -11,6 +11,7 @@ use reth_evm::execute::BlockExecutorProvider; use reth_network_api::FullNetwork; use reth_payload_builder::PayloadBuilderHandle; use reth_provider::FullProvider; +use reth_rpc_eth_api::EthApiTypes; use reth_tasks::TaskExecutor; use reth_transaction_pool::TransactionPool; @@ -64,7 +65,7 @@ where /// node. /// /// Its types are configured by node internally and are not intended to be user configurable. -pub trait FullNodeTypes: NodeTypes + 'static { +pub trait FullNodeTypes: NodeTypes + 'static { /// Underlying database type used by the node to store and retrieve data. type DB: Database + DatabaseMetrics + DatabaseMetadata + Clone + Unpin + 'static; /// The provider type used to interact with the node. @@ -114,7 +115,7 @@ where impl FullNodeTypes for FullNodeTypesAdapter where - Types: NodeTypes, + Types: NodeTypes, Provider: FullProvider, DB: Database + DatabaseMetrics + DatabaseMetadata + Clone + Unpin + 'static, { @@ -162,7 +163,7 @@ pub trait FullNodeComponents: FullNodeTypes + Clone + 'static { pub trait NodeAddOns: Send + Sync + Unpin + Clone + 'static { /// The core `eth` namespace API type to install on the RPC server (see /// `reth_rpc_eth_api::EthApiServer`). - type EthApi: Send + Clone; + type EthApi: EthApiTypes + Send + Clone; } impl NodeAddOns for () { diff --git a/crates/node/builder/Cargo.toml b/crates/node/builder/Cargo.toml index 106337d17b1a..e5290233b8eb 100644 --- a/crates/node/builder/Cargo.toml +++ b/crates/node/builder/Cargo.toml @@ -55,6 +55,9 @@ reth-engine-service.workspace = true reth-tokio-util.workspace = true reth-engine-tree.workspace = true +## ethereum +alloy-network.workspace = true + ## async futures.workspace = true tokio = { workspace = true, features = [ diff --git a/crates/node/builder/src/builder/add_ons.rs b/crates/node/builder/src/builder/add_ons.rs index 54a776fd69aa..e8eb3b49dc7b 100644 --- a/crates/node/builder/src/builder/add_ons.rs +++ b/crates/node/builder/src/builder/add_ons.rs @@ -2,7 +2,7 @@ use std::marker::PhantomData; -use reth_node_api::{FullNodeComponents, NodeAddOns}; +use reth_node_api::{EthApiTypes, FullNodeComponents, NodeAddOns}; use crate::{exex::BoxedLaunchExEx, hooks::NodeHooks, rpc::RpcHooks}; @@ -21,7 +21,7 @@ pub struct AddOns> { /// Captures node specific addons that can be installed on top of the type configured node and are /// required for launching the node, such as RPC. #[derive(Default)] -pub struct RpcAddOns { +pub struct RpcAddOns { /// Core `eth` API type to install on the RPC server, configured w.r.t. network. pub _eth_api: PhantomData, /// Additional RPC hooks. diff --git a/crates/node/builder/src/builder/mod.rs b/crates/node/builder/src/builder/mod.rs index c40c2490074f..a4303023a776 100644 --- a/crates/node/builder/src/builder/mod.rs +++ b/crates/node/builder/src/builder/mod.rs @@ -328,7 +328,11 @@ where >>::Components, > > - + FullEthApiServer + + FullEthApiServer< + NetworkTypes: alloy_network::Network< + TransactionResponse = reth_rpc_types::Transaction + >, + > + AddDevSigners >, { @@ -474,8 +478,9 @@ where AO: NodeAddOns< NodeAdapter, CB::Components>, EthApi: EthApiBuilderProvider, CB::Components>> - + FullEthApiServer - + AddDevSigners, + + FullEthApiServer< + NetworkTypes: alloy_network::Network, + > + AddDevSigners, >, { /// Launches the node with the [`DefaultNodeLauncher`] that sets up engine API consensus and rpc diff --git a/crates/node/builder/src/launch/engine.rs b/crates/node/builder/src/launch/engine.rs index 362938c7322b..0f3f9dc95e70 100644 --- a/crates/node/builder/src/launch/engine.rs +++ b/crates/node/builder/src/launch/engine.rs @@ -35,13 +35,11 @@ use tokio::sync::{mpsc::unbounded_channel, oneshot}; use tokio_stream::wrappers::UnboundedReceiverStream; use crate::{ - components::NodeComponents, hooks::NodeHooks, - launch::{LaunchContext, LaunchNode}, rpc::{launch_rpc_servers, EthApiBuilderProvider}, setup::build_networked_pipeline, - AddOns, ExExLauncher, FullNode, NodeAdapter, NodeBuilderWithComponents, NodeComponentsBuilder, - NodeHandle, NodeTypesAdapter, + AddOns, ExExLauncher, FullNode, LaunchContext, LaunchNode, NodeAdapter, + NodeBuilderWithComponents, NodeComponents, NodeComponentsBuilder, NodeHandle, NodeTypesAdapter, }; /// The engine node launcher. @@ -68,8 +66,9 @@ where AO: NodeAddOns< NodeAdapter, EthApi: EthApiBuilderProvider> - + FullEthApiServer - + AddDevSigners, + + FullEthApiServer< + NetworkTypes: alloy_network::Network, + > + AddDevSigners, >, { type Node = NodeHandle, AO>; diff --git a/crates/node/builder/src/launch/mod.rs b/crates/node/builder/src/launch/mod.rs index bb7715c89fad..b46747f3ca99 100644 --- a/crates/node/builder/src/launch/mod.rs +++ b/crates/node/builder/src/launch/mod.rs @@ -110,8 +110,9 @@ where AO: NodeAddOns< NodeAdapter, EthApi: EthApiBuilderProvider> - + FullEthApiServer - + AddDevSigners, + + FullEthApiServer< + NetworkTypes: alloy_network::Network, + > + AddDevSigners, >, { type Node = NodeHandle, AO>; diff --git a/crates/node/builder/src/rpc.rs b/crates/node/builder/src/rpc.rs index cb229f8601d6..123eae88e727 100644 --- a/crates/node/builder/src/rpc.rs +++ b/crates/node/builder/src/rpc.rs @@ -6,11 +6,13 @@ use std::{ }; use futures::TryFutureExt; -use reth_chainspec::ChainSpec; use reth_node_api::{BuilderProvider, FullNodeComponents}; use reth_node_core::{ node_config::NodeConfig, - rpc::{api::EngineApiServer, eth::FullEthApiServer}, + rpc::{ + api::EngineApiServer, + eth::{EthApiTypes, FullEthApiServer}, + }, }; use reth_payload_builder::PayloadBuilderHandle; use reth_rpc_builder::{ @@ -43,13 +45,21 @@ pub struct RpcHooks { pub extend_rpc_modules: Box>, } -impl Default for RpcHooks { +impl Default for RpcHooks +where + Node: FullNodeComponents, + EthApi: EthApiTypes, +{ fn default() -> Self { Self { on_rpc_started: Box::<()>::default(), extend_rpc_modules: Box::<()>::default() } } } -impl RpcHooks { +impl RpcHooks +where + Node: FullNodeComponents, + EthApi: EthApiTypes, +{ /// Sets the hook that is run once the rpc server is started. pub(crate) fn set_on_rpc_started(&mut self, hook: F) -> &mut Self where @@ -89,7 +99,11 @@ impl RpcHooks { } } -impl fmt::Debug for RpcHooks { +impl fmt::Debug for RpcHooks +where + Node: FullNodeComponents, + EthApi: EthApiTypes, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RpcHooks") .field("on_rpc_started", &"...") @@ -99,7 +113,7 @@ impl fmt::Debug for RpcHooks { } /// Event hook that is called once the rpc server is started. -pub trait OnRpcStarted: Send { +pub trait OnRpcStarted: Send { /// The hook that is called once the rpc server is started. fn on_rpc_started( self: Box, @@ -112,6 +126,7 @@ impl OnRpcStarted for F where F: FnOnce(RpcContext<'_, Node, EthApi>, RethRpcServerHandles) -> eyre::Result<()> + Send, Node: FullNodeComponents, + EthApi: EthApiTypes, { fn on_rpc_started( self: Box, @@ -122,7 +137,11 @@ where } } -impl OnRpcStarted for () { +impl OnRpcStarted for () +where + Node: FullNodeComponents, + EthApi: EthApiTypes, +{ fn on_rpc_started( self: Box, _: RpcContext<'_, Node, EthApi>, @@ -133,7 +152,7 @@ impl OnRpcStarted for () { } /// Event hook that is called when the rpc server is started. -pub trait ExtendRpcModules: Send { +pub trait ExtendRpcModules: Send { /// The hook that is called once the rpc server is started. fn extend_rpc_modules(self: Box, ctx: RpcContext<'_, Node, EthApi>) -> eyre::Result<()>; } @@ -142,13 +161,18 @@ impl ExtendRpcModules for F where F: FnOnce(RpcContext<'_, Node, EthApi>) -> eyre::Result<()> + Send, Node: FullNodeComponents, + EthApi: EthApiTypes, { fn extend_rpc_modules(self: Box, ctx: RpcContext<'_, Node, EthApi>) -> eyre::Result<()> { (*self)(ctx) } } -impl ExtendRpcModules for () { +impl ExtendRpcModules for () +where + Node: FullNodeComponents, + EthApi: EthApiTypes, +{ fn extend_rpc_modules(self: Box, _: RpcContext<'_, Node, EthApi>) -> eyre::Result<()> { Ok(()) } @@ -157,7 +181,7 @@ impl ExtendRpcModules for () { /// Helper wrapper type to encapsulate the [`RpcRegistryInner`] over components trait. #[derive(Debug, Clone)] #[allow(clippy::type_complexity)] -pub struct RpcRegistry { +pub struct RpcRegistry { pub(crate) registry: RpcRegistryInner< Node::Provider, Node::Pool, @@ -168,7 +192,11 @@ pub struct RpcRegistry { >, } -impl Deref for RpcRegistry { +impl Deref for RpcRegistry +where + Node: FullNodeComponents, + EthApi: EthApiTypes, +{ type Target = RpcRegistryInner< Node::Provider, Node::Pool, @@ -183,7 +211,11 @@ impl Deref for RpcRegistry { } } -impl DerefMut for RpcRegistry { +impl DerefMut for RpcRegistry +where + Node: FullNodeComponents, + EthApi: EthApiTypes, +{ fn deref_mut(&mut self) -> &mut Self::Target { &mut self.registry } @@ -197,7 +229,7 @@ impl DerefMut for RpcRegistry { /// transport modules [`TransportRpcModules`] as well as configured authenticated methods /// [`AuthRpcModule`]. #[allow(missing_debug_implementations)] -pub struct RpcContext<'a, Node: FullNodeComponents, EthApi> { +pub struct RpcContext<'a, Node: FullNodeComponents, EthApi: EthApiTypes> { /// The node components. pub(crate) node: Node, @@ -219,7 +251,11 @@ pub struct RpcContext<'a, Node: FullNodeComponents, EthApi> { pub auth_module: &'a mut AuthRpcModule, } -impl<'a, Node: FullNodeComponents, EthApi> RpcContext<'a, Node, EthApi> { +impl<'a, Node, EthApi> RpcContext<'a, Node, EthApi> +where + Node: FullNodeComponents, + EthApi: EthApiTypes, +{ /// Returns the config of the node. pub const fn config(&self) -> &NodeConfig { self.config @@ -260,9 +296,12 @@ pub async fn launch_rpc_servers( add_ons: RpcAddOns, ) -> eyre::Result<(RethRpcServerHandles, RpcRegistry)> where - EthApi: EthApiBuilderProvider + FullEthApiServer, - Node: FullNodeComponents + Clone, + Node: FullNodeComponents + Clone, Engine: EngineApiServer, + EthApi: EthApiBuilderProvider + + FullEthApiServer< + NetworkTypes: alloy_network::Network, + >, { let auth_config = config.rpc.auth_server_config(jwt_secret)?; let module_config = config.rpc.transport_rpc_module_config(); @@ -334,7 +373,7 @@ where } /// Provides builder for the core `eth` API type. -pub trait EthApiBuilderProvider: BuilderProvider { +pub trait EthApiBuilderProvider: BuilderProvider + EthApiTypes { /// Returns the eth api builder. #[allow(clippy::type_complexity)] fn eth_api_builder() -> Box) -> Self + Send>; @@ -343,7 +382,7 @@ pub trait EthApiBuilderProvider: BuilderProvider { impl EthApiBuilderProvider for F where N: FullNodeComponents, - for<'a> F: BuilderProvider = &'a EthApiBuilderCtx>, + for<'a> F: BuilderProvider = &'a EthApiBuilderCtx> + EthApiTypes, { fn eth_api_builder() -> Box) -> Self + Send> { F::builder() diff --git a/crates/optimism/node/Cargo.toml b/crates/optimism/node/Cargo.toml index 52b622e22eca..52c436ecb16c 100644 --- a/crates/optimism/node/Cargo.toml +++ b/crates/optimism/node/Cargo.toml @@ -36,6 +36,7 @@ reth-discv5.workspace = true reth-rpc-eth-types.workspace = true reth-rpc-eth-api.workspace = true reth-optimism-rpc.workspace = true +reth-rpc.workspace = true # async async-trait.workspace = true diff --git a/crates/optimism/node/src/node.rs b/crates/optimism/node/src/node.rs index 1dca4b7da5b1..823395d4ac08 100644 --- a/crates/optimism/node/src/node.rs +++ b/crates/optimism/node/src/node.rs @@ -119,7 +119,7 @@ pub struct OptimismExecutorBuilder; impl ExecutorBuilder for OptimismExecutorBuilder where - Node: FullNodeTypes, + Node: FullNodeTypes, { type EVM = OptimismEvmConfig; type Executor = OpExecutorProvider; @@ -146,7 +146,7 @@ pub struct OptimismPoolBuilder; impl PoolBuilder for OptimismPoolBuilder where - Node: FullNodeTypes, + Node: FullNodeTypes, { type Pool = OpTransactionPool; @@ -290,7 +290,7 @@ pub struct OptimismNetworkBuilder { impl NetworkBuilder for OptimismNetworkBuilder where - Node: FullNodeTypes, + Node: FullNodeTypes, Pool: TransactionPool + Unpin + 'static, { async fn build_network( @@ -347,7 +347,7 @@ pub struct OptimismConsensusBuilder; impl ConsensusBuilder for OptimismConsensusBuilder where - Node: FullNodeTypes, + Node: FullNodeTypes, { type Consensus = Arc; diff --git a/crates/optimism/primitives/Cargo.toml b/crates/optimism/primitives/Cargo.toml index 0acd2f1ebdca..262cb5881504 100644 --- a/crates/optimism/primitives/Cargo.toml +++ b/crates/optimism/primitives/Cargo.toml @@ -9,4 +9,4 @@ repository.workspace = true description = "OP primitive types" [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/crates/optimism/rpc/Cargo.toml b/crates/optimism/rpc/Cargo.toml index b75b461d6545..1e0031cf14d4 100644 --- a/crates/optimism/rpc/Cargo.toml +++ b/crates/optimism/rpc/Cargo.toml @@ -26,10 +26,12 @@ reth-transaction-pool.workspace = true reth-rpc.workspace = true reth-node-api.workspace = true reth-network-api.workspace = true +reth-node-builder.workspace = true reth-chainspec.workspace = true # ethereum alloy-primitives.workspace = true +op-alloy-network.workspace = true revm.workspace = true # async @@ -60,5 +62,5 @@ optimism = [ "reth-primitives/optimism", "reth-provider/optimism", "reth-rpc-eth-api/optimism", - "revm/optimism" + "revm/optimism", ] \ No newline at end of file diff --git a/crates/optimism/rpc/src/eth/call.rs b/crates/optimism/rpc/src/eth/call.rs index e877d9ae660b..5018ab129a53 100644 --- a/crates/optimism/rpc/src/eth/call.rs +++ b/crates/optimism/rpc/src/eth/call.rs @@ -1,4 +1,3 @@ -use reth_chainspec::ChainSpec; use reth_evm::ConfigureEvm; use reth_node_api::FullNodeComponents; use reth_primitives::{ @@ -17,7 +16,7 @@ use crate::{OpEthApi, OpEthApiError}; impl EthCall for OpEthApi where Self: Call, - N: FullNodeComponents, + N: FullNodeComponents, { } diff --git a/crates/optimism/rpc/src/eth/mod.rs b/crates/optimism/rpc/src/eth/mod.rs index 3d379c9d3ae3..9fd6d0e17662 100644 --- a/crates/optimism/rpc/src/eth/mod.rs +++ b/crates/optimism/rpc/src/eth/mod.rs @@ -11,10 +11,12 @@ use std::{fmt, sync::Arc}; use alloy_primitives::U256; use derive_more::Deref; +use op_alloy_network::Optimism; use reth_chainspec::ChainSpec; use reth_evm::ConfigureEvm; use reth_network_api::NetworkInfo; use reth_node_api::{BuilderProvider, FullNodeComponents, FullNodeTypes}; +use reth_node_builder::EthApiBuilderCtx; use reth_provider::{ BlockIdReader, BlockNumReader, BlockReaderIdExt, ChainSpecProvider, HeaderProvider, StageCheckpointReader, StateProviderFactory, @@ -22,15 +24,15 @@ use reth_provider::{ use reth_rpc::eth::{core::EthApiInner, DevSigner}; use reth_rpc_eth_api::{ helpers::{ - AddDevSigners, EthApiSpec, EthFees, EthState, LoadBlock, LoadFee, LoadState, SpawnBlocking, - Trace, + AddDevSigners, EthApiSpec, EthFees, EthSigner, EthState, LoadBlock, LoadFee, LoadState, + SpawnBlocking, Trace, }, EthApiTypes, }; use reth_rpc_eth_types::{EthStateCache, FeeHistoryCache, GasPriceOracle}; use reth_tasks::{ pool::{BlockingTaskGuard, BlockingTaskPool}, - TaskExecutor, TaskSpawner, + TaskSpawner, }; use reth_transaction_pool::TransactionPool; @@ -44,16 +46,6 @@ pub type EthApiNodeBackend = EthApiInner< ::Evm, >; -/// Adapter for [`EthApiBuilderCtx`]. -pub type EthApiBuilderCtx = reth_rpc_eth_types::EthApiBuilderCtx< - ::Provider, - ::Pool, - ::Evm, - ::Network, - TaskExecutor, - ::Provider, ->; - /// OP-Reth `Eth` API implementation. /// /// This type provides the functionality for handling `eth_` related requests. @@ -66,6 +58,7 @@ pub type EthApiBuilderCtx = reth_rpc_eth_types::EthApiBuilderCtx< /// all the `Eth` helper traits and prerequisite traits. #[derive(Clone, Deref)] pub struct OpEthApi { + #[deref] inner: Arc>, } @@ -99,14 +92,16 @@ impl OpEthApi { impl EthApiTypes for OpEthApi where Self: Send + Sync, - N: FullNodeComponents, + N: FullNodeComponents, { type Error = OpEthApiError; + type NetworkTypes = Optimism; } impl EthApiSpec for OpEthApi where - N: FullNodeComponents, + Self: Send + Sync, + N: FullNodeComponents, { #[inline] fn provider( @@ -127,7 +122,7 @@ where } #[inline] - fn signers(&self) -> &parking_lot::RwLock>> { + fn signers(&self) -> &parking_lot::RwLock>> { self.inner.signers() } } @@ -135,7 +130,7 @@ where impl SpawnBlocking for OpEthApi where Self: Send + Sync + Clone + 'static, - N: FullNodeComponents, + N: FullNodeComponents, { #[inline] fn io_task_spawner(&self) -> impl TaskSpawner { @@ -156,7 +151,7 @@ where impl LoadFee for OpEthApi where Self: LoadBlock, - N: FullNodeComponents, + N: FullNodeComponents, { #[inline] fn provider( @@ -184,7 +179,7 @@ where impl LoadState for OpEthApi where Self: Send + Sync, - N: FullNodeComponents, + N: FullNodeComponents, { #[inline] fn provider(&self) -> impl StateProviderFactory + ChainSpecProvider { @@ -239,6 +234,7 @@ impl AddDevSigners for OpEthApi { impl BuilderProvider for OpEthApi where + Self: Send, N: FullNodeComponents, { type Ctx<'a> = &'a EthApiBuilderCtx; @@ -249,7 +245,7 @@ where } impl fmt::Debug for OpEthApi { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> 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 62aaee682dad..4474c8ef4d93 100644 --- a/crates/optimism/rpc/src/eth/pending_block.rs +++ b/crates/optimism/rpc/src/eth/pending_block.rs @@ -1,6 +1,5 @@ //! Loads OP pending block for a RPC response. -use crate::OpEthApi; use reth_chainspec::ChainSpec; use reth_evm::ConfigureEvm; use reth_node_api::FullNodeComponents; @@ -18,10 +17,12 @@ use reth_rpc_eth_api::{ use reth_rpc_eth_types::{EthApiError, PendingBlock}; use reth_transaction_pool::TransactionPool; +use crate::OpEthApi; + impl LoadPendingBlock for OpEthApi where Self: SpawnBlocking, - N: FullNodeComponents, + N: FullNodeComponents, { #[inline] fn provider( diff --git a/crates/rpc/rpc-api/Cargo.toml b/crates/rpc/rpc-api/Cargo.toml index 8108e75852be..3bfb2e9a7662 100644 --- a/crates/rpc/rpc-api/Cargo.toml +++ b/crates/rpc/rpc-api/Cargo.toml @@ -19,6 +19,9 @@ reth-rpc-eth-api.workspace = true reth-engine-primitives.workspace = true reth-network-peers.workspace = true +# ethereum +alloy-json-rpc.workspace = true + # misc jsonrpsee = { workspace = true, features = ["server", "macros"] } diff --git a/crates/rpc/rpc-api/src/engine.rs b/crates/rpc/rpc-api/src/engine.rs index 01451e4a9a84..0b1ca76fa995 100644 --- a/crates/rpc/rpc-api/src/engine.rs +++ b/crates/rpc/rpc-api/src/engine.rs @@ -3,6 +3,7 @@ //! This contains the `engine_` namespace and the subset of the `eth_` namespace that is exposed to //! the consensus client. +use alloy_json_rpc::RpcObject; use jsonrpsee::{core::RpcResult, proc_macros::rpc}; use reth_engine_primitives::EngineTypes; use reth_primitives::{Address, BlockHash, BlockId, BlockNumberOrTag, Bytes, B256, U256, U64}; @@ -13,8 +14,8 @@ use reth_rpc_types::{ ForkchoiceState, ForkchoiceUpdated, PayloadId, PayloadStatus, TransitionConfiguration, }, state::StateOverride, - BlockOverrides, EIP1186AccountProofResponse, Filter, JsonStorageKey, Log, RichBlock, - SyncStatus, TransactionRequest, + BlockOverrides, EIP1186AccountProofResponse, Filter, JsonStorageKey, Log, SyncStatus, + TransactionRequest, }; // NOTE: We can't use associated types in the `EngineApi` trait because of jsonrpsee, so we use a // generic here. It would be nice if the rpc macro would understand which types need to have serde. @@ -219,7 +220,7 @@ pub trait EngineApi { /// Specifically for the engine auth server: #[cfg_attr(not(feature = "client"), rpc(server, namespace = "eth"))] #[cfg_attr(feature = "client", rpc(server, client, namespace = "eth"))] -pub trait EngineEthApi { +pub trait EngineEthApi { /// Returns an object with data about the sync status or false. #[method(name = "syncing")] fn syncing(&self) -> RpcResult; @@ -248,15 +249,11 @@ pub trait EngineEthApi { /// Returns information about a block by hash. #[method(name = "getBlockByHash")] - async fn block_by_hash(&self, hash: B256, full: bool) -> RpcResult>; + async fn block_by_hash(&self, hash: B256, full: bool) -> RpcResult>; /// Returns information about a block by number. #[method(name = "getBlockByNumber")] - async fn block_by_number( - &self, - number: BlockNumberOrTag, - full: bool, - ) -> RpcResult>; + async fn block_by_number(&self, number: BlockNumberOrTag, full: bool) -> RpcResult>; /// Sends signed transaction, returning its hash. #[method(name = "sendRawTransaction")] diff --git a/crates/rpc/rpc-builder/Cargo.toml b/crates/rpc/rpc-builder/Cargo.toml index 790feb70b913..f4b8e4f64b61 100644 --- a/crates/rpc/rpc-builder/Cargo.toml +++ b/crates/rpc/rpc-builder/Cargo.toml @@ -28,6 +28,7 @@ reth-tasks = { workspace = true, features = ["rayon"] } reth-transaction-pool.workspace = true reth-evm.workspace = true reth-engine-primitives.workspace = true +reth-rpc-types.workspace = true # rpc/net jsonrpsee = { workspace = true, features = ["server"] } diff --git a/crates/rpc/rpc-builder/src/lib.rs b/crates/rpc/rpc-builder/src/lib.rs index cf38fd1fa7bc..3deaba61864b 100644 --- a/crates/rpc/rpc-builder/src/lib.rs +++ b/crates/rpc/rpc-builder/src/lib.rs @@ -807,7 +807,7 @@ where /// If called outside of the tokio runtime. See also [`Self::eth_api`] pub fn register_eth(&mut self) -> &mut Self where - EthApi: EthApiServer, + EthApi: EthApiServer, { let eth_api = self.eth_api().clone(); self.modules.insert(RethRpcModule::Eth, eth_api.into_rpc().into()); @@ -821,7 +821,7 @@ where /// If called outside of the tokio runtime. See also [`Self::eth_api`] pub fn register_ots(&mut self) -> &mut Self where - EthApi: EthApiServer + TraceExt, + EthApi: EthApiServer + TraceExt, { let otterscan_api = self.otterscan_api(); self.modules.insert(RethRpcModule::Ots, otterscan_api.into_rpc().into()); @@ -921,7 +921,7 @@ where /// If called outside of the tokio runtime. See also [`Self::eth_api`] pub fn otterscan_api(&self) -> OtterscanApi where - EthApi: EthApiServer, + EthApi: EthApiServer, { let eth_api = self.eth_api().clone(); OtterscanApi::new(eth_api) diff --git a/crates/rpc/rpc-builder/tests/it/http.rs b/crates/rpc/rpc-builder/tests/it/http.rs index 9a858d5a4751..2b65bc19a8db 100644 --- a/crates/rpc/rpc-builder/tests/it/http.rs +++ b/crates/rpc/rpc-builder/tests/it/http.rs @@ -116,20 +116,21 @@ async fn test_filter_calls(client: &C) where C: ClientT + SubscriptionClientT + Sync, { - EthFilterApiClient::new_filter(client, Filter::default()).await.unwrap(); - EthFilterApiClient::new_pending_transaction_filter(client, None).await.unwrap(); - EthFilterApiClient::new_pending_transaction_filter( + EthFilterApiClient::::new_filter(client, Filter::default()).await.unwrap(); + EthFilterApiClient::::new_pending_transaction_filter(client, None).await.unwrap(); + EthFilterApiClient::::new_pending_transaction_filter( client, Some(PendingTransactionFilterKind::Full), ) .await .unwrap(); - let id = EthFilterApiClient::new_block_filter(client).await.unwrap(); - EthFilterApiClient::filter_changes(client, id.clone()).await.unwrap(); - EthFilterApiClient::logs(client, Filter::default()).await.unwrap(); - let id = EthFilterApiClient::new_filter(client, Filter::default()).await.unwrap(); - EthFilterApiClient::filter_logs(client, id.clone()).await.unwrap(); - EthFilterApiClient::uninstall_filter(client, id).await.unwrap(); + let id = EthFilterApiClient::::new_block_filter(client).await.unwrap(); + EthFilterApiClient::::filter_changes(client, id.clone()).await.unwrap(); + EthFilterApiClient::::logs(client, Filter::default()).await.unwrap(); + let id = + EthFilterApiClient::::new_filter(client, Filter::default()).await.unwrap(); + EthFilterApiClient::::filter_logs(client, id.clone()).await.unwrap(); + EthFilterApiClient::::uninstall_filter(client, id).await.unwrap(); } async fn test_basic_admin_calls(client: &C) @@ -172,60 +173,136 @@ where .unwrap(); // Implemented - EthApiClient::protocol_version(client).await.unwrap(); - EthApiClient::chain_id(client).await.unwrap(); - EthApiClient::accounts(client).await.unwrap(); - EthApiClient::get_account(client, address, block_number.into()).await.unwrap(); - EthApiClient::block_number(client).await.unwrap(); - EthApiClient::get_code(client, address, None).await.unwrap(); - EthApiClient::send_raw_transaction(client, tx).await.unwrap(); - EthApiClient::fee_history(client, U64::from(0), block_number, None).await.unwrap(); - EthApiClient::balance(client, address, None).await.unwrap(); - EthApiClient::transaction_count(client, address, None).await.unwrap(); - EthApiClient::storage_at(client, address, U256::default().into(), None).await.unwrap(); - EthApiClient::block_by_hash(client, hash, false).await.unwrap(); - EthApiClient::block_by_number(client, block_number, false).await.unwrap(); - EthApiClient::block_transaction_count_by_number(client, block_number).await.unwrap(); - EthApiClient::block_transaction_count_by_hash(client, hash).await.unwrap(); - EthApiClient::block_uncles_count_by_hash(client, hash).await.unwrap(); - EthApiClient::block_uncles_count_by_number(client, block_number).await.unwrap(); - EthApiClient::uncle_by_block_hash_and_index(client, hash, index).await.unwrap(); - EthApiClient::uncle_by_block_number_and_index(client, block_number, index).await.unwrap(); - EthApiClient::sign(client, address, bytes.clone()).await.unwrap_err(); - EthApiClient::sign_typed_data(client, address, typed_data).await.unwrap_err(); - EthApiClient::transaction_by_hash(client, tx_hash).await.unwrap(); - EthApiClient::transaction_by_block_hash_and_index(client, hash, index).await.unwrap(); - EthApiClient::transaction_by_block_number_and_index(client, block_number, index).await.unwrap(); - EthApiClient::create_access_list(client, call_request.clone(), Some(block_number.into())) + EthApiClient::::protocol_version(client).await.unwrap(); + EthApiClient::::chain_id(client).await.unwrap(); + EthApiClient::::accounts(client).await.unwrap(); + EthApiClient::::get_account(client, address, block_number.into()) .await .unwrap(); - EthApiClient::estimate_gas(client, call_request.clone(), Some(block_number.into()), None) + EthApiClient::::block_number(client).await.unwrap(); + EthApiClient::::get_code(client, address, None).await.unwrap(); + EthApiClient::::send_raw_transaction(client, tx).await.unwrap(); + EthApiClient::::fee_history(client, U64::from(0), block_number, None) .await .unwrap(); - EthApiClient::call(client, call_request.clone(), Some(block_number.into()), None, None) + EthApiClient::::balance(client, address, None).await.unwrap(); + EthApiClient::::transaction_count(client, address, None).await.unwrap(); + EthApiClient::::storage_at( + client, + address, + U256::default().into(), + None, + ) + .await + .unwrap(); + EthApiClient::::block_by_hash(client, hash, false).await.unwrap(); + EthApiClient::::block_by_number(client, block_number, false) + .await + .unwrap(); + EthApiClient::::block_transaction_count_by_number(client, block_number) + .await + .unwrap(); + EthApiClient::::block_transaction_count_by_hash(client, hash) + .await + .unwrap(); + EthApiClient::::block_uncles_count_by_hash(client, hash).await.unwrap(); + EthApiClient::::block_uncles_count_by_number(client, block_number) .await .unwrap(); - EthApiClient::syncing(client).await.unwrap(); - EthApiClient::send_transaction(client, transaction_request).await.unwrap_err(); - EthApiClient::hashrate(client).await.unwrap(); - EthApiClient::submit_hashrate(client, U256::default(), B256::default()).await.unwrap(); - EthApiClient::gas_price(client).await.unwrap_err(); - EthApiClient::max_priority_fee_per_gas(client).await.unwrap_err(); - EthApiClient::get_proof(client, address, vec![], None).await.unwrap(); + EthApiClient::::uncle_by_block_hash_and_index(client, hash, index) + .await + .unwrap(); + EthApiClient::::uncle_by_block_number_and_index( + client, + block_number, + index, + ) + .await + .unwrap(); + EthApiClient::::sign(client, address, bytes.clone()).await.unwrap_err(); + EthApiClient::::sign_typed_data(client, address, typed_data) + .await + .unwrap_err(); + EthApiClient::::transaction_by_hash(client, tx_hash).await.unwrap(); + EthApiClient::::transaction_by_block_hash_and_index( + client, hash, index, + ) + .await + .unwrap(); + EthApiClient::::transaction_by_block_number_and_index( + client, + block_number, + index, + ) + .await + .unwrap(); + EthApiClient::::create_access_list( + client, + call_request.clone(), + Some(block_number.into()), + ) + .await + .unwrap(); + EthApiClient::::estimate_gas( + client, + call_request.clone(), + Some(block_number.into()), + None, + ) + .await + .unwrap(); + EthApiClient::::call( + client, + call_request.clone(), + Some(block_number.into()), + None, + None, + ) + .await + .unwrap(); + EthApiClient::::syncing(client).await.unwrap(); + EthApiClient::::send_transaction(client, transaction_request) + .await + .unwrap_err(); + EthApiClient::::hashrate(client).await.unwrap(); + EthApiClient::::submit_hashrate( + client, + U256::default(), + B256::default(), + ) + .await + .unwrap(); + EthApiClient::::gas_price(client).await.unwrap_err(); + EthApiClient::::max_priority_fee_per_gas(client).await.unwrap_err(); + EthApiClient::::get_proof(client, address, vec![], None).await.unwrap(); // Unimplemented - assert!(is_unimplemented(EthApiClient::author(client).await.err().unwrap())); - assert!(is_unimplemented(EthApiClient::is_mining(client).await.err().unwrap())); - assert!(is_unimplemented(EthApiClient::get_work(client).await.err().unwrap())); assert!(is_unimplemented( - EthApiClient::submit_work(client, B64::default(), B256::default(), B256::default()) + EthApiClient::::author(client).await.err().unwrap() + )); + assert!(is_unimplemented( + EthApiClient::::is_mining(client).await.err().unwrap() + )); + assert!(is_unimplemented( + EthApiClient::::get_work(client).await.err().unwrap() + )); + assert!(is_unimplemented( + EthApiClient::::submit_work( + client, + B64::default(), + B256::default(), + B256::default() + ) + .await + .err() + .unwrap() + )); + assert!(is_unimplemented( + EthApiClient::::sign_transaction(client, call_request.clone()) .await .err() .unwrap() )); - assert!(is_unimplemented( - EthApiClient::sign_transaction(client, call_request.clone()).await.err().unwrap() - )); } async fn test_basic_debug_calls(client: &C) diff --git a/crates/rpc/rpc-builder/tests/it/middleware.rs b/crates/rpc/rpc-builder/tests/it/middleware.rs index 59cc86d4dc86..6641157e9f35 100644 --- a/crates/rpc/rpc-builder/tests/it/middleware.rs +++ b/crates/rpc/rpc-builder/tests/it/middleware.rs @@ -8,6 +8,7 @@ use reth_rpc::EthApi; use reth_rpc_builder::{RpcServerConfig, TransportRpcModuleConfig}; use reth_rpc_eth_api::EthApiClient; use reth_rpc_server_types::RpcModuleSelection; +use reth_rpc_types::{RichBlock, Transaction}; use std::{ future::Future, pin::Pin, @@ -74,7 +75,7 @@ async fn test_rpc_middleware() { .unwrap(); let client = handle.http_client().unwrap(); - EthApiClient::protocol_version(&client).await.unwrap(); + EthApiClient::::protocol_version(&client).await.unwrap(); let count = mylayer.count.load(Ordering::Relaxed); assert_eq!(count, 1); } diff --git a/crates/rpc/rpc-eth-api/Cargo.toml b/crates/rpc/rpc-eth-api/Cargo.toml index d571e4f82f48..e1b83821d160 100644 --- a/crates/rpc/rpc-eth-api/Cargo.toml +++ b/crates/rpc/rpc-eth-api/Cargo.toml @@ -33,6 +33,8 @@ reth-network-api.workspace = true # ethereum alloy-dyn-abi = { workspace = true, features = ["eip712"] } +alloy-network.workspace = true +alloy-json-rpc.workspace = true # rpc jsonrpsee = { workspace = true, features = ["server", "macros"] } diff --git a/crates/rpc/rpc-eth-api/src/core.rs b/crates/rpc/rpc-eth-api/src/core.rs index 8437db5c38bd..d66bc91597de 100644 --- a/crates/rpc/rpc-eth-api/src/core.rs +++ b/crates/rpc/rpc-eth-api/src/core.rs @@ -1,11 +1,8 @@ //! Implementation of the [`jsonrpsee`] generated [`EthApiServer`] trait. Handles RPC requests for //! the `eth_` namespace. -use crate::helpers::{ - transaction::UpdateRawTxForwarder, EthApiSpec, EthBlocks, EthCall, EthFees, EthState, - EthTransactions, FullEthApi, -}; use alloy_dyn_abi::TypedData; +use alloy_json_rpc::RpcObject; use jsonrpsee::{core::RpcResult, proc_macros::rpc}; use reth_primitives::{ transaction::AccessListResult, Address, BlockId, BlockNumberOrTag, Bytes, B256, B64, U256, U64, @@ -15,22 +12,41 @@ use reth_rpc_types::{ serde_helpers::JsonStorageKey, simulate::{SimBlock, SimulatedBlock}, state::{EvmOverrides, StateOverride}, - AnyTransactionReceipt, Block, BlockOverrides, Bundle, EIP1186AccountProofResponse, - EthCallResponse, FeeHistory, Header, Index, RichBlock, StateContext, SyncStatus, Transaction, - TransactionRequest, Work, + AnyTransactionReceipt, BlockOverrides, Bundle, EIP1186AccountProofResponse, EthCallResponse, + FeeHistory, Header, Index, StateContext, SyncStatus, TransactionRequest, Work, }; use tracing::trace; +use crate::{ + helpers::{ + transaction::UpdateRawTxForwarder, EthApiSpec, EthBlocks, EthCall, EthFees, EthState, + EthTransactions, FullEthApi, + }, + RpcBlock, RpcTransaction, +}; + /// Helper trait, unifies functionality that must be supported to implement all RPC methods for /// server. -pub trait FullEthApiServer: EthApiServer + FullEthApi + UpdateRawTxForwarder + Clone {} +pub trait FullEthApiServer: + EthApiServer, RpcBlock> + + FullEthApi + + UpdateRawTxForwarder + + Clone +{ +} -impl FullEthApiServer for T where T: EthApiServer + FullEthApi + UpdateRawTxForwarder + Clone {} +impl FullEthApiServer for T where + T: EthApiServer, RpcBlock> + + FullEthApi + + UpdateRawTxForwarder + + Clone +{ +} /// Eth rpc interface: #[cfg_attr(not(feature = "client"), rpc(server, namespace = "eth"))] #[cfg_attr(feature = "client", rpc(server, client, namespace = "eth"))] -pub trait EthApi { +pub trait EthApi { /// Returns the protocol version encoded as a string. #[method(name = "protocolVersion")] async fn protocol_version(&self) -> RpcResult; @@ -57,15 +73,11 @@ pub trait EthApi { /// Returns information about a block by hash. #[method(name = "getBlockByHash")] - async fn block_by_hash(&self, hash: B256, full: bool) -> RpcResult>; + async fn block_by_hash(&self, hash: B256, full: bool) -> RpcResult>; /// Returns information about a block by number. #[method(name = "getBlockByNumber")] - async fn block_by_number( - &self, - number: BlockNumberOrTag, - full: bool, - ) -> RpcResult>; + async fn block_by_number(&self, number: BlockNumberOrTag, full: bool) -> RpcResult>; /// Returns the number of transactions in a block from a block matching the given block hash. #[method(name = "getBlockTransactionCountByHash")] @@ -98,11 +110,8 @@ pub trait EthApi { /// Returns an uncle block of the given block and index. #[method(name = "getUncleByBlockHashAndIndex")] - async fn uncle_by_block_hash_and_index( - &self, - hash: B256, - index: Index, - ) -> RpcResult>; + async fn uncle_by_block_hash_and_index(&self, hash: B256, index: Index) + -> RpcResult>; /// Returns an uncle block of the given block and index. #[method(name = "getUncleByBlockNumberAndIndex")] @@ -110,7 +119,7 @@ pub trait EthApi { &self, number: BlockNumberOrTag, index: Index, - ) -> RpcResult>; + ) -> RpcResult>; /// Returns the EIP-2718 encoded transaction if it exists. /// @@ -120,7 +129,7 @@ pub trait EthApi { /// Returns the information about a transaction requested by transaction hash. #[method(name = "getTransactionByHash")] - async fn transaction_by_hash(&self, hash: B256) -> RpcResult>; + async fn transaction_by_hash(&self, hash: B256) -> RpcResult>; /// Returns information about a raw transaction by block hash and transaction index position. #[method(name = "getRawTransactionByBlockHashAndIndex")] @@ -136,7 +145,7 @@ pub trait EthApi { &self, hash: B256, index: Index, - ) -> RpcResult>; + ) -> RpcResult>; /// Returns information about a raw transaction by block number and transaction index /// position. @@ -153,7 +162,7 @@ pub trait EthApi { &self, number: BlockNumberOrTag, index: Index, - ) -> RpcResult>; + ) -> RpcResult>; /// Returns the receipt of a transaction by transaction hash. #[method(name = "getTransactionReceipt")] @@ -347,7 +356,7 @@ pub trait EthApi { } #[async_trait::async_trait] -impl EthApiServer for T +impl EthApiServer, RpcBlock> for T where T: FullEthApi, jsonrpsee_types::error::ErrorObject<'static>: From, @@ -390,7 +399,11 @@ where } /// Handler for: `eth_getBlockByHash` - async fn block_by_hash(&self, hash: B256, full: bool) -> RpcResult> { + async fn block_by_hash( + &self, + hash: B256, + full: bool, + ) -> RpcResult>> { trace!(target: "rpc::eth", ?hash, ?full, "Serving eth_getBlockByHash"); Ok(EthBlocks::rpc_block(self, hash.into(), full).await?) } @@ -400,7 +413,7 @@ where &self, number: BlockNumberOrTag, full: bool, - ) -> RpcResult> { + ) -> RpcResult>> { trace!(target: "rpc::eth", ?number, ?full, "Serving eth_getBlockByNumber"); Ok(EthBlocks::rpc_block(self, number.into(), full).await?) } @@ -449,7 +462,7 @@ where &self, hash: B256, index: Index, - ) -> RpcResult> { + ) -> RpcResult>> { trace!(target: "rpc::eth", ?hash, ?index, "Serving eth_getUncleByBlockHashAndIndex"); Ok(EthBlocks::ommer_by_block_and_index(self, hash.into(), index).await?) } @@ -459,7 +472,7 @@ where &self, number: BlockNumberOrTag, index: Index, - ) -> RpcResult> { + ) -> RpcResult>> { trace!(target: "rpc::eth", ?number, ?index, "Serving eth_getUncleByBlockNumberAndIndex"); Ok(EthBlocks::ommer_by_block_and_index(self, number.into(), index).await?) } @@ -471,7 +484,10 @@ where } /// Handler for: `eth_getTransactionByHash` - async fn transaction_by_hash(&self, hash: B256) -> RpcResult> { + async fn transaction_by_hash( + &self, + hash: B256, + ) -> RpcResult>> { trace!(target: "rpc::eth", ?hash, "Serving eth_getTransactionByHash"); Ok(EthTransactions::transaction_by_hash(self, hash).await?.map(Into::into)) } @@ -492,7 +508,7 @@ where &self, hash: B256, index: Index, - ) -> RpcResult> { + ) -> RpcResult>> { trace!(target: "rpc::eth", ?hash, ?index, "Serving eth_getTransactionByBlockHashAndIndex"); Ok(EthTransactions::transaction_by_block_and_tx_index(self, hash.into(), index.into()) .await?) @@ -518,7 +534,7 @@ where &self, number: BlockNumberOrTag, index: Index, - ) -> RpcResult> { + ) -> RpcResult>> { trace!(target: "rpc::eth", ?number, ?index, "Serving eth_getTransactionByBlockNumberAndIndex"); Ok(EthTransactions::transaction_by_block_and_tx_index(self, number.into(), index.into()) .await?) diff --git a/crates/rpc/rpc-eth-api/src/filter.rs b/crates/rpc/rpc-eth-api/src/filter.rs index da53b577eec5..26c47226cfc3 100644 --- a/crates/rpc/rpc-eth-api/src/filter.rs +++ b/crates/rpc/rpc-eth-api/src/filter.rs @@ -1,12 +1,13 @@ //! `eth_` RPC API for filtering. +use alloy_json_rpc::RpcObject; use jsonrpsee::{core::RpcResult, proc_macros::rpc}; use reth_rpc_types::{Filter, FilterChanges, FilterId, Log, PendingTransactionFilterKind}; /// Rpc Interface for poll-based ethereum filter API. #[cfg_attr(not(feature = "client"), rpc(server, namespace = "eth"))] #[cfg_attr(feature = "client", rpc(server, client, namespace = "eth"))] -pub trait EthFilterApi { +pub trait EthFilterApi { /// Creates anew filter and returns its id. #[method(name = "newFilter")] async fn new_filter(&self, filter: Filter) -> RpcResult; @@ -24,7 +25,7 @@ pub trait EthFilterApi { /// Returns all filter changes since last poll. #[method(name = "getFilterChanges")] - async fn filter_changes(&self, id: FilterId) -> RpcResult; + async fn filter_changes(&self, id: FilterId) -> RpcResult>; /// Returns all logs matching given filter (in a range 'from' - 'to'). #[method(name = "getFilterLogs")] diff --git a/crates/rpc/rpc-eth-api/src/helpers/block.rs b/crates/rpc/rpc-eth-api/src/helpers/block.rs index accf5089b422..42745a9a631a 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/block.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/block.rs @@ -6,10 +6,10 @@ use futures::Future; use reth_primitives::{BlockId, Receipt, SealedBlock, SealedBlockWithSenders, TransactionMeta}; use reth_provider::{BlockIdReader, BlockReader, BlockReaderIdExt, HeaderProvider}; use reth_rpc_eth_types::{EthApiError, EthStateCache, ReceiptBuilder}; -use reth_rpc_types::{AnyTransactionReceipt, Block, Header, Index, RichBlock}; +use reth_rpc_types::{AnyTransactionReceipt, Header, Index}; use reth_rpc_types_compat::block::{from_block, uncle_block_from_header}; -use crate::FromEthApiError; +use crate::{FromEthApiError, RpcBlock}; use super::{LoadPendingBlock, LoadReceipt, SpawnBlocking}; @@ -25,11 +25,8 @@ pub trait EthBlocks: LoadBlock { fn rpc_block_header( &self, block_id: BlockId, - ) -> impl Future, Self::Error>> + Send - where - Self: LoadPendingBlock + SpawnBlocking, - { - async move { Ok(self.rpc_block(block_id, false).await?.map(|block| block.inner.header)) } + ) -> impl Future, Self::Error>> + Send { + async move { Ok(self.rpc_block(block_id, false).await?.map(|block| block.header)) } } /// Returns the populated rpc block object for the given block id. @@ -40,9 +37,7 @@ pub trait EthBlocks: LoadBlock { &self, block_id: BlockId, full: bool, - ) -> impl Future, Self::Error>> + Send - where - Self: LoadPendingBlock + SpawnBlocking, + ) -> impl Future>, Self::Error>> + Send { async move { let block = match self.block_with_senders(block_id).await? { @@ -56,7 +51,7 @@ pub trait EthBlocks: LoadBlock { .ok_or(EthApiError::UnknownBlockNumber)?; let block = from_block(block.unseal(), total_difficulty, full.into(), Some(block_hash)) .map_err(Self::Error::from_eth_err)?; - Ok(Some(block.into())) + Ok(Some(block)) } } @@ -187,7 +182,8 @@ pub trait EthBlocks: LoadBlock { &self, block_id: BlockId, index: Index, - ) -> impl Future, Self::Error>> + Send { + ) -> impl Future>, Self::Error>> + Send + { async move { let uncles = if block_id.is_pending() { // Pending block can be fetched directly without need for caching diff --git a/crates/rpc/rpc-eth-api/src/helpers/mod.rs b/crates/rpc/rpc-eth-api/src/helpers/mod.rs index ecfd63388e3b..4f12b7dac861 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/mod.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/mod.rs @@ -26,7 +26,6 @@ pub mod spec; pub mod state; pub mod trace; pub mod transaction; -pub mod types; pub use block::{EthBlocks, LoadBlock}; pub use blocking_task::SpawnBlocking; diff --git a/crates/rpc/rpc-eth-api/src/helpers/transaction.rs b/crates/rpc/rpc-eth-api/src/helpers/transaction.rs index c4387a25537d..124da5f31d5b 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/transaction.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/transaction.rs @@ -19,12 +19,12 @@ use reth_rpc_types::{ EIP1559TransactionRequest, EIP2930TransactionRequest, EIP4844TransactionRequest, LegacyTransactionRequest, }, - AnyTransactionReceipt, Transaction, TransactionRequest, TypedTransactionRequest, + AnyTransactionReceipt, TransactionRequest, TypedTransactionRequest, }; use reth_rpc_types_compat::transaction::from_recovered_with_block_context; use reth_transaction_pool::{PoolTransaction, TransactionOrigin, TransactionPool}; -use crate::{FromEthApiError, IntoEthApiError}; +use crate::{FromEthApiError, IntoEthApiError, RpcTransaction}; use super::{ Call, EthApiSpec, EthSigner, LoadBlock, LoadFee, LoadPendingBlock, LoadReceipt, SpawnBlocking, @@ -188,14 +188,14 @@ pub trait EthTransactions: LoadTransaction { }) } - /// Get [`Transaction`] by [`BlockId`] and index of transaction within that block. + /// Get transaction by [`BlockId`] and index of transaction within that block. /// /// Returns `Ok(None)` if the block does not exist, or index is out of range. fn transaction_by_block_and_tx_index( &self, block_id: BlockId, index: usize, - ) -> impl Future, Self::Error>> + Send + ) -> impl Future>, Self::Error>> + Send where Self: LoadBlock, { diff --git a/crates/rpc/rpc-eth-api/src/helpers/types.rs b/crates/rpc/rpc-eth-api/src/helpers/types.rs deleted file mode 100644 index 088f9d9b69e9..000000000000 --- a/crates/rpc/rpc-eth-api/src/helpers/types.rs +++ /dev/null @@ -1,17 +0,0 @@ -//! Trait for specifying `eth` API types that may be network dependent. - -use std::error::Error; - -use crate::{AsEthApiError, FromEthApiError, FromEvmError}; - -/// Network specific `eth` API types. -pub trait EthApiTypes: Send + Sync { - /// Extension of [`EthApiError`](reth_rpc_eth_types::EthApiError), with network specific errors. - type Error: Into> - + FromEthApiError - + AsEthApiError - + FromEvmError - + Error - + Send - + Sync; -} diff --git a/crates/rpc/rpc-eth-api/src/lib.rs b/crates/rpc/rpc-eth-api/src/lib.rs index c707a94eef4f..c3ea0746a119 100644 --- a/crates/rpc/rpc-eth-api/src/lib.rs +++ b/crates/rpc/rpc-eth-api/src/lib.rs @@ -17,17 +17,17 @@ pub mod core; pub mod filter; pub mod helpers; pub mod pubsub; +pub mod types; pub use bundle::{EthBundleApiServer, EthCallBundleApiServer}; pub use core::{EthApiServer, FullEthApiServer}; pub use filter::EthFilterApiServer; pub use helpers::{ error::{AsEthApiError, FromEthApiError, FromEvmError, IntoEthApiError}, - types::EthApiTypes, + transaction::RawTransactionForwarder, }; pub use pubsub::EthPubSubApiServer; - -pub use helpers::transaction::RawTransactionForwarder; +pub use types::{EthApiTypes, RpcBlock, RpcTransaction}; #[cfg(feature = "client")] pub use bundle::{EthBundleApiClient, EthCallBundleApiClient}; diff --git a/crates/rpc/rpc-eth-api/src/pubsub.rs b/crates/rpc/rpc-eth-api/src/pubsub.rs index 8de125152823..8282e6b6af64 100644 --- a/crates/rpc/rpc-eth-api/src/pubsub.rs +++ b/crates/rpc/rpc-eth-api/src/pubsub.rs @@ -1,11 +1,12 @@ //! `eth_` RPC API for pubsub subscription. +use alloy_json_rpc::RpcObject; use jsonrpsee::proc_macros::rpc; use reth_rpc_types::pubsub::{Params, SubscriptionKind}; /// Ethereum pub-sub rpc interface. #[rpc(server, namespace = "eth")] -pub trait EthPubSubApi { +pub trait EthPubSubApi { /// Create an ethereum subscription for the given params #[subscription( name = "subscribe" => "subscription", diff --git a/crates/rpc/rpc-eth-api/src/types.rs b/crates/rpc/rpc-eth-api/src/types.rs new file mode 100644 index 000000000000..4ab1e947b179 --- /dev/null +++ b/crates/rpc/rpc-eth-api/src/types.rs @@ -0,0 +1,35 @@ +//! Trait for specifying `eth` network dependent API types. + +use std::error::Error; + +use alloy_network::{Ethereum, Network}; +use reth_rpc_eth_types::EthApiError; +use reth_rpc_types::{Block, Transaction}; + +use crate::{AsEthApiError, FromEthApiError, FromEvmError}; + +/// Network specific `eth` API types. +pub trait EthApiTypes: Send + Sync + Clone { + /// Extension of [`EthApiError`], with network specific errors. + type Error: Into> + + FromEthApiError + + AsEthApiError + + FromEvmError + + Error + + Send + + Sync; + /// Blockchain primitive types, specific to network, e.g. block and transaction. + // todo: remove restriction `reth_rpc_types::Transaction` + type NetworkTypes: Network; +} + +impl EthApiTypes for () { + type Error = EthApiError; + type NetworkTypes = Ethereum; +} + +/// Adapter for network specific transaction type. +pub type RpcTransaction = ::TransactionResponse; + +/// Adapter for network specific block type. +pub type RpcBlock = Block>; diff --git a/crates/rpc/rpc-testing-util/Cargo.toml b/crates/rpc/rpc-testing-util/Cargo.toml index 8ab37d1b18d0..19cef0b02de8 100644 --- a/crates/rpc/rpc-testing-util/Cargo.toml +++ b/crates/rpc/rpc-testing-util/Cargo.toml @@ -30,3 +30,4 @@ similar-asserts.workspace = true [dev-dependencies] tokio = { workspace = true, features = ["rt-multi-thread", "macros", "rt"] } reth-rpc-eth-api.workspace = true +jsonrpsee-http-client.workspace = true diff --git a/crates/rpc/rpc-testing-util/src/debug.rs b/crates/rpc/rpc-testing-util/src/debug.rs index c0151e2d1be2..532e9555f8ba 100644 --- a/crates/rpc/rpc-testing-util/src/debug.rs +++ b/crates/rpc/rpc-testing-util/src/debug.rs @@ -1,5 +1,11 @@ //! Helpers for testing debug trace calls. +use std::{ + future::Future, + pin::Pin, + task::{Context, Poll}, +}; + use futures::{Stream, StreamExt}; use jsonrpsee::core::client::Error as RpcError; use reth_primitives::{BlockId, TxHash, B256}; @@ -9,12 +15,7 @@ use reth_rpc_types::{ common::TraceResult, geth::{GethDebugTracerType, GethDebugTracingOptions, GethTrace}, }, - TransactionRequest, -}; -use std::{ - future::Future, - pin::Pin, - task::{Context, Poll}, + RichBlock, Transaction, TransactionRequest, }; const NOOP_TRACER: &str = include_str!("../assets/noop-tracer.js"); @@ -76,7 +77,7 @@ pub trait DebugApiExt { impl DebugApiExt for T where - T: EthApiClient + DebugApiClient + Sync, + T: EthApiClient + DebugApiClient + Sync, { type Provider = T; diff --git a/crates/rpc/rpc-testing-util/tests/it/trace.rs b/crates/rpc/rpc-testing-util/tests/it/trace.rs index 029e9fbbc8b5..4d1234e1ae26 100644 --- a/crates/rpc/rpc-testing-util/tests/it/trace.rs +++ b/crates/rpc/rpc-testing-util/tests/it/trace.rs @@ -1,11 +1,14 @@ +use std::{collections::HashSet, time::Instant}; + use futures::StreamExt; use jsonrpsee::http_client::HttpClientBuilder; +use jsonrpsee_http_client::HttpClient; use reth_rpc_api_testing_util::{debug::DebugApiExt, trace::TraceApiExt, utils::parse_env_url}; use reth_rpc_eth_api::EthApiClient; -use reth_rpc_types::trace::{ - filter::TraceFilter, parity::TraceType, tracerequest::TraceCallRequest, +use reth_rpc_types::{ + trace::{filter::TraceFilter, parity::TraceType, tracerequest::TraceCallRequest}, + RichBlock, Transaction, }; -use std::{collections::HashSet, time::Instant}; /// This is intended to be run locally against a running node. /// @@ -106,7 +109,12 @@ async fn debug_trace_block_entire_chain() { let url = url.unwrap(); let client = HttpClientBuilder::default().build(url).unwrap(); - let current_block: u64 = client.block_number().await.unwrap().try_into().unwrap(); + let current_block: u64 = + >::block_number(&client) + .await + .unwrap() + .try_into() + .unwrap(); let range = 0..=current_block; let mut stream = client.debug_trace_block_buffered_unordered(range, None, 20); let now = Instant::now(); diff --git a/crates/rpc/rpc/Cargo.toml b/crates/rpc/rpc/Cargo.toml index 0142545f45c9..20b596681b40 100644 --- a/crates/rpc/rpc/Cargo.toml +++ b/crates/rpc/rpc/Cargo.toml @@ -41,6 +41,7 @@ alloy-dyn-abi.workspace = true alloy-rlp.workspace = true alloy-primitives.workspace = true alloy-genesis.workspace = true +alloy-network.workspace = true revm = { workspace = true, features = [ "optional_block_gas_limit", "optional_eip3607", diff --git a/crates/rpc/rpc/src/engine.rs b/crates/rpc/rpc/src/engine.rs index 71d4ff94130e..5149d276d005 100644 --- a/crates/rpc/rpc/src/engine.rs +++ b/crates/rpc/rpc/src/engine.rs @@ -1,11 +1,13 @@ +use alloy_network::Network; use jsonrpsee::core::RpcResult as Result; use reth_primitives::{Address, BlockId, BlockNumberOrTag, Bytes, B256, U256, U64}; use reth_rpc_api::{EngineEthApiServer, EthApiServer, EthFilterApiServer}; /// Re-export for convenience pub use reth_rpc_engine_api::EngineApi; +use reth_rpc_eth_api::{EthApiTypes, RpcBlock, RpcTransaction}; use reth_rpc_types::{ state::StateOverride, BlockOverrides, EIP1186AccountProofResponse, Filter, JsonStorageKey, Log, - RichBlock, SyncStatus, TransactionRequest, + SyncStatus, TransactionRequest, }; use tracing_futures::Instrument; @@ -31,10 +33,15 @@ impl EngineEthApi { } #[async_trait::async_trait] -impl EngineEthApiServer for EngineEthApi +impl + EngineEthApiServer< + reth_rpc_types::Transaction, + reth_rpc_types::Block, + > for EngineEthApi where - Eth: EthApiServer, - EthFilter: EthFilterApiServer, + Eth: EthApiServer, RpcBlock> + + EthApiTypes>, + EthFilter: EthFilterApiServer, { /// Handler for: `eth_syncing` fn syncing(&self) -> Result { @@ -77,7 +84,11 @@ where } /// Handler for: `eth_getBlockByHash` - async fn block_by_hash(&self, hash: B256, full: bool) -> Result> { + async fn block_by_hash( + &self, + hash: B256, + full: bool, + ) -> Result>> { self.eth.block_by_hash(hash, full).instrument(engine_span!()).await } @@ -86,7 +97,7 @@ where &self, number: BlockNumberOrTag, full: bool, - ) -> Result> { + ) -> Result>> { self.eth.block_by_number(number, full).instrument(engine_span!()).await } diff --git a/crates/rpc/rpc/src/eth/core.rs b/crates/rpc/rpc/src/eth/core.rs index 281d0768e46f..774f1e71baa6 100644 --- a/crates/rpc/rpc/src/eth/core.rs +++ b/crates/rpc/rpc/src/eth/core.rs @@ -3,6 +3,7 @@ use std::sync::Arc; +use alloy_network::Ethereum; use derive_more::Deref; use reth_node_api::{BuilderProvider, FullNodeComponents}; use reth_primitives::{BlockNumberOrTag, U256}; @@ -36,6 +37,12 @@ pub struct EthApi { pub(super) inner: Arc>, } +impl Clone for EthApi { + fn clone(&self) -> Self { + Self { inner: self.inner.clone() } + } +} + impl EthApi where Provider: BlockReaderIdExt, @@ -119,6 +126,7 @@ where Self: Send + Sync, { type Error = EthApiError; + type NetworkTypes = Ethereum; } impl std::fmt::Debug @@ -129,12 +137,6 @@ impl std::fmt::Debug } } -impl Clone for EthApi { - fn clone(&self) -> Self { - Self { inner: Arc::clone(&self.inner) } - } -} - impl SpawnBlocking for EthApi where @@ -509,7 +511,7 @@ mod tests { /// Invalid block range #[tokio::test] async fn test_fee_history_empty() { - let response = as EthApiServer>::fee_history( + let response = as EthApiServer<_, _>>::fee_history( &build_test_eth_api(NoopProvider::default()), U64::from(1), BlockNumberOrTag::Latest, @@ -531,7 +533,7 @@ mod tests { let (eth_api, _, _) = prepare_eth_api(newest_block, oldest_block, block_count, MockEthProvider::default()); - let response = as EthApiServer>::fee_history( + let response = as EthApiServer<_, _>>::fee_history( ð_api, U64::from(newest_block + 1), newest_block.into(), @@ -554,7 +556,7 @@ mod tests { let (eth_api, _, _) = prepare_eth_api(newest_block, oldest_block, block_count, MockEthProvider::default()); - let response = as EthApiServer>::fee_history( + let response = as EthApiServer<_, _>>::fee_history( ð_api, U64::from(1), (newest_block + 1000).into(), @@ -577,7 +579,7 @@ mod tests { let (eth_api, _, _) = prepare_eth_api(newest_block, oldest_block, block_count, MockEthProvider::default()); - let response = as EthApiServer>::fee_history( + let response = as EthApiServer<_, _>>::fee_history( ð_api, U64::from(0), newest_block.into(), diff --git a/crates/rpc/rpc/src/eth/filter.rs b/crates/rpc/rpc/src/eth/filter.rs index ef26a5781de5..a809f76aea39 100644 --- a/crates/rpc/rpc/src/eth/filter.rs +++ b/crates/rpc/rpc/src/eth/filter.rs @@ -219,7 +219,7 @@ where } #[async_trait] -impl EthFilterApiServer for EthFilter +impl EthFilterApiServer for EthFilter where Provider: BlockReader + BlockIdReader + EvmEnvProvider + 'static, Pool: TransactionPool + 'static, diff --git a/crates/rpc/rpc/src/eth/helpers/block.rs b/crates/rpc/rpc/src/eth/helpers/block.rs index 2ce6c7ed2e93..92f8d5e0344d 100644 --- a/crates/rpc/rpc/src/eth/helpers/block.rs +++ b/crates/rpc/rpc/src/eth/helpers/block.rs @@ -12,7 +12,7 @@ where Provider: HeaderProvider, { #[inline] - fn provider(&self) -> impl reth_provider::HeaderProvider { + fn provider(&self) -> impl HeaderProvider { self.inner.provider() } } diff --git a/crates/rpc/rpc/src/eth/pubsub.rs b/crates/rpc/rpc/src/eth/pubsub.rs index 426923dc4458..5509f3e933a3 100644 --- a/crates/rpc/rpc/src/eth/pubsub.rs +++ b/crates/rpc/rpc/src/eth/pubsub.rs @@ -68,7 +68,7 @@ impl EthPubSub } #[async_trait::async_trait] -impl EthPubSubApiServer +impl EthPubSubApiServer for EthPubSub where Provider: BlockReader + EvmEnvProvider + Clone + 'static, diff --git a/crates/rpc/rpc/src/otterscan.rs b/crates/rpc/rpc/src/otterscan.rs index 6cd94246609a..e9990277e247 100644 --- a/crates/rpc/rpc/src/otterscan.rs +++ b/crates/rpc/rpc/src/otterscan.rs @@ -1,9 +1,10 @@ +use alloy_network::Network; use alloy_primitives::Bytes; use async_trait::async_trait; use jsonrpsee::core::RpcResult; use reth_primitives::{Address, BlockNumberOrTag, TxHash, B256, U256}; use reth_rpc_api::{EthApiServer, OtterscanServer}; -use reth_rpc_eth_api::helpers::TraceExt; +use reth_rpc_eth_api::{helpers::TraceExt, EthApiTypes, RpcBlock, RpcTransaction}; use reth_rpc_eth_types::EthApiError; use reth_rpc_server_types::result::internal_rpc_err; use reth_rpc_types::{ @@ -14,7 +15,7 @@ use reth_rpc_types::{ }, parity::{Action, CreateAction, CreateOutput, TraceOutput}, }, - AnyTransactionReceipt, BlockTransactions, Header, RichBlock, + AnyTransactionReceipt, BlockTransactions, Header, Rich, }; use revm_inspectors::{ tracing::{types::CallTraceNode, TracingInspectorConfig}, @@ -36,11 +37,16 @@ impl OtterscanApi { pub const fn new(eth: Eth) -> Self { Self { eth } } +} +impl OtterscanApi +where + Eth: EthApiTypes>, +{ /// Constructs a `BlockDetails` from a block and its receipts. fn block_details( &self, - block: Option, + block: Option>, receipts: Option>, ) -> RpcResult { let block = block.ok_or_else(|| EthApiError::UnknownBlockNumber)?; @@ -52,14 +58,21 @@ impl OtterscanApi { .map(|receipt| receipt.gas_used.saturating_mul(receipt.effective_gas_price)) .sum::(); - Ok(BlockDetails::new(block, Default::default(), U256::from(total_fees))) + Ok(BlockDetails::new( + Rich { inner: block, extra_info: Default::default() }, + Default::default(), + U256::from(total_fees), + )) } } #[async_trait] impl OtterscanServer for OtterscanApi where - Eth: EthApiServer + TraceExt + 'static, + Eth: EthApiServer, RpcBlock> + + EthApiTypes> + + TraceExt + + 'static, { /// Handler for `{ots,erigon}_getHeaderByNumber` async fn get_header_by_number(&self, block_number: u64) -> RpcResult> { @@ -193,7 +206,7 @@ where } // make sure the block is full - let BlockTransactions::Full(transactions) = &mut block.inner.transactions else { + let BlockTransactions::Full(transactions) = &mut block.transactions else { return Err(internal_rpc_err("block is not full")); }; @@ -235,7 +248,7 @@ where .collect(); // use `transaction_count` to indicate the paginate information - let mut block = OtsBlockTransactions { fullblock: block.inner.into(), receipts }; + let mut block = OtsBlockTransactions { fullblock: block.into(), receipts }; block.fullblock.transaction_count = tx_len; Ok(block) } @@ -299,14 +312,14 @@ where .await?; let Some(BlockTransactions::Full(transactions)) = - self.eth.block_by_number(num.into(), true).await?.map(|block| block.inner.transactions) + self.eth.block_by_number(num.into(), true).await?.map(|block| block.transactions) else { return Err(EthApiError::UnknownBlockNumber.into()); }; Ok(transactions .into_iter() - .find(|tx| tx.from == sender && tx.nonce == nonce) + .find(|tx| *tx.from == *sender && tx.nonce == nonce) .map(|tx| tx.hash)) } diff --git a/examples/custom-evm/src/main.rs b/examples/custom-evm/src/main.rs index 349dd5a84564..c8b8a20f7a4c 100644 --- a/examples/custom-evm/src/main.rs +++ b/examples/custom-evm/src/main.rs @@ -144,7 +144,7 @@ pub struct MyExecutorBuilder; impl ExecutorBuilder for MyExecutorBuilder where - Node: FullNodeTypes, + Node: FullNodeTypes, { type EVM = MyEvmConfig; type Executor = EthExecutorProvider; diff --git a/examples/custom-node-components/Cargo.toml b/examples/custom-node-components/Cargo.toml index 1aa422447afd..507088970de8 100644 --- a/examples/custom-node-components/Cargo.toml +++ b/examples/custom-node-components/Cargo.toml @@ -11,7 +11,5 @@ reth.workspace = true reth-node-ethereum.workspace = true reth-transaction-pool.workspace = true reth-tracing.workspace = true -reth-chainspec.workspace = true - eyre.workspace = true diff --git a/examples/custom-node-components/src/main.rs b/examples/custom-node-components/src/main.rs index 921f8cb3eabb..2c44e18d85cd 100644 --- a/examples/custom-node-components/src/main.rs +++ b/examples/custom-node-components/src/main.rs @@ -10,7 +10,6 @@ use reth::{ blobstore::InMemoryBlobStore, EthTransactionPool, TransactionValidationTaskExecutor, }, }; -use reth_chainspec::ChainSpec; use reth_node_ethereum::{node::EthereumAddOns, EthereumNode}; use reth_tracing::tracing::{debug, info}; use reth_transaction_pool::PoolConfig; @@ -46,7 +45,7 @@ pub struct CustomPoolBuilder { /// This will be used to build the transaction pool and its maintenance tasks during launch. impl PoolBuilder for CustomPoolBuilder where - Node: FullNodeTypes, + Node: FullNodeTypes, { type Pool = EthTransactionPool; diff --git a/examples/stateful-precompile/src/main.rs b/examples/stateful-precompile/src/main.rs index 253aea6df8a7..5505f6d16c01 100644 --- a/examples/stateful-precompile/src/main.rs +++ b/examples/stateful-precompile/src/main.rs @@ -207,7 +207,7 @@ pub struct MyExecutorBuilder { impl ExecutorBuilder for MyExecutorBuilder where - Node: FullNodeTypes, + Node: FullNodeTypes, { type EVM = MyEvmConfig; type Executor = EthExecutorProvider;