Skip to main content

tempo_primitives/
header.rs

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