Skip to main content

reth_ethereum_payload_builder/
config.rs

1pub use alloy_eips::eip1559::calculate_block_gas_limit;
2use alloy_eips::eip1559::ETHEREUM_BLOCK_GAS_LIMIT_30M;
3use alloy_primitives::Bytes;
4
5/// Settings for the Ethereum builder.
6#[derive(PartialEq, Eq, Clone, Debug)]
7pub struct EthereumBuilderConfig {
8    /// Desired gas limit.
9    pub desired_gas_limit: u64,
10    /// Waits for the first payload to be built if there is no payload built when the payload is
11    /// being resolved.
12    pub await_payload_on_missing: bool,
13    /// Maximum number of blobs to include per block (EIP-7872).
14    ///
15    /// If `None`, defaults to the protocol maximum.
16    pub max_blobs_per_block: Option<u64>,
17    /// Extra data for built blocks.
18    pub extra_data: Bytes,
19    /// Whether payload builds should skip state-root computation.
20    pub skip_state_root: bool,
21}
22
23impl Default for EthereumBuilderConfig {
24    fn default() -> Self {
25        Self::new()
26    }
27}
28
29impl EthereumBuilderConfig {
30    /// Create new payload builder config.
31    pub const fn new() -> Self {
32        Self {
33            desired_gas_limit: ETHEREUM_BLOCK_GAS_LIMIT_30M,
34            await_payload_on_missing: true,
35            max_blobs_per_block: None,
36            extra_data: Bytes::new(),
37            skip_state_root: false,
38        }
39    }
40
41    /// Set desired gas limit.
42    pub const fn with_gas_limit(mut self, desired_gas_limit: u64) -> Self {
43        self.desired_gas_limit = desired_gas_limit;
44        self
45    }
46
47    /// Configures whether the initial payload should be awaited when the payload job is being
48    /// resolved and no payload has been built yet.
49    pub const fn with_await_payload_on_missing(mut self, await_payload_on_missing: bool) -> Self {
50        self.await_payload_on_missing = await_payload_on_missing;
51        self
52    }
53
54    /// Set the maximum number of blobs per block (EIP-7872).
55    pub const fn with_max_blobs_per_block(mut self, max_blobs_per_block: Option<u64>) -> Self {
56        self.max_blobs_per_block = max_blobs_per_block;
57        self
58    }
59
60    /// Set the extra data for built blocks.
61    pub fn with_extra_data(mut self, extra_data: Bytes) -> Self {
62        self.extra_data = extra_data;
63        self
64    }
65
66    /// Configures whether payload builds should skip state-root computation.
67    pub const fn with_skip_state_root(mut self, skip_state_root: bool) -> Self {
68        self.skip_state_root = skip_state_root;
69        self
70    }
71}
72
73impl EthereumBuilderConfig {
74    /// Returns the gas limit for the next block based
75    /// on parent and desired gas limits.
76    pub fn gas_limit(&self, parent_gas_limit: u64) -> u64 {
77        self.gas_limit_with_target(parent_gas_limit, None)
78    }
79
80    /// Returns the gas limit for the next block based on the parent gas limit and an optional
81    /// target from payload attributes.
82    pub fn gas_limit_with_target(
83        &self,
84        parent_gas_limit: u64,
85        target_gas_limit: Option<u64>,
86    ) -> u64 {
87        calculate_block_gas_limit(
88            parent_gas_limit,
89            target_gas_limit.unwrap_or(self.desired_gas_limit),
90        )
91    }
92}
93
94#[cfg(test)]
95mod tests {
96    use super::*;
97
98    #[test]
99    fn gas_limit_uses_payload_target_when_present() {
100        let parent_gas_limit = 30_000_000;
101        let target_gas_limit = parent_gas_limit - 100;
102        let config = EthereumBuilderConfig::new().with_gas_limit(parent_gas_limit + 100);
103
104        assert_eq!(
105            config.gas_limit_with_target(parent_gas_limit, Some(target_gas_limit)),
106            target_gas_limit
107        );
108    }
109
110    #[test]
111    fn gas_limit_falls_back_to_configured_target() {
112        let parent_gas_limit = 30_000_000;
113        let desired_gas_limit = parent_gas_limit + 100;
114        let config = EthereumBuilderConfig::new().with_gas_limit(desired_gas_limit);
115
116        assert_eq!(config.gas_limit_with_target(parent_gas_limit, None), desired_gas_limit);
117        assert_eq!(config.gas_limit(parent_gas_limit), desired_gas_limit);
118    }
119}