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