Skip to main content

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