reth_payload_primitives/
payload.rs

1//! Types and traits for execution payload data structures.
2
3use crate::{MessageValidationKind, PayloadAttributes};
4use alloc::vec::Vec;
5use alloy_eips::{eip1898::BlockWithParent, eip4895::Withdrawal, eip7685::Requests, BlockNumHash};
6use alloy_primitives::B256;
7use alloy_rpc_types_engine::ExecutionData;
8use core::fmt::Debug;
9use serde::{de::DeserializeOwned, Serialize};
10
11/// Represents the core data structure of an execution payload.
12///
13/// Contains all necessary information to execute and validate a block, including
14/// headers, transactions, and consensus fields. Provides a unified interface
15/// regardless of protocol version.
16pub trait ExecutionPayload:
17    Serialize + DeserializeOwned + Debug + Clone + Send + Sync + 'static
18{
19    /// Returns the hash of this block's parent.
20    fn parent_hash(&self) -> B256;
21
22    /// Returns this block's hash.
23    fn block_hash(&self) -> B256;
24
25    /// Returns this block's number (height).
26    fn block_number(&self) -> u64;
27
28    /// Returns this block's number hash.
29    fn num_hash(&self) -> BlockNumHash {
30        BlockNumHash::new(self.block_number(), self.block_hash())
31    }
32
33    /// Returns a [`BlockWithParent`] for this block.
34    fn block_with_parent(&self) -> BlockWithParent {
35        BlockWithParent::new(self.parent_hash(), self.num_hash())
36    }
37
38    /// Returns the withdrawals included in this payload.
39    ///
40    /// Returns `None` for pre-Shanghai blocks.
41    fn withdrawals(&self) -> Option<&Vec<Withdrawal>>;
42
43    /// Returns the beacon block root associated with this payload.
44    ///
45    /// Returns `None` for pre-merge payloads.
46    fn parent_beacon_block_root(&self) -> Option<B256>;
47
48    /// Returns this block's timestamp (seconds since Unix epoch).
49    fn timestamp(&self) -> u64;
50
51    /// Returns the total gas consumed by all transactions in this block.
52    fn gas_used(&self) -> u64;
53}
54
55impl ExecutionPayload for ExecutionData {
56    fn parent_hash(&self) -> B256 {
57        self.payload.parent_hash()
58    }
59
60    fn block_hash(&self) -> B256 {
61        self.payload.block_hash()
62    }
63
64    fn block_number(&self) -> u64 {
65        self.payload.block_number()
66    }
67
68    fn withdrawals(&self) -> Option<&Vec<Withdrawal>> {
69        self.payload.withdrawals()
70    }
71
72    fn parent_beacon_block_root(&self) -> Option<B256> {
73        self.sidecar.parent_beacon_block_root()
74    }
75
76    fn timestamp(&self) -> u64 {
77        self.payload.timestamp()
78    }
79
80    fn gas_used(&self) -> u64 {
81        self.payload.as_v1().gas_used
82    }
83}
84
85/// A unified type for handling both execution payloads and payload attributes.
86///
87/// Enables generic validation and processing logic for both complete payloads
88/// and payload attributes, useful for version-specific validation.
89#[derive(Debug)]
90pub enum PayloadOrAttributes<'a, Payload, Attributes> {
91    /// A complete execution payload containing block data
92    ExecutionPayload(&'a Payload),
93    /// Attributes specifying how to build a new payload
94    PayloadAttributes(&'a Attributes),
95}
96
97impl<'a, Payload, Attributes> PayloadOrAttributes<'a, Payload, Attributes> {
98    /// Creates a `PayloadOrAttributes` from an execution payload reference
99    pub const fn from_execution_payload(payload: &'a Payload) -> Self {
100        Self::ExecutionPayload(payload)
101    }
102
103    /// Creates a `PayloadOrAttributes` from a payload attributes reference
104    pub const fn from_attributes(attributes: &'a Attributes) -> Self {
105        Self::PayloadAttributes(attributes)
106    }
107}
108
109impl<Payload, Attributes> PayloadOrAttributes<'_, Payload, Attributes>
110where
111    Payload: ExecutionPayload,
112    Attributes: PayloadAttributes,
113{
114    /// Returns withdrawals from either the payload or attributes.
115    pub fn withdrawals(&self) -> Option<&Vec<Withdrawal>> {
116        match self {
117            Self::ExecutionPayload(payload) => payload.withdrawals(),
118            Self::PayloadAttributes(attributes) => attributes.withdrawals(),
119        }
120    }
121
122    /// Returns the timestamp from either the payload or attributes.
123    pub fn timestamp(&self) -> u64 {
124        match self {
125            Self::ExecutionPayload(payload) => payload.timestamp(),
126            Self::PayloadAttributes(attributes) => attributes.timestamp(),
127        }
128    }
129
130    /// Returns the parent beacon block root from either the payload or attributes.
131    pub fn parent_beacon_block_root(&self) -> Option<B256> {
132        match self {
133            Self::ExecutionPayload(payload) => payload.parent_beacon_block_root(),
134            Self::PayloadAttributes(attributes) => attributes.parent_beacon_block_root(),
135        }
136    }
137
138    /// Determines the validation context based on the contained type.
139    pub const fn message_validation_kind(&self) -> MessageValidationKind {
140        match self {
141            Self::ExecutionPayload { .. } => MessageValidationKind::Payload,
142            Self::PayloadAttributes(_) => MessageValidationKind::PayloadAttributes,
143        }
144    }
145}
146
147impl<'a, Payload, AttributesType> From<&'a AttributesType>
148    for PayloadOrAttributes<'a, Payload, AttributesType>
149where
150    AttributesType: PayloadAttributes,
151{
152    fn from(attributes: &'a AttributesType) -> Self {
153        Self::PayloadAttributes(attributes)
154    }
155}
156
157#[cfg(feature = "op")]
158impl ExecutionPayload for op_alloy_rpc_types_engine::OpExecutionData {
159    fn parent_hash(&self) -> B256 {
160        self.parent_hash()
161    }
162
163    fn block_hash(&self) -> B256 {
164        self.block_hash()
165    }
166
167    fn block_number(&self) -> u64 {
168        self.block_number()
169    }
170
171    fn withdrawals(&self) -> Option<&Vec<Withdrawal>> {
172        self.payload.as_v2().map(|p| &p.withdrawals)
173    }
174
175    fn parent_beacon_block_root(&self) -> Option<B256> {
176        self.sidecar.parent_beacon_block_root()
177    }
178
179    fn timestamp(&self) -> u64 {
180        self.payload.as_v1().timestamp
181    }
182
183    fn gas_used(&self) -> u64 {
184        self.payload.as_v1().gas_used
185    }
186}
187
188/// Extended functionality for Ethereum execution payloads
189impl<Attributes> PayloadOrAttributes<'_, ExecutionData, Attributes>
190where
191    Attributes: PayloadAttributes,
192{
193    /// Extracts execution layer requests from the payload.
194    ///
195    /// Returns `Some(requests)` if this is an execution payload with request data,
196    /// `None` otherwise.
197    pub fn execution_requests(&self) -> Option<&Requests> {
198        if let Self::ExecutionPayload(payload) = self {
199            payload.sidecar.requests()
200        } else {
201            None
202        }
203    }
204}