mina_core/block/
prevalidate.rs1use super::ArcBlockWithHash;
2use crate::constants::PROTOCOL_VERSION;
3use serde::{Deserialize, Serialize};
4
5#[derive(Serialize, Deserialize, Debug, Clone)]
6pub enum BlockPrevalidationError {
7 GenesisNotReady,
8 ReceivedTooEarly {
9 current_global_slot: u32,
10 block_global_slot: u32,
11 },
12 ReceivedTooLate {
13 current_global_slot: u32,
14 block_global_slot: u32,
15 delta: u32,
16 },
17 InvalidGenesisProtocolState,
18 InvalidProtocolVersion,
19 MismatchedProtocolVersion,
20 ConsantsMismatch,
21 InvalidDeltaBlockChainProof,
22}
23
24impl BlockPrevalidationError {
25 pub fn is_forever_invalid(&self) -> bool {
26 !matches!(self, Self::ReceivedTooEarly { .. })
27 }
28}
29
30pub fn validate_block_timing(
31 block: &ArcBlockWithHash,
32 genesis: &ArcBlockWithHash,
33 cur_global_slot: u32,
34 allow_block_too_late: bool,
35) -> Result<(), BlockPrevalidationError> {
36 let block_global_slot = block.global_slot();
37 let delta = genesis.constants().delta.as_u32();
38
39 if cur_global_slot < block_global_slot {
40 return Err(BlockPrevalidationError::ReceivedTooEarly {
41 current_global_slot: cur_global_slot,
42 block_global_slot,
43 });
44 } else if !allow_block_too_late && cur_global_slot.saturating_sub(block_global_slot) > delta {
45 return Err(BlockPrevalidationError::ReceivedTooLate {
46 current_global_slot: cur_global_slot,
47 block_global_slot,
48 delta,
49 });
50 }
51
52 Ok(())
53}
54
55pub fn validate_genesis_state(
56 block: &ArcBlockWithHash,
57 genesis: &ArcBlockWithHash,
58) -> Result<(), BlockPrevalidationError> {
59 if block.header().genesis_state_hash() != genesis.hash() {
60 return Err(BlockPrevalidationError::InvalidGenesisProtocolState);
61 }
62 Ok(())
63}
64
65pub fn validate_protocol_versions(block: &ArcBlockWithHash) -> Result<(), BlockPrevalidationError> {
66 let min_transaction_version = 1.into();
67 let v = &block.header().current_protocol_version;
68 let nv = block
69 .header()
70 .proposed_protocol_version_opt
71 .as_ref()
72 .unwrap_or(v);
73
74 let valid =
77 v.transaction >= min_transaction_version && nv.transaction >= min_transaction_version;
78 if !valid {
79 return Err(BlockPrevalidationError::InvalidProtocolVersion);
80 }
81
82 let compatible =
83 v.transaction == PROTOCOL_VERSION.transaction && v.network == PROTOCOL_VERSION.network;
84 if !compatible {
85 return Err(BlockPrevalidationError::MismatchedProtocolVersion);
86 }
87
88 Ok(())
89}
90
91pub fn validate_constants(
92 block: &ArcBlockWithHash,
93 genesis: &ArcBlockWithHash,
94) -> Result<(), BlockPrevalidationError> {
95 if block.constants() != genesis.constants() {
98 return Err(BlockPrevalidationError::ConsantsMismatch);
99 }
100 Ok(())
101}
102
103pub fn prevalidate_block(
104 block: &ArcBlockWithHash,
105 genesis: &ArcBlockWithHash,
106 cur_global_slot: u32,
107 allow_block_too_late: bool,
108) -> Result<(), BlockPrevalidationError> {
109 validate_block_timing(block, genesis, cur_global_slot, allow_block_too_late)?;
110 validate_genesis_state(block, genesis)?;
111 validate_protocol_versions(block)?;
112 validate_constants(block, genesis)?;
113
114 Ok(())
119}