Skip to content

Commit e98fb4a

Browse files
authored
feat(engine): convert built payload to execution data (#23859)
1 parent fa2279f commit e98fb4a

1 file changed

Lines changed: 103 additions & 3 deletions

File tree

crates/ethereum/engine-primitives/src/payload.rs

Lines changed: 103 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ use alloy_eips::{
88
};
99
use alloy_primitives::{Bytes, U256};
1010
use alloy_rpc_types_engine::{
11-
BlobsBundleV1, BlobsBundleV2, ExecutionPayloadEnvelopeV2, ExecutionPayloadEnvelopeV3,
12-
ExecutionPayloadEnvelopeV4, ExecutionPayloadEnvelopeV5, ExecutionPayloadEnvelopeV6,
13-
ExecutionPayloadFieldV2, ExecutionPayloadV1, ExecutionPayloadV3, ExecutionPayloadV4,
11+
BlobsBundleV1, BlobsBundleV2, CancunPayloadFields, ExecutionData, ExecutionPayload,
12+
ExecutionPayloadEnvelopeV2, ExecutionPayloadEnvelopeV3, ExecutionPayloadEnvelopeV4,
13+
ExecutionPayloadEnvelopeV5, ExecutionPayloadEnvelopeV6, ExecutionPayloadFieldV2,
14+
ExecutionPayloadSidecar, ExecutionPayloadV1, ExecutionPayloadV3, ExecutionPayloadV4,
15+
PraguePayloadFields,
1416
};
1517
use reth_ethereum_primitives::EthPrimitives;
1618
use reth_payload_primitives::BuiltPayload;
@@ -189,6 +191,39 @@ impl EthBuiltPayload {
189191
execution_requests: requests.unwrap_or_default(),
190192
})
191193
}
194+
195+
/// Converts built payload into [`ExecutionData`].
196+
pub fn into_execution_data(self) -> ExecutionData {
197+
let Self { block, requests, block_access_list, .. } = self;
198+
let block_hash = block.hash();
199+
let block = Arc::unwrap_or_clone(block).into_block();
200+
201+
let (payload, sidecar) = ExecutionPayload::from_block_unchecked_with_extras(
202+
block_hash,
203+
&block,
204+
block_access_list,
205+
);
206+
207+
let sidecar = if let Some(requests) = requests {
208+
block.header.parent_beacon_block_root.map_or(sidecar, |parent_beacon_block_root| {
209+
ExecutionPayloadSidecar::v4(
210+
CancunPayloadFields {
211+
parent_beacon_block_root,
212+
versioned_hashes: block
213+
.body
214+
.blob_versioned_hashes_iter()
215+
.copied()
216+
.collect(),
217+
},
218+
PraguePayloadFields::new(requests),
219+
)
220+
})
221+
} else {
222+
sidecar
223+
};
224+
225+
ExecutionData::new(payload, sidecar)
226+
}
192227
}
193228

194229
impl<N: NodePrimitives> BuiltPayload for EthBuiltPayload<N> {
@@ -264,6 +299,12 @@ impl TryFrom<EthBuiltPayload> for ExecutionPayloadEnvelopeV6 {
264299
}
265300
}
266301

302+
impl From<EthBuiltPayload> for ExecutionData {
303+
fn from(value: EthBuiltPayload) -> Self {
304+
value.into_execution_data()
305+
}
306+
}
307+
267308
/// An enum representing blob transaction sidecars belonging to [`EthBuiltPayload`].
268309
#[derive(Clone, Default, Debug)]
269310
pub enum BlobSidecars {
@@ -350,3 +391,62 @@ impl From<alloc::vec::IntoIter<BlobTransactionSidecarEip7594>> for BlobSidecars
350391
value.collect::<Vec<_>>().into()
351392
}
352393
}
394+
395+
#[cfg(test)]
396+
mod tests {
397+
use super::*;
398+
use alloy_primitives::B256;
399+
use reth_primitives_traits::Block as _;
400+
401+
#[test]
402+
fn into_execution_data_preserves_requests() {
403+
let requests = Requests::from_requests([Bytes::from_static(&[1, 2])]);
404+
let parent_beacon_block_root = B256::with_last_byte(1);
405+
406+
let mut block = reth_ethereum_primitives::Block::default();
407+
block.header.parent_beacon_block_root = Some(parent_beacon_block_root);
408+
block.header.requests_hash = Some(requests.requests_hash());
409+
410+
let payload = EthBuiltPayload::new(
411+
Arc::new(block.seal_slow()),
412+
U256::ZERO,
413+
Some(requests.clone()),
414+
None,
415+
);
416+
417+
let execution_data: ExecutionData = payload.into();
418+
419+
assert_eq!(
420+
execution_data.sidecar.parent_beacon_block_root(),
421+
Some(parent_beacon_block_root)
422+
);
423+
assert_eq!(execution_data.sidecar.requests(), Some(&requests));
424+
}
425+
426+
#[test]
427+
fn into_execution_data_preserves_block_access_list() {
428+
let block_access_list = Bytes::from_static(&[0xc0]);
429+
430+
let mut block = reth_ethereum_primitives::Block::default();
431+
block.header.parent_beacon_block_root = Some(B256::ZERO);
432+
block.header.block_access_list_hash = Some(B256::ZERO);
433+
434+
let payload = EthBuiltPayload::new(
435+
Arc::new(block.seal_slow()),
436+
U256::ZERO,
437+
None,
438+
Some(block_access_list.clone()),
439+
);
440+
441+
let execution_data: ExecutionData = payload.into();
442+
443+
assert_eq!(execution_data.payload.block_access_list(), Some(&block_access_list));
444+
}
445+
446+
#[test]
447+
fn execution_data_has_infallible_try_from_impl() {
448+
fn assert_try_from<T: TryFrom<EthBuiltPayload, Error = core::convert::Infallible>>() {}
449+
450+
assert_try_from::<ExecutionData>();
451+
}
452+
}

0 commit comments

Comments
 (0)