Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bridge: check bridge GRANDPA pallet call limits from signed extension #4385

Merged
merged 1 commit into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 65 additions & 2 deletions bridges/modules/grandpa/src/call_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,13 @@ impl<T: Config<I>, I: 'static> SubmitFinalityProofHelper<T, I> {
}
}

// we do not check whether the header matches free submission criteria here - it is the
// relayer responsibility to check that
// let's also check whether the header submission fits the hardcoded limits. A normal
// relayer would check that before submitting a transaction (since limits are constants
// and do not depend on a volatile runtime state), but the ckeck itself is cheap, so
// let's do it here too
if !call_info.fits_limits() {
return Err(Error::<T, I>::HeaderOverflowLimits);
}

Ok(improved_by)
}
Expand Down Expand Up @@ -468,6 +473,64 @@ mod tests {
})
}

#[test]
fn extension_rejects_new_header_if_it_overflow_size_limits() {
run_test(|| {
let mut large_finality_target = test_header(10 + FreeHeadersInterval::get() as u64);
large_finality_target
.digest_mut()
.push(DigestItem::Other(vec![42u8; 1024 * 1024]));
let justification_params = JustificationGeneratorParams {
header: large_finality_target.clone(),
..Default::default()
};
let large_justification = make_justification_for_header(justification_params);

let bridge_grandpa_call = crate::Call::<TestRuntime, ()>::submit_finality_proof_ex {
finality_target: Box::new(large_finality_target),
justification: large_justification,
current_set_id: 0,
is_free_execution_expected: true,
};
sync_to_header_10();

// if overflow size limits => Err
FreeHeadersRemaining::<TestRuntime, ()>::put(2);
assert!(RuntimeCall::check_obsolete_submit_finality_proof(&RuntimeCall::Grandpa(
bridge_grandpa_call.clone(),
),)
.is_err());
})
}

#[test]
fn extension_rejects_new_header_if_it_overflow_weight_limits() {
run_test(|| {
let finality_target = test_header(10 + FreeHeadersInterval::get() as u64);
let justification_params = JustificationGeneratorParams {
header: finality_target.clone(),
ancestors: TestBridgedChain::REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY,
..Default::default()
};
let justification = make_justification_for_header(justification_params);

let bridge_grandpa_call = crate::Call::<TestRuntime, ()>::submit_finality_proof_ex {
finality_target: Box::new(finality_target),
justification,
current_set_id: 0,
is_free_execution_expected: true,
};
sync_to_header_10();

// if overflow weight limits => Err
FreeHeadersRemaining::<TestRuntime, ()>::put(2);
assert!(RuntimeCall::check_obsolete_submit_finality_proof(&RuntimeCall::Grandpa(
bridge_grandpa_call.clone(),
),)
.is_err());
})
}

#[test]
fn extension_rejects_new_header_if_free_execution_is_requested_and_improved_by_is_below_expected(
) {
Expand Down
3 changes: 3 additions & 0 deletions bridges/modules/grandpa/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,9 @@ pub mod pallet {
/// The submitter wanted free execution, but the difference between best known and
/// bundled header numbers is below the `FreeHeadersInterval`.
BelowFreeHeaderInterval,
/// The header (and its finality) submission overflows hardcoded chain limits: size
/// and/or weight are larger than expected.
HeaderOverflowLimits,
}

/// Called when new free header is imported.
Expand Down
Loading