mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-01-08 15:03:58 -05:00
feat: add --rpc.evm-memory-limit flag (#19279)
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
21
Cargo.lock
generated
21
Cargo.lock
generated
@@ -10650,7 +10650,7 @@ dependencies = [
|
||||
"reth-storage-api",
|
||||
"reth-tasks",
|
||||
"reth-tracing",
|
||||
"revm-interpreter 27.0.2",
|
||||
"revm-interpreter",
|
||||
"revm-primitives",
|
||||
"rustc-hash",
|
||||
"schnellru",
|
||||
@@ -10867,7 +10867,7 @@ dependencies = [
|
||||
"revm-database-interface",
|
||||
"revm-handler",
|
||||
"revm-inspector",
|
||||
"revm-interpreter 28.0.0",
|
||||
"revm-interpreter",
|
||||
"revm-precompile",
|
||||
"revm-primitives",
|
||||
"revm-state",
|
||||
@@ -10957,7 +10957,7 @@ dependencies = [
|
||||
"revm-context",
|
||||
"revm-context-interface",
|
||||
"revm-database-interface",
|
||||
"revm-interpreter 28.0.0",
|
||||
"revm-interpreter",
|
||||
"revm-precompile",
|
||||
"revm-primitives",
|
||||
"revm-state",
|
||||
@@ -10975,7 +10975,7 @@ dependencies = [
|
||||
"revm-context",
|
||||
"revm-database-interface",
|
||||
"revm-handler",
|
||||
"revm-interpreter 28.0.0",
|
||||
"revm-interpreter",
|
||||
"revm-primitives",
|
||||
"revm-state",
|
||||
"serde",
|
||||
@@ -11002,19 +11002,6 @@ dependencies = [
|
||||
"thiserror 2.0.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "revm-interpreter"
|
||||
version = "27.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0834fc25c020061f0f801d8de8bb53c88a63631cca5884a6c65b90c85e241138"
|
||||
dependencies = [
|
||||
"revm-bytecode",
|
||||
"revm-context-interface",
|
||||
"revm-primitives",
|
||||
"revm-state",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "revm-interpreter"
|
||||
version = "28.0.0"
|
||||
|
||||
@@ -474,7 +474,7 @@ revm-bytecode = { version = "7.0.2", default-features = false }
|
||||
revm-database = { version = "9.0.2", default-features = false }
|
||||
revm-state = { version = "8.0.2", default-features = false }
|
||||
revm-primitives = { version = "21.0.1", default-features = false }
|
||||
revm-interpreter = { version = "27.0.2", default-features = false }
|
||||
revm-interpreter = { version = "28.0.0", default-features = false }
|
||||
revm-inspector = { version = "11.1.2", default-features = false }
|
||||
revm-context = { version = "10.1.2", default-features = false }
|
||||
revm-context-interface = { version = "11.1.2", default-features = false }
|
||||
|
||||
@@ -49,7 +49,7 @@ tokio.workspace = true
|
||||
|
||||
# revm with required ethereum features
|
||||
# Note: this must be kept to ensure all features are properly enabled/forwarded
|
||||
revm = { workspace = true, features = ["secp256k1", "blst", "c-kzg"] }
|
||||
revm = { workspace = true, features = ["secp256k1", "blst", "c-kzg", "memory_limit"] }
|
||||
|
||||
# misc
|
||||
eyre.workspace = true
|
||||
|
||||
@@ -1156,6 +1156,7 @@ impl<'a, N: FullNodeComponents<Types: NodeTypes<ChainSpec: Hardforks + EthereumH
|
||||
.max_batch_size(self.config.max_batch_size)
|
||||
.pending_block_kind(self.config.pending_block_kind)
|
||||
.raw_tx_forwarder(self.config.raw_tx_forwarder)
|
||||
.evm_memory_limit(self.config.rpc_evm_memory_limit)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -188,6 +188,16 @@ pub struct RpcServerArgs {
|
||||
)]
|
||||
pub rpc_gas_cap: u64,
|
||||
|
||||
/// Maximum memory the EVM can allocate per RPC request.
|
||||
#[arg(
|
||||
long = "rpc.evm-memory-limit",
|
||||
alias = "rpc-evm-memory-limit",
|
||||
value_name = "MEMORY_LIMIT",
|
||||
value_parser = MaxOr::new(RangedU64ValueParser::<u64>::new().range(1..)),
|
||||
default_value_t = (1 << 32) - 1
|
||||
)]
|
||||
pub rpc_evm_memory_limit: u64,
|
||||
|
||||
/// Maximum eth transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)
|
||||
#[arg(
|
||||
long = "rpc.txfeecap",
|
||||
@@ -408,6 +418,7 @@ impl Default for RpcServerArgs {
|
||||
rpc_max_blocks_per_filter: constants::DEFAULT_MAX_BLOCKS_PER_FILTER.into(),
|
||||
rpc_max_logs_per_response: (constants::DEFAULT_MAX_LOGS_PER_RESPONSE as u64).into(),
|
||||
rpc_gas_cap: constants::gas_oracle::RPC_DEFAULT_GAS_CAP,
|
||||
rpc_evm_memory_limit: (1 << 32) - 1,
|
||||
rpc_tx_fee_cap: constants::DEFAULT_TX_FEE_CAP_WEI,
|
||||
rpc_max_simulate_blocks: constants::DEFAULT_MAX_SIMULATE_BLOCKS,
|
||||
rpc_eth_proof_window: constants::DEFAULT_ETH_PROOF_WINDOW,
|
||||
|
||||
@@ -45,7 +45,7 @@ reth-optimism-primitives = { workspace = true, features = ["serde", "serde-binco
|
||||
|
||||
# revm with required optimism features
|
||||
# Note: this must be kept to ensure all features are properly enabled/forwarded
|
||||
revm = { workspace = true, features = ["secp256k1", "blst", "c-kzg"] }
|
||||
revm = { workspace = true, features = ["secp256k1", "blst", "c-kzg", "memory_limit"] }
|
||||
op-revm.workspace = true
|
||||
|
||||
# ethereum
|
||||
|
||||
@@ -35,4 +35,9 @@ where
|
||||
fn max_simulate_blocks(&self) -> u64 {
|
||||
self.inner.eth_api.max_simulate_blocks()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn evm_memory_limit(&self) -> u64 {
|
||||
self.inner.eth_api.evm_memory_limit()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,3 +68,4 @@ optional-checks = [
|
||||
"optional-eip3607",
|
||||
"optional-no-base-fee",
|
||||
]
|
||||
memory_limit = ["revm/memory_limit"]
|
||||
|
||||
@@ -105,6 +105,7 @@ impl RethRpcServerConfig for RpcServerArgs {
|
||||
.proof_permits(self.rpc_proof_permits)
|
||||
.pending_block_kind(self.rpc_pending_block)
|
||||
.raw_tx_forwarder(self.rpc_forwarder.clone())
|
||||
.rpc_evm_memory_limit(self.rpc_evm_memory_limit)
|
||||
}
|
||||
|
||||
fn flashbots_config(&self) -> ValidationApiConfig {
|
||||
|
||||
@@ -13,7 +13,7 @@ workspace = true
|
||||
|
||||
[dependencies]
|
||||
# reth
|
||||
revm = { workspace = true, features = ["optional_block_gas_limit", "optional_eip3607", "optional_no_base_fee", "optional_fee_charge"] }
|
||||
revm = { workspace = true, features = ["optional_block_gas_limit", "optional_eip3607", "optional_no_base_fee", "optional_fee_charge", "memory_limit"] }
|
||||
reth-chain-state.workspace = true
|
||||
revm-inspectors.workspace = true
|
||||
reth-primitives-traits = { workspace = true, features = ["rpc-compat"] }
|
||||
|
||||
@@ -493,6 +493,9 @@ pub trait Call:
|
||||
/// Returns the maximum number of blocks accepted for `eth_simulateV1`.
|
||||
fn max_simulate_blocks(&self) -> u64;
|
||||
|
||||
/// Returns the maximum memory the EVM can allocate per RPC request.
|
||||
fn evm_memory_limit(&self) -> u64;
|
||||
|
||||
/// Returns the max gas limit that the caller can afford given a transaction environment.
|
||||
fn caller_gas_allowance(
|
||||
&self,
|
||||
@@ -811,6 +814,8 @@ pub trait Call:
|
||||
// <https://github.com/paradigmxyz/reth/issues/18470>
|
||||
evm_env.cfg_env.disable_fee_charge = true;
|
||||
|
||||
evm_env.cfg_env.memory_limit = self.evm_memory_limit();
|
||||
|
||||
// set nonce to None so that the correct nonce is chosen by the EVM
|
||||
request.as_mut().take_nonce();
|
||||
|
||||
|
||||
@@ -95,6 +95,8 @@ pub struct EthConfig {
|
||||
pub raw_tx_forwarder: ForwardConfig,
|
||||
/// Timeout duration for `send_raw_transaction_sync` RPC method.
|
||||
pub send_raw_transaction_sync_timeout: Duration,
|
||||
/// Maximum memory the EVM can allocate per RPC request.
|
||||
pub rpc_evm_memory_limit: u64,
|
||||
}
|
||||
|
||||
impl EthConfig {
|
||||
@@ -126,6 +128,7 @@ impl Default for EthConfig {
|
||||
pending_block_kind: PendingBlockKind::Full,
|
||||
raw_tx_forwarder: ForwardConfig::default(),
|
||||
send_raw_transaction_sync_timeout: RPC_DEFAULT_SEND_RAW_TX_SYNC_TIMEOUT_SECS,
|
||||
rpc_evm_memory_limit: (1 << 32) - 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -216,6 +219,12 @@ impl EthConfig {
|
||||
self.send_raw_transaction_sync_timeout = timeout;
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the maximum memory the EVM can allocate per RPC request.
|
||||
pub const fn rpc_evm_memory_limit(mut self, memory_limit: u64) -> Self {
|
||||
self.rpc_evm_memory_limit = memory_limit;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Config for the filter
|
||||
|
||||
@@ -619,6 +619,9 @@ pub enum RpcInvalidTransactionError {
|
||||
/// Contains the gas limit.
|
||||
#[error("out of gas: gas exhausted during memory expansion: {0}")]
|
||||
MemoryOutOfGas(u64),
|
||||
/// Memory limit was exceeded during memory expansion.
|
||||
#[error("out of memory: memory limit exceeded during memory expansion")]
|
||||
MemoryLimitOutOfGas,
|
||||
/// Gas limit was exceeded during precompile execution.
|
||||
/// Contains the gas limit.
|
||||
#[error("out of gas: gas exhausted during precompiled contract execution: {0}")]
|
||||
@@ -723,7 +726,8 @@ impl RpcInvalidTransactionError {
|
||||
OutOfGasError::Basic | OutOfGasError::ReentrancySentry => {
|
||||
Self::BasicOutOfGas(gas_limit)
|
||||
}
|
||||
OutOfGasError::Memory | OutOfGasError::MemoryLimit => Self::MemoryOutOfGas(gas_limit),
|
||||
OutOfGasError::Memory => Self::MemoryOutOfGas(gas_limit),
|
||||
OutOfGasError::MemoryLimit => Self::MemoryLimitOutOfGas,
|
||||
OutOfGasError::Precompile => Self::PrecompileOutOfGas(gas_limit),
|
||||
OutOfGasError::InvalidOperand => Self::InvalidOperandOutOfGas(gas_limit),
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ alloy-rpc-types-txpool.workspace = true
|
||||
alloy-rpc-types-admin.workspace = true
|
||||
alloy-rpc-types-engine = { workspace = true, features = ["kzg"] }
|
||||
alloy-serde.workspace = true
|
||||
revm = { workspace = true, features = ["optional_block_gas_limit", "optional_eip3607", "optional_no_base_fee"] }
|
||||
revm = { workspace = true, features = ["optional_block_gas_limit", "optional_eip3607", "optional_no_base_fee", "memory_limit"] }
|
||||
revm-primitives = { workspace = true, features = ["serde"] }
|
||||
|
||||
# rpc
|
||||
|
||||
@@ -44,6 +44,7 @@ pub struct EthApiBuilder<N: RpcNodeCore, Rpc, NextEnv = ()> {
|
||||
pending_block_kind: PendingBlockKind,
|
||||
raw_tx_forwarder: ForwardConfig,
|
||||
send_raw_transaction_sync_timeout: Duration,
|
||||
evm_memory_limit: u64,
|
||||
}
|
||||
|
||||
impl<Provider, Pool, Network, EvmConfig, ChainSpec>
|
||||
@@ -94,6 +95,7 @@ impl<N: RpcNodeCore, Rpc, NextEnv> EthApiBuilder<N, Rpc, NextEnv> {
|
||||
pending_block_kind,
|
||||
raw_tx_forwarder,
|
||||
send_raw_transaction_sync_timeout,
|
||||
evm_memory_limit,
|
||||
} = self;
|
||||
EthApiBuilder {
|
||||
components,
|
||||
@@ -114,6 +116,7 @@ impl<N: RpcNodeCore, Rpc, NextEnv> EthApiBuilder<N, Rpc, NextEnv> {
|
||||
pending_block_kind,
|
||||
raw_tx_forwarder,
|
||||
send_raw_transaction_sync_timeout,
|
||||
evm_memory_limit,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -145,6 +148,7 @@ where
|
||||
pending_block_kind: PendingBlockKind::Full,
|
||||
raw_tx_forwarder: ForwardConfig::default(),
|
||||
send_raw_transaction_sync_timeout: Duration::from_secs(30),
|
||||
evm_memory_limit: (1 << 32) - 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,6 +187,7 @@ where
|
||||
pending_block_kind,
|
||||
raw_tx_forwarder,
|
||||
send_raw_transaction_sync_timeout,
|
||||
evm_memory_limit,
|
||||
} = self;
|
||||
EthApiBuilder {
|
||||
components,
|
||||
@@ -203,6 +208,7 @@ where
|
||||
pending_block_kind,
|
||||
raw_tx_forwarder,
|
||||
send_raw_transaction_sync_timeout,
|
||||
evm_memory_limit,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,6 +236,7 @@ where
|
||||
pending_block_kind,
|
||||
raw_tx_forwarder,
|
||||
send_raw_transaction_sync_timeout,
|
||||
evm_memory_limit,
|
||||
} = self;
|
||||
EthApiBuilder {
|
||||
components,
|
||||
@@ -250,6 +257,7 @@ where
|
||||
pending_block_kind,
|
||||
raw_tx_forwarder,
|
||||
send_raw_transaction_sync_timeout,
|
||||
evm_memory_limit,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -477,6 +485,7 @@ where
|
||||
pending_block_kind,
|
||||
raw_tx_forwarder,
|
||||
send_raw_transaction_sync_timeout,
|
||||
evm_memory_limit,
|
||||
} = self;
|
||||
|
||||
let provider = components.provider().clone();
|
||||
@@ -517,6 +526,7 @@ where
|
||||
pending_block_kind,
|
||||
raw_tx_forwarder.forwarder_client(),
|
||||
send_raw_transaction_sync_timeout,
|
||||
evm_memory_limit,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -541,4 +551,10 @@ where
|
||||
self.send_raw_transaction_sync_timeout = timeout;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the maximum memory the EVM can allocate per RPC request.
|
||||
pub const fn evm_memory_limit(mut self, memory_limit: u64) -> Self {
|
||||
self.evm_memory_limit = memory_limit;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,6 +155,7 @@ where
|
||||
pending_block_kind: PendingBlockKind,
|
||||
raw_tx_forwarder: ForwardConfig,
|
||||
send_raw_transaction_sync_timeout: Duration,
|
||||
evm_memory_limit: u64,
|
||||
) -> Self {
|
||||
let inner = EthApiInner::new(
|
||||
components,
|
||||
@@ -173,6 +174,7 @@ where
|
||||
pending_block_kind,
|
||||
raw_tx_forwarder.forwarder_client(),
|
||||
send_raw_transaction_sync_timeout,
|
||||
evm_memory_limit,
|
||||
);
|
||||
|
||||
Self { inner: Arc::new(inner) }
|
||||
@@ -318,6 +320,9 @@ pub struct EthApiInner<N: RpcNodeCore, Rpc: RpcConvert> {
|
||||
|
||||
/// Blob sidecar converter
|
||||
blob_sidecar_converter: BlobSidecarConverter,
|
||||
|
||||
/// Maximum memory the EVM can allocate per RPC request.
|
||||
evm_memory_limit: u64,
|
||||
}
|
||||
|
||||
impl<N, Rpc> EthApiInner<N, Rpc>
|
||||
@@ -344,6 +349,7 @@ where
|
||||
pending_block_kind: PendingBlockKind,
|
||||
raw_tx_forwarder: Option<RpcClient>,
|
||||
send_raw_transaction_sync_timeout: Duration,
|
||||
evm_memory_limit: u64,
|
||||
) -> Self {
|
||||
let signers = parking_lot::RwLock::new(Default::default());
|
||||
// get the block number of the latest block
|
||||
@@ -386,6 +392,7 @@ where
|
||||
pending_block_kind,
|
||||
send_raw_transaction_sync_timeout,
|
||||
blob_sidecar_converter: BlobSidecarConverter::new(),
|
||||
evm_memory_limit,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -563,6 +570,12 @@ where
|
||||
pub const fn blob_sidecar_converter(&self) -> &BlobSidecarConverter {
|
||||
&self.blob_sidecar_converter
|
||||
}
|
||||
|
||||
/// Returns the EVM memory limit.
|
||||
#[inline]
|
||||
pub const fn evm_memory_limit(&self) -> u64 {
|
||||
self.evm_memory_limit
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -31,6 +31,11 @@ where
|
||||
fn max_simulate_blocks(&self) -> u64 {
|
||||
self.inner.max_simulate_blocks()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn evm_memory_limit(&self) -> u64 {
|
||||
self.inner.evm_memory_limit()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N, Rpc> EstimateCall for EthApi<N, Rpc>
|
||||
|
||||
@@ -405,6 +405,11 @@ RPC:
|
||||
|
||||
[default: 50000000]
|
||||
|
||||
--rpc.evm-memory-limit <MEMORY_LIMIT>
|
||||
Maximum memory the EVM can allocate per RPC request
|
||||
|
||||
[default: 4294967295]
|
||||
|
||||
--rpc.txfeecap <TX_FEE_CAP>
|
||||
Maximum eth transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ reth-stateless = { workspace = true, features = ["secp256k1"] }
|
||||
reth-tracing.workspace = true
|
||||
reth-trie.workspace = true
|
||||
reth-trie-db.workspace = true
|
||||
revm = { workspace = true, features = ["secp256k1", "blst", "c-kzg"] }
|
||||
revm = { workspace = true, features = ["secp256k1", "blst", "c-kzg", "memory_limit"] }
|
||||
|
||||
alloy-rlp.workspace = true
|
||||
alloy-primitives.workspace = true
|
||||
|
||||
Reference in New Issue
Block a user