reth_payload_primitives/
traits.rs1use crate::PayloadBuilderError;
4use alloc::{boxed::Box, sync::Arc, vec::Vec};
5use alloy_eips::{
6 eip4895::{Withdrawal, Withdrawals},
7 eip7685::Requests,
8};
9use alloy_primitives::{Address, B256, U256};
10use alloy_rpc_types_engine::{PayloadAttributes as EthPayloadAttributes, PayloadId};
11use core::fmt;
12use either::Either;
13use reth_execution_types::ExecutionOutcome;
14use reth_primitives_traits::{NodePrimitives, RecoveredBlock, SealedBlock, SealedHeader};
15use reth_trie_common::{
16 updates::{TrieUpdates, TrieUpdatesSorted},
17 HashedPostState, HashedPostStateSorted,
18};
19
20#[derive(Clone, Debug, PartialEq, Eq)]
25pub struct BuiltPayloadExecutedBlock<N: NodePrimitives> {
26 pub recovered_block: Arc<RecoveredBlock<N::Block>>,
28 pub execution_output: Arc<ExecutionOutcome<N::Receipt>>,
30 pub hashed_state: Either<Arc<HashedPostState>, Arc<HashedPostStateSorted>>,
35 pub trie_updates: Either<Arc<TrieUpdates>, Arc<TrieUpdatesSorted>>,
40}
41
42impl<N: NodePrimitives> BuiltPayloadExecutedBlock<N> {
43 pub fn into_executed_payload(self) -> reth_chain_state::ExecutedBlock<N> {
48 let hashed_state = match self.hashed_state {
49 Either::Left(unsorted) => Arc::new(Arc::unwrap_or_clone(unsorted).into_sorted()),
51 Either::Right(sorted) => sorted,
53 };
54
55 let trie_updates = match self.trie_updates {
56 Either::Left(unsorted) => Arc::new(Arc::unwrap_or_clone(unsorted).into_sorted()),
58 Either::Right(sorted) => sorted,
60 };
61
62 reth_chain_state::ExecutedBlock {
63 recovered_block: self.recovered_block,
64 execution_output: self.execution_output,
65 hashed_state,
66 trie_updates,
67 }
68 }
69}
70
71#[auto_impl::auto_impl(&, Arc)]
76pub trait BuiltPayload: Send + Sync + fmt::Debug {
77 type Primitives: NodePrimitives;
79
80 fn block(&self) -> &SealedBlock<<Self::Primitives as NodePrimitives>::Block>;
82
83 fn fees(&self) -> U256;
85
86 fn executed_block(&self) -> Option<BuiltPayloadExecutedBlock<Self::Primitives>> {
90 None
91 }
92
93 fn requests(&self) -> Option<Requests>;
98}
99
100pub trait PayloadBuilderAttributes: Send + Sync + Unpin + fmt::Debug + 'static {
105 type RpcPayloadAttributes: Send + Sync + 'static;
107 type Error: core::error::Error + Send + Sync + 'static;
109
110 fn try_new(
115 parent: B256,
116 rpc_payload_attributes: Self::RpcPayloadAttributes,
117 version: u8,
118 ) -> Result<Self, Self::Error>
119 where
120 Self: Sized;
121
122 fn payload_id(&self) -> PayloadId;
124
125 fn parent(&self) -> B256;
127
128 fn timestamp(&self) -> u64;
130
131 fn parent_beacon_block_root(&self) -> Option<B256>;
135
136 fn suggested_fee_recipient(&self) -> Address;
138
139 fn prev_randao(&self) -> B256;
141
142 fn withdrawals(&self) -> &Withdrawals;
144}
145
146pub trait PayloadAttributes:
151 serde::de::DeserializeOwned + serde::Serialize + fmt::Debug + Clone + Send + Sync + 'static
152{
153 fn timestamp(&self) -> u64;
155
156 fn withdrawals(&self) -> Option<&Vec<Withdrawal>>;
160
161 fn parent_beacon_block_root(&self) -> Option<B256>;
165}
166
167impl PayloadAttributes for EthPayloadAttributes {
168 fn timestamp(&self) -> u64 {
169 self.timestamp
170 }
171
172 fn withdrawals(&self) -> Option<&Vec<Withdrawal>> {
173 self.withdrawals.as_ref()
174 }
175
176 fn parent_beacon_block_root(&self) -> Option<B256> {
177 self.parent_beacon_block_root
178 }
179}
180
181#[cfg(feature = "op")]
182impl PayloadAttributes for op_alloy_rpc_types_engine::OpPayloadAttributes {
183 fn timestamp(&self) -> u64 {
184 self.payload_attributes.timestamp
185 }
186
187 fn withdrawals(&self) -> Option<&Vec<Withdrawal>> {
188 self.payload_attributes.withdrawals.as_ref()
189 }
190
191 fn parent_beacon_block_root(&self) -> Option<B256> {
192 self.payload_attributes.parent_beacon_block_root
193 }
194}
195
196pub trait PayloadAttributesBuilder<Attributes, Header = alloy_consensus::Header>:
201 Send + Sync + 'static
202{
203 fn build(&self, parent: &SealedHeader<Header>) -> Attributes;
205}
206
207impl<Attributes, Header, F> PayloadAttributesBuilder<Attributes, Header> for F
208where
209 Header: Clone,
210 F: Fn(SealedHeader<Header>) -> Attributes + Send + Sync + 'static,
211{
212 fn build(&self, parent: &SealedHeader<Header>) -> Attributes {
213 self(parent.clone())
214 }
215}
216
217impl<Attributes, Header, L, R> PayloadAttributesBuilder<Attributes, Header> for Either<L, R>
218where
219 L: PayloadAttributesBuilder<Attributes, Header>,
220 R: PayloadAttributesBuilder<Attributes, Header>,
221{
222 fn build(&self, parent: &SealedHeader<Header>) -> Attributes {
223 match self {
224 Self::Left(l) => l.build(parent),
225 Self::Right(r) => r.build(parent),
226 }
227 }
228}
229
230impl<Attributes, Header> PayloadAttributesBuilder<Attributes, Header>
231 for Box<dyn PayloadAttributesBuilder<Attributes, Header>>
232where
233 Header: 'static,
234 Attributes: 'static,
235{
236 fn build(&self, parent: &SealedHeader<Header>) -> Attributes {
237 self.as_ref().build(parent)
238 }
239}
240
241pub trait BuildNextEnv<Attributes, Header, Ctx>: Sized {
245 fn build_next_env(
247 attributes: &Attributes,
248 parent: &SealedHeader<Header>,
249 ctx: &Ctx,
250 ) -> Result<Self, PayloadBuilderError>;
251}