@@ -148,8 +148,13 @@ impl<T: Config<I>, I: 'static> SubmitFinalityProofHelper<T, I> {
148148 }
149149 }
150150
151- // we do not check whether the header matches free submission criteria here - it is the
152- // relayer responsibility to check that
151+ // let's also check whether the header submission fits the hardcoded limits. A normal
152+ // relayer would check that before submitting a transaction (since limits are constants
153+ // and do not depend on a volatile runtime state), but the ckeck itself is cheap, so
154+ // let's do it here too
155+ if !call_info. fits_limits ( ) {
156+ return Err ( Error :: < T , I > :: HeaderOverflowLimits ) ;
157+ }
153158
154159 Ok ( improved_by)
155160 }
@@ -468,6 +473,64 @@ mod tests {
468473 } )
469474 }
470475
476+ #[ test]
477+ fn extension_rejects_new_header_if_it_overflow_size_limits ( ) {
478+ run_test ( || {
479+ let mut large_finality_target = test_header ( 10 + FreeHeadersInterval :: get ( ) as u64 ) ;
480+ large_finality_target
481+ . digest_mut ( )
482+ . push ( DigestItem :: Other ( vec ! [ 42u8 ; 1024 * 1024 ] ) ) ;
483+ let justification_params = JustificationGeneratorParams {
484+ header : large_finality_target. clone ( ) ,
485+ ..Default :: default ( )
486+ } ;
487+ let large_justification = make_justification_for_header ( justification_params) ;
488+
489+ let bridge_grandpa_call = crate :: Call :: < TestRuntime , ( ) > :: submit_finality_proof_ex {
490+ finality_target : Box :: new ( large_finality_target) ,
491+ justification : large_justification,
492+ current_set_id : 0 ,
493+ is_free_execution_expected : true ,
494+ } ;
495+ sync_to_header_10 ( ) ;
496+
497+ // if overflow size limits => Err
498+ FreeHeadersRemaining :: < TestRuntime , ( ) > :: put ( 2 ) ;
499+ assert ! ( RuntimeCall :: check_obsolete_submit_finality_proof( & RuntimeCall :: Grandpa (
500+ bridge_grandpa_call. clone( ) ,
501+ ) , )
502+ . is_err( ) ) ;
503+ } )
504+ }
505+
506+ #[ test]
507+ fn extension_rejects_new_header_if_it_overflow_weight_limits ( ) {
508+ run_test ( || {
509+ let finality_target = test_header ( 10 + FreeHeadersInterval :: get ( ) as u64 ) ;
510+ let justification_params = JustificationGeneratorParams {
511+ header : finality_target. clone ( ) ,
512+ ancestors : TestBridgedChain :: REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY ,
513+ ..Default :: default ( )
514+ } ;
515+ let justification = make_justification_for_header ( justification_params) ;
516+
517+ let bridge_grandpa_call = crate :: Call :: < TestRuntime , ( ) > :: submit_finality_proof_ex {
518+ finality_target : Box :: new ( finality_target) ,
519+ justification,
520+ current_set_id : 0 ,
521+ is_free_execution_expected : true ,
522+ } ;
523+ sync_to_header_10 ( ) ;
524+
525+ // if overflow weight limits => Err
526+ FreeHeadersRemaining :: < TestRuntime , ( ) > :: put ( 2 ) ;
527+ assert ! ( RuntimeCall :: check_obsolete_submit_finality_proof( & RuntimeCall :: Grandpa (
528+ bridge_grandpa_call. clone( ) ,
529+ ) , )
530+ . is_err( ) ) ;
531+ } )
532+ }
533+
471534 #[ test]
472535 fn extension_rejects_new_header_if_free_execution_is_requested_and_improved_by_is_below_expected (
473536 ) {
0 commit comments