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::U256;
10use alloy_rpc_types_engine::{
11 BlobsBundleV1, BlobsBundleV2, ExecutionPayloadEnvelopeV2, ExecutionPayloadEnvelopeV3,
12 ExecutionPayloadEnvelopeV4, ExecutionPayloadEnvelopeV5, ExecutionPayloadEnvelopeV6,
13 ExecutionPayloadFieldV2, ExecutionPayloadV1, ExecutionPayloadV3,
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}
40
41impl<N: NodePrimitives> EthBuiltPayload<N> {
44 pub const fn new(
48 block: Arc<SealedBlock<N::Block>>,
49 fees: U256,
50 requests: Option<Requests>,
51 ) -> Self {
52 Self { block, fees, requests, sidecars: BlobSidecars::Empty }
53 }
54
55 pub fn block(&self) -> &SealedBlock<N::Block> {
57 &self.block
58 }
59
60 pub const fn fees(&self) -> U256 {
62 self.fees
63 }
64
65 pub const fn sidecars(&self) -> &BlobSidecars {
67 &self.sidecars
68 }
69
70 pub fn with_sidecars(mut self, sidecars: impl Into<BlobSidecars>) -> Self {
72 self.sidecars = sidecars.into();
73 self
74 }
75}
76
77impl EthBuiltPayload {
78 pub fn try_into_v3(self) -> Result<ExecutionPayloadEnvelopeV3, BuiltPayloadConversionError> {
82 let Self { block, fees, sidecars, .. } = self;
83
84 let blobs_bundle = match sidecars {
85 BlobSidecars::Empty => BlobsBundleV1::empty(),
86 BlobSidecars::Eip4844(sidecars) => BlobsBundleV1::from(sidecars),
87 BlobSidecars::Eip7594(_) => {
88 return Err(BuiltPayloadConversionError::UnexpectedEip7594Sidecars)
89 }
90 };
91
92 Ok(ExecutionPayloadEnvelopeV3 {
93 execution_payload: ExecutionPayloadV3::from_block_unchecked(
94 block.hash(),
95 &Arc::unwrap_or_clone(block).into_block(),
96 ),
97 block_value: fees,
98 should_override_builder: false,
107 blobs_bundle,
108 })
109 }
110
111 pub fn try_into_v4(
115 mut self,
116 ) -> Result<ExecutionPayloadEnvelopeV4, BuiltPayloadConversionError> {
117 let execution_requests = self.requests.take().unwrap_or_default();
118 Ok(ExecutionPayloadEnvelopeV4 { execution_requests, envelope_inner: self.try_into()? })
119 }
120
121 pub fn try_into_v5(self) -> Result<ExecutionPayloadEnvelopeV5, BuiltPayloadConversionError> {
123 let Self { block, fees, sidecars, requests, .. } = self;
124
125 let blobs_bundle = match sidecars {
126 BlobSidecars::Empty => BlobsBundleV2::empty(),
127 BlobSidecars::Eip7594(sidecars) => BlobsBundleV2::from(sidecars),
128 BlobSidecars::Eip4844(_) => {
129 return Err(BuiltPayloadConversionError::UnexpectedEip4844Sidecars)
130 }
131 };
132
133 Ok(ExecutionPayloadEnvelopeV5 {
134 execution_payload: ExecutionPayloadV3::from_block_unchecked(
135 block.hash(),
136 &Arc::unwrap_or_clone(block).into_block(),
137 ),
138 block_value: fees,
139 should_override_builder: false,
148 blobs_bundle,
149 execution_requests: requests.unwrap_or_default(),
150 })
151 }
152
153 pub fn try_into_v6(self) -> Result<ExecutionPayloadEnvelopeV6, BuiltPayloadConversionError> {
157 unimplemented!("ExecutionPayloadEnvelopeV6 not yet supported")
158 }
159}
160
161impl<N: NodePrimitives> BuiltPayload for EthBuiltPayload<N> {
162 type Primitives = N;
163
164 fn block(&self) -> &SealedBlock<N::Block> {
165 &self.block
166 }
167
168 fn fees(&self) -> U256 {
169 self.fees
170 }
171
172 fn requests(&self) -> Option<Requests> {
173 self.requests.clone()
174 }
175}
176
177impl From<EthBuiltPayload> for ExecutionPayloadV1 {
179 fn from(value: EthBuiltPayload) -> Self {
180 Self::from_block_unchecked(
181 value.block().hash(),
182 &Arc::unwrap_or_clone(value.block).into_block(),
183 )
184 }
185}
186
187impl From<EthBuiltPayload> for ExecutionPayloadEnvelopeV2 {
189 fn from(value: EthBuiltPayload) -> Self {
190 let EthBuiltPayload { block, fees, .. } = value;
191
192 Self {
193 block_value: fees,
194 execution_payload: ExecutionPayloadFieldV2::from_block_unchecked(
195 block.hash(),
196 &Arc::unwrap_or_clone(block).into_block(),
197 ),
198 }
199 }
200}
201
202impl TryFrom<EthBuiltPayload> for ExecutionPayloadEnvelopeV3 {
203 type Error = BuiltPayloadConversionError;
204
205 fn try_from(value: EthBuiltPayload) -> Result<Self, Self::Error> {
206 value.try_into_v3()
207 }
208}
209
210impl TryFrom<EthBuiltPayload> for ExecutionPayloadEnvelopeV4 {
211 type Error = BuiltPayloadConversionError;
212
213 fn try_from(value: EthBuiltPayload) -> Result<Self, Self::Error> {
214 value.try_into_v4()
215 }
216}
217
218impl TryFrom<EthBuiltPayload> for ExecutionPayloadEnvelopeV5 {
219 type Error = BuiltPayloadConversionError;
220
221 fn try_from(value: EthBuiltPayload) -> Result<Self, Self::Error> {
222 value.try_into_v5()
223 }
224}
225
226impl TryFrom<EthBuiltPayload> for ExecutionPayloadEnvelopeV6 {
227 type Error = BuiltPayloadConversionError;
228
229 fn try_from(value: EthBuiltPayload) -> Result<Self, Self::Error> {
230 value.try_into_v6()
231 }
232}
233
234#[derive(Clone, Default, Debug)]
236pub enum BlobSidecars {
237 #[default]
239 Empty,
240 Eip4844(Vec<BlobTransactionSidecar>),
242 Eip7594(Vec<BlobTransactionSidecarEip7594>),
244}
245
246impl BlobSidecars {
247 pub const fn eip4844(sidecars: Vec<BlobTransactionSidecar>) -> Self {
249 Self::Eip4844(sidecars)
250 }
251
252 pub const fn eip7594(sidecars: Vec<BlobTransactionSidecarEip7594>) -> Self {
254 Self::Eip7594(sidecars)
255 }
256
257 pub fn push_eip4844_sidecar(&mut self, sidecar: BlobTransactionSidecar) {
259 match self {
260 Self::Empty => {
261 *self = Self::Eip4844(Vec::from([sidecar]));
262 }
263 Self::Eip4844(sidecars) => {
264 sidecars.push(sidecar);
265 }
266 Self::Eip7594(_) => {}
267 }
268 }
269
270 pub fn push_eip7594_sidecar(&mut self, sidecar: BlobTransactionSidecarEip7594) {
272 match self {
273 Self::Empty => {
274 *self = Self::Eip7594(Vec::from([sidecar]));
275 }
276 Self::Eip7594(sidecars) => {
277 sidecars.push(sidecar);
278 }
279 Self::Eip4844(_) => {}
280 }
281 }
282
283 pub fn push_sidecar_variant(&mut self, sidecar: BlobTransactionSidecarVariant) {
286 match sidecar {
287 BlobTransactionSidecarVariant::Eip4844(sidecar) => {
288 self.push_eip4844_sidecar(sidecar);
289 }
290 BlobTransactionSidecarVariant::Eip7594(sidecar) => {
291 self.push_eip7594_sidecar(sidecar);
292 }
293 }
294 }
295}
296
297impl From<Vec<BlobTransactionSidecar>> for BlobSidecars {
298 fn from(value: Vec<BlobTransactionSidecar>) -> Self {
299 Self::eip4844(value)
300 }
301}
302
303impl From<Vec<BlobTransactionSidecarEip7594>> for BlobSidecars {
304 fn from(value: Vec<BlobTransactionSidecarEip7594>) -> Self {
305 Self::eip7594(value)
306 }
307}
308
309impl From<alloc::vec::IntoIter<BlobTransactionSidecar>> for BlobSidecars {
310 fn from(value: alloc::vec::IntoIter<BlobTransactionSidecar>) -> Self {
311 value.collect::<Vec<_>>().into()
312 }
313}
314
315impl From<alloc::vec::IntoIter<BlobTransactionSidecarEip7594>> for BlobSidecars {
316 fn from(value: alloc::vec::IntoIter<BlobTransactionSidecarEip7594>) -> Self {
317 value.collect::<Vec<_>>().into()
318 }
319}