reth_ethereum_engine_primitives/
payload.rs1use alloc::{sync::Arc, vec::Vec};
4use alloy_eips::{
5 eip4844::BlobTransactionSidecar,
6 eip7594::{BlobTransactionSidecarEip7594, BlobTransactionSidecarVariant},
7 eip7685::Requests,
8};
9use alloy_primitives::{Bytes, U256};
10use alloy_rpc_types_engine::{
11 BlobsBundleV1, BlobsBundleV2, ExecutionPayloadEnvelopeV2, ExecutionPayloadEnvelopeV3,
12 ExecutionPayloadEnvelopeV4, ExecutionPayloadEnvelopeV5, ExecutionPayloadEnvelopeV6,
13 ExecutionPayloadFieldV2, ExecutionPayloadV1, ExecutionPayloadV3, ExecutionPayloadV4,
14};
15use reth_ethereum_primitives::EthPrimitives;
16use reth_payload_primitives::BuiltPayload;
17use reth_primitives_traits::{NodePrimitives, SealedBlock};
18
19use crate::BuiltPayloadConversionError;
20
21#[derive(Debug, Clone)]
29pub struct EthBuiltPayload<N: NodePrimitives = EthPrimitives> {
30 pub(crate) block: Arc<SealedBlock<N::Block>>,
32 pub(crate) fees: U256,
34 pub(crate) sidecars: BlobSidecars,
37 pub(crate) requests: Option<Requests>,
39 pub(crate) block_access_list: Option<Bytes>,
41}
42
43impl<N: NodePrimitives> EthBuiltPayload<N> {
46 pub const fn new(
50 block: Arc<SealedBlock<N::Block>>,
51 fees: U256,
52 requests: Option<Requests>,
53 block_access_list: Option<Bytes>,
54 ) -> Self {
55 Self { block, fees, requests, sidecars: BlobSidecars::Empty, block_access_list }
56 }
57
58 pub fn block(&self) -> &SealedBlock<N::Block> {
60 &self.block
61 }
62
63 pub const fn fees(&self) -> U256 {
65 self.fees
66 }
67
68 pub const fn sidecars(&self) -> &BlobSidecars {
70 &self.sidecars
71 }
72
73 pub fn with_sidecars(mut self, sidecars: impl Into<BlobSidecars>) -> Self {
75 self.sidecars = sidecars.into();
76 self
77 }
78}
79
80impl EthBuiltPayload {
81 pub fn try_into_v3(self) -> Result<ExecutionPayloadEnvelopeV3, BuiltPayloadConversionError> {
85 let Self { block, fees, sidecars, .. } = self;
86
87 let blobs_bundle = match sidecars {
88 BlobSidecars::Empty => BlobsBundleV1::empty(),
89 BlobSidecars::Eip4844(sidecars) => BlobsBundleV1::from(sidecars),
90 BlobSidecars::Eip7594(_) => {
91 return Err(BuiltPayloadConversionError::UnexpectedEip7594Sidecars)
92 }
93 };
94
95 Ok(ExecutionPayloadEnvelopeV3 {
96 execution_payload: ExecutionPayloadV3::from_block_unchecked(
97 block.hash(),
98 &Arc::unwrap_or_clone(block).into_block(),
99 ),
100 block_value: fees,
101 should_override_builder: false,
110 blobs_bundle,
111 })
112 }
113
114 pub fn try_into_v4(
118 mut self,
119 ) -> Result<ExecutionPayloadEnvelopeV4, BuiltPayloadConversionError> {
120 let execution_requests = self.requests.take().unwrap_or_default();
121 Ok(ExecutionPayloadEnvelopeV4 { execution_requests, envelope_inner: self.try_into()? })
122 }
123
124 pub fn try_into_v5(self) -> Result<ExecutionPayloadEnvelopeV5, BuiltPayloadConversionError> {
126 let Self { block, fees, sidecars, requests, .. } = self;
127
128 let blobs_bundle = match sidecars {
129 BlobSidecars::Empty => BlobsBundleV2::empty(),
130 BlobSidecars::Eip7594(sidecars) => BlobsBundleV2::from(sidecars),
131 BlobSidecars::Eip4844(_) => {
132 return Err(BuiltPayloadConversionError::UnexpectedEip4844Sidecars)
133 }
134 };
135
136 Ok(ExecutionPayloadEnvelopeV5 {
137 execution_payload: ExecutionPayloadV3::from_block_unchecked(
138 block.hash(),
139 &Arc::unwrap_or_clone(block).into_block(),
140 ),
141 block_value: fees,
142 should_override_builder: false,
151 blobs_bundle,
152 execution_requests: requests.unwrap_or_default(),
153 })
154 }
155
156 pub fn try_into_v6(self) -> Result<ExecutionPayloadEnvelopeV6, BuiltPayloadConversionError> {
160 let Self { block, fees, sidecars, requests, block_access_list, .. } = self;
161
162 let block_access_list =
163 block_access_list.ok_or(BuiltPayloadConversionError::MissingBlockAccessList)?;
164
165 let blobs_bundle = match sidecars {
166 BlobSidecars::Empty => BlobsBundleV2::empty(),
167 BlobSidecars::Eip7594(sidecars) => BlobsBundleV2::from(sidecars),
168 BlobSidecars::Eip4844(_) => {
169 return Err(BuiltPayloadConversionError::UnexpectedEip4844Sidecars)
170 }
171 };
172 Ok(ExecutionPayloadEnvelopeV6 {
173 execution_payload: ExecutionPayloadV4::from_block_unchecked_with_bal(
174 block.hash(),
175 &Arc::unwrap_or_clone(block).into_block(),
176 block_access_list,
177 ),
178 block_value: fees,
179 should_override_builder: false,
188 blobs_bundle,
189 execution_requests: requests.unwrap_or_default(),
190 })
191 }
192}
193
194impl<N: NodePrimitives> BuiltPayload for EthBuiltPayload<N> {
195 type Primitives = N;
196
197 fn block(&self) -> &SealedBlock<N::Block> {
198 &self.block
199 }
200
201 fn fees(&self) -> U256 {
202 self.fees
203 }
204
205 fn requests(&self) -> Option<Requests> {
206 self.requests.clone()
207 }
208}
209
210impl From<EthBuiltPayload> for ExecutionPayloadV1 {
212 fn from(value: EthBuiltPayload) -> Self {
213 Self::from_block_unchecked(
214 value.block().hash(),
215 &Arc::unwrap_or_clone(value.block).into_block(),
216 )
217 }
218}
219
220impl From<EthBuiltPayload> for ExecutionPayloadEnvelopeV2 {
222 fn from(value: EthBuiltPayload) -> Self {
223 let EthBuiltPayload { block, fees, .. } = value;
224
225 Self {
226 block_value: fees,
227 execution_payload: ExecutionPayloadFieldV2::from_block_unchecked(
228 block.hash(),
229 &Arc::unwrap_or_clone(block).into_block(),
230 ),
231 }
232 }
233}
234
235impl TryFrom<EthBuiltPayload> for ExecutionPayloadEnvelopeV3 {
236 type Error = BuiltPayloadConversionError;
237
238 fn try_from(value: EthBuiltPayload) -> Result<Self, Self::Error> {
239 value.try_into_v3()
240 }
241}
242
243impl TryFrom<EthBuiltPayload> for ExecutionPayloadEnvelopeV4 {
244 type Error = BuiltPayloadConversionError;
245
246 fn try_from(value: EthBuiltPayload) -> Result<Self, Self::Error> {
247 value.try_into_v4()
248 }
249}
250
251impl TryFrom<EthBuiltPayload> for ExecutionPayloadEnvelopeV5 {
252 type Error = BuiltPayloadConversionError;
253
254 fn try_from(value: EthBuiltPayload) -> Result<Self, Self::Error> {
255 value.try_into_v5()
256 }
257}
258
259impl TryFrom<EthBuiltPayload> for ExecutionPayloadEnvelopeV6 {
260 type Error = BuiltPayloadConversionError;
261
262 fn try_from(value: EthBuiltPayload) -> Result<Self, Self::Error> {
263 value.try_into_v6()
264 }
265}
266
267#[derive(Clone, Default, Debug)]
269pub enum BlobSidecars {
270 #[default]
272 Empty,
273 Eip4844(Vec<BlobTransactionSidecar>),
275 Eip7594(Vec<BlobTransactionSidecarEip7594>),
277}
278
279impl BlobSidecars {
280 pub const fn eip4844(sidecars: Vec<BlobTransactionSidecar>) -> Self {
282 Self::Eip4844(sidecars)
283 }
284
285 pub const fn eip7594(sidecars: Vec<BlobTransactionSidecarEip7594>) -> Self {
287 Self::Eip7594(sidecars)
288 }
289
290 pub fn push_eip4844_sidecar(&mut self, sidecar: BlobTransactionSidecar) {
292 match self {
293 Self::Empty => {
294 *self = Self::Eip4844(Vec::from([sidecar]));
295 }
296 Self::Eip4844(sidecars) => {
297 sidecars.push(sidecar);
298 }
299 Self::Eip7594(_) => {}
300 }
301 }
302
303 pub fn push_eip7594_sidecar(&mut self, sidecar: BlobTransactionSidecarEip7594) {
305 match self {
306 Self::Empty => {
307 *self = Self::Eip7594(Vec::from([sidecar]));
308 }
309 Self::Eip7594(sidecars) => {
310 sidecars.push(sidecar);
311 }
312 Self::Eip4844(_) => {}
313 }
314 }
315
316 pub fn push_sidecar_variant(&mut self, sidecar: BlobTransactionSidecarVariant) {
319 match sidecar {
320 BlobTransactionSidecarVariant::Eip4844(sidecar) => {
321 self.push_eip4844_sidecar(sidecar);
322 }
323 BlobTransactionSidecarVariant::Eip7594(sidecar) => {
324 self.push_eip7594_sidecar(sidecar);
325 }
326 }
327 }
328}
329
330impl From<Vec<BlobTransactionSidecar>> for BlobSidecars {
331 fn from(value: Vec<BlobTransactionSidecar>) -> Self {
332 Self::eip4844(value)
333 }
334}
335
336impl From<Vec<BlobTransactionSidecarEip7594>> for BlobSidecars {
337 fn from(value: Vec<BlobTransactionSidecarEip7594>) -> Self {
338 Self::eip7594(value)
339 }
340}
341
342impl From<alloc::vec::IntoIter<BlobTransactionSidecar>> for BlobSidecars {
343 fn from(value: alloc::vec::IntoIter<BlobTransactionSidecar>) -> Self {
344 value.collect::<Vec<_>>().into()
345 }
346}
347
348impl From<alloc::vec::IntoIter<BlobTransactionSidecarEip7594>> for BlobSidecars {
349 fn from(value: alloc::vec::IntoIter<BlobTransactionSidecarEip7594>) -> Self {
350 value.collect::<Vec<_>>().into()
351 }
352}