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::{Bytes, 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 access list included in this payload.
44    ///
45    /// Returns `None` for pre-Amsterdam blocks.
46    fn block_access_list(&self) -> Option<&Bytes>;
47
48    /// Returns the beacon block root associated with this payload.
49    ///
50    /// Returns `None` for pre-merge payloads.
51    fn parent_beacon_block_root(&self) -> Option<B256>;
52
53    /// Returns this block's timestamp (seconds since Unix epoch).
54    fn timestamp(&self) -> u64;
55
56    /// Returns the total gas consumed by all transactions in this block.
57    fn gas_used(&self) -> u64;
58}
59
60impl ExecutionPayload for ExecutionData {
61    fn parent_hash(&self) -> B256 {
62        self.payload.parent_hash()
63    }
64
65    fn block_hash(&self) -> B256 {
66        self.payload.block_hash()
67    }
68
69    fn block_number(&self) -> u64 {
70        self.payload.block_number()
71    }
72
73    fn withdrawals(&self) -> Option<&Vec<Withdrawal>> {
74        self.payload.withdrawals()
75    }
76
77    fn block_access_list(&self) -> Option<&Bytes> {
78        None
79    }
80
81    fn parent_beacon_block_root(&self) -> Option<B256> {
82        self.sidecar.parent_beacon_block_root()
83    }
84
85    fn timestamp(&self) -> u64 {
86        self.payload.timestamp()
87    }
88
89    fn gas_used(&self) -> u64 {
90        self.payload.as_v1().gas_used
91    }
92}
93
94/// A unified type for handling both execution payloads and payload attributes.
95///
96/// Enables generic validation and processing logic for both complete payloads
97/// and payload attributes, useful for version-specific validation.
98#[derive(Debug)]
99pub enum PayloadOrAttributes<'a, Payload, Attributes> {
100    /// A complete execution payload containing block data
101    ExecutionPayload(&'a Payload),
102    /// Attributes specifying how to build a new payload
103    PayloadAttributes(&'a Attributes),
104}
105
106impl<'a, Payload, Attributes> PayloadOrAttributes<'a, Payload, Attributes> {
107    /// Creates a `PayloadOrAttributes` from an execution payload reference
108    pub const fn from_execution_payload(payload: &'a Payload) -> Self {
109        Self::ExecutionPayload(payload)
110    }
111
112    /// Creates a `PayloadOrAttributes` from a payload attributes reference
113    pub const fn from_attributes(attributes: &'a Attributes) -> Self {
114        Self::PayloadAttributes(attributes)
115    }
116}
117
118impl<Payload, Attributes> PayloadOrAttributes<'_, Payload, Attributes>
119where
120    Payload: ExecutionPayload,
121    Attributes: PayloadAttributes,
122{
123    /// Returns withdrawals from either the payload or attributes.
124    pub fn withdrawals(&self) -> Option<&Vec<Withdrawal>> {
125        match self {
126            Self::ExecutionPayload(payload) => payload.withdrawals(),
127            Self::PayloadAttributes(attributes) => attributes.withdrawals(),
128        }
129    }
130
131    /// Returns the timestamp from either the payload or attributes.
132    pub fn timestamp(&self) -> u64 {
133        match self {
134            Self::ExecutionPayload(payload) => payload.timestamp(),
135            Self::PayloadAttributes(attributes) => attributes.timestamp(),
136        }
137    }
138
139    /// Returns the parent beacon block root from either the payload or attributes.
140    pub fn parent_beacon_block_root(&self) -> Option<B256> {
141        match self {
142            Self::ExecutionPayload(payload) => payload.parent_beacon_block_root(),
143            Self::PayloadAttributes(attributes) => attributes.parent_beacon_block_root(),
144        }
145    }
146
147    /// Determines the validation context based on the contained type.
148    pub const fn message_validation_kind(&self) -> MessageValidationKind {
149        match self {
150            Self::ExecutionPayload { .. } => MessageValidationKind::Payload,
151            Self::PayloadAttributes(_) => MessageValidationKind::PayloadAttributes,
152        }
153    }
154}
155
156impl<'a, Payload, AttributesType> From<&'a AttributesType>
157    for PayloadOrAttributes<'a, Payload, AttributesType>
158where
159    AttributesType: PayloadAttributes,
160{
161    fn from(attributes: &'a AttributesType) -> Self {
162        Self::PayloadAttributes(attributes)
163    }
164}
165
166#[cfg(feature = "op")]
167impl ExecutionPayload for op_alloy_rpc_types_engine::OpExecutionData {
168    fn parent_hash(&self) -> B256 {
169        self.parent_hash()
170    }
171
172    fn block_hash(&self) -> B256 {
173        self.block_hash()
174    }
175
176    fn block_number(&self) -> u64 {
177        self.block_number()
178    }
179
180    fn withdrawals(&self) -> Option<&Vec<Withdrawal>> {
181        self.payload.as_v2().map(|p| &p.withdrawals)
182    }
183
184    fn block_access_list(&self) -> Option<&Bytes> {
185        None
186    }
187
188    fn parent_beacon_block_root(&self) -> Option<B256> {
189        self.sidecar.parent_beacon_block_root()
190    }
191
192    fn timestamp(&self) -> u64 {
193        self.payload.as_v1().timestamp
194    }
195
196    fn gas_used(&self) -> u64 {
197        self.payload.as_v1().gas_used
198    }
199}
200
201/// Extended functionality for Ethereum execution payloads
202impl<Attributes> PayloadOrAttributes<'_, ExecutionData, Attributes>
203where
204    Attributes: PayloadAttributes,
205{
206    /// Extracts execution layer requests from the payload.
207    ///
208    /// Returns `Some(requests)` if this is an execution payload with request data,
209    /// `None` otherwise.
210    pub fn execution_requests(&self) -> Option<&Requests> {
211        if let Self::ExecutionPayload(payload) = self {
212            payload.sidecar.requests()
213        } else {
214            None
215        }
216    }
217}