tempo_payload_types/
lib.rs1#![cfg_attr(not(test), warn(unused_crate_dependencies))]
4#![cfg_attr(docsrs, feature(doc_cfg))]
5
6mod attrs;
7mod budget;
8
9use alloy_primitives::{B256, Bytes};
10pub use attrs::TempoPayloadAttributes;
11pub use budget::{
12 MarshalPersistEstimator, ValidationLatencyEstimate, ValidationLatencyEstimator,
13 ValidationLatencyWorkload, marshal_persist_estimate, observe_marshal_persist,
14};
15use std::{
16 sync::{Arc, OnceLock},
17 time::Duration,
18};
19
20use alloy_eips::eip7685::Requests;
21use alloy_primitives::U256;
22use alloy_rpc_types_eth::Withdrawal;
23use reth_ethereum_engine_primitives::EthBuiltPayload;
24use reth_node_api::{BlockBody, ExecutionPayload, PayloadTypes};
25use reth_payload_primitives::{BuiltPayload, BuiltPayloadExecutedBlock};
26use reth_primitives_traits::{AlloyBlockHeader as _, SealedBlock, SealedOrRecoveredBlock};
27use serde::{Deserialize, Serialize};
28use tempo_primitives::{Block, TempoPrimitives};
29
30#[derive(Debug, Clone, Copy, Default)]
32#[non_exhaustive]
33pub struct TempoPayloadTypes;
34
35#[derive(Debug, Clone)]
40pub struct TempoBuiltPayload {
41 inner: EthBuiltPayload<TempoPrimitives>,
43 block_access_list: Option<Bytes>,
45 executed_block: Option<BuiltPayloadExecutedBlock<TempoPrimitives>>,
47 validation_work_duration: Duration,
52 validation_latency_duration: Duration,
54 execution_block_size_estimate: usize,
56 execution_block_encoded: EncodedBlock,
58}
59
60impl TempoBuiltPayload {
61 pub fn new(
63 inner: EthBuiltPayload<TempoPrimitives>,
64 block_access_list: Option<Bytes>,
65 executed_block: Option<BuiltPayloadExecutedBlock<TempoPrimitives>>,
66 validation_work_duration: Duration,
67 validation_latency_duration: Duration,
68 execution_block_size_estimate: usize,
69 execution_block_encoded: EncodedBlock,
70 ) -> Self {
71 Self {
72 inner,
73 block_access_list,
74 executed_block,
75 validation_work_duration,
76 validation_latency_duration,
77 execution_block_size_estimate,
78 execution_block_encoded,
79 }
80 }
81
82 pub fn into_execution_payload(self) -> (SealedBlock<Block>, Option<Bytes>) {
84 (
85 Arc::unwrap_or_clone(self.inner.block_arc().clone()).into_sealed_block(),
86 self.block_access_list,
87 )
88 }
89
90 pub fn into_consensus_execution_payload(
92 self,
93 ) -> (SealedOrRecoveredBlock<Block>, Option<Bytes>, EncodedBlock) {
94 let execution_block = SealedOrRecoveredBlock::recovered_arc(self.inner.block_arc().clone());
95
96 (
97 execution_block,
98 self.block_access_list,
99 self.execution_block_encoded,
100 )
101 }
102
103 pub fn execution_block_size_estimate(&self) -> usize {
105 self.execution_block_size_estimate
106 }
107
108 pub fn validation_work_duration(&self) -> Duration {
110 self.validation_work_duration
111 }
112
113 pub fn validation_latency_duration(&self) -> Duration {
115 self.validation_latency_duration
116 }
117
118 pub fn into_execution_data(self) -> TempoExecutionData {
120 let (block, block_access_list, _) = self.into_consensus_execution_payload();
121 TempoExecutionData {
122 block,
123 block_access_list,
124 validator_set: None,
125 }
126 }
127}
128
129impl BuiltPayload for TempoBuiltPayload {
130 type Primitives = TempoPrimitives;
131
132 fn block(&self) -> &SealedBlock<Block> {
133 self.inner.block()
134 }
135
136 fn fees(&self) -> U256 {
137 self.inner.fees()
138 }
139
140 fn executed_block(&self) -> Option<BuiltPayloadExecutedBlock<Self::Primitives>> {
141 self.executed_block.clone()
142 }
143
144 fn requests(&self) -> Option<Requests> {
145 self.inner.requests()
146 }
147
148 fn block_access_list(&self) -> Option<&Bytes> {
149 self.block_access_list.as_ref()
150 }
151}
152
153#[derive(Debug, Clone, Serialize, Deserialize)]
155pub struct TempoExecutionData {
156 pub block: SealedOrRecoveredBlock<Block>,
158 pub block_access_list: Option<Bytes>,
160 pub validator_set: Option<Vec<B256>>,
162}
163
164impl ExecutionPayload for TempoExecutionData {
165 fn parent_hash(&self) -> alloy_primitives::B256 {
166 self.block.parent_hash()
167 }
168
169 fn block_hash(&self) -> alloy_primitives::B256 {
170 self.block.hash()
171 }
172
173 fn block_number(&self) -> u64 {
174 self.block.number()
175 }
176
177 fn withdrawals(&self) -> Option<&Vec<Withdrawal>> {
178 self.block
179 .body()
180 .withdrawals
181 .as_ref()
182 .map(|withdrawals| &withdrawals.0)
183 }
184
185 fn parent_beacon_block_root(&self) -> Option<alloy_primitives::B256> {
186 self.block.parent_beacon_block_root()
187 }
188
189 fn timestamp(&self) -> u64 {
190 self.block.timestamp()
191 }
192
193 fn transaction_count(&self) -> usize {
194 self.block.body().transaction_count()
195 }
196
197 fn gas_used(&self) -> u64 {
198 self.block.gas_used()
199 }
200
201 fn gas_limit(&self) -> u64 {
202 self.block.gas_limit()
203 }
204
205 fn slot_number(&self) -> Option<u64> {
206 self.block.slot_number()
207 }
208
209 fn block_access_list(&self) -> Option<&Bytes> {
210 self.block_access_list.as_ref()
211 }
212}
213
214impl From<TempoBuiltPayload> for TempoExecutionData {
215 fn from(value: TempoBuiltPayload) -> Self {
216 value.into_execution_data()
217 }
218}
219
220impl PayloadTypes for TempoPayloadTypes {
221 type ExecutionData = TempoExecutionData;
222 type BuiltPayload = TempoBuiltPayload;
223 type PayloadAttributes = TempoPayloadAttributes;
224
225 fn block_to_payload(block: SealedBlock<Block>, bal: Option<Bytes>) -> Self::ExecutionData {
226 TempoExecutionData {
227 block: block.into(),
228 block_access_list: bal,
229 validator_set: None,
230 }
231 }
232}
233
234#[derive(Clone, Debug, Default)]
240pub struct EncodedBlock(Arc<OnceLock<Bytes>>);
241
242impl EncodedBlock {
243 pub fn new(bytes: Bytes) -> Self {
244 Self(Arc::new(OnceLock::from(bytes)))
245 }
246
247 pub fn get(&self) -> Option<&Bytes> {
249 self.0.get()
250 }
251
252 pub fn get_or_encode<T>(&self, block: &T) -> &Bytes
254 where
255 T: alloy_rlp::Encodable,
256 {
257 self.get_or_encode_with(|| {
258 let mut encoded = Vec::new();
259 block.encode(&mut encoded);
260 encoded.into()
261 })
262 }
263
264 pub fn get_or_encode_with(&self, encode: impl FnOnce() -> Bytes) -> &Bytes {
266 self.0.get_or_init(encode)
267 }
268}