tempo_primitives/
header.rs

1use alloy_consensus::{BlockHeader, Header, Sealable};
2use alloy_primitives::{Address, B64, B256, BlockHash, BlockNumber, Bloom, Bytes, U256, keccak256};
3use alloy_rlp::{RlpDecodable, RlpEncodable};
4use reth_primitives_traits::InMemorySize;
5
6/// Tempo block header.
7///
8/// Encoded as `rlp([inner, general_gas_limit])` meaning that any new
9/// fields added to the inner header will only affect the first list element.
10#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, RlpEncodable, RlpDecodable)]
11#[cfg_attr(feature = "reth-codec", derive(reth_codecs::Compact))]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
14#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
15#[cfg_attr(test, reth_codecs::add_arbitrary_tests(compact, rlp))]
16pub struct TempoHeader {
17    /// Non-payment gas limit for the block.
18    #[cfg_attr(
19        feature = "serde",
20        serde(with = "alloy_serde::quantity", rename = "mainBlockGeneralGasLimit")
21    )]
22    pub general_gas_limit: u64,
23
24    /// Shared gas limit allocated for the subblocks section of the block.
25    #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))]
26    pub shared_gas_limit: u64,
27
28    /// Sub-second (milliseconds) portion of the timestamp.
29    #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))]
30    pub timestamp_millis_part: u64,
31
32    /// Inner Ethereum [`Header`].
33    #[cfg_attr(feature = "serde", serde(flatten))]
34    pub inner: Header,
35}
36
37impl TempoHeader {
38    /// Returns the timestamp in milliseconds.
39    pub fn timestamp_millis(&self) -> u64 {
40        self.inner
41            .timestamp()
42            .saturating_mul(1000)
43            .saturating_add(self.timestamp_millis_part)
44    }
45}
46
47impl AsRef<Self> for TempoHeader {
48    fn as_ref(&self) -> &Self {
49        self
50    }
51}
52
53#[cfg(feature = "serde-bincode-compat")]
54impl reth_primitives_traits::serde_bincode_compat::RlpBincode for TempoHeader {}
55
56impl BlockHeader for TempoHeader {
57    fn parent_hash(&self) -> B256 {
58        self.inner.parent_hash()
59    }
60
61    fn ommers_hash(&self) -> B256 {
62        self.inner.ommers_hash()
63    }
64
65    fn beneficiary(&self) -> Address {
66        self.inner.beneficiary()
67    }
68
69    fn state_root(&self) -> B256 {
70        self.inner.state_root()
71    }
72
73    fn transactions_root(&self) -> B256 {
74        self.inner.transactions_root()
75    }
76
77    fn receipts_root(&self) -> B256 {
78        self.inner.receipts_root()
79    }
80
81    fn withdrawals_root(&self) -> Option<B256> {
82        self.inner.withdrawals_root()
83    }
84
85    fn logs_bloom(&self) -> Bloom {
86        self.inner.logs_bloom()
87    }
88
89    fn difficulty(&self) -> U256 {
90        self.inner.difficulty()
91    }
92
93    fn number(&self) -> BlockNumber {
94        self.inner.number()
95    }
96
97    fn gas_limit(&self) -> u64 {
98        self.inner.gas_limit()
99    }
100
101    fn gas_used(&self) -> u64 {
102        self.inner.gas_used()
103    }
104
105    fn timestamp(&self) -> u64 {
106        self.inner.timestamp()
107    }
108
109    fn mix_hash(&self) -> Option<B256> {
110        self.inner.mix_hash()
111    }
112
113    fn nonce(&self) -> Option<B64> {
114        self.inner.nonce()
115    }
116
117    fn base_fee_per_gas(&self) -> Option<u64> {
118        self.inner.base_fee_per_gas()
119    }
120
121    fn blob_gas_used(&self) -> Option<u64> {
122        self.inner.blob_gas_used()
123    }
124
125    fn excess_blob_gas(&self) -> Option<u64> {
126        self.inner.excess_blob_gas()
127    }
128
129    fn parent_beacon_block_root(&self) -> Option<B256> {
130        self.inner.parent_beacon_block_root()
131    }
132
133    fn requests_hash(&self) -> Option<B256> {
134        self.inner.requests_hash()
135    }
136
137    fn extra_data(&self) -> &Bytes {
138        self.inner.extra_data()
139    }
140}
141
142impl InMemorySize for TempoHeader {
143    fn size(&self) -> usize {
144        let Self {
145            inner,
146            general_gas_limit,
147            timestamp_millis_part,
148            shared_gas_limit,
149        } = self;
150        inner.size()
151            + general_gas_limit.size()
152            + timestamp_millis_part.size()
153            + shared_gas_limit.size()
154    }
155}
156
157impl Sealable for TempoHeader {
158    fn hash_slow(&self) -> B256 {
159        keccak256(alloy_rlp::encode(self))
160    }
161}
162
163impl reth_primitives_traits::BlockHeader for TempoHeader {}
164
165impl reth_primitives_traits::header::HeaderMut for TempoHeader {
166    fn set_parent_hash(&mut self, hash: BlockHash) {
167        self.inner.set_parent_hash(hash);
168    }
169
170    fn set_block_number(&mut self, number: BlockNumber) {
171        self.inner.set_block_number(number);
172    }
173
174    fn set_timestamp(&mut self, timestamp: u64) {
175        self.inner.set_timestamp(timestamp);
176    }
177
178    fn set_state_root(&mut self, state_root: B256) {
179        self.inner.set_state_root(state_root);
180    }
181
182    fn set_difficulty(&mut self, difficulty: U256) {
183        self.inner.set_difficulty(difficulty);
184    }
185}
186
187#[cfg(feature = "reth-codec")]
188impl reth_db_api::table::Compress for TempoHeader {
189    type Compressed = Vec<u8>;
190
191    fn compress_to_buf<B: alloy_primitives::bytes::BufMut + AsMut<[u8]>>(&self, buf: &mut B) {
192        let _ = reth_codecs::Compact::to_compact(self, buf);
193    }
194}
195
196#[cfg(feature = "reth-codec")]
197impl reth_db_api::table::Decompress for TempoHeader {
198    fn decompress(value: &[u8]) -> Result<Self, reth_db_api::DatabaseError> {
199        let (obj, _) = reth_codecs::Compact::from_compact(value, value.len());
200        Ok(obj)
201    }
202}