Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions crates/cli/util/src/parsers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ pub fn parse_duration_from_secs_or_ms(
}
}

/// Helper to format a [Duration] to the format that can be parsed by
/// [`parse_duration_from_secs_or_ms`].
pub fn format_duration_as_secs_or_ms(duration: Duration) -> String {
if duration.as_millis().is_multiple_of(1000) {
format!("{}", duration.as_secs())
} else {
format!("{}ms", duration.as_millis())
}
}

/// Parse [`BlockHashOrNumber`]
pub fn hash_or_num_value_parser(value: &str) -> eyre::Result<BlockHashOrNumber, eyre::Error> {
match B256::from_str(value) {
Expand Down
2 changes: 1 addition & 1 deletion crates/node/core/src/args/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub use metric::MetricArgs;

/// `PayloadBuilderArgs` struct for configuring the payload builder
mod payload_builder;
pub use payload_builder::PayloadBuilderArgs;
pub use payload_builder::{DefaultPayloadBuilderValues, PayloadBuilderArgs};

/// Stage related arguments
mod stage;
Expand Down
108 changes: 97 additions & 11 deletions crates/node/core/src/args/payload_builder.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,90 @@
use crate::{cli::config::PayloadBuilderConfig, version::default_extra_data};
use alloy_consensus::constants::MAXIMUM_EXTRA_DATA_SIZE;
use alloy_eips::merge::SLOT_DURATION;
use clap::{
builder::{RangedU64ValueParser, TypedValueParser},
Arg, Args, Command,
};
use reth_cli_util::{parse_duration_from_secs, parse_duration_from_secs_or_ms};
use std::{borrow::Cow, ffi::OsStr, time::Duration};
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};

/// Global static payload builder defaults
static PAYLOAD_BUILDER_DEFAULTS: OnceLock<DefaultPayloadBuilderValues> = OnceLock::new();

/// Default values for payload builder that can be customized
///
/// Global defaults can be set via [`DefaultPayloadBuilderValues::try_init`].
#[derive(Debug, Clone)]
pub struct DefaultPayloadBuilderValues {
/// Default extra data for blocks
extra_data: String,
/// Default interval between payload builds in seconds
interval: String,
/// Default deadline for payload builds in seconds
deadline: String,
/// Default maximum number of concurrent payload building tasks
max_payload_tasks: usize,
}

impl DefaultPayloadBuilderValues {
/// Initialize the global payload builder defaults with this configuration
pub fn try_init(self) -> Result<(), Self> {
PAYLOAD_BUILDER_DEFAULTS.set(self)
}

/// Get a reference to the global payload builder defaults
pub fn get_global() -> &'static Self {
PAYLOAD_BUILDER_DEFAULTS.get_or_init(Self::default)
}

/// Set the default extra data
pub fn with_extra_data(mut self, v: impl Into<String>) -> Self {
self.extra_data = v.into();
self
}

/// Set the default interval in seconds
pub fn with_interval(mut self, v: Duration) -> Self {
self.interval = format_duration_as_secs_or_ms(v);
self
}

/// Set the default deadline in seconds
pub fn with_deadline(mut self, v: u64) -> Self {
self.deadline = format!("{}", v);
self
}

/// Set the default maximum payload tasks
pub const fn with_max_payload_tasks(mut self, v: usize) -> Self {
self.max_payload_tasks = v;
self
}
}

impl Default for DefaultPayloadBuilderValues {
fn default() -> Self {
Self {
extra_data: default_extra_data(),
interval: "1".to_string(),
deadline: "12".to_string(),
max_payload_tasks: 3,
}
}
}

/// Parameters for configuring the Payload Builder
#[derive(Debug, Clone, Args, PartialEq, Eq)]
#[command(next_help_heading = "Builder")]
pub struct PayloadBuilderArgs {
/// Block extra data set by the payload builder.
#[arg(long = "builder.extradata", value_parser = ExtraDataValueParser::default(), default_value_t = default_extra_data())]
#[arg(
long = "builder.extradata",
value_parser = ExtraDataValueParser::default(),
default_value_t = DefaultPayloadBuilderValues::get_global().extra_data.clone()
)]
pub extra_data: String,

/// Target gas limit for built blocks.
Expand All @@ -25,15 +96,29 @@ pub struct PayloadBuilderArgs {
/// Interval is specified in seconds or in milliseconds if the value ends with `ms`:
/// * `50ms` -> 50 milliseconds
/// * `1` -> 1 second
#[arg(long = "builder.interval", value_parser = parse_duration_from_secs_or_ms, default_value = "1", value_name = "DURATION")]
#[arg(
long = "builder.interval",
value_parser = parse_duration_from_secs_or_ms,
default_value = DefaultPayloadBuilderValues::get_global().interval.as_str(),
value_name = "DURATION"
)]
pub interval: Duration,

/// The deadline for when the payload builder job should resolve.
#[arg(long = "builder.deadline", value_parser = parse_duration_from_secs, default_value = "12", value_name = "SECONDS")]
#[arg(
long = "builder.deadline",
value_parser = parse_duration_from_secs,
default_value = DefaultPayloadBuilderValues::get_global().deadline.as_str(),
value_name = "SECONDS"
)]
pub deadline: Duration,

/// Maximum number of tasks to spawn for building a payload.
#[arg(long = "builder.max-tasks", default_value = "3", value_parser = RangedU64ValueParser::<usize>::new().range(1..))]
#[arg(
long = "builder.max-tasks",
value_parser = RangedU64ValueParser::<usize>::new().range(1..),
default_value_t = DefaultPayloadBuilderValues::get_global().max_payload_tasks
)]
pub max_payload_tasks: usize,

/// Maximum number of blobs to include per block.
Expand All @@ -43,12 +128,13 @@ pub struct PayloadBuilderArgs {

impl Default for PayloadBuilderArgs {
fn default() -> Self {
let defaults = DefaultPayloadBuilderValues::get_global();
Self {
extra_data: default_extra_data(),
interval: Duration::from_secs(1),
extra_data: defaults.extra_data.clone(),
interval: parse_duration_from_secs_or_ms(defaults.interval.as_str()).unwrap(),
gas_limit: None,
deadline: SLOT_DURATION,
max_payload_tasks: 3,
deadline: Duration::from_secs(defaults.deadline.parse().unwrap()),
max_payload_tasks: defaults.max_payload_tasks,
max_blobs_per_block: None,
}
}
Expand Down