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