@@ -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,18 @@ 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+ ConsantsMismatch ,
86+ InvalidDeltaBlockChainProof ,
87+ }
88+
7689// Substate accessors that will be used in reducers
7790use openmina_core:: { impl_substate_access, SubstateAccess } ;
7891
@@ -356,15 +369,18 @@ impl State {
356369 } )
357370 }
358371
359- pub fn prevalidate_block ( & self , block : & ArcBlockWithHash ) -> bool {
372+ pub fn prevalidate_block (
373+ & self ,
374+ block : & ArcBlockWithHash ,
375+ ) -> Result < ( ) , BlockPrevalidationError > {
360376 let Some ( ( genesis, cur_global_slot) ) =
361377 None . or_else ( || Some ( ( self . genesis_block ( ) ?, self . cur_global_slot ( ) ?) ) )
362378 else {
363379 // we don't have genesis block. This should be impossible
364380 // because we don't even know chain_id before we have genesis
365381 // block, so we can't be connected to any peers from which
366382 // we would receive a block.
367- return false ;
383+ return Err ( BlockPrevalidationError :: GenesisNotReady ) ;
368384 } ;
369385
370386 // received_at_valid_time
@@ -375,23 +391,53 @@ impl State {
375391 let delta = genesis. constants ( ) . delta . as_u32 ( ) ;
376392 if cur_global_slot < block_global_slot {
377393 // Too_early
378- return false ;
394+ return Err ( BlockPrevalidationError :: ReceivedTooEarly ) ;
379395 } else if cur_global_slot. saturating_sub ( block_global_slot) > delta {
380396 // Too_late
381- return false ;
397+ return Err ( BlockPrevalidationError :: ReceivedTooLate ) ;
382398 }
383399 }
384400
385- if block. constants ( ) != genesis. constants ( ) {
386- return false ;
401+ if block. header ( ) . genesis_state_hash ( ) != genesis. hash ( ) {
402+ return Err ( BlockPrevalidationError :: InvalidGenesisProtocolState ) ;
387403 }
388404
389- if block. header ( ) . genesis_state_hash ( ) != genesis. hash ( ) {
390- return false ;
405+ let ( protocol_versions_are_valid, protocol_version_matches_daemon) = {
406+ let min_transaction_version = 1 . into ( ) ;
407+ let v = & block. header ( ) . current_protocol_version ;
408+ let nv = block
409+ . header ( )
410+ . proposed_protocol_version_opt
411+ . as_ref ( )
412+ . unwrap_or ( v) ;
413+
414+ // Our version values are unsigned, so there is no need to check that the
415+ // other parts are not negative.
416+ let valid = v. transaction >= min_transaction_version
417+ && nv. transaction >= min_transaction_version;
418+ let compatible = v. transaction == PROTOCOL_VERSION . transaction
419+ && v. network == PROTOCOL_VERSION . network ;
420+
421+ ( valid, compatible)
422+ } ;
423+
424+ if !protocol_versions_are_valid {
425+ return Err ( BlockPrevalidationError :: InvalidProtocolVersion ) ;
426+ } else if !protocol_version_matches_daemon {
427+ return Err ( BlockPrevalidationError :: MismatchedProtocolVersion ) ;
428+ }
429+
430+ // NOTE: currently these cannot change between blocks, but that
431+ // may not always be true?
432+ if block. constants ( ) != genesis. constants ( ) {
433+ return Err ( BlockPrevalidationError :: ConsantsMismatch ) ;
391434 }
392435
393- // TODO(binier): more checks.
394- true
436+ // TODO(tizoc): check for InvalidDeltaBlockChainProof
437+ // https://github.com/MinaProtocol/mina/blob/d800da86a764d8d37ffb8964dd8d54d9f522b358/src/lib/mina_block/validation.ml#L369
438+ // https://github.com/MinaProtocol/mina/blob/d800da86a764d8d37ffb8964dd8d54d9f522b358/src/lib/transition_chain_verifier/transition_chain_verifier.ml
439+
440+ Ok ( ( ) )
395441 }
396442
397443 pub fn should_log_node_id ( & self ) -> bool {
0 commit comments