openmina_core/block/
block_with_hash.rs

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