Skip to content

Commit e400f0d

Browse files
svyatonikhitchho
authored andcommitted
Bridge: check bridge GRANDPA pallet call limits from signed extension (paritytech#4385)
silent, because it'll be deployed with the paritytech#4102, where this code has been introduced I've planned originally to avoid doing that check in the runtime code, because it **may be** checked offchain. But actually, the check is quite cheap and we could do that onchain too.
1 parent 18511d0 commit e400f0d

2 files changed

Lines changed: 68 additions & 2 deletions

File tree

bridges/modules/grandpa/src/call_ext.rs

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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
) {

bridges/modules/grandpa/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,9 @@ pub mod pallet {
504504
/// The submitter wanted free execution, but the difference between best known and
505505
/// bundled header numbers is below the `FreeHeadersInterval`.
506506
BelowFreeHeaderInterval,
507+
/// The header (and its finality) submission overflows hardcoded chain limits: size
508+
/// and/or weight are larger than expected.
509+
HeaderOverflowLimits,
507510
}
508511

509512
/// Called when new free header is imported.

0 commit comments

Comments
 (0)