@@ -2,6 +2,7 @@ use std::sync::Arc;
22use std:: time:: Duration ;
33
44use mina_p2p_messages:: v2:: { MinaBaseUserCommandStableV2 , MinaBlockBlockStableV2 } ;
5+ use openmina_core:: constants:: PROTOCOL_VERSION ;
56use rand:: prelude:: * ;
67
78use openmina_core:: block:: BlockWithHash ;
@@ -73,6 +74,17 @@ pub struct State {
7374 applied_actions_count : u64 ,
7475}
7576
77+ #[ derive( Serialize , Deserialize , Debug , Clone ) ]
78+ pub enum BlockPrevalidationError {
79+ GenesisNotReady ,
80+ ReceivedTooEarly ,
81+ ReceivedTooLate ,
82+ InvalidGenesisProtocolState ,
83+ InvalidProtocolVersion ,
84+ MismatchedProtocolVersion ,
85+ InvalidDeltaBlockChainProof ,
86+ }
87+
7688// Substate accessors that will be used in reducers
7789use openmina_core:: { impl_substate_access, SubstateAccess } ;
7890
@@ -356,15 +368,18 @@ impl State {
356368 } )
357369 }
358370
359- pub fn prevalidate_block ( & self , block : & ArcBlockWithHash ) -> bool {
371+ pub fn prevalidate_block (
372+ & self ,
373+ block : & ArcBlockWithHash ,
374+ ) -> Result < ( ) , BlockPrevalidationError > {
360375 let Some ( ( genesis, cur_global_slot) ) =
361376 None . or_else ( || Some ( ( self . genesis_block ( ) ?, self . cur_global_slot ( ) ?) ) )
362377 else {
363378 // we don't have genesis block. This should be impossible
364379 // because we don't even know chain_id before we have genesis
365380 // block, so we can't be connected to any peers from which
366381 // we would receive a block.
367- return false ;
382+ return Err ( BlockPrevalidationError :: GenesisNotReady ) ;
368383 } ;
369384
370385 // received_at_valid_time
@@ -375,23 +390,47 @@ impl State {
375390 let delta = genesis. constants ( ) . delta . as_u32 ( ) ;
376391 if cur_global_slot < block_global_slot {
377392 // Too_early
378- return false ;
393+ return Err ( BlockPrevalidationError :: ReceivedTooEarly ) ;
379394 } else if cur_global_slot. saturating_sub ( block_global_slot) > delta {
380395 // Too_late
381- return false ;
396+ return Err ( BlockPrevalidationError :: ReceivedTooLate ) ;
382397 }
383398 }
384399
385- if block. constants ( ) != genesis. constants ( ) {
386- return false ;
400+ if block. header ( ) . genesis_state_hash ( ) != genesis. hash ( ) {
401+ return Err ( BlockPrevalidationError :: InvalidGenesisProtocolState ) ;
387402 }
388403
389- if block. header ( ) . genesis_state_hash ( ) != genesis. hash ( ) {
390- return false ;
404+ let ( protocol_versions_are_valid, protocol_version_matches_daemon) = {
405+ let min_transaction_version = 1 . into ( ) ;
406+ let v = & block. header ( ) . current_protocol_version ;
407+ let nv = block
408+ . header ( )
409+ . proposed_protocol_version_opt
410+ . as_ref ( )
411+ . unwrap_or ( v) ;
412+
413+ // Our version values are unsigned, so there is no need to check that the
414+ // other parts are not negative.
415+ let valid = v. transaction >= min_transaction_version
416+ && nv. transaction >= min_transaction_version;
417+ let compatible = v. transaction == PROTOCOL_VERSION . transaction
418+ && v. network == PROTOCOL_VERSION . network ;
419+
420+ ( valid, compatible)
421+ } ;
422+
423+ if !protocol_versions_are_valid {
424+ return Err ( BlockPrevalidationError :: InvalidProtocolVersion ) ;
425+ } else if !protocol_version_matches_daemon {
426+ return Err ( BlockPrevalidationError :: MismatchedProtocolVersion ) ;
391427 }
392428
393- // TODO(binier): more checks.
394- true
429+ // TODO(tizoc): check for InvalidDeltaBlockChainProof
430+ // https://github.com/MinaProtocol/mina/blob/d800da86a764d8d37ffb8964dd8d54d9f522b358/src/lib/mina_block/validation.ml#L369
431+ // https://github.com/MinaProtocol/mina/blob/d800da86a764d8d37ffb8964dd8d54d9f522b358/src/lib/transition_chain_verifier/transition_chain_verifier.ml
432+
433+ Ok ( ( ) )
395434 }
396435
397436 pub fn should_log_node_id ( & self ) -> bool {
0 commit comments