From 8c645d57628e6df3c842b024ec642d86bbe428a8 Mon Sep 17 00:00:00 2001 From: Georgios Konstantopoulos Date: Wed, 21 Jan 2026 13:04:10 -0800 Subject: [PATCH] feat(reth-bench): accept short notation for --target-gas-limit (#21273) --- bin/reth-bench/src/bench/gas_limit_ramp.rs | 74 +++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/bin/reth-bench/src/bench/gas_limit_ramp.rs b/bin/reth-bench/src/bench/gas_limit_ramp.rs index 7c9e894ea3..3a969d17cb 100644 --- a/bin/reth-bench/src/bench/gas_limit_ramp.rs +++ b/bin/reth-bench/src/bench/gas_limit_ramp.rs @@ -22,6 +22,29 @@ use reth_primitives_traits::constants::{GAS_LIMIT_BOUND_DIVISOR, MAXIMUM_GAS_LIM use std::{path::PathBuf, time::Instant}; use tracing::info; +/// Parses a gas limit value with optional suffix: K for thousand, M for million, G for billion. +/// +/// Examples: "30000000", "30M", "1G", "2G" +fn parse_gas_limit(s: &str) -> eyre::Result { + let s = s.trim(); + if s.is_empty() { + return Err(eyre::eyre!("empty value")); + } + + let (num_str, multiplier) = if let Some(prefix) = s.strip_suffix(['G', 'g']) { + (prefix, 1_000_000_000u64) + } else if let Some(prefix) = s.strip_suffix(['M', 'm']) { + (prefix, 1_000_000u64) + } else if let Some(prefix) = s.strip_suffix(['K', 'k']) { + (prefix, 1_000u64) + } else { + (s, 1u64) + }; + + let base: u64 = num_str.trim().parse()?; + base.checked_mul(multiplier).ok_or_else(|| eyre::eyre!("value overflow")) +} + /// `reth benchmark gas-limit-ramp` command. #[derive(Debug, Parser)] pub struct Command { @@ -31,7 +54,9 @@ pub struct Command { /// Target gas limit to ramp up to. The benchmark will generate blocks until the gas limit /// reaches or exceeds this value. Mutually exclusive with --blocks. - #[arg(long, value_name = "TARGET_GAS_LIMIT", conflicts_with = "blocks")] + /// Accepts short notation: K for thousand, M for million, G for billion (e.g., 2G = 2 + /// billion). + #[arg(long, value_name = "TARGET_GAS_LIMIT", conflicts_with = "blocks", value_parser = parse_gas_limit)] target_gas_limit: Option, /// The Engine API RPC URL. @@ -212,3 +237,50 @@ const fn should_stop(mode: RampMode, blocks_processed: u64, current_gas_limit: u RampMode::TargetGasLimit(target) => current_gas_limit >= target, } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse_gas_limit_plain_number() { + assert_eq!(parse_gas_limit("30000000").unwrap(), 30_000_000); + assert_eq!(parse_gas_limit("1").unwrap(), 1); + assert_eq!(parse_gas_limit("0").unwrap(), 0); + } + + #[test] + fn test_parse_gas_limit_k_suffix() { + assert_eq!(parse_gas_limit("1K").unwrap(), 1_000); + assert_eq!(parse_gas_limit("30k").unwrap(), 30_000); + assert_eq!(parse_gas_limit("100K").unwrap(), 100_000); + } + + #[test] + fn test_parse_gas_limit_m_suffix() { + assert_eq!(parse_gas_limit("1M").unwrap(), 1_000_000); + assert_eq!(parse_gas_limit("30m").unwrap(), 30_000_000); + assert_eq!(parse_gas_limit("100M").unwrap(), 100_000_000); + } + + #[test] + fn test_parse_gas_limit_g_suffix() { + assert_eq!(parse_gas_limit("1G").unwrap(), 1_000_000_000); + assert_eq!(parse_gas_limit("2g").unwrap(), 2_000_000_000); + assert_eq!(parse_gas_limit("10G").unwrap(), 10_000_000_000); + } + + #[test] + fn test_parse_gas_limit_with_whitespace() { + assert_eq!(parse_gas_limit(" 1G ").unwrap(), 1_000_000_000); + assert_eq!(parse_gas_limit("2 M").unwrap(), 2_000_000); + } + + #[test] + fn test_parse_gas_limit_errors() { + assert!(parse_gas_limit("").is_err()); + assert!(parse_gas_limit("abc").is_err()); + assert!(parse_gas_limit("G").is_err()); + assert!(parse_gas_limit("-1G").is_err()); + } +}