From f77d7d59833018ab165b03e87f8fed2ba55b6e1c Mon Sep 17 00:00:00 2001 From: Georgios Konstantopoulos Date: Fri, 23 Jan 2026 06:24:34 -0800 Subject: [PATCH] feat(reth-bench): support human-readable gas format in generate-big-block (#21361) --- bin/reth-bench/src/bench/gas_limit_ramp.rs | 72 +------------------ .../src/bench/generate_big_block.rs | 8 ++- bin/reth-bench/src/bench/helpers.rs | 70 ++++++++++++++++++ 3 files changed, 77 insertions(+), 73 deletions(-) diff --git a/bin/reth-bench/src/bench/gas_limit_ramp.rs b/bin/reth-bench/src/bench/gas_limit_ramp.rs index 3a969d17cb..7712683583 100644 --- a/bin/reth-bench/src/bench/gas_limit_ramp.rs +++ b/bin/reth-bench/src/bench/gas_limit_ramp.rs @@ -3,7 +3,7 @@ use crate::{ authenticated_transport::AuthenticatedTransportConnect, bench::{ - helpers::{build_payload, prepare_payload_request, rpc_block_to_header}, + helpers::{build_payload, parse_gas_limit, prepare_payload_request, rpc_block_to_header}, output::GasRampPayloadFile, }, valid_payload::{call_forkchoice_updated, call_new_payload, payload_to_new_payload}, @@ -22,29 +22,6 @@ 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 { @@ -237,50 +214,3 @@ 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()); - } -} diff --git a/bin/reth-bench/src/bench/generate_big_block.rs b/bin/reth-bench/src/bench/generate_big_block.rs index 7ddab1125e..f237bfd47a 100644 --- a/bin/reth-bench/src/bench/generate_big_block.rs +++ b/bin/reth-bench/src/bench/generate_big_block.rs @@ -3,7 +3,9 @@ //! This command fetches transactions from existing blocks and packs them into a single //! large block using the `testing_buildBlockV1` RPC endpoint. -use crate::authenticated_transport::AuthenticatedTransportConnect; +use crate::{ + authenticated_transport::AuthenticatedTransportConnect, bench::helpers::parse_gas_limit, +}; use alloy_eips::{BlockNumberOrTag, Typed2718}; use alloy_primitives::{Bytes, B256}; use alloy_provider::{ext::EngineApi, network::AnyNetwork, Provider, RootProvider}; @@ -202,7 +204,9 @@ pub struct Command { jwt_secret: std::path::PathBuf, /// Target gas to pack into the block. - #[arg(long, value_name = "TARGET_GAS", default_value = "30000000")] + /// Accepts short notation: K for thousand, M for million, G for billion (e.g., 1G = 1 + /// billion). + #[arg(long, value_name = "TARGET_GAS", default_value = "30000000", value_parser = parse_gas_limit)] target_gas: u64, /// Starting block number to fetch transactions from. diff --git a/bin/reth-bench/src/bench/helpers.rs b/bin/reth-bench/src/bench/helpers.rs index f367fd69a1..cb78d1c4e3 100644 --- a/bin/reth-bench/src/bench/helpers.rs +++ b/bin/reth-bench/src/bench/helpers.rs @@ -1,6 +1,29 @@ //! Common helpers for reth-bench commands. use crate::valid_payload::call_forkchoice_updated; + +/// Parses a gas limit value with optional suffix: K for thousand, M for million, G for billion. +/// +/// Examples: "30000000", "30M", "1G", "2G" +pub(crate) 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")) +} use alloy_consensus::Header; use alloy_eips::eip4844::kzg_to_versioned_hash; use alloy_primitives::{Address, B256}; @@ -194,3 +217,50 @@ pub(crate) async fn get_payload_with_sidecar( _ => panic!("This tool does not support getPayload versions past v5"), } } + +#[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()); + } +}