@@ -15,7 +15,7 @@ use crate::mock::{
1515
1616pub use crate :: mock:: * ;
1717
18- use crate :: config:: { EPOCHS_PER_SYNC_COMMITTEE_PERIOD , SLOTS_PER_EPOCH } ;
18+ use crate :: config:: { EPOCHS_PER_SYNC_COMMITTEE_PERIOD , SLOTS_PER_EPOCH , SLOTS_PER_HISTORICAL_ROOT } ;
1919use frame_support:: { assert_err, assert_noop, assert_ok} ;
2020use hex_literal:: hex;
2121use primitives:: {
@@ -884,6 +884,61 @@ fn submit_execution_header_not_finalized() {
884884 } ) ;
885885}
886886
887+ /// Check that a gap of more than 8192 slots between finalized headers is not allowed.
888+ #[ test]
889+ fn submit_finalized_header_update_with_too_large_gap ( ) {
890+ let checkpoint = Box :: new ( load_checkpoint_update_fixture ( ) ) ;
891+ let update = Box :: new ( load_sync_committee_update_fixture ( ) ) ;
892+ let mut next_update = Box :: new ( load_next_sync_committee_update_fixture ( ) ) ;
893+
894+ // Adds 8193 slots, so that the next update is still in the next sync committee, but the
895+ // gap between the finalized headers is more than 8192 slots.
896+ let slot_with_large_gap = checkpoint. header . slot + SLOTS_PER_HISTORICAL_ROOT as u64 + 1 ;
897+
898+ next_update. finalized_header . slot = slot_with_large_gap;
899+ // Adding some slots to the attested header and signature slot since they need to be ahead
900+ // of the finalized header.
901+ next_update. attested_header . slot = slot_with_large_gap + 33 ;
902+ next_update. signature_slot = slot_with_large_gap + 43 ;
903+
904+ new_tester ( ) . execute_with ( || {
905+ assert_ok ! ( EthereumBeaconClient :: process_checkpoint_update( & checkpoint) ) ;
906+ assert_ok ! ( EthereumBeaconClient :: submit( RuntimeOrigin :: signed( 1 ) , update. clone( ) ) ) ;
907+ assert ! ( <NextSyncCommittee <Test >>:: exists( ) ) ;
908+ assert_err ! (
909+ EthereumBeaconClient :: submit( RuntimeOrigin :: signed( 1 ) , next_update. clone( ) ) ,
910+ Error :: <Test >:: InvalidFinalizedHeaderGap
911+ ) ;
912+ } ) ;
913+ }
914+
915+ /// Check that a gap of 8192 slots between finalized headers is allowed.
916+ #[ test]
917+ fn submit_finalized_header_update_with_gap_at_limit ( ) {
918+ let checkpoint = Box :: new ( load_checkpoint_update_fixture ( ) ) ;
919+ let update = Box :: new ( load_sync_committee_update_fixture ( ) ) ;
920+ let mut next_update = Box :: new ( load_next_sync_committee_update_fixture ( ) ) ;
921+
922+ next_update. finalized_header . slot = checkpoint. header . slot + SLOTS_PER_HISTORICAL_ROOT as u64 ;
923+ // Adding some slots to the attested header and signature slot since they need to be ahead
924+ // of the finalized header.
925+ next_update. attested_header . slot =
926+ checkpoint. header . slot + SLOTS_PER_HISTORICAL_ROOT as u64 + 33 ;
927+ next_update. signature_slot = checkpoint. header . slot + SLOTS_PER_HISTORICAL_ROOT as u64 + 43 ;
928+
929+ new_tester ( ) . execute_with ( || {
930+ assert_ok ! ( EthereumBeaconClient :: process_checkpoint_update( & checkpoint) ) ;
931+ assert_ok ! ( EthereumBeaconClient :: submit( RuntimeOrigin :: signed( 1 ) , update. clone( ) ) ) ;
932+ assert ! ( <NextSyncCommittee <Test >>:: exists( ) ) ;
933+ assert_err ! (
934+ EthereumBeaconClient :: submit( RuntimeOrigin :: signed( 1 ) , next_update. clone( ) ) ,
935+ // The test should pass the InvalidFinalizedHeaderGap check, and will fail at the
936+ // next check, the merkle proof, because we changed the next_update slots.
937+ Error :: <Test >:: InvalidHeaderMerkleProof
938+ ) ;
939+ } ) ;
940+ }
941+
887942/* IMPLS */
888943
889944#[ test]
0 commit comments