Skip to content

Commit

Permalink
limit maximal "free" parachain head size
Browse files Browse the repository at this point in the history
  • Loading branch information
svyatonik committed Mar 25, 2024
1 parent 36d7162 commit bb4ad4b
Show file tree
Hide file tree
Showing 12 changed files with 71 additions and 11 deletions.
1 change: 1 addition & 0 deletions bin/runtime-common/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,7 @@ impl Chain for BridgedUnderlyingParachain {

impl Parachain for BridgedUnderlyingParachain {
const PARACHAIN_ID: u32 = 42;
const MAX_HEADER_SIZE: u32 = 1_024;
}

/// The other, bridged chain, used in tests.
Expand Down
41 changes: 30 additions & 11 deletions modules/parachains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,7 @@ pub mod pallet {
}

// convert from parachain head into stored parachain head data
let parachain_head_size = parachain_head.0.len();
let parachain_head_data =
match T::ParaStoredHeaderDataBuilder::try_build(parachain, &parachain_head) {
Some(parachain_head_data) => parachain_head_data,
Expand All @@ -521,15 +522,17 @@ pub mod pallet {

let update_result: Result<_, ()> =
ParasInfo::<T, I>::try_mutate(parachain, |stored_best_head| {
let is_free = match stored_best_head {
Some(ref best_head)
if at_relay_block.0.saturating_sub(
best_head.best_head_hash.at_relay_block_number,
) >= free_headers_interval =>
true,
Some(_) => false,
None => true,
};
let is_free = parachain_head_size <
T::ParaStoredHeaderDataBuilder::max_free_head_size() as usize &&
match stored_best_head {
Some(ref best_head)
if at_relay_block.0.saturating_sub(
best_head.best_head_hash.at_relay_block_number,
) >= free_headers_interval =>
true,
Some(_) => false,
None => true,
};
let artifacts = Pallet::<T, I>::update_parachain_head(
parachain,
stored_best_head.take(),
Expand Down Expand Up @@ -582,7 +585,8 @@ pub mod pallet {
&& SubmitFinalityProofHelper::<T, T::BridgesGrandpaPalletInstance>::can_import_anything_for_free();
let pays_fee = if is_free {
log::trace!(target: LOG_TARGET, "Parachain heads update transaction is free");
pallet_bridge_grandpa::on_free_header_imported::<T, T::BridgesGrandpaPalletInstance>();
pallet_bridge_grandpa::on_free_header_imported::<T, T::BridgesGrandpaPalletInstance>(
);
Pays::No
} else {
log::trace!(target: LOG_TARGET, "Parachain heads update transaction is paid");
Expand Down Expand Up @@ -818,7 +822,7 @@ pub fn initialize_for_benchmarks<T: Config<I>, I: 'static, PC: Parachain<Hash =
pub(crate) mod tests {
use super::*;
use crate::mock::{
run_test, test_relay_header, BigParachainHeader, FreeHeadersInterval,
run_test, test_relay_header, BigParachain, BigParachainHeader, FreeHeadersInterval,
RegularParachainHasher, RegularParachainHeader, RelayBlockHeader,
RuntimeEvent as TestEvent, RuntimeOrigin, TestRuntime, UNTRACKED_PARACHAIN_ID,
};
Expand Down Expand Up @@ -1809,6 +1813,21 @@ pub(crate) mod tests {
proof,
);
assert_eq!(result.unwrap().pays_fee, Pays::No);
// then we submit new BIG head, proved after `FreeHeadersInterval` => Pays::Yes
// then we submit new head, proved after `FreeHeadersInterval` => Pays::No
let mut large_head = head_data(2, 100);
large_head.0.extend(&[42u8; BigParachain::MAX_HEADER_SIZE as _]);
let (state_root, proof, parachains) =
prepare_parachain_heads_proof::<RegularParachainHeader>(vec![(2, large_head)]);
let relay_block_number = relay_block_number + FreeHeadersInterval::get();
proceed(relay_block_number, state_root);
let result = Pallet::<TestRuntime>::submit_parachain_heads(
RuntimeOrigin::signed(1),
(relay_block_number, test_relay_header(relay_block_number, state_root).hash()),
parachains,
proof,
);
assert_eq!(result.unwrap().pays_fee, Pays::Yes);
})
}
}
4 changes: 4 additions & 0 deletions modules/parachains/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ impl Chain for Parachain1 {

impl Parachain for Parachain1 {
const PARACHAIN_ID: u32 = 1;
const MAX_HEADER_SIZE: u32 = 1_024;
}

pub struct Parachain2;
Expand All @@ -96,6 +97,7 @@ impl Chain for Parachain2 {

impl Parachain for Parachain2 {
const PARACHAIN_ID: u32 = 2;
const MAX_HEADER_SIZE: u32 = 1_024;
}

pub struct Parachain3;
Expand All @@ -122,6 +124,7 @@ impl Chain for Parachain3 {

impl Parachain for Parachain3 {
const PARACHAIN_ID: u32 = 3;
const MAX_HEADER_SIZE: u32 = 1_024;
}

// this parachain is using u128 as block number and stored head data size exceeds limit
Expand Down Expand Up @@ -149,6 +152,7 @@ impl Chain for BigParachain {

impl Parachain for BigParachain {
const PARACHAIN_ID: u32 = 4;
const MAX_HEADER_SIZE: u32 = 2_048;
}

construct_runtime! {
Expand Down
3 changes: 3 additions & 0 deletions primitives/chain-bridge-hub-cumulus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ use frame_support::{
use frame_system::limits;
use sp_std::time::Duration;

/// Maximal bridge hub header size.
pub const MAX_BRIDGE_HUB_HEADER_SIZE: u32 = 4_096;

/// Average block interval in Cumulus-based parachains.
///
/// Corresponds to the `MILLISECS_PER_BLOCK` from `parachains_common` crate.
Expand Down
1 change: 1 addition & 0 deletions primitives/chain-bridge-hub-kusama/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ impl Chain for BridgeHubKusama {

impl Parachain for BridgeHubKusama {
const PARACHAIN_ID: u32 = BRIDGE_HUB_KUSAMA_PARACHAIN_ID;
const MAX_HEADER_SIZE: u32 = MAX_BRIDGE_HUB_HEADER_SIZE;
}

impl ChainWithMessages for BridgeHubKusama {
Expand Down
1 change: 1 addition & 0 deletions primitives/chain-bridge-hub-polkadot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ impl Chain for BridgeHubPolkadot {

impl Parachain for BridgeHubPolkadot {
const PARACHAIN_ID: u32 = BRIDGE_HUB_POLKADOT_PARACHAIN_ID;
const MAX_HEADER_SIZE: u32 = MAX_BRIDGE_HUB_HEADER_SIZE;
}

impl ChainWithMessages for BridgeHubPolkadot {
Expand Down
1 change: 1 addition & 0 deletions primitives/chain-bridge-hub-rococo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ impl Chain for BridgeHubRococo {

impl Parachain for BridgeHubRococo {
const PARACHAIN_ID: u32 = BRIDGE_HUB_ROCOCO_PARACHAIN_ID;
const MAX_HEADER_SIZE: u32 = MAX_BRIDGE_HUB_HEADER_SIZE;
}

impl ChainWithMessages for BridgeHubRococo {
Expand Down
1 change: 1 addition & 0 deletions primitives/chain-bridge-hub-westend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ impl Chain for BridgeHubWestend {

impl Parachain for BridgeHubWestend {
const PARACHAIN_ID: u32 = BRIDGE_HUB_WESTEND_PARACHAIN_ID;
const MAX_HEADER_SIZE: u32 = MAX_BRIDGE_HUB_HEADER_SIZE;
}

impl ChainWithMessages for BridgeHubWestend {
Expand Down
19 changes: 19 additions & 0 deletions primitives/parachains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ impl ParaStoredHeaderData {

/// Stored parachain head data builder.
pub trait ParaStoredHeaderDataBuilder {
/// Maximal parachain head size that we may accept for free. All heads above
/// this limit are submitted for a regular fee.
fn max_free_head_size() -> u32;

/// Return number of parachains that are supported by this builder.
fn supported_parachains() -> u32;

Expand All @@ -127,6 +131,10 @@ pub trait ParaStoredHeaderDataBuilder {
pub struct SingleParaStoredHeaderDataBuilder<C: Parachain>(PhantomData<C>);

impl<C: Parachain> ParaStoredHeaderDataBuilder for SingleParaStoredHeaderDataBuilder<C> {
fn max_free_head_size() -> u32 {
C::MAX_HEADER_SIZE
}

fn supported_parachains() -> u32 {
1
}
Expand All @@ -147,6 +155,17 @@ impl<C: Parachain> ParaStoredHeaderDataBuilder for SingleParaStoredHeaderDataBui
#[impl_trait_for_tuples::impl_for_tuples(1, 30)]
#[tuple_types_custom_trait_bound(Parachain)]
impl ParaStoredHeaderDataBuilder for C {
fn max_free_head_size() -> u32 {
let mut result = 0_u32;
for_tuples!( #(
result = sp_std::cmp::max(
result,
SingleParaStoredHeaderDataBuilder::<C>::max_free_head_size(),
);
)* );
result
}

fn supported_parachains() -> u32 {
let mut result = 0;
for_tuples!( #(
Expand Down
8 changes: 8 additions & 0 deletions primitives/runtime/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,12 @@ where
pub trait Parachain: Chain {
/// Parachain identifier.
const PARACHAIN_ID: u32;
/// Maximal size of the parachain header.
///
/// This isn't a strict limit. The relayer may submit larger headers and the
/// pallet will accept the call. The limit is only used to compute whether
/// the refund can be made.
const MAX_HEADER_SIZE: u32;
}

impl<T> Parachain for T
Expand All @@ -255,6 +261,8 @@ where
<T as UnderlyingChainProvider>::Chain: Parachain,
{
const PARACHAIN_ID: u32 = <<T as UnderlyingChainProvider>::Chain as Parachain>::PARACHAIN_ID;
const MAX_HEADER_SIZE: u32 =
<<T as UnderlyingChainProvider>::Chain as Parachain>::MAX_HEADER_SIZE;
}

/// Adapter for `Get<u32>` to access `PARACHAIN_ID` from `trait Parachain`
Expand Down
1 change: 1 addition & 0 deletions relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ impl bp_runtime::Chain for BaseBridgeHubRococoAsBridgeHubPolkadot {

impl bp_runtime::Parachain for BaseBridgeHubRococoAsBridgeHubPolkadot {
const PARACHAIN_ID: u32 = bp_bridge_hub_rococo::BridgeHubRococo::PARACHAIN_ID;
const MAX_HEADER_SIZE: u32 = bp_bridge_hub_rococo::BridgeHubRococo::MAX_HEADER_SIZE;
}

impl bp_messages::ChainWithMessages for BaseBridgeHubRococoAsBridgeHubPolkadot {
Expand Down
1 change: 1 addition & 0 deletions relays/client-substrate/src/test_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ impl bp_runtime::Chain for TestParachainBase {

impl bp_runtime::Parachain for TestParachainBase {
const PARACHAIN_ID: u32 = 1000;
const MAX_HEADER_SIZE: u32 = 1_024;
}

/// Parachain that may be used in tests.
Expand Down

0 comments on commit bb4ad4b

Please sign in to comment.