reth_basic_payload_builder/
stack.rs1use crate::{
2 BuildArguments, BuildOutcome, HeaderForPayload, PayloadBuilder, PayloadBuilderAttributes,
3 PayloadBuilderError, PayloadConfig,
4};
5
6use alloy_eips::eip4895::Withdrawals;
7use alloy_primitives::{Address, B256, U256};
8use reth_payload_builder::PayloadId;
9use reth_payload_primitives::BuiltPayload;
10use reth_primitives_traits::{NodePrimitives, SealedBlock};
11
12use alloy_eips::eip7685::Requests;
13use std::{error::Error, fmt};
14
15#[derive(Debug, Clone)]
17pub enum Either<L, R> {
18 Left(L),
20 Right(R),
22}
23
24impl<L, R> fmt::Display for Either<L, R>
25where
26 L: fmt::Display,
27 R: fmt::Display,
28{
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 match self {
31 Self::Left(l) => write!(f, "Left: {l}"),
32 Self::Right(r) => write!(f, "Right: {r}"),
33 }
34 }
35}
36
37impl<L, R> Error for Either<L, R>
38where
39 L: Error + 'static,
40 R: Error + 'static,
41{
42 fn source(&self) -> Option<&(dyn Error + 'static)> {
43 match self {
44 Self::Left(l) => Some(l),
45 Self::Right(r) => Some(r),
46 }
47 }
48}
49
50impl<L, R> PayloadBuilderAttributes for Either<L, R>
51where
52 L: PayloadBuilderAttributes,
53 R: PayloadBuilderAttributes,
54 L::Error: Error + 'static,
55 R::Error: Error + 'static,
56{
57 type RpcPayloadAttributes = Either<L::RpcPayloadAttributes, R::RpcPayloadAttributes>;
58 type Error = Either<L::Error, R::Error>;
59
60 fn try_new(
61 parent: B256,
62 rpc_payload_attributes: Self::RpcPayloadAttributes,
63 version: u8,
64 ) -> Result<Self, Self::Error> {
65 match rpc_payload_attributes {
66 Either::Left(attr) => {
67 L::try_new(parent, attr, version).map(Either::Left).map_err(Either::Left)
68 }
69 Either::Right(attr) => {
70 R::try_new(parent, attr, version).map(Either::Right).map_err(Either::Right)
71 }
72 }
73 }
74
75 fn payload_id(&self) -> PayloadId {
76 match self {
77 Self::Left(l) => l.payload_id(),
78 Self::Right(r) => r.payload_id(),
79 }
80 }
81
82 fn parent(&self) -> B256 {
83 match self {
84 Self::Left(l) => l.parent(),
85 Self::Right(r) => r.parent(),
86 }
87 }
88
89 fn timestamp(&self) -> u64 {
90 match self {
91 Self::Left(l) => l.timestamp(),
92 Self::Right(r) => r.timestamp(),
93 }
94 }
95
96 fn parent_beacon_block_root(&self) -> Option<B256> {
97 match self {
98 Self::Left(l) => l.parent_beacon_block_root(),
99 Self::Right(r) => r.parent_beacon_block_root(),
100 }
101 }
102
103 fn suggested_fee_recipient(&self) -> Address {
104 match self {
105 Self::Left(l) => l.suggested_fee_recipient(),
106 Self::Right(r) => r.suggested_fee_recipient(),
107 }
108 }
109
110 fn prev_randao(&self) -> B256 {
111 match self {
112 Self::Left(l) => l.prev_randao(),
113 Self::Right(r) => r.prev_randao(),
114 }
115 }
116
117 fn withdrawals(&self) -> &Withdrawals {
118 match self {
119 Self::Left(l) => l.withdrawals(),
120 Self::Right(r) => r.withdrawals(),
121 }
122 }
123}
124
125#[derive(Debug)]
129pub struct PayloadBuilderStack<L, R> {
130 left: L,
131 right: R,
132}
133
134impl<L, R> PayloadBuilderStack<L, R> {
135 pub const fn new(left: L, right: R) -> Self {
137 Self { left, right }
138 }
139}
140
141impl<L, R> Clone for PayloadBuilderStack<L, R>
142where
143 L: Clone,
144 R: Clone,
145{
146 fn clone(&self) -> Self {
147 Self::new(self.left.clone(), self.right.clone())
148 }
149}
150
151impl<L, R> BuiltPayload for Either<L, R>
152where
153 L: BuiltPayload,
154 R: BuiltPayload<Primitives = L::Primitives>,
155{
156 type Primitives = L::Primitives;
157
158 fn block(&self) -> &SealedBlock<<L::Primitives as NodePrimitives>::Block> {
159 match self {
160 Self::Left(l) => l.block(),
161 Self::Right(r) => r.block(),
162 }
163 }
164
165 fn fees(&self) -> U256 {
166 match self {
167 Self::Left(l) => l.fees(),
168 Self::Right(r) => r.fees(),
169 }
170 }
171
172 fn requests(&self) -> Option<Requests> {
173 match self {
174 Self::Left(l) => l.requests(),
175 Self::Right(r) => r.requests(),
176 }
177 }
178}
179
180impl<L, R> PayloadBuilder for PayloadBuilderStack<L, R>
181where
182 L: PayloadBuilder + Unpin + 'static,
183 R: PayloadBuilder + Unpin + 'static,
184 L::Attributes: Unpin + Clone,
185 R::Attributes: Unpin + Clone,
186 L::BuiltPayload: Unpin + Clone,
187 R::BuiltPayload:
188 BuiltPayload<Primitives = <L::BuiltPayload as BuiltPayload>::Primitives> + Unpin + Clone,
189{
190 type Attributes = Either<L::Attributes, R::Attributes>;
191 type BuiltPayload = Either<L::BuiltPayload, R::BuiltPayload>;
192
193 fn try_build(
194 &self,
195 args: BuildArguments<Self::Attributes, Self::BuiltPayload>,
196 ) -> Result<BuildOutcome<Self::BuiltPayload>, PayloadBuilderError> {
197 let BuildArguments { cached_reads, config, cancel, best_payload } = args;
198 let PayloadConfig { parent_header, attributes } = config;
199
200 match attributes {
201 Either::Left(left_attr) => {
202 let left_args: BuildArguments<L::Attributes, L::BuiltPayload> = BuildArguments {
203 cached_reads,
204 config: PayloadConfig { parent_header, attributes: left_attr },
205 cancel,
206 best_payload: best_payload.and_then(|payload| {
207 if let Either::Left(p) = payload {
208 Some(p)
209 } else {
210 None
211 }
212 }),
213 };
214 self.left.try_build(left_args).map(|out| out.map_payload(Either::Left))
215 }
216 Either::Right(right_attr) => {
217 let right_args = BuildArguments {
218 cached_reads,
219 config: PayloadConfig { parent_header, attributes: right_attr },
220 cancel,
221 best_payload: best_payload.and_then(|payload| {
222 if let Either::Right(p) = payload {
223 Some(p)
224 } else {
225 None
226 }
227 }),
228 };
229 self.right.try_build(right_args).map(|out| out.map_payload(Either::Right))
230 }
231 }
232 }
233
234 fn build_empty_payload(
235 &self,
236 config: PayloadConfig<Self::Attributes, HeaderForPayload<Self::BuiltPayload>>,
237 ) -> Result<Self::BuiltPayload, PayloadBuilderError> {
238 match config {
239 PayloadConfig { parent_header, attributes: Either::Left(left_attr) } => {
240 let left_config = PayloadConfig { parent_header, attributes: left_attr };
241 self.left.build_empty_payload(left_config).map(Either::Left)
242 }
243 PayloadConfig { parent_header, attributes: Either::Right(right_attr) } => {
244 let right_config = PayloadConfig { parent_header, attributes: right_attr };
245 self.right.build_empty_payload(right_config).map(Either::Right)
246 }
247 }
248 }
249}