mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-02-19 03:04:27 -05:00
fix(cli): store extradata as Bytes, decode hex in parser (#22344)
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
committed by
GitHub
parent
8fa539225b
commit
8529da976f
@@ -55,7 +55,7 @@ where
|
||||
EthereumBuilderConfig::new()
|
||||
.with_gas_limit(gas_limit)
|
||||
.with_max_blobs_per_block(conf.max_blobs_per_block())
|
||||
.with_extra_data(conf.extra_data_bytes()),
|
||||
.with_extra_data(conf.extra_data()),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::{cli::config::PayloadBuilderConfig, version::default_extra_data};
|
||||
use alloy_consensus::constants::MAXIMUM_EXTRA_DATA_SIZE;
|
||||
use alloy_primitives::Bytes;
|
||||
use clap::{
|
||||
builder::{RangedU64ValueParser, TypedValueParser},
|
||||
Arg, Args, Command,
|
||||
@@ -8,7 +9,7 @@ use reth_cli_util::{
|
||||
parse_duration_from_secs, parse_duration_from_secs_or_ms,
|
||||
parsers::format_duration_as_secs_or_ms,
|
||||
};
|
||||
use std::{borrow::Cow, ffi::OsStr, sync::OnceLock, time::Duration};
|
||||
use std::{ffi::OsStr, sync::OnceLock, time::Duration};
|
||||
|
||||
/// Global static payload builder defaults
|
||||
static PAYLOAD_BUILDER_DEFAULTS: OnceLock<DefaultPayloadBuilderValues> = OnceLock::new();
|
||||
@@ -80,12 +81,15 @@ impl Default for DefaultPayloadBuilderValues {
|
||||
#[command(next_help_heading = "Builder")]
|
||||
pub struct PayloadBuilderArgs {
|
||||
/// Block extra data set by the payload builder.
|
||||
///
|
||||
/// If the value is a `0x`-prefixed hex string, it is decoded into raw bytes. Otherwise, the
|
||||
/// raw UTF-8 bytes of the string are used.
|
||||
#[arg(
|
||||
long = "builder.extradata",
|
||||
value_parser = ExtraDataValueParser::default(),
|
||||
default_value_t = DefaultPayloadBuilderValues::get_global().extra_data.clone()
|
||||
default_value = DefaultPayloadBuilderValues::get_global().extra_data.as_str()
|
||||
)]
|
||||
pub extra_data: String,
|
||||
pub extra_data: Bytes,
|
||||
|
||||
/// Target gas limit for built blocks.
|
||||
#[arg(long = "builder.gaslimit", alias = "miner.gaslimit", value_name = "GAS_LIMIT")]
|
||||
@@ -130,7 +134,7 @@ impl Default for PayloadBuilderArgs {
|
||||
fn default() -> Self {
|
||||
let defaults = DefaultPayloadBuilderValues::get_global();
|
||||
Self {
|
||||
extra_data: defaults.extra_data.clone(),
|
||||
extra_data: Bytes::from(defaults.extra_data.as_bytes().to_vec()),
|
||||
interval: parse_duration_from_secs_or_ms(defaults.interval.as_str()).unwrap(),
|
||||
gas_limit: None,
|
||||
deadline: Duration::from_secs(defaults.deadline.parse().unwrap()),
|
||||
@@ -141,8 +145,8 @@ impl Default for PayloadBuilderArgs {
|
||||
}
|
||||
|
||||
impl PayloadBuilderConfig for PayloadBuilderArgs {
|
||||
fn extra_data(&self) -> Cow<'_, str> {
|
||||
self.extra_data.as_str().into()
|
||||
fn extra_data(&self) -> Bytes {
|
||||
self.extra_data.clone()
|
||||
}
|
||||
|
||||
fn interval(&self) -> Duration {
|
||||
@@ -171,7 +175,7 @@ impl PayloadBuilderConfig for PayloadBuilderArgs {
|
||||
struct ExtraDataValueParser;
|
||||
|
||||
impl TypedValueParser for ExtraDataValueParser {
|
||||
type Value = String;
|
||||
type Value = Bytes;
|
||||
|
||||
fn parse_ref(
|
||||
&self,
|
||||
@@ -181,7 +185,19 @@ impl TypedValueParser for ExtraDataValueParser {
|
||||
) -> Result<Self::Value, clap::Error> {
|
||||
let val =
|
||||
value.to_str().ok_or_else(|| clap::Error::new(clap::error::ErrorKind::InvalidUtf8))?;
|
||||
if val.len() > MAXIMUM_EXTRA_DATA_SIZE {
|
||||
|
||||
let bytes = if let Some(hex) = val.strip_prefix("0x") {
|
||||
alloy_primitives::hex::decode(hex).map_err(|e| {
|
||||
clap::Error::raw(
|
||||
clap::error::ErrorKind::InvalidValue,
|
||||
format!("Invalid hex in extradata: {e}"),
|
||||
)
|
||||
})?
|
||||
} else {
|
||||
val.as_bytes().to_vec()
|
||||
};
|
||||
|
||||
if bytes.len() > MAXIMUM_EXTRA_DATA_SIZE {
|
||||
return Err(clap::Error::raw(
|
||||
clap::error::ErrorKind::InvalidValue,
|
||||
format!(
|
||||
@@ -189,7 +205,8 @@ impl TypedValueParser for ExtraDataValueParser {
|
||||
),
|
||||
))
|
||||
}
|
||||
Ok(val.to_string())
|
||||
|
||||
Ok(bytes.into())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,7 +249,7 @@ mod tests {
|
||||
extra_data.as_str(),
|
||||
])
|
||||
.args;
|
||||
assert_eq!(args.extra_data, extra_data);
|
||||
assert_eq!(args.extra_data.as_ref(), extra_data.as_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -246,6 +263,49 @@ mod tests {
|
||||
assert!(args.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_valid_hex_extra_data() {
|
||||
let hex = format!("0x{}", "ab".repeat(MAXIMUM_EXTRA_DATA_SIZE));
|
||||
let args = CommandParser::<PayloadBuilderArgs>::parse_from([
|
||||
"reth",
|
||||
"--builder.extradata",
|
||||
hex.as_str(),
|
||||
])
|
||||
.args;
|
||||
assert_eq!(args.extra_data.as_ref(), vec![0xab; MAXIMUM_EXTRA_DATA_SIZE].as_slice());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_oversized_hex_extra_data() {
|
||||
let hex = format!("0x{}", "ab".repeat(MAXIMUM_EXTRA_DATA_SIZE + 1));
|
||||
assert!(CommandParser::<PayloadBuilderArgs>::try_parse_from([
|
||||
"reth",
|
||||
"--builder.extradata",
|
||||
hex.as_str(),
|
||||
])
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_hex_extra_data() {
|
||||
assert!(CommandParser::<PayloadBuilderArgs>::try_parse_from([
|
||||
"reth",
|
||||
"--builder.extradata",
|
||||
"0xZZZZ",
|
||||
])
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_odd_length_hex_extra_data() {
|
||||
assert!(CommandParser::<PayloadBuilderArgs>::try_parse_from([
|
||||
"reth",
|
||||
"--builder.extradata",
|
||||
"0xabc",
|
||||
])
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn payload_builder_args_default_sanity_check() {
|
||||
let default_args = PayloadBuilderArgs::default();
|
||||
|
||||
@@ -5,7 +5,7 @@ use alloy_primitives::Bytes;
|
||||
use reth_chainspec::{Chain, ChainKind, NamedChain};
|
||||
use reth_network::{protocol::IntoRlpxSubProtocol, NetworkPrimitives};
|
||||
use reth_transaction_pool::PoolConfig;
|
||||
use std::{borrow::Cow, time::Duration};
|
||||
use std::time::Duration;
|
||||
|
||||
/// 60M gas limit
|
||||
const ETHEREUM_BLOCK_GAS_LIMIT_60M: u64 = 60_000_000;
|
||||
@@ -15,13 +15,8 @@ const ETHEREUM_BLOCK_GAS_LIMIT_60M: u64 = 60_000_000;
|
||||
/// This provides all basic payload builder settings and is implemented by the
|
||||
/// [`PayloadBuilderArgs`](crate::args::PayloadBuilderArgs) type.
|
||||
pub trait PayloadBuilderConfig {
|
||||
/// Block extra data set by the payload builder.
|
||||
fn extra_data(&self) -> Cow<'_, str>;
|
||||
|
||||
/// Returns the extra data as bytes.
|
||||
fn extra_data_bytes(&self) -> Bytes {
|
||||
self.extra_data().as_bytes().to_vec().into()
|
||||
}
|
||||
fn extra_data(&self) -> Bytes;
|
||||
|
||||
/// The interval at which the job should build a new payload after the last.
|
||||
fn interval(&self) -> Duration;
|
||||
|
||||
@@ -685,7 +685,9 @@ TxPool:
|
||||
|
||||
Builder:
|
||||
--builder.extradata <EXTRA_DATA>
|
||||
Block extra data set by the payload builder
|
||||
Block extra data set by the payload builder.
|
||||
|
||||
If the value is a `0x`-prefixed hex string, it is decoded into raw bytes. Otherwise, the raw UTF-8 bytes of the string are used.
|
||||
|
||||
[default: reth/<VERSION>/<OS>]
|
||||
|
||||
|
||||
@@ -339,7 +339,7 @@ where
|
||||
pool,
|
||||
evm_config,
|
||||
EthereumBuilderConfig::new()
|
||||
.with_extra_data(ctx.payload_builder_config().extra_data_bytes()),
|
||||
.with_extra_data(ctx.payload_builder_config().extra_data()),
|
||||
),
|
||||
};
|
||||
Ok(payload_builder)
|
||||
|
||||
@@ -62,8 +62,7 @@ where
|
||||
ctx.provider().clone(),
|
||||
pool,
|
||||
evm_config,
|
||||
EthereumBuilderConfig::new()
|
||||
.with_extra_data(ctx.payload_builder_config().extra_data_bytes()),
|
||||
EthereumBuilderConfig::new().with_extra_data(ctx.payload_builder_config().extra_data()),
|
||||
);
|
||||
|
||||
let conf = ctx.payload_builder_config();
|
||||
|
||||
Reference in New Issue
Block a user