mina_core/block/
block_with_hash.rs

1use mina_p2p_messages::{bigint::InvalidBigInt, v2};
2use redux::Timestamp;
3use serde::{Deserialize, Serialize};
4
5use crate::constants::constraint_constants;
6
7use super::{Block, BlockHash, BlockHeader};
8
9#[derive(Serialize, Deserialize, Debug, Clone)]
10pub struct BlockWithHash<T: AsRef<Block>> {
11    pub hash: BlockHash,
12    pub block: T,
13}
14
15impl<T: AsRef<Block>> std::cmp::PartialEq for BlockWithHash<T> {
16    fn eq(&self, other: &Self) -> bool {
17        self.hash == other.hash
18    }
19}
20
21#[derive(Serialize, Deserialize, Debug, Clone)]
22pub struct BlockHeaderWithHash<T: AsRef<BlockHeader>> {
23    pub hash: BlockHash,
24    pub header: T,
25}
26
27impl<T: AsRef<Block>> BlockWithHash<T> {
28    pub fn try_new(block: T) -> Result<Self, InvalidBigInt> {
29        Ok(Self {
30            hash: block.as_ref().try_hash()?,
31            block,
32        })
33    }
34
35    pub fn hash(&self) -> &BlockHash {
36        &self.hash
37    }
38
39    pub fn pred_hash(&self) -> &BlockHash {
40        &self.header().protocol_state.previous_state_hash
41    }
42
43    pub fn header(&self) -> &BlockHeader {
44        &self.block.as_ref().header
45    }
46
47    pub fn body(&self) -> &v2::StagedLedgerDiffBodyStableV1 {
48        &self.block.as_ref().body
49    }
50
51    pub fn consensus_state(&self) -> &v2::ConsensusProofOfStakeDataConsensusStateValueStableV2 {
52        consensus_state(self.header())
53    }
54
55    pub fn height(&self) -> u32 {
56        height(self.header())
57    }
58
59    pub fn global_slot(&self) -> u32 {
60        global_slot(self.header())
61    }
62
63    pub fn slot(&self) -> u32 {
64        slot(self.header())
65    }
66
67    pub fn global_slot_since_genesis(&self) -> u32 {
68        global_slot_since_genesis(self.header())
69    }
70
71    pub fn curr_global_slot_since_hard_fork(&self) -> &v2::ConsensusGlobalSlotStableV1 {
72        curr_global_slot_since_hard_fork(self.header())
73    }
74
75    pub fn global_slot_diff(&self) -> u32 {
76        global_slot_diff(self.header())
77    }
78
79    pub fn timestamp(&self) -> Timestamp {
80        timestamp(self.header())
81    }
82
83    pub fn genesis_timestamp(&self) -> Timestamp {
84        genesis_timestamp(self.header())
85    }
86
87    pub fn constants(&self) -> &v2::MinaBaseProtocolConstantsCheckedValueStableV1 {
88        constants(self.header())
89    }
90
91    pub fn producer(&self) -> &v2::NonZeroCurvePoint {
92        producer(self.header())
93    }
94
95    pub fn genesis_ledger_hash(&self) -> &v2::LedgerHash {
96        genesis_ledger_hash(self.header())
97    }
98
99    pub fn snarked_ledger_hash(&self) -> &v2::LedgerHash {
100        snarked_ledger_hash(self.header())
101    }
102
103    pub fn staking_epoch_ledger_hash(&self) -> &v2::LedgerHash {
104        staking_epoch_ledger_hash(self.header())
105    }
106
107    pub fn next_epoch_ledger_hash(&self) -> &v2::LedgerHash {
108        next_epoch_ledger_hash(self.header())
109    }
110
111    pub fn merkle_root_hash(&self) -> &v2::LedgerHash {
112        merkle_root_hash(self.header())
113    }
114
115    pub fn staged_ledger_hashes(&self) -> &v2::MinaBaseStagedLedgerHashStableV1 {
116        staged_ledger_hashes(self.header())
117    }
118
119    pub fn is_genesis(&self) -> bool {
120        self.height() == 1
121            || constraint_constants()
122                .fork
123                .as_ref()
124                .is_some_and(|fork| fork.blockchain_length + 1 == self.height())
125    }
126
127    pub fn root_block_height(&self) -> u32 {
128        let k = self.constants().k.as_u32();
129        self.height().saturating_sub(k).max(1)
130    }
131
132    pub fn staged_ledger_diff(&self) -> &v2::StagedLedgerDiffDiffDiffStableV2 {
133        self.body().diff()
134    }
135
136    pub fn commands_iter<'a>(
137        &'a self,
138    ) -> Box<
139        dyn 'a + Iterator<Item = &'a v2::StagedLedgerDiffDiffPreDiffWithAtMostTwoCoinbaseStableV2B>,
140    > {
141        self.body().commands_iter()
142    }
143
144    pub fn coinbase_fee_transfers_iter(
145        &self,
146    ) -> impl Iterator<Item = &v2::StagedLedgerDiffDiffFtStableV1> {
147        self.body().coinbase_fee_transfers_iter()
148    }
149
150    pub fn completed_works_iter<'a>(
151        &'a self,
152    ) -> Box<dyn 'a + Iterator<Item = &'a v2::TransactionSnarkWorkTStableV2>> {
153        self.body().completed_works_iter()
154    }
155
156    pub fn block_stake_winner(&self) -> &v2::NonZeroCurvePoint {
157        block_stake_winner(self.header())
158    }
159}
160
161impl<T: AsRef<BlockHeader>> BlockHeaderWithHash<T> {
162    pub fn hash(&self) -> &BlockHash {
163        &self.hash
164    }
165
166    pub fn pred_hash(&self) -> &BlockHash {
167        &self.header().protocol_state.previous_state_hash
168    }
169
170    pub fn header(&self) -> &BlockHeader {
171        self.header.as_ref()
172    }
173
174    pub fn consensus_state(&self) -> &v2::ConsensusProofOfStakeDataConsensusStateValueStableV2 {
175        consensus_state(self.header())
176    }
177
178    pub fn height(&self) -> u32 {
179        height(self.header())
180    }
181
182    pub fn global_slot(&self) -> u32 {
183        global_slot(self.header())
184    }
185
186    pub fn slot(&self) -> u32 {
187        slot(self.header())
188    }
189
190    pub fn global_slot_since_genesis(&self) -> u32 {
191        global_slot_since_genesis(self.header())
192    }
193
194    pub fn curr_global_slot_since_hard_fork(&self) -> &v2::ConsensusGlobalSlotStableV1 {
195        curr_global_slot_since_hard_fork(self.header())
196    }
197
198    pub fn global_slot_diff(&self) -> u32 {
199        global_slot_diff(self.header())
200    }
201
202    pub fn timestamp(&self) -> Timestamp {
203        timestamp(self.header())
204    }
205
206    pub fn genesis_timestamp(&self) -> Timestamp {
207        genesis_timestamp(self.header())
208    }
209
210    pub fn constants(&self) -> &v2::MinaBaseProtocolConstantsCheckedValueStableV1 {
211        constants(self.header())
212    }
213
214    pub fn producer(&self) -> &v2::NonZeroCurvePoint {
215        producer(self.header())
216    }
217
218    pub fn genesis_ledger_hash(&self) -> &v2::LedgerHash {
219        genesis_ledger_hash(self.header())
220    }
221
222    pub fn snarked_ledger_hash(&self) -> &v2::LedgerHash {
223        snarked_ledger_hash(self.header())
224    }
225
226    pub fn staking_epoch_ledger_hash(&self) -> &v2::LedgerHash {
227        staking_epoch_ledger_hash(self.header())
228    }
229
230    pub fn next_epoch_ledger_hash(&self) -> &v2::LedgerHash {
231        next_epoch_ledger_hash(self.header())
232    }
233
234    pub fn merkle_root_hash(&self) -> &v2::LedgerHash {
235        merkle_root_hash(self.header())
236    }
237
238    pub fn staged_ledger_hashes(&self) -> &v2::MinaBaseStagedLedgerHashStableV1 {
239        staged_ledger_hashes(self.header())
240    }
241
242    pub fn block_stake_winner(&self) -> &v2::NonZeroCurvePoint {
243        block_stake_winner(self.header())
244    }
245}
246
247fn consensus_state(
248    header: &BlockHeader,
249) -> &v2::ConsensusProofOfStakeDataConsensusStateValueStableV2 {
250    &header.protocol_state.body.consensus_state
251}
252
253fn height(header: &BlockHeader) -> u32 {
254    consensus_state(header).blockchain_length.as_u32()
255}
256
257fn global_slot(header: &BlockHeader) -> u32 {
258    consensus_state(header).global_slot()
259}
260
261fn slot(header: &BlockHeader) -> u32 {
262    let slot_struct = &consensus_state(header).curr_global_slot_since_hard_fork;
263    slot_struct
264        .slot_number
265        .as_u32()
266        .checked_rem(slot_struct.slots_per_epoch.as_u32())
267        .expect("division by zero")
268}
269
270fn global_slot_since_genesis(header: &BlockHeader) -> u32 {
271    consensus_state(header).global_slot_since_genesis.as_u32()
272}
273
274fn curr_global_slot_since_hard_fork(header: &BlockHeader) -> &v2::ConsensusGlobalSlotStableV1 {
275    &consensus_state(header).curr_global_slot_since_hard_fork
276}
277
278fn global_slot_diff(header: &BlockHeader) -> u32 {
279    let s = consensus_state(header);
280    s.global_slot_since_genesis
281        .as_u32()
282        .saturating_sub(s.global_slot())
283}
284
285fn timestamp(header: &BlockHeader) -> Timestamp {
286    let ms = header
287        .protocol_state
288        .body
289        .blockchain_state
290        .timestamp
291        .as_u64();
292    Timestamp::new(ms * 1_000_000)
293}
294
295fn genesis_timestamp(header: &BlockHeader) -> Timestamp {
296    let genesis_timestamp = constants(header).genesis_state_timestamp.0.as_u64();
297    Timestamp::new(genesis_timestamp * 1_000_000)
298}
299
300fn constants(header: &BlockHeader) -> &v2::MinaBaseProtocolConstantsCheckedValueStableV1 {
301    &header.protocol_state.body.constants
302}
303
304fn producer(header: &BlockHeader) -> &v2::NonZeroCurvePoint {
305    &header.protocol_state.body.consensus_state.block_creator
306}
307
308fn genesis_ledger_hash(header: &BlockHeader) -> &v2::LedgerHash {
309    &header
310        .protocol_state
311        .body
312        .blockchain_state
313        .genesis_ledger_hash
314}
315
316fn snarked_ledger_hash(header: &BlockHeader) -> &v2::LedgerHash {
317    &header
318        .protocol_state
319        .body
320        .blockchain_state
321        .ledger_proof_statement
322        .target
323        .first_pass_ledger
324}
325
326fn staking_epoch_ledger_hash(header: &BlockHeader) -> &v2::LedgerHash {
327    &consensus_state(header).staking_epoch_data.ledger.hash
328}
329
330fn next_epoch_ledger_hash(header: &BlockHeader) -> &v2::LedgerHash {
331    &consensus_state(header).next_epoch_data.ledger.hash
332}
333
334fn merkle_root_hash(header: &BlockHeader) -> &v2::LedgerHash {
335    &staged_ledger_hashes(header).non_snark.ledger_hash
336}
337
338fn staged_ledger_hashes(header: &BlockHeader) -> &v2::MinaBaseStagedLedgerHashStableV1 {
339    &header
340        .protocol_state
341        .body
342        .blockchain_state
343        .staged_ledger_hash
344}
345
346fn block_stake_winner(header: &BlockHeader) -> &v2::NonZeroCurvePoint {
347    &header
348        .protocol_state
349        .body
350        .consensus_state
351        .block_stake_winner
352}