reth_engine_local/
payload.rs1use 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#[derive(Debug)]
14#[non_exhaustive]
15pub struct LocalPayloadAttributesBuilder<ChainSpec> {
16 pub chain_spec: Arc<ChainSpec>,
18
19 pub enforce_increasing_timestamp: bool,
21}
22
23impl<ChainSpec> LocalPayloadAttributesBuilder<ChainSpec> {
24 pub const fn new(chain_spec: Arc<ChainSpec>) -> Self {
26 Self { chain_spec, enforce_increasing_timestamp: true }
27 }
28
29 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 use alloy_primitives::B64;
76 use reth_chainspec::BaseFeeParams;
77 use std::env;
78 const TX_SET_L1_BLOCK_OP_MAINNET_BLOCK_124665056: [u8; 251] = alloy_primitives::hex!(
83 "7ef8f8a0683079df94aa5b9cf86687d739a60a9b4f0835e520ec4d664e2e415dca17a6df94deaddeaddeaddeaddeaddeaddeaddeaddead00019442000000000000000000000000000000000000158080830f424080b8a4440a5e200000146b000f79c500000000000000040000000066d052e700000000013ad8a3000000000000000000000000000000000000000000000000000000003ef1278700000000000000000000000000000000000000000000000000000000000000012fdf87b89884a61e74b322bbcf60386f543bfae7827725efaaf0ab1de2294a590000000000000000000000006887246668a3b87f54deb3b94ba47a6f63f32985"
84 );
85
86 let default_eip_1559_params = BaseFeeParams::optimism();
91 let denominator = env::var("OP_DEV_EIP1559_DENOMINATOR")
92 .ok()
93 .and_then(|v| v.parse::<u32>().ok())
94 .unwrap_or(default_eip_1559_params.max_change_denominator as u32);
95 let elasticity = env::var("OP_DEV_EIP1559_ELASTICITY")
96 .ok()
97 .and_then(|v| v.parse::<u32>().ok())
98 .unwrap_or(default_eip_1559_params.elasticity_multiplier as u32);
99 let gas_limit = env::var("OP_DEV_GAS_LIMIT").ok().and_then(|v| v.parse::<u64>().ok());
100
101 let mut eip1559_bytes = [0u8; 8];
102 eip1559_bytes[0..4].copy_from_slice(&denominator.to_be_bytes());
103 eip1559_bytes[4..8].copy_from_slice(&elasticity.to_be_bytes());
104 let eip_1559_params = Some(B64::from(eip1559_bytes));
105
106 op_alloy_rpc_types_engine::OpPayloadAttributes {
107 payload_attributes: self.build(parent),
108 transactions: Some(vec![TX_SET_L1_BLOCK_OP_MAINNET_BLOCK_124665056.into()]),
109 no_tx_pool: None,
110 gas_limit,
111 eip_1559_params,
112 min_base_fee: Some(0),
113 }
114 }
115}