diff --git a/bin/reth/src/args/gas_price_oracle_args.rs b/bin/reth/src/args/gas_price_oracle_args.rs new file mode 100644 index 0000000000..4c09903637 --- /dev/null +++ b/bin/reth/src/args/gas_price_oracle_args.rs @@ -0,0 +1,49 @@ +use clap::Args; + +/// Parameters to configure Gas Price Oracle +#[derive(Debug, Args, PartialEq, Eq, Default)] +#[command(next_help_heading = "GAS PRICE ORACLE")] +pub struct GasPriceOracleArgs { + /// Number of recent blocks to check for gas price + #[arg(long = "gpo.blocks", default_value = "20")] + pub blocks: Option, + + /// Gas Price below which gpo will ignore transactions + #[arg(long = "gpo.ignoreprice", default_value = "2")] + pub ignore_price: Option, + + /// Maximum transaction priority fee(or gasprice before London Fork) to be recommended by gpo + #[arg(long = "gpo.maxprice", default_value = "500000000000")] + pub max_price: Option, + + /// The percentile of gas prices to use for the estimate + #[arg(long = "gpo.percentile", default_value = "60")] + pub percentile: Option, +} + +#[cfg(test)] +mod tests { + use super::*; + use clap::Parser; + + /// A helper type to parse Args more easily + #[derive(Parser)] + struct CommandParser { + #[clap(flatten)] + args: T, + } + + #[test] + fn test_parse_gpo_args() { + let args = CommandParser::::parse_from(["reth"]).args; + assert_eq!( + args, + GasPriceOracleArgs { + blocks: Some(20), + ignore_price: Some(2), + max_price: Some(500000000000), + percentile: Some(60), + } + ); + } +} diff --git a/bin/reth/src/args/mod.rs b/bin/reth/src/args/mod.rs index 021bc8d37e..30b7066e6d 100644 --- a/bin/reth/src/args/mod.rs +++ b/bin/reth/src/args/mod.rs @@ -22,3 +22,6 @@ pub use payload_build_args::PayloadBuilderArgs; /// Stage related arguments mod stage_args; pub use stage_args::StageEnum; + +mod gas_price_oracle_args; +pub use gas_price_oracle_args::GasPriceOracleArgs; diff --git a/bin/reth/src/args/rpc_server_args.rs b/bin/reth/src/args/rpc_server_args.rs index 284ab1e726..4c67e548bb 100644 --- a/bin/reth/src/args/rpc_server_args.rs +++ b/bin/reth/src/args/rpc_server_args.rs @@ -1,5 +1,6 @@ //! clap [Args](clap::Args) for RPC related arguments. +use crate::args::GasPriceOracleArgs; use clap::{ builder::{PossibleValue, TypedValueParser}, Arg, Args, Command, @@ -10,13 +11,13 @@ use reth_provider::{ BlockProviderIdExt, CanonStateSubscriptions, EvmEnvProvider, HeaderProvider, StateProviderFactory, }; -use reth_rpc::{JwtError, JwtSecret}; +use reth_rpc::{eth::gas_oracle::GasPriceOracleConfig, JwtError, JwtSecret}; use reth_rpc_builder::{ auth::{AuthServerConfig, AuthServerHandle}, constants, error::RpcError, - IpcServerBuilder, RethRpcModule, RpcModuleBuilder, RpcModuleSelection, RpcServerConfig, - RpcServerHandle, ServerBuilder, TransportRpcModuleConfig, + EthConfig, IpcServerBuilder, RethRpcModule, RpcModuleBuilder, RpcModuleConfig, + RpcModuleSelection, RpcServerConfig, RpcServerHandle, ServerBuilder, TransportRpcModuleConfig, }; use reth_rpc_engine_api::{EngineApi, EngineApiServer}; use reth_tasks::TaskSpawner; @@ -38,8 +39,8 @@ pub(crate) const RPC_DEFAULT_MAX_RESPONSE_SIZE_MB: u32 = 25; pub(crate) const RPC_DEFAULT_MAX_CONNECTIONS: u32 = 100; /// Parameters for configuring the rpc more granularity via CLI -#[derive(Debug, Args, PartialEq, Default)] -#[command(next_help_heading = "Rpc")] +#[derive(Debug, Args, PartialEq, Eq, Default)] +#[command(next_help_heading = "RPC")] pub struct RpcServerArgs { /// Enable the HTTP-RPC server #[arg(long)] @@ -116,6 +117,10 @@ pub struct RpcServerArgs { /// Maximum number of RPC server connections. #[arg(long, value_name = "COUNT", default_value_t = RPC_DEFAULT_MAX_CONNECTIONS)] pub rpc_max_connections: u32, + + /// Gas price oracle configuration. + #[clap(flatten)] + pub gas_price_oracle: GasPriceOracleArgs, } impl RpcServerArgs { @@ -129,6 +134,21 @@ impl RpcServerArgs { self.rpc_max_response_size * 1024 * 1024 } + /// Extracts the gas price oracle config from the args. + pub fn gas_price_oracle_config(&self) -> GasPriceOracleConfig { + GasPriceOracleConfig::new( + self.gas_price_oracle.blocks, + self.gas_price_oracle.ignore_price, + self.gas_price_oracle.max_price, + self.gas_price_oracle.percentile, + ) + } + + /// Extracts the [EthConfig] from the args. + pub fn eth_config(&self) -> EthConfig { + EthConfig::default().with_gpo_config(self.gas_price_oracle_config()) + } + /// The execution layer and consensus layer clients SHOULD accept a configuration parameter: /// jwt-secret, which designates a file containing the hex-encoded 256 bit secret key to be used /// for verifying/generating JWT tokens. @@ -293,8 +313,12 @@ impl RpcServerArgs { } /// Creates the [TransportRpcModuleConfig] from cli args. + /// + /// This sets all the api modules, and configures additional settings like gas price oracle + /// settings in the [TransportRpcModuleConfig]. fn transport_rpc_module_config(&self) -> TransportRpcModuleConfig { - let mut config = TransportRpcModuleConfig::default(); + let mut config = TransportRpcModuleConfig::default() + .with_config(RpcModuleConfig::new(self.eth_config())); let rpc_modules = RpcModuleSelection::Selection(vec![RethRpcModule::Admin, RethRpcModule::Eth]); if self.http { @@ -304,7 +328,6 @@ impl RpcServerArgs { if self.ws { config = config.with_ws(self.ws_api.as_ref().unwrap_or(&rpc_modules).clone()); } - config } diff --git a/crates/rpc/rpc-builder/src/eth.rs b/crates/rpc/rpc-builder/src/eth.rs index 90f2cda17f..c0377f791e 100644 --- a/crates/rpc/rpc-builder/src/eth.rs +++ b/crates/rpc/rpc-builder/src/eth.rs @@ -46,3 +46,11 @@ impl Default for EthConfig { } } } + +impl EthConfig { + /// Configures the gas price oracle settings + pub fn with_gpo_config(mut self, gas_oracle_config: GasPriceOracleConfig) -> Self { + self.gas_oracle = gas_oracle_config; + self + } +} diff --git a/crates/rpc/rpc-builder/src/lib.rs b/crates/rpc/rpc-builder/src/lib.rs index d0391459ca..a785029446 100644 --- a/crates/rpc/rpc-builder/src/lib.rs +++ b/crates/rpc/rpc-builder/src/lib.rs @@ -349,6 +349,10 @@ impl RpcModuleConfig { pub fn builder() -> RpcModuleConfigBuilder { RpcModuleConfigBuilder::default() } + /// Returns a new RPC module config given the eth namespace config + pub fn new(eth: EthConfig) -> Self { + Self { eth } + } } /// Configures [RpcModuleConfig] diff --git a/crates/rpc/rpc/src/eth/gas_oracle.rs b/crates/rpc/rpc/src/eth/gas_oracle.rs index 3e21513211..9d18493e14 100644 --- a/crates/rpc/rpc/src/eth/gas_oracle.rs +++ b/crates/rpc/rpc/src/eth/gas_oracle.rs @@ -59,6 +59,26 @@ impl Default for GasPriceOracleConfig { } } +impl GasPriceOracleConfig { + /// Creating a new gpo config with blocks, ignoreprice, maxprice and percentile + pub fn new( + blocks: Option, + ignore_price: Option, + max_price: Option, + percentile: Option, + ) -> Self { + Self { + blocks: blocks.unwrap_or(20), + percentile: percentile.unwrap_or(60), + max_header_history: 1024, + max_block_history: 1024, + default: None, + max_price: max_price.map(U256::from).or(Some(DEFAULT_MAX_PRICE)), + ignore_price: ignore_price.map(U256::from).or(Some(DEFAULT_IGNORE_PRICE)), + } + } +} + /// Calculates a gas price depending on recent blocks. #[derive(Debug)] pub struct GasPriceOracle {