reth_engine_local/
payload.rs

1//! The implementation of the [`PayloadAttributesBuilder`] for the
2//! [`LocalMiner`](super::LocalMiner).
3
4use alloy_consensus::BlockHeader;
5use alloy_primitives::{Address, B256};
6use reth_chainspec::{EthChainSpec, EthereumHardforks};
7use reth_ethereum_engine_primitives::EthPayloadAttributes;
8use reth_payload_primitives::PayloadAttributesBuilder;
9use reth_primitives_traits::SealedHeader;
10use std::sync::Arc;
11
12/// The attributes builder for local Ethereum payload.
13#[derive(Debug)]
14#[non_exhaustive]
15pub struct LocalPayloadAttributesBuilder<ChainSpec> {
16    /// The chainspec
17    pub chain_spec: Arc<ChainSpec>,
18
19    /// Whether to enforce increasing timestamp.
20    pub enforce_increasing_timestamp: bool,
21}
22
23impl<ChainSpec> LocalPayloadAttributesBuilder<ChainSpec> {
24    /// Creates a new instance of the builder.
25    pub const fn new(chain_spec: Arc<ChainSpec>) -> Self {
26        Self { chain_spec, enforce_increasing_timestamp: true }
27    }
28
29    /// Creates a new instance of the builder without enforcing increasing timestamps.
30    pub fn without_increasing_timestamp(self) -> Self {
31        Self { enforce_increasing_timestamp: false, ..self }
32    }
33}
34
35impl<ChainSpec> PayloadAttributesBuilder<EthPayloadAttributes, ChainSpec::Header>
36    for LocalPayloadAttributesBuilder<ChainSpec>
37where
38    ChainSpec: EthChainSpec + EthereumHardforks + 'static,
39{
40    fn build(&self, parent: &SealedHeader<ChainSpec::Header>) -> EthPayloadAttributes {
41        let mut timestamp =
42            std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs();
43
44        if self.enforce_increasing_timestamp {
45            timestamp = std::cmp::max(parent.timestamp().saturating_add(1), timestamp);
46        }
47
48        EthPayloadAttributes {
49            timestamp,
50            prev_randao: B256::random(),
51            suggested_fee_recipient: Address::random(),
52            withdrawals: self
53                .chain_spec
54                .is_shanghai_active_at_timestamp(timestamp)
55                .then(Default::default),
56            parent_beacon_block_root: self
57                .chain_spec
58                .is_cancun_active_at_timestamp(timestamp)
59                .then(B256::random),
60        }
61    }
62}
63
64#[cfg(feature = "op")]
65impl<ChainSpec>
66    PayloadAttributesBuilder<op_alloy_rpc_types_engine::OpPayloadAttributes, ChainSpec::Header>
67    for LocalPayloadAttributesBuilder<ChainSpec>
68where
69    ChainSpec: EthChainSpec + EthereumHardforks + 'static,
70{
71    fn build(
72        &self,
73        parent: &SealedHeader<ChainSpec::Header>,
74    ) -> op_alloy_rpc_types_engine::OpPayloadAttributes {
75        op_alloy_rpc_types_engine::OpPayloadAttributes {
76            payload_attributes: self.build(parent),
77            // Add dummy system transaction
78            transactions: Some(vec![
79                reth_optimism_chainspec::constants::TX_SET_L1_BLOCK_OP_MAINNET_BLOCK_124665056
80                    .into(),
81            ]),
82            no_tx_pool: None,
83            gas_limit: None,
84            eip_1559_params: None,
85            min_base_fee: None,
86        }
87    }
88}