Skip to main content

reth_node_core/args/
rpc_server.rs

1//! clap [Args](clap::Args) for RPC related arguments.
2
3use crate::args::{
4    types::{MaxU32, ZeroAsNoneU64},
5    GasPriceOracleArgs, RpcStateCacheArgs,
6};
7use alloy_primitives::map::AddressSet;
8use alloy_rpc_types_engine::JwtSecret;
9use clap::{
10    builder::{PossibleValue, RangedU64ValueParser, Resettable, TypedValueParser},
11    Arg, Args, Command,
12};
13use rand::Rng;
14use reth_cli_util::{parse_duration_from_secs_or_ms, parse_ether_value};
15use reth_rpc_eth_types::builder::config::PendingBlockKind;
16use reth_rpc_server_types::{constants, RethRpcModule, RpcModuleSelection};
17use std::{
18    ffi::OsStr,
19    net::{IpAddr, Ipv4Addr},
20    path::PathBuf,
21    sync::OnceLock,
22    time::Duration,
23};
24use url::Url;
25
26use super::types::MaxOr;
27
28/// Global static RPC server defaults
29static RPC_SERVER_DEFAULTS: OnceLock<DefaultRpcServerArgs> = OnceLock::new();
30
31/// Default max number of subscriptions per connection.
32pub(crate) const RPC_DEFAULT_MAX_SUBS_PER_CONN: u32 = 1024;
33
34/// Default max request size in MB.
35pub(crate) const RPC_DEFAULT_MAX_REQUEST_SIZE_MB: u32 = 15;
36
37/// Default max response size in MB.
38///
39/// This is only relevant for very large trace responses.
40pub(crate) const RPC_DEFAULT_MAX_RESPONSE_SIZE_MB: u32 = 160;
41
42/// Default number of incoming connections.
43///
44/// This restricts how many active connections (http, ws) the server accepts.
45/// Once exceeded, the server can reject new connections.
46pub(crate) const RPC_DEFAULT_MAX_CONNECTIONS: u32 = 500;
47
48/// Default values for RPC server that can be customized
49///
50/// Global defaults can be set via [`DefaultRpcServerArgs::try_init`].
51#[derive(Debug, Clone)]
52pub struct DefaultRpcServerArgs {
53    http: bool,
54    http_addr: IpAddr,
55    http_port: u16,
56    http_disable_compression: bool,
57    http_api: Option<RpcModuleSelection>,
58    http_corsdomain: Option<String>,
59    ws: bool,
60    ws_addr: IpAddr,
61    ws_port: u16,
62    ws_allowed_origins: Option<String>,
63    ws_api: Option<RpcModuleSelection>,
64    ipcdisable: bool,
65    ipcpath: String,
66    ipc_socket_permissions: Option<String>,
67    auth_addr: IpAddr,
68    auth_port: u16,
69    auth_jwtsecret: Option<PathBuf>,
70    auth_ipc: bool,
71    auth_ipc_path: String,
72    disable_auth_server: bool,
73    rpc_jwtsecret: Option<JwtSecret>,
74    rpc_disable_metrics: bool,
75    rpc_max_request_size: MaxU32,
76    rpc_max_response_size: MaxU32,
77    rpc_max_subscriptions_per_connection: MaxU32,
78    rpc_max_connections: MaxU32,
79    rpc_max_tracing_requests: usize,
80    rpc_max_blocking_io_requests: usize,
81    rpc_max_trace_filter_blocks: u64,
82    rpc_max_blocks_per_filter: ZeroAsNoneU64,
83    rpc_max_logs_per_response: ZeroAsNoneU64,
84    rpc_gas_cap: u64,
85    rpc_evm_memory_limit: u64,
86    rpc_tx_fee_cap: u128,
87    rpc_max_simulate_blocks: u64,
88    rpc_compute_state_root_for_eth_simulate: bool,
89    rpc_eth_proof_window: u64,
90    rpc_proof_permits: usize,
91    rpc_pending_block: PendingBlockKind,
92    rpc_forwarder: Option<Url>,
93    builder_disallow: Option<AddressSet>,
94    rpc_state_cache: RpcStateCacheArgs,
95    gas_price_oracle: GasPriceOracleArgs,
96    rpc_send_raw_transaction_sync_timeout: Duration,
97}
98
99impl DefaultRpcServerArgs {
100    /// Initialize the global RPC server defaults with this configuration
101    pub fn try_init(self) -> Result<(), Self> {
102        RPC_SERVER_DEFAULTS.set(self)
103    }
104
105    /// Get a reference to the global RPC server defaults
106    pub fn get_global() -> &'static Self {
107        RPC_SERVER_DEFAULTS.get_or_init(Self::default)
108    }
109
110    /// Set the default HTTP enabled state
111    pub const fn with_http(mut self, v: bool) -> Self {
112        self.http = v;
113        self
114    }
115
116    /// Set the default HTTP address
117    pub const fn with_http_addr(mut self, v: IpAddr) -> Self {
118        self.http_addr = v;
119        self
120    }
121
122    /// Set the default HTTP port
123    pub const fn with_http_port(mut self, v: u16) -> Self {
124        self.http_port = v;
125        self
126    }
127
128    /// Set whether to disable HTTP compression by default
129    pub const fn with_http_disable_compression(mut self, v: bool) -> Self {
130        self.http_disable_compression = v;
131        self
132    }
133
134    /// Set the default HTTP API modules
135    pub fn with_http_api(mut self, v: Option<RpcModuleSelection>) -> Self {
136        self.http_api = v;
137        self
138    }
139
140    /// Set the default HTTP CORS domain
141    pub fn with_http_corsdomain(mut self, v: Option<String>) -> Self {
142        self.http_corsdomain = v;
143        self
144    }
145
146    /// Set the default WS enabled state
147    pub const fn with_ws(mut self, v: bool) -> Self {
148        self.ws = v;
149        self
150    }
151
152    /// Set the default WS address
153    pub const fn with_ws_addr(mut self, v: IpAddr) -> Self {
154        self.ws_addr = v;
155        self
156    }
157
158    /// Set the default WS port
159    pub const fn with_ws_port(mut self, v: u16) -> Self {
160        self.ws_port = v;
161        self
162    }
163
164    /// Set the default WS allowed origins
165    pub fn with_ws_allowed_origins(mut self, v: Option<String>) -> Self {
166        self.ws_allowed_origins = v;
167        self
168    }
169
170    /// Set the default WS API modules
171    pub fn with_ws_api(mut self, v: Option<RpcModuleSelection>) -> Self {
172        self.ws_api = v;
173        self
174    }
175
176    /// Set whether to disable IPC by default
177    pub const fn with_ipcdisable(mut self, v: bool) -> Self {
178        self.ipcdisable = v;
179        self
180    }
181
182    /// Set the default IPC path
183    pub fn with_ipcpath(mut self, v: String) -> Self {
184        self.ipcpath = v;
185        self
186    }
187
188    /// Set the default IPC socket permissions
189    pub fn with_ipc_socket_permissions(mut self, v: Option<String>) -> Self {
190        self.ipc_socket_permissions = v;
191        self
192    }
193
194    /// Set the default auth server address
195    pub const fn with_auth_addr(mut self, v: IpAddr) -> Self {
196        self.auth_addr = v;
197        self
198    }
199
200    /// Set the default auth server port
201    pub const fn with_auth_port(mut self, v: u16) -> Self {
202        self.auth_port = v;
203        self
204    }
205
206    /// Set the default auth JWT secret path
207    pub fn with_auth_jwtsecret(mut self, v: Option<PathBuf>) -> Self {
208        self.auth_jwtsecret = v;
209        self
210    }
211
212    /// Set the default auth IPC enabled state
213    pub const fn with_auth_ipc(mut self, v: bool) -> Self {
214        self.auth_ipc = v;
215        self
216    }
217
218    /// Set the default auth IPC path
219    pub fn with_auth_ipc_path(mut self, v: String) -> Self {
220        self.auth_ipc_path = v;
221        self
222    }
223
224    /// Set whether to disable the auth server by default
225    pub const fn with_disable_auth_server(mut self, v: bool) -> Self {
226        self.disable_auth_server = v;
227        self
228    }
229
230    /// Set the default RPC JWT secret
231    pub const fn with_rpc_jwtsecret(mut self, v: Option<JwtSecret>) -> Self {
232        self.rpc_jwtsecret = v;
233        self
234    }
235
236    /// Set whether to disable RPC request metrics by default
237    pub const fn with_rpc_disable_metrics(mut self, v: bool) -> Self {
238        self.rpc_disable_metrics = v;
239        self
240    }
241
242    /// Set the default max request size
243    pub const fn with_rpc_max_request_size(mut self, v: MaxU32) -> Self {
244        self.rpc_max_request_size = v;
245        self
246    }
247
248    /// Set the default max response size
249    pub const fn with_rpc_max_response_size(mut self, v: MaxU32) -> Self {
250        self.rpc_max_response_size = v;
251        self
252    }
253
254    /// Set the default max subscriptions per connection
255    pub const fn with_rpc_max_subscriptions_per_connection(mut self, v: MaxU32) -> Self {
256        self.rpc_max_subscriptions_per_connection = v;
257        self
258    }
259
260    /// Set the default max connections
261    pub const fn with_rpc_max_connections(mut self, v: MaxU32) -> Self {
262        self.rpc_max_connections = v;
263        self
264    }
265
266    /// Set the default max tracing requests
267    pub const fn with_rpc_max_tracing_requests(mut self, v: usize) -> Self {
268        self.rpc_max_tracing_requests = v;
269        self
270    }
271
272    /// Set the default max blocking IO requests
273    pub const fn with_rpc_max_blocking_io_requests(mut self, v: usize) -> Self {
274        self.rpc_max_blocking_io_requests = v;
275        self
276    }
277
278    /// Set the default max trace filter blocks
279    pub const fn with_rpc_max_trace_filter_blocks(mut self, v: u64) -> Self {
280        self.rpc_max_trace_filter_blocks = v;
281        self
282    }
283
284    /// Set the default max blocks per filter
285    pub const fn with_rpc_max_blocks_per_filter(mut self, v: ZeroAsNoneU64) -> Self {
286        self.rpc_max_blocks_per_filter = v;
287        self
288    }
289
290    /// Set the default max logs per response
291    pub const fn with_rpc_max_logs_per_response(mut self, v: ZeroAsNoneU64) -> Self {
292        self.rpc_max_logs_per_response = v;
293        self
294    }
295
296    /// Set the default gas cap
297    pub const fn with_rpc_gas_cap(mut self, v: u64) -> Self {
298        self.rpc_gas_cap = v;
299        self
300    }
301
302    /// Set the default EVM memory limit
303    pub const fn with_rpc_evm_memory_limit(mut self, v: u64) -> Self {
304        self.rpc_evm_memory_limit = v;
305        self
306    }
307
308    /// Set the default tx fee cap
309    pub const fn with_rpc_tx_fee_cap(mut self, v: u128) -> Self {
310        self.rpc_tx_fee_cap = v;
311        self
312    }
313
314    /// Set the default max simulate blocks
315    pub const fn with_rpc_max_simulate_blocks(mut self, v: u64) -> Self {
316        self.rpc_max_simulate_blocks = v;
317        self
318    }
319
320    /// Set whether to compute state roots for `eth_simulateV1` responses by default.
321    pub const fn with_rpc_compute_state_root_for_eth_simulate(mut self, v: bool) -> Self {
322        self.rpc_compute_state_root_for_eth_simulate = v;
323        self
324    }
325
326    /// Set the default eth proof window
327    pub const fn with_rpc_eth_proof_window(mut self, v: u64) -> Self {
328        self.rpc_eth_proof_window = v;
329        self
330    }
331
332    /// Set the default proof permits
333    pub const fn with_rpc_proof_permits(mut self, v: usize) -> Self {
334        self.rpc_proof_permits = v;
335        self
336    }
337
338    /// Set the default pending block kind
339    pub const fn with_rpc_pending_block(mut self, v: PendingBlockKind) -> Self {
340        self.rpc_pending_block = v;
341        self
342    }
343
344    /// Set the default RPC forwarder
345    pub fn with_rpc_forwarder(mut self, v: Option<Url>) -> Self {
346        self.rpc_forwarder = v;
347        self
348    }
349
350    /// Set the default builder disallow addresses
351    pub fn with_builder_disallow(mut self, v: Option<AddressSet>) -> Self {
352        self.builder_disallow = v;
353        self
354    }
355
356    /// Set the default RPC state cache args
357    pub const fn with_rpc_state_cache(mut self, v: RpcStateCacheArgs) -> Self {
358        self.rpc_state_cache = v;
359        self
360    }
361
362    /// Set the default gas price oracle args
363    pub const fn with_gas_price_oracle(mut self, v: GasPriceOracleArgs) -> Self {
364        self.gas_price_oracle = v;
365        self
366    }
367
368    /// Set the default send raw transaction sync timeout
369    pub const fn with_rpc_send_raw_transaction_sync_timeout(mut self, v: Duration) -> Self {
370        self.rpc_send_raw_transaction_sync_timeout = v;
371        self
372    }
373}
374
375impl Default for DefaultRpcServerArgs {
376    fn default() -> Self {
377        Self {
378            http: false,
379            http_addr: Ipv4Addr::LOCALHOST.into(),
380            http_port: constants::DEFAULT_HTTP_RPC_PORT,
381            http_disable_compression: false,
382            http_api: None,
383            http_corsdomain: None,
384            ws: false,
385            ws_addr: Ipv4Addr::LOCALHOST.into(),
386            ws_port: constants::DEFAULT_WS_RPC_PORT,
387            ws_allowed_origins: None,
388            ws_api: None,
389            ipcdisable: false,
390            ipcpath: constants::DEFAULT_IPC_ENDPOINT.to_string(),
391            ipc_socket_permissions: None,
392            auth_addr: Ipv4Addr::LOCALHOST.into(),
393            auth_port: constants::DEFAULT_AUTH_PORT,
394            auth_jwtsecret: None,
395            auth_ipc: false,
396            auth_ipc_path: constants::DEFAULT_ENGINE_API_IPC_ENDPOINT.to_string(),
397            disable_auth_server: false,
398            rpc_jwtsecret: None,
399            rpc_disable_metrics: false,
400            rpc_max_request_size: RPC_DEFAULT_MAX_REQUEST_SIZE_MB.into(),
401            rpc_max_response_size: RPC_DEFAULT_MAX_RESPONSE_SIZE_MB.into(),
402            rpc_max_subscriptions_per_connection: RPC_DEFAULT_MAX_SUBS_PER_CONN.into(),
403            rpc_max_connections: RPC_DEFAULT_MAX_CONNECTIONS.into(),
404            rpc_max_tracing_requests: constants::default_max_tracing_requests(),
405            rpc_max_blocking_io_requests: constants::DEFAULT_MAX_BLOCKING_IO_REQUEST,
406            rpc_max_trace_filter_blocks: constants::DEFAULT_MAX_TRACE_FILTER_BLOCKS,
407            rpc_max_blocks_per_filter: constants::DEFAULT_MAX_BLOCKS_PER_FILTER.into(),
408            rpc_max_logs_per_response: (constants::DEFAULT_MAX_LOGS_PER_RESPONSE as u64).into(),
409            rpc_gas_cap: constants::gas_oracle::RPC_DEFAULT_GAS_CAP,
410            rpc_evm_memory_limit: (1 << 32) - 1,
411            rpc_tx_fee_cap: constants::DEFAULT_TX_FEE_CAP_WEI,
412            rpc_max_simulate_blocks: constants::DEFAULT_MAX_SIMULATE_BLOCKS,
413            rpc_compute_state_root_for_eth_simulate: false,
414            rpc_eth_proof_window: constants::DEFAULT_ETH_PROOF_WINDOW,
415            rpc_proof_permits: constants::DEFAULT_PROOF_PERMITS,
416            rpc_pending_block: PendingBlockKind::Full,
417            rpc_forwarder: None,
418            builder_disallow: None,
419            rpc_state_cache: RpcStateCacheArgs::default(),
420            gas_price_oracle: GasPriceOracleArgs::default(),
421            rpc_send_raw_transaction_sync_timeout:
422                constants::RPC_DEFAULT_SEND_RAW_TX_SYNC_TIMEOUT_SECS,
423        }
424    }
425}
426
427/// Parameters for configuring the rpc more granularity via CLI
428#[derive(Debug, Clone, Args, PartialEq, Eq)]
429#[command(next_help_heading = "RPC")]
430pub struct RpcServerArgs {
431    /// Enable the HTTP-RPC server
432    #[arg(long, default_value_if("dev", "true", "true"), default_value_t = DefaultRpcServerArgs::get_global().http)]
433    pub http: bool,
434
435    /// Http server address to listen on
436    #[arg(long = "http.addr", default_value_t = DefaultRpcServerArgs::get_global().http_addr)]
437    pub http_addr: IpAddr,
438
439    /// Http server port to listen on
440    #[arg(long = "http.port", default_value_t = DefaultRpcServerArgs::get_global().http_port)]
441    pub http_port: u16,
442
443    /// Disable compression for HTTP responses
444    #[arg(long = "http.disable-compression", default_value_t = DefaultRpcServerArgs::get_global().http_disable_compression)]
445    pub http_disable_compression: bool,
446
447    /// Rpc Modules to be configured for the HTTP server
448    #[arg(long = "http.api", value_parser = RpcModuleSelectionValueParser::default(), default_value = Resettable::from(DefaultRpcServerArgs::get_global().http_api.as_ref().map(|v| v.to_string().into())))]
449    pub http_api: Option<RpcModuleSelection>,
450
451    /// Http Corsdomain to allow request from
452    #[arg(long = "http.corsdomain", default_value = Resettable::from(DefaultRpcServerArgs::get_global().http_corsdomain.as_ref().map(|v| v.to_string().into())))]
453    pub http_corsdomain: Option<String>,
454
455    /// Enable the WS-RPC server
456    #[arg(long, default_value_t = DefaultRpcServerArgs::get_global().ws)]
457    pub ws: bool,
458
459    /// Ws server address to listen on
460    #[arg(long = "ws.addr", default_value_t = DefaultRpcServerArgs::get_global().ws_addr)]
461    pub ws_addr: IpAddr,
462
463    /// Ws server port to listen on
464    #[arg(long = "ws.port", default_value_t = DefaultRpcServerArgs::get_global().ws_port)]
465    pub ws_port: u16,
466
467    /// Origins from which to accept `WebSocket` requests
468    #[arg(id = "ws.origins", long = "ws.origins", alias = "ws.corsdomain", default_value = Resettable::from(DefaultRpcServerArgs::get_global().ws_allowed_origins.as_ref().map(|v| v.to_string().into())))]
469    pub ws_allowed_origins: Option<String>,
470
471    /// Rpc Modules to be configured for the WS server
472    #[arg(long = "ws.api", value_parser = RpcModuleSelectionValueParser::default(), default_value = Resettable::from(DefaultRpcServerArgs::get_global().ws_api.as_ref().map(|v| v.to_string().into())))]
473    pub ws_api: Option<RpcModuleSelection>,
474
475    /// Disable the IPC-RPC server
476    #[arg(long, default_value_t = DefaultRpcServerArgs::get_global().ipcdisable)]
477    pub ipcdisable: bool,
478
479    /// Filename for IPC socket/pipe within the datadir
480    #[arg(long, default_value_t = DefaultRpcServerArgs::get_global().ipcpath.clone())]
481    pub ipcpath: String,
482
483    /// Set the permissions for the IPC socket file, in octal format.
484    ///
485    /// If not specified, the permissions will be set by the system's umask.
486    #[arg(long = "ipc.permissions", default_value = Resettable::from(DefaultRpcServerArgs::get_global().ipc_socket_permissions.as_ref().map(|v| v.to_string().into())))]
487    pub ipc_socket_permissions: Option<String>,
488
489    /// Auth server address to listen on
490    #[arg(long = "authrpc.addr", default_value_t = DefaultRpcServerArgs::get_global().auth_addr)]
491    pub auth_addr: IpAddr,
492
493    /// Auth server port to listen on
494    #[arg(long = "authrpc.port", default_value_t = DefaultRpcServerArgs::get_global().auth_port)]
495    pub auth_port: u16,
496
497    /// Path to a JWT secret to use for the authenticated engine-API RPC server.
498    ///
499    /// This will enforce JWT authentication for all requests coming from the consensus layer.
500    ///
501    /// If no path is provided, a secret will be generated and stored in the datadir under
502    /// `<DIR>/<CHAIN_ID>/jwt.hex`. For mainnet this would be `~/.local/share/reth/mainnet/jwt.hex`
503    /// by default.
504    #[arg(long = "authrpc.jwtsecret", value_name = "PATH", global = true, required = false, default_value = Resettable::from(DefaultRpcServerArgs::get_global().auth_jwtsecret.as_ref().map(|v| v.to_string_lossy().into())))]
505    pub auth_jwtsecret: Option<PathBuf>,
506
507    /// Enable auth engine API over IPC
508    #[arg(long, default_value_t = DefaultRpcServerArgs::get_global().auth_ipc)]
509    pub auth_ipc: bool,
510
511    /// Filename for auth IPC socket/pipe within the datadir
512    #[arg(long = "auth-ipc.path", default_value_t = DefaultRpcServerArgs::get_global().auth_ipc_path.clone())]
513    pub auth_ipc_path: String,
514
515    /// Disable the auth/engine API server.
516    ///
517    /// This will prevent the authenticated engine-API server from starting. Use this if you're
518    /// running a node that doesn't need to serve engine API requests.
519    #[arg(long = "disable-auth-server", alias = "disable-engine-api", default_value_t = DefaultRpcServerArgs::get_global().disable_auth_server)]
520    pub disable_auth_server: bool,
521
522    /// Hex encoded JWT secret to authenticate the regular RPC server(s), see `--http.api` and
523    /// `--ws.api`.
524    ///
525    /// This is __not__ used for the authenticated engine-API RPC server, see
526    /// `--authrpc.jwtsecret`.
527    #[arg(long = "rpc.jwtsecret", value_name = "HEX", global = true, required = false, default_value = Resettable::from(DefaultRpcServerArgs::get_global().rpc_jwtsecret.as_ref().map(|v| format!("{:?}", v).into())))]
528    pub rpc_jwtsecret: Option<JwtSecret>,
529
530    /// Disable built-in RPC request metrics.
531    #[arg(long = "rpc.disable-metrics", default_value_t = DefaultRpcServerArgs::get_global().rpc_disable_metrics)]
532    pub rpc_disable_metrics: bool,
533
534    /// Set the maximum RPC request payload size for both HTTP and WS in megabytes.
535    #[arg(long = "rpc.max-request-size", alias = "rpc-max-request-size", default_value_t = DefaultRpcServerArgs::get_global().rpc_max_request_size)]
536    pub rpc_max_request_size: MaxU32,
537
538    /// Set the maximum RPC response payload size for both HTTP and WS in megabytes.
539    #[arg(long = "rpc.max-response-size", alias = "rpc-max-response-size", visible_alias = "rpc.returndata.limit", default_value_t = DefaultRpcServerArgs::get_global().rpc_max_response_size)]
540    pub rpc_max_response_size: MaxU32,
541
542    /// Set the maximum concurrent subscriptions per connection.
543    #[arg(long = "rpc.max-subscriptions-per-connection", alias = "rpc-max-subscriptions-per-connection", default_value_t = DefaultRpcServerArgs::get_global().rpc_max_subscriptions_per_connection)]
544    pub rpc_max_subscriptions_per_connection: MaxU32,
545
546    /// Maximum number of RPC server connections.
547    #[arg(long = "rpc.max-connections", alias = "rpc-max-connections", value_name = "COUNT", default_value_t = DefaultRpcServerArgs::get_global().rpc_max_connections)]
548    pub rpc_max_connections: MaxU32,
549
550    /// Maximum number of concurrent tracing requests.
551    ///
552    /// By default this chooses a sensible value based on the number of available cores.
553    /// Tracing requests are generally CPU bound.
554    /// Choosing a value that is higher than the available CPU cores can have a negative impact on
555    /// the performance of the node and affect the node's ability to maintain sync.
556    #[arg(long = "rpc.max-tracing-requests", alias = "rpc-max-tracing-requests", value_name = "COUNT", default_value_t = DefaultRpcServerArgs::get_global().rpc_max_tracing_requests)]
557    pub rpc_max_tracing_requests: usize,
558
559    /// Maximum number of concurrent blocking IO requests.
560    ///
561    /// Blocking IO requests include `eth_call`, `eth_estimateGas`, and similar methods that
562    /// require EVM execution. These are spawned as blocking tasks to avoid blocking the async
563    /// runtime.
564    #[arg(long = "rpc.max-blocking-io-requests", alias = "rpc-max-blocking-io-requests", value_name = "COUNT", default_value_t = DefaultRpcServerArgs::get_global().rpc_max_blocking_io_requests)]
565    pub rpc_max_blocking_io_requests: usize,
566
567    /// Maximum number of blocks for `trace_filter` requests.
568    #[arg(long = "rpc.max-trace-filter-blocks", alias = "rpc-max-trace-filter-blocks", value_name = "COUNT", default_value_t = DefaultRpcServerArgs::get_global().rpc_max_trace_filter_blocks)]
569    pub rpc_max_trace_filter_blocks: u64,
570
571    /// Maximum number of blocks that could be scanned per filter request. (0 = entire chain)
572    #[arg(long = "rpc.max-blocks-per-filter", alias = "rpc-max-blocks-per-filter", value_name = "COUNT", default_value_t = DefaultRpcServerArgs::get_global().rpc_max_blocks_per_filter)]
573    pub rpc_max_blocks_per_filter: ZeroAsNoneU64,
574
575    /// Maximum number of logs that can be returned in a single response. (0 = no limit)
576    #[arg(long = "rpc.max-logs-per-response", alias = "rpc-max-logs-per-response", value_name = "COUNT", default_value_t = DefaultRpcServerArgs::get_global().rpc_max_logs_per_response)]
577    pub rpc_max_logs_per_response: ZeroAsNoneU64,
578
579    /// Maximum gas limit for `eth_call` and call tracing RPC methods.
580    #[arg(
581        long = "rpc.gascap",
582        alias = "rpc-gascap",
583        value_name = "GAS_CAP",
584        value_parser = MaxOr::new(RangedU64ValueParser::<u64>::new().range(1..)),
585        default_value_t = DefaultRpcServerArgs::get_global().rpc_gas_cap
586    )]
587    pub rpc_gas_cap: u64,
588
589    /// Maximum memory the EVM can allocate per RPC request.
590    #[arg(
591        long = "rpc.evm-memory-limit",
592        alias = "rpc-evm-memory-limit",
593        value_name = "MEMORY_LIMIT",
594        value_parser = MaxOr::new(RangedU64ValueParser::<u64>::new().range(1..)),
595        default_value_t = DefaultRpcServerArgs::get_global().rpc_evm_memory_limit
596    )]
597    pub rpc_evm_memory_limit: u64,
598
599    /// Maximum eth transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)
600    #[arg(
601        long = "rpc.txfeecap",
602        alias = "rpc-txfeecap",
603        value_name = "TX_FEE_CAP",
604        value_parser = parse_ether_value,
605        default_value = "1.0"
606    )]
607    pub rpc_tx_fee_cap: u128,
608
609    /// Maximum number of blocks for `eth_simulateV1` call.
610    #[arg(
611        long = "rpc.max-simulate-blocks",
612        value_name = "BLOCKS_COUNT",
613        default_value_t = DefaultRpcServerArgs::get_global().rpc_max_simulate_blocks
614    )]
615    pub rpc_max_simulate_blocks: u64,
616
617    /// Compute state roots for `eth_simulateV1` responses.
618    #[arg(
619        long = "rpc.compute-state-root-for-eth-simulate",
620        env = "RETH_RPC_COMPUTE_STATE_ROOT_FOR_ETH_SIMULATE",
621        default_value_t = DefaultRpcServerArgs::get_global().rpc_compute_state_root_for_eth_simulate
622    )]
623    pub rpc_compute_state_root_for_eth_simulate: bool,
624
625    /// The maximum proof window for historical proof generation.
626    /// This value allows for generating historical proofs up to
627    /// configured number of blocks from current tip (up to `tip - window`).
628    #[arg(
629        long = "rpc.eth-proof-window",
630        default_value_t = DefaultRpcServerArgs::get_global().rpc_eth_proof_window,
631        value_parser = RangedU64ValueParser::<u64>::new().range(..=constants::MAX_ETH_PROOF_WINDOW)
632    )]
633    pub rpc_eth_proof_window: u64,
634
635    /// Maximum number of concurrent getproof requests.
636    #[arg(long = "rpc.proof-permits", alias = "rpc-proof-permits", value_name = "COUNT", default_value_t = DefaultRpcServerArgs::get_global().rpc_proof_permits)]
637    pub rpc_proof_permits: usize,
638
639    /// Configures the pending block behavior for RPC responses.
640    ///
641    /// Options: full (include all transactions), empty (header only), none (disable pending
642    /// blocks).
643    #[arg(long = "rpc.pending-block", default_value = "full", value_name = "KIND")]
644    pub rpc_pending_block: PendingBlockKind,
645
646    /// Endpoint to forward transactions to.
647    #[arg(long = "rpc.forwarder", alias = "rpc-forwarder", value_name = "FORWARDER")]
648    pub rpc_forwarder: Option<Url>,
649
650    /// Path to file containing disallowed addresses, json-encoded list of strings. Block
651    /// validation API will reject blocks containing transactions from these addresses.
652    #[arg(long = "builder.disallow", value_name = "PATH", value_parser = reth_cli_util::parsers::read_json_from_file::<AddressSet>, default_value = Resettable::from(DefaultRpcServerArgs::get_global().builder_disallow.as_ref().map(|v| format!("{:?}", v).into())))]
653    pub builder_disallow: Option<AddressSet>,
654
655    /// State cache configuration.
656    #[command(flatten)]
657    pub rpc_state_cache: RpcStateCacheArgs,
658
659    /// Gas price oracle configuration.
660    #[command(flatten)]
661    pub gas_price_oracle: GasPriceOracleArgs,
662
663    /// Timeout for `send_raw_transaction_sync` RPC method.
664    #[arg(
665        long = "rpc.send-raw-transaction-sync-timeout",
666        value_name = "SECONDS",
667        default_value = "30s",
668        value_parser = parse_duration_from_secs_or_ms,
669    )]
670    pub rpc_send_raw_transaction_sync_timeout: Duration,
671
672    /// Skip invalid transactions in `testing_buildBlockV1` instead of failing.
673    ///
674    /// When enabled, transactions that fail execution will be skipped, and all subsequent
675    /// transactions from the same sender will also be skipped.
676    #[arg(long = "testing.skip-invalid-transactions", default_value_t = true)]
677    pub testing_skip_invalid_transactions: bool,
678
679    /// Override the gas limit used by `testing_buildBlockV1`.
680    ///
681    /// When set, `testing_buildBlockV1` will use this exact value instead of moving toward the
682    /// payload builder's configured gas limit. Accepts short notation: K for thousand, M for
683    /// million, G for billion (e.g., 1G = 1 billion).
684    #[arg(long = "testing.gas-limit", value_name = "GAS_LIMIT", hide = true)]
685    pub testing_gas_limit: Option<u64>,
686
687    /// Force upcasting EIP-4844 blob sidecars to EIP-7594 format when Osaka is active.
688    ///
689    /// When enabled, blob transactions submitted via `eth_sendRawTransaction` with EIP-4844
690    /// sidecars will be automatically converted to EIP-7594 format if the next block is Osaka.
691    /// By default this is disabled, meaning transactions are submitted as-is.
692    #[arg(long = "rpc.force-blob-sidecar-upcasting", default_value_t = false)]
693    pub rpc_force_blob_sidecar_upcasting: bool,
694}
695
696impl RpcServerArgs {
697    /// Enables the HTTP-RPC server.
698    pub const fn with_http(mut self) -> Self {
699        self.http = true;
700        self
701    }
702
703    /// Configures modules for the HTTP-RPC server.
704    pub fn with_http_api(mut self, http_api: RpcModuleSelection) -> Self {
705        self.http_api = Some(http_api);
706        self
707    }
708
709    /// Enables the WS-RPC server.
710    pub const fn with_ws(mut self) -> Self {
711        self.ws = true;
712        self
713    }
714
715    /// Configures modules for WS-RPC server.
716    pub fn with_ws_api(mut self, ws_api: RpcModuleSelection) -> Self {
717        self.ws_api = Some(ws_api);
718        self
719    }
720
721    /// Enables the Auth IPC
722    pub const fn with_auth_ipc(mut self) -> Self {
723        self.auth_ipc = true;
724        self
725    }
726
727    /// Configures modules for both the HTTP-RPC server and WS-RPC server.
728    ///
729    /// This is the same as calling both [`Self::with_http_api`] and [`Self::with_ws_api`].
730    pub fn with_api(self, api: RpcModuleSelection) -> Self {
731        self.with_http_api(api.clone()).with_ws_api(api)
732    }
733
734    /// Change rpc port numbers based on the instance number, if provided.
735    /// * The `auth_port` is scaled by a factor of `instance * 100`
736    /// * The `http_port` is scaled by a factor of `-instance`
737    /// * The `ws_port` is scaled by a factor of `instance * 2`
738    /// * The `ipcpath` is appended with the instance number: `/tmp/reth.ipc-<instance>`
739    ///
740    /// # Panics
741    /// Warning: if `instance` is zero in debug mode, this will panic.
742    ///
743    /// This will also panic in debug mode if either:
744    /// * `instance` is greater than `655` (scaling would overflow `u16`)
745    /// * `self.auth_port / 100 + (instance - 1)` would overflow `u16`
746    ///
747    /// In release mode, this will silently wrap around.
748    pub fn adjust_instance_ports(&mut self, instance: Option<u16>) {
749        if let Some(instance) = instance {
750            debug_assert_ne!(instance, 0, "instance must be non-zero");
751            // auth port is scaled by a factor of instance * 100
752            self.auth_port += instance * 100 - 100;
753            // http port is scaled by a factor of -instance
754            self.http_port -= instance - 1;
755            // ws port is scaled by a factor of instance * 2
756            self.ws_port += instance * 2 - 2;
757            // append instance file to ipc path
758            self.ipcpath = format!("{}-{}", self.ipcpath, instance);
759        }
760    }
761
762    /// Set the http port to zero, to allow the OS to assign a random unused port when the rpc
763    /// server binds to a socket.
764    pub const fn with_http_unused_port(mut self) -> Self {
765        self.http_port = 0;
766        self
767    }
768
769    /// Set the ws port to zero, to allow the OS to assign a random unused port when the rpc
770    /// server binds to a socket.
771    pub const fn with_ws_unused_port(mut self) -> Self {
772        self.ws_port = 0;
773        self
774    }
775
776    /// Set the auth port to zero, to allow the OS to assign a random unused port when the rpc
777    /// server binds to a socket.
778    pub const fn with_auth_unused_port(mut self) -> Self {
779        self.auth_port = 0;
780        self
781    }
782
783    /// Append a random string to the ipc path, to prevent possible collisions when multiple nodes
784    /// are being run on the same machine.
785    pub fn with_ipc_random_path(mut self) -> Self {
786        let random_string: String =
787            rand::rng().sample_iter(rand::distr::Alphanumeric).take(8).map(char::from).collect();
788        self.ipcpath = format!("{}-{}", self.ipcpath, random_string);
789        self
790    }
791
792    /// Configure all ports to be set to a random unused port when bound, and set the IPC path to a
793    /// random path.
794    pub fn with_unused_ports(mut self) -> Self {
795        self = self.with_http_unused_port();
796        self = self.with_ws_unused_port();
797        self = self.with_auth_unused_port();
798        self = self.with_ipc_random_path();
799        self
800    }
801
802    /// Apply a function to the args.
803    pub fn apply<F>(self, f: F) -> Self
804    where
805        F: FnOnce(Self) -> Self,
806    {
807        f(self)
808    }
809
810    /// Configures the timeout for send raw transaction sync.
811    pub const fn with_send_raw_transaction_sync_timeout(mut self, timeout: Duration) -> Self {
812        self.rpc_send_raw_transaction_sync_timeout = timeout;
813        self
814    }
815
816    /// Returns `true` if the given RPC namespace is enabled on any transport.
817    pub fn is_namespace_enabled(&self, ns: RethRpcModule) -> bool {
818        if self.http && self.http_api.as_ref().is_some_and(|api| api.contains(&ns)) {
819            return true;
820        }
821        if self.ws && self.ws_api.as_ref().is_some_and(|api| api.contains(&ns)) {
822            return true;
823        }
824        // IPC exposes all modules when enabled
825        !self.ipcdisable
826    }
827
828    /// Enables forced blob sidecar upcasting from EIP-4844 to EIP-7594 format.
829    pub const fn with_force_blob_sidecar_upcasting(mut self) -> Self {
830        self.rpc_force_blob_sidecar_upcasting = true;
831        self
832    }
833}
834
835impl Default for RpcServerArgs {
836    fn default() -> Self {
837        let DefaultRpcServerArgs {
838            http,
839            http_addr,
840            http_port,
841            http_disable_compression,
842            http_api,
843            http_corsdomain,
844            ws,
845            ws_addr,
846            ws_port,
847            ws_allowed_origins,
848            ws_api,
849            ipcdisable,
850            ipcpath,
851            ipc_socket_permissions,
852            auth_addr,
853            auth_port,
854            auth_jwtsecret,
855            auth_ipc,
856            auth_ipc_path,
857            disable_auth_server,
858            rpc_jwtsecret,
859            rpc_disable_metrics,
860            rpc_max_request_size,
861            rpc_max_response_size,
862            rpc_max_subscriptions_per_connection,
863            rpc_max_connections,
864            rpc_max_tracing_requests,
865            rpc_max_blocking_io_requests,
866            rpc_max_trace_filter_blocks,
867            rpc_max_blocks_per_filter,
868            rpc_max_logs_per_response,
869            rpc_gas_cap,
870            rpc_evm_memory_limit,
871            rpc_tx_fee_cap,
872            rpc_max_simulate_blocks,
873            rpc_compute_state_root_for_eth_simulate,
874            rpc_eth_proof_window,
875            rpc_proof_permits,
876            rpc_pending_block,
877            rpc_forwarder,
878            builder_disallow,
879            rpc_state_cache,
880            gas_price_oracle,
881            rpc_send_raw_transaction_sync_timeout,
882        } = DefaultRpcServerArgs::get_global().clone();
883        Self {
884            http,
885            http_addr,
886            http_port,
887            http_disable_compression,
888            http_api,
889            http_corsdomain,
890            ws,
891            ws_addr,
892            ws_port,
893            ws_allowed_origins,
894            ws_api,
895            ipcdisable,
896            ipcpath,
897            ipc_socket_permissions,
898            auth_addr,
899            auth_port,
900            auth_jwtsecret,
901            auth_ipc,
902            auth_ipc_path,
903            disable_auth_server,
904            rpc_jwtsecret,
905            rpc_disable_metrics,
906            rpc_max_request_size,
907            rpc_max_response_size,
908            rpc_max_subscriptions_per_connection,
909            rpc_max_connections,
910            rpc_max_tracing_requests,
911            rpc_max_blocking_io_requests,
912            rpc_max_trace_filter_blocks,
913            rpc_max_blocks_per_filter,
914            rpc_max_logs_per_response,
915            rpc_gas_cap,
916            rpc_evm_memory_limit,
917            rpc_tx_fee_cap,
918            rpc_max_simulate_blocks,
919            rpc_compute_state_root_for_eth_simulate,
920            rpc_eth_proof_window,
921            rpc_proof_permits,
922            rpc_pending_block,
923            rpc_forwarder,
924            builder_disallow,
925            rpc_state_cache,
926            gas_price_oracle,
927            rpc_send_raw_transaction_sync_timeout,
928            testing_skip_invalid_transactions: true,
929            testing_gas_limit: None,
930            rpc_force_blob_sidecar_upcasting: false,
931        }
932    }
933}
934
935/// clap value parser for [`RpcModuleSelection`] with configurable validation.
936#[derive(Clone, Debug, Default)]
937#[non_exhaustive]
938struct RpcModuleSelectionValueParser;
939
940impl TypedValueParser for RpcModuleSelectionValueParser {
941    type Value = RpcModuleSelection;
942
943    fn parse_ref(
944        &self,
945        _cmd: &Command,
946        _arg: Option<&Arg>,
947        value: &OsStr,
948    ) -> Result<Self::Value, clap::Error> {
949        let val =
950            value.to_str().ok_or_else(|| clap::Error::new(clap::error::ErrorKind::InvalidUtf8))?;
951        // This will now accept any module name, creating Other(name) for unknowns
952        Ok(val
953            .parse::<RpcModuleSelection>()
954            .expect("RpcModuleSelection parsing cannot fail with Other variant"))
955    }
956
957    fn possible_values(&self) -> Option<Box<dyn Iterator<Item = PossibleValue> + '_>> {
958        // Only show standard modules in help text (excludes "other")
959        let values = RethRpcModule::standard_variant_names().map(PossibleValue::new);
960        Some(Box::new(values))
961    }
962}
963
964#[cfg(test)]
965mod tests {
966    use super::*;
967    use clap::{Args, Parser};
968
969    /// A helper type to parse Args more easily
970    #[derive(Parser)]
971    struct CommandParser<T: Args> {
972        #[command(flatten)]
973        args: T,
974    }
975
976    #[test]
977    fn test_rpc_server_args_parser() {
978        let args =
979            CommandParser::<RpcServerArgs>::parse_from(["reth", "--http.api", "eth,admin,debug"])
980                .args;
981
982        let apis = args.http_api.unwrap();
983        let expected = RpcModuleSelection::try_from_selection(["eth", "admin", "debug"]).unwrap();
984
985        assert_eq!(apis, expected);
986    }
987
988    #[test]
989    fn test_rpc_server_eth_call_bundle_args() {
990        let args =
991            CommandParser::<RpcServerArgs>::parse_from(["reth", "--http.api", "eth,admin,debug"])
992                .args;
993
994        let apis = args.http_api.unwrap();
995        let expected = RpcModuleSelection::try_from_selection(["eth", "admin", "debug"]).unwrap();
996
997        assert_eq!(apis, expected);
998    }
999
1000    #[test]
1001    fn test_rpc_server_args_parser_none() {
1002        let args = CommandParser::<RpcServerArgs>::parse_from(["reth", "--http.api", "none"]).args;
1003        let apis = args.http_api.unwrap();
1004        let expected = RpcModuleSelection::Selection(Default::default());
1005        assert_eq!(apis, expected);
1006    }
1007
1008    #[test]
1009    fn rpc_server_args_default_sanity_test() {
1010        let default_args = RpcServerArgs::default();
1011        let args = CommandParser::<RpcServerArgs>::parse_from(["reth"]).args;
1012
1013        assert_eq!(args, default_args);
1014    }
1015
1016    #[test]
1017    fn test_rpc_disable_metrics_arg() {
1018        let args = CommandParser::<RpcServerArgs>::parse_from(["reth"]).args;
1019        assert!(!args.rpc_disable_metrics);
1020
1021        let args =
1022            CommandParser::<RpcServerArgs>::parse_from(["reth", "--rpc.disable-metrics"]).args;
1023        assert!(args.rpc_disable_metrics);
1024    }
1025
1026    #[test]
1027    fn test_rpc_tx_fee_cap_parse_integer() {
1028        let args = CommandParser::<RpcServerArgs>::parse_from(["reth", "--rpc.txfeecap", "2"]).args;
1029        let expected = 2_000_000_000_000_000_000u128; // 2 ETH in wei
1030        assert_eq!(args.rpc_tx_fee_cap, expected);
1031    }
1032
1033    #[test]
1034    fn test_rpc_tx_fee_cap_parse_decimal() {
1035        let args =
1036            CommandParser::<RpcServerArgs>::parse_from(["reth", "--rpc.txfeecap", "1.5"]).args;
1037        let expected = 1_500_000_000_000_000_000u128; // 1.5 ETH in wei
1038        assert_eq!(args.rpc_tx_fee_cap, expected);
1039    }
1040
1041    #[test]
1042    fn test_rpc_tx_fee_cap_parse_zero() {
1043        let args = CommandParser::<RpcServerArgs>::parse_from(["reth", "--rpc.txfeecap", "0"]).args;
1044        assert_eq!(args.rpc_tx_fee_cap, 0); // 0 = no cap
1045    }
1046
1047    #[test]
1048    fn test_rpc_tx_fee_cap_parse_none() {
1049        let args = CommandParser::<RpcServerArgs>::parse_from(["reth"]).args;
1050        let expected = 1_000_000_000_000_000_000u128;
1051        assert_eq!(args.rpc_tx_fee_cap, expected); // 1 ETH default cap
1052    }
1053
1054    #[test]
1055    fn test_rpc_server_args() {
1056        let args = RpcServerArgs {
1057            http: true,
1058            http_addr: "127.0.0.1".parse().unwrap(),
1059            http_port: 8545,
1060            http_disable_compression: false,
1061            http_api: Some(RpcModuleSelection::try_from_selection(["eth", "admin"]).unwrap()),
1062            http_corsdomain: Some("*".to_string()),
1063            ws: true,
1064            ws_addr: "127.0.0.1".parse().unwrap(),
1065            ws_port: 8546,
1066            ws_allowed_origins: Some("*".to_string()),
1067            ws_api: Some(RpcModuleSelection::try_from_selection(["eth", "admin"]).unwrap()),
1068            ipcdisable: false,
1069            ipcpath: "reth.ipc".to_string(),
1070            ipc_socket_permissions: Some("0o666".to_string()),
1071            auth_addr: "127.0.0.1".parse().unwrap(),
1072            auth_port: 8551,
1073            auth_jwtsecret: Some(std::path::PathBuf::from("/tmp/jwt.hex")),
1074            auth_ipc: false,
1075            auth_ipc_path: "engine.ipc".to_string(),
1076            disable_auth_server: false,
1077            rpc_jwtsecret: Some(
1078                JwtSecret::from_hex(
1079                    "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
1080                )
1081                .unwrap(),
1082            ),
1083            rpc_disable_metrics: false,
1084            rpc_max_request_size: 15u32.into(),
1085            rpc_max_response_size: 160u32.into(),
1086            rpc_max_subscriptions_per_connection: 1024u32.into(),
1087            rpc_max_connections: 500u32.into(),
1088            rpc_max_tracing_requests: 16,
1089            rpc_max_blocking_io_requests: 256,
1090            rpc_max_trace_filter_blocks: 4000,
1091            rpc_max_blocks_per_filter: 1000u64.into(),
1092            rpc_max_logs_per_response: 10000u64.into(),
1093            rpc_gas_cap: 50_000_000,
1094            rpc_evm_memory_limit: 256,
1095            rpc_tx_fee_cap: 2_000_000_000_000_000_000u128,
1096            rpc_max_simulate_blocks: 256,
1097            rpc_compute_state_root_for_eth_simulate: false,
1098            rpc_eth_proof_window: 100_000,
1099            rpc_proof_permits: 16,
1100            rpc_pending_block: PendingBlockKind::Full,
1101            rpc_forwarder: Some("http://localhost:8545".parse().unwrap()),
1102            builder_disallow: None,
1103            rpc_state_cache: RpcStateCacheArgs {
1104                max_blocks: 5000,
1105                max_receipts: 2000,
1106                max_headers: 1000,
1107                max_bals: 1000,
1108                max_concurrent_db_requests: 512,
1109                max_cached_tx_hashes: 30_000,
1110            },
1111            gas_price_oracle: GasPriceOracleArgs {
1112                blocks: 20,
1113                ignore_price: 2,
1114                max_price: 500_000_000_000,
1115                percentile: 60,
1116                default_suggested_fee: None,
1117            },
1118            rpc_send_raw_transaction_sync_timeout: std::time::Duration::from_secs(30),
1119            testing_skip_invalid_transactions: true,
1120            testing_gas_limit: None,
1121            rpc_force_blob_sidecar_upcasting: false,
1122        };
1123
1124        let parsed_args = CommandParser::<RpcServerArgs>::parse_from([
1125            "reth",
1126            "--http",
1127            "--http.addr",
1128            "127.0.0.1",
1129            "--http.port",
1130            "8545",
1131            "--http.api",
1132            "eth,admin",
1133            "--http.corsdomain",
1134            "*",
1135            "--ws",
1136            "--ws.addr",
1137            "127.0.0.1",
1138            "--ws.port",
1139            "8546",
1140            "--ws.origins",
1141            "*",
1142            "--ws.api",
1143            "eth,admin",
1144            "--ipcpath",
1145            "reth.ipc",
1146            "--ipc.permissions",
1147            "0o666",
1148            "--authrpc.addr",
1149            "127.0.0.1",
1150            "--authrpc.port",
1151            "8551",
1152            "--authrpc.jwtsecret",
1153            "/tmp/jwt.hex",
1154            "--auth-ipc.path",
1155            "engine.ipc",
1156            "--rpc.jwtsecret",
1157            "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
1158            "--rpc.max-request-size",
1159            "15",
1160            "--rpc.max-response-size",
1161            "160",
1162            "--rpc.max-subscriptions-per-connection",
1163            "1024",
1164            "--rpc.max-connections",
1165            "500",
1166            "--rpc.max-tracing-requests",
1167            "16",
1168            "--rpc.max-blocking-io-requests",
1169            "256",
1170            "--rpc.max-trace-filter-blocks",
1171            "4000",
1172            "--rpc.max-blocks-per-filter",
1173            "1000",
1174            "--rpc.max-logs-per-response",
1175            "10000",
1176            "--rpc.gascap",
1177            "50000000",
1178            "--rpc.evm-memory-limit",
1179            "256",
1180            "--rpc.txfeecap",
1181            "2.0",
1182            "--rpc.max-simulate-blocks",
1183            "256",
1184            "--rpc.eth-proof-window",
1185            "100000",
1186            "--rpc.proof-permits",
1187            "16",
1188            "--rpc.pending-block",
1189            "full",
1190            "--rpc.forwarder",
1191            "http://localhost:8545",
1192            "--rpc-cache.max-blocks",
1193            "5000",
1194            "--rpc-cache.max-receipts",
1195            "2000",
1196            "--rpc-cache.max-headers",
1197            "1000",
1198            "--rpc-cache.max-bals",
1199            "1000",
1200            "--rpc-cache.max-concurrent-db-requests",
1201            "512",
1202            "--gpo.blocks",
1203            "20",
1204            "--gpo.ignoreprice",
1205            "2",
1206            "--gpo.maxprice",
1207            "500000000000",
1208            "--gpo.percentile",
1209            "60",
1210            "--rpc.send-raw-transaction-sync-timeout",
1211            "30s",
1212            "--testing.skip-invalid-transactions",
1213        ])
1214        .args;
1215
1216        assert_eq!(parsed_args, args);
1217    }
1218}