openmina_core/block/
block_with_hash.rs1use 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}