diff --git a/bin/reth/src/args/rpc_server_args.rs b/bin/reth/src/args/rpc_server_args.rs index 230741885bc6..4a1f8d2fb89a 100644 --- a/bin/reth/src/args/rpc_server_args.rs +++ b/bin/reth/src/args/rpc_server_args.rs @@ -2,11 +2,12 @@ use crate::args::GasPriceOracleArgs; use clap::{ - builder::{PossibleValue, TypedValueParser}, + builder::{PossibleValue, RangedU64ValueParser, TypedValueParser}, Arg, Args, Command, }; use futures::TryFutureExt; use reth_network_api::{NetworkInfo, Peers}; +use reth_primitives::constants::ETHEREUM_BLOCK_GAS_LIMIT; use reth_provider::{ BlockReaderIdExt, CanonStateSubscriptions, ChainSpecProvider, EvmEnvProvider, HeaderProvider, StateProviderFactory, @@ -48,6 +49,9 @@ pub(crate) const RPC_DEFAULT_MAX_CONNECTIONS: u32 = 100; /// Default number of incoming connections. pub(crate) const RPC_DEFAULT_MAX_TRACING_REQUESTS: u32 = 25; +/// Default max gas limit for `eth_call` and call tracing RPC methods. +pub(crate) const RPC_DEFAULT_GAS_CAP: u64 = ETHEREUM_BLOCK_GAS_LIMIT; + /// Parameters for configuring the rpc more granularity via CLI #[derive(Debug, Args, PartialEq, Eq, Default)] #[command(next_help_heading = "RPC")] @@ -132,6 +136,16 @@ pub struct RpcServerArgs { #[arg(long, value_name = "COUNT", default_value_t = RPC_DEFAULT_MAX_TRACING_REQUESTS)] pub rpc_max_tracing_requests: u32, + /// Maximum gas limit for `eth_call` and call tracing RPC methods. + #[arg( + long, + alias = "rpc.gascap", + value_name = "GAS_CAP", + value_parser = RangedU64ValueParser::::new().range(1..), + default_value_t = RPC_DEFAULT_GAS_CAP + )] + pub rpc_gas_cap: u64, + /// Gas price oracle configuration. #[clap(flatten)] pub gas_price_oracle: GasPriceOracleArgs, @@ -174,6 +188,7 @@ impl RpcServerArgs { pub fn eth_config(&self) -> EthConfig { EthConfig::default() .max_tracing_requests(self.rpc_max_tracing_requests) + .rpc_gas_cap(self.rpc_gas_cap) .gpo_config(self.gas_price_oracle_config()) } @@ -495,6 +510,21 @@ mod tests { args: T, } + #[test] + fn test_rpc_gas_cap() { + let args = CommandParser::::parse_from(["reth"]).args; + let config = args.eth_config(); + assert_eq!(config.rpc_gas_cap, RPC_DEFAULT_GAS_CAP); + + let args = + CommandParser::::parse_from(["reth", "--rpc.gascap", "1000"]).args; + let config = args.eth_config(); + assert_eq!(config.rpc_gas_cap, 1000); + + let args = CommandParser::::try_parse_from(["reth", "--rpc.gascap", "0"]); + assert!(args.is_err()); + } + #[test] fn test_rpc_server_args_parser() { let args = diff --git a/book/cli/node.md b/book/cli/node.md index 4d447428a4c6..78d9b40dba2f 100644 --- a/book/cli/node.md +++ b/book/cli/node.md @@ -187,6 +187,9 @@ Gas Price Oracle: The percentile of gas prices to use for the estimate [default: 60] + + --rpc.gascap + Maximum gas limit for `eth_call` and call tracing RPC methods --block-cache-len Maximum number of block cache entries diff --git a/crates/rpc/rpc-builder/src/auth.rs b/crates/rpc/rpc-builder/src/auth.rs index 567f10bfca4f..758713bbdebc 100644 --- a/crates/rpc/rpc-builder/src/auth.rs +++ b/crates/rpc/rpc-builder/src/auth.rs @@ -2,6 +2,7 @@ use crate::{ constants, error::{RpcError, ServerKind}, eth::DEFAULT_MAX_LOGS_PER_RESPONSE, + EthConfig, }; use hyper::header::AUTHORIZATION; pub use jsonrpsee::server::ServerBuilder; @@ -61,6 +62,7 @@ where network, eth_cache.clone(), gas_oracle, + EthConfig::default().rpc_gas_cap, Box::new(executor.clone()), ); let eth_filter = EthFilter::new( diff --git a/crates/rpc/rpc-builder/src/eth.rs b/crates/rpc/rpc-builder/src/eth.rs index 3968eef6f83e..767660249e27 100644 --- a/crates/rpc/rpc-builder/src/eth.rs +++ b/crates/rpc/rpc-builder/src/eth.rs @@ -1,3 +1,4 @@ +use reth_primitives::constants::ETHEREUM_BLOCK_GAS_LIMIT; use reth_rpc::{ eth::{ cache::{EthStateCache, EthStateCacheConfig}, @@ -37,6 +38,8 @@ pub struct EthConfig { pub max_tracing_requests: u32, /// Maximum number of logs that can be returned in a single response in `eth_getLogs` calls. pub max_logs_per_response: usize, + /// Maximum gas limit for `eth_call` and call tracing RPC methods. + pub rpc_gas_cap: u64, } impl Default for EthConfig { @@ -46,6 +49,7 @@ impl Default for EthConfig { gas_oracle: GasPriceOracleConfig::default(), max_tracing_requests: DEFAULT_MAX_TRACING_REQUESTS, max_logs_per_response: DEFAULT_MAX_LOGS_PER_RESPONSE, + rpc_gas_cap: ETHEREUM_BLOCK_GAS_LIMIT, } } } @@ -74,4 +78,10 @@ impl EthConfig { self.max_logs_per_response = max_logs; self } + + /// Configures the maximum gas limit for `eth_call` and call tracing RPC methods + pub fn rpc_gas_cap(mut self, rpc_gas_cap: u64) -> Self { + self.rpc_gas_cap = rpc_gas_cap; + self + } } diff --git a/crates/rpc/rpc-builder/src/lib.rs b/crates/rpc/rpc-builder/src/lib.rs index 7013131ec5c0..d01036f8d4b7 100644 --- a/crates/rpc/rpc-builder/src/lib.rs +++ b/crates/rpc/rpc-builder/src/lib.rs @@ -967,6 +967,7 @@ where self.network.clone(), cache.clone(), gas_oracle, + self.config.eth.rpc_gas_cap, executor.clone(), ); let filter = EthFilter::new( diff --git a/crates/rpc/rpc/src/eth/api/mod.rs b/crates/rpc/rpc/src/eth/api/mod.rs index b53a80993aed..f291bf2566fb 100644 --- a/crates/rpc/rpc/src/eth/api/mod.rs +++ b/crates/rpc/rpc/src/eth/api/mod.rs @@ -83,6 +83,7 @@ where network: Network, eth_cache: EthStateCache, gas_oracle: GasPriceOracle, + gas_cap: u64, ) -> Self { Self::with_spawner( provider, @@ -90,6 +91,7 @@ where network, eth_cache, gas_oracle, + gas_cap, Box::::default(), ) } @@ -101,6 +103,7 @@ where network: Network, eth_cache: EthStateCache, gas_oracle: GasPriceOracle, + gas_cap: u64, task_spawner: Box, ) -> Self { // get the block number of the latest block @@ -118,6 +121,7 @@ where signers: Default::default(), eth_cache, gas_oracle, + gas_cap, starting_block: U256::from(latest_block), task_spawner, pending_block: Default::default(), @@ -155,6 +159,12 @@ where &self.inner.gas_oracle } + /// Returns the configured gas limit cap for `eth_call` and tracing related calls + #[allow(unused)] + pub(crate) fn gas_cap(&self) -> u64 { + self.inner.gas_cap + } + /// Returns the inner `Provider` pub fn provider(&self) -> &Provider { &self.inner.provider @@ -354,6 +364,8 @@ struct EthApiInner { eth_cache: EthStateCache, /// The async gas oracle frontend for gas price suggestions gas_oracle: GasPriceOracle, + /// Maximum gas limit for `eth_call` and call tracing RPC methods. + gas_cap: u64, /// The block number at which the node started starting_block: U256, /// The type that can spawn tasks which would otherwise block. diff --git a/crates/rpc/rpc/src/eth/api/server.rs b/crates/rpc/rpc/src/eth/api/server.rs index b1643e89671a..1cca7addc90c 100644 --- a/crates/rpc/rpc/src/eth/api/server.rs +++ b/crates/rpc/rpc/src/eth/api/server.rs @@ -398,8 +398,8 @@ mod tests { use reth_interfaces::test_utils::{generators, generators::Rng}; use reth_network_api::noop::NoopNetwork; use reth_primitives::{ - basefee::calculate_next_block_base_fee, Block, BlockNumberOrTag, Header, TransactionSigned, - H256, U256, + basefee::calculate_next_block_base_fee, constants::ETHEREUM_BLOCK_GAS_LIMIT, Block, + BlockNumberOrTag, Header, TransactionSigned, H256, U256, }; use reth_provider::{ test_utils::{MockEthProvider, NoopProvider}, @@ -427,6 +427,7 @@ mod tests { NoopNetwork::default(), cache.clone(), GasPriceOracle::new(provider, Default::default(), cache), + ETHEREUM_BLOCK_GAS_LIMIT, ) } diff --git a/crates/rpc/rpc/src/eth/api/state.rs b/crates/rpc/rpc/src/eth/api/state.rs index 281198be0796..0930bf0b6c50 100644 --- a/crates/rpc/rpc/src/eth/api/state.rs +++ b/crates/rpc/rpc/src/eth/api/state.rs @@ -147,7 +147,7 @@ where mod tests { use super::*; use crate::eth::{cache::EthStateCache, gas_oracle::GasPriceOracle}; - use reth_primitives::{StorageKey, StorageValue}; + use reth_primitives::{constants::ETHEREUM_BLOCK_GAS_LIMIT, StorageKey, StorageValue}; use reth_provider::test_utils::{ExtendedAccount, MockEthProvider, NoopProvider}; use reth_transaction_pool::test_utils::testing_pool; use std::collections::HashMap; @@ -164,6 +164,7 @@ mod tests { (), cache.clone(), GasPriceOracle::new(NoopProvider::default(), Default::default(), cache), + ETHEREUM_BLOCK_GAS_LIMIT, ); let address = Address::random(); let storage = eth_api.storage_at(address, U256::ZERO.into(), None).unwrap(); @@ -184,6 +185,7 @@ mod tests { (), cache.clone(), GasPriceOracle::new(mock_provider, Default::default(), cache), + ETHEREUM_BLOCK_GAS_LIMIT, ); let storage_key: U256 = storage_key.into(); diff --git a/crates/rpc/rpc/src/eth/api/transactions.rs b/crates/rpc/rpc/src/eth/api/transactions.rs index c932ec825bcf..6a5e21d5e162 100644 --- a/crates/rpc/rpc/src/eth/api/transactions.rs +++ b/crates/rpc/rpc/src/eth/api/transactions.rs @@ -872,7 +872,7 @@ mod tests { EthApi, }; use reth_network_api::noop::NoopNetwork; - use reth_primitives::{hex_literal::hex, Bytes}; + use reth_primitives::{constants::ETHEREUM_BLOCK_GAS_LIMIT, hex_literal::hex, Bytes}; use reth_provider::test_utils::NoopProvider; use reth_transaction_pool::{test_utils::testing_pool, TransactionPool}; @@ -890,6 +890,7 @@ mod tests { noop_network_provider, cache.clone(), GasPriceOracle::new(noop_provider, Default::default(), cache), + ETHEREUM_BLOCK_GAS_LIMIT, ); // https://etherscan.io/tx/0xa694b71e6c128a2ed8e2e0f6770bddbe52e3bb8f10e8472f9a79ab81497a8b5d