From baf407f5edba76140ce53b7aee0bc0fbb5653dd0 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Thu, 16 Nov 2023 20:06:29 +0100 Subject: [PATCH] feat: add eth-call-bundle module (#5465) --- crates/rpc/rpc-builder/src/lib.rs | 103 +++++++++++++++++++++--------- 1 file changed, 74 insertions(+), 29 deletions(-) diff --git a/crates/rpc/rpc-builder/src/lib.rs b/crates/rpc/rpc-builder/src/lib.rs index e691036280..b23029b75f 100644 --- a/crates/rpc/rpc-builder/src/lib.rs +++ b/crates/rpc/rpc-builder/src/lib.rs @@ -135,19 +135,32 @@ #![warn(missing_debug_implementations, missing_docs, unreachable_pub, rustdoc::all)] #![deny(unused_must_use, rust_2018_idioms)] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] -use crate::{ - auth::AuthRpcModule, error::WsHttpSamePortError, metrics::RpcServerMetrics, - RpcModuleSelection::Selection, + +use std::{ + collections::{HashMap, HashSet}, + fmt, + net::{Ipv4Addr, SocketAddr, SocketAddrV4}, + str::FromStr, + time::{Duration, SystemTime, UNIX_EPOCH}, }; -use constants::*; -use error::{RpcError, ServerKind}; + use hyper::{header::AUTHORIZATION, HeaderMap}; +pub use jsonrpsee::server::ServerBuilder; use jsonrpsee::{ server::{IdProvider, Server, ServerHandle}, Methods, RpcModule, }; +use serde::{Deserialize, Serialize, Serializer}; +use strum::{AsRefStr, EnumVariantNames, ParseError, VariantNames}; +use tower::layer::util::{Identity, Stack}; +use tower_http::cors::CorsLayer; +use tracing::{instrument, trace}; + +use constants::*; +use error::{RpcError, ServerKind}; use reth_ipc::server::IpcServer; -use reth_network_api::{NetworkInfo, Peers}; +pub use reth_ipc::server::{Builder as IpcServerBuilder, Endpoint}; +use reth_network_api::{noop::NoopNetwork, NetworkInfo, Peers}; use reth_provider::{ AccountReader, BlockReader, BlockReaderIdExt, CanonStateSubscriptions, ChainSpecProvider, ChangeSetReader, EvmEnvProvider, StateProviderFactory, @@ -156,6 +169,7 @@ use reth_rpc::{ eth::{ cache::{cache_new_blocks_task, EthStateCache}, gas_oracle::GasPriceOracle, + EthBundle, }, AdminApi, AuthLayer, BlockingTaskGuard, BlockingTaskPool, Claims, DebugApi, EngineEthApi, EthApi, EthFilter, EthPubSub, EthSubscriptionIdProvider, JwtAuthValidator, JwtSecret, NetApi, @@ -163,19 +177,14 @@ use reth_rpc::{ }; use reth_rpc_api::{servers::*, EngineApiServer}; use reth_tasks::{TaskSpawner, TokioTaskExecutor}; -use reth_transaction_pool::TransactionPool; -use serde::{Deserialize, Serialize, Serializer}; -use std::{ - collections::{HashMap, HashSet}, - fmt, - net::{Ipv4Addr, SocketAddr, SocketAddrV4}, - str::FromStr, - time::{Duration, SystemTime, UNIX_EPOCH}, +use reth_transaction_pool::{noop::NoopTransactionPool, TransactionPool}; + +use crate::{ + auth::AuthRpcModule, error::WsHttpSamePortError, metrics::RpcServerMetrics, + RpcModuleSelection::Selection, }; -use strum::{AsRefStr, EnumString, EnumVariantNames, ParseError, VariantNames}; -use tower::layer::util::{Identity, Stack}; -use tower_http::cors::CorsLayer; -use tracing::{instrument, trace}; +// re-export for convenience +pub use crate::eth::{EthConfig, EthHandlers}; /// Auth server utilities. pub mod auth; @@ -195,14 +204,6 @@ pub mod constants; // Rpc server metrics mod metrics; -// re-export for convenience -pub use crate::eth::{EthConfig, EthHandlers}; -pub use jsonrpsee::server::ServerBuilder; -pub use reth_ipc::server::{Builder as IpcServerBuilder, Endpoint}; -use reth_network_api::noop::NoopNetwork; -use reth_rpc::eth::EthBundle; -use reth_transaction_pool::noop::NoopTransactionPool; - /// Convenience function for starting a server in one step. pub async fn launch( provider: Provider, @@ -706,9 +707,7 @@ impl fmt::Display for RpcModuleSelection { } /// Represents RPC modules that are supported by reth -#[derive( - Debug, Clone, Copy, Eq, PartialEq, Hash, AsRefStr, EnumVariantNames, EnumString, Deserialize, -)] +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, AsRefStr, EnumVariantNames, Deserialize)] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "kebab-case")] pub enum RethRpcModule { @@ -732,6 +731,11 @@ pub enum RethRpcModule { Reth, /// `ots_` module Ots, + /// For single non-standard `eth_` namespace call `eth_callBundle` + /// + /// This is separate from [RethRpcModule::Eth] because it is a non standardized call that + /// should be opt-in. + EthCallBundle, } // === impl RethRpcModule === @@ -743,6 +747,34 @@ impl RethRpcModule { } } +impl FromStr for RethRpcModule { + type Err = ParseError; + + fn from_str(s: &str) -> Result { + Ok(match s { + "admin" => RethRpcModule::Admin, + "debug" => RethRpcModule::Debug, + "eth" => RethRpcModule::Eth, + "net" => RethRpcModule::Net, + "trace" => RethRpcModule::Trace, + "txpool" => RethRpcModule::Txpool, + "web3" => RethRpcModule::Web3, + "rpc" => RethRpcModule::Rpc, + "reth" => RethRpcModule::Reth, + "ots" => RethRpcModule::Ots, + "eth-call-bundle" | "eth_callBundle" => RethRpcModule::EthCallBundle, + _ => return Err(ParseError::VariantNotFound), + }) + } +} + +impl TryFrom<&str> for RethRpcModule { + type Error = ParseError; + fn try_from(s: &str) -> Result>::Error> { + FromStr::from_str(s) + } +} + impl fmt::Display for RethRpcModule { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.pad(self.as_ref()) @@ -1038,6 +1070,11 @@ where .into_rpc() .into() } + RethRpcModule::EthCallBundle => { + EthBundle::new(eth_api.clone(), self.blocking_pool_guard.clone()) + .into_rpc() + .into() + } }) .clone() }) @@ -2036,6 +2073,14 @@ impl fmt::Debug for RpcServerHandle { mod tests { use super::*; + #[test] + fn parse_eth_call_bundle() { + let selection = "eth-call-bundle".parse::().unwrap(); + assert_eq!(selection, RethRpcModule::EthCallBundle); + let selection = "eth_callBundle".parse::().unwrap(); + assert_eq!(selection, RethRpcModule::EthCallBundle); + } + #[test] fn parse_rpc_module_selection() { let selection = "all".parse::().unwrap();