From c6cb9cca64cab34eb68d1f348b6b345d93bd12a5 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Thu, 16 May 2024 12:43:56 +0200 Subject: [PATCH] [Runtime] Bound XCMP queue (#3952) Re-applying #2302 after increasing the `MaxPageSize`. Remove `without_storage_info` from the XCMP queue pallet. Part of https://github.com/paritytech/polkadot-sdk/issues/323 Changes: - Limit the number of messages and signals a HRMP channel can have at most. - Limit the number of HRML channels. A No-OP migration is put in place to ensure that all `BoundedVec`s still decode and not truncate after upgrade. The storage version is thereby bumped to 5 to have our tooling remind us to deploy that migration. ## Integration If you see this error in your try-runtime-cli: ```pre Max message size for channel is too large. This means that the V5 migration can be front-run and an attacker could place a large message just right before the migration to make other messages un-decodable. Please either increase `MaxPageSize` or decrease the `max_message_size` for this channel. Channel max: 102400, MaxPageSize: 65535 ``` Then increase the `MaxPageSize` of the `cumulus_pallet_xcmp_queue` to something like this: ```rust type MaxPageSize = ConstU32<{ 103 * 1024 }>; ``` There is currently no easy way for on-chain governance to adjust the HRMP max message size of all channels, but it could be done: https://github.com/paritytech/polkadot-sdk/issues/3145. --------- Signed-off-by: Oliver Tale-Yazdi Co-authored-by: Francisco Aguirre --- cumulus/pallets/parachain-system/src/lib.rs | 9 +- cumulus/pallets/parachain-system/src/mock.rs | 2 +- cumulus/pallets/xcmp-queue/src/lib.rs | 120 +++++++++++++----- cumulus/pallets/xcmp-queue/src/migration.rs | 4 +- .../pallets/xcmp-queue/src/migration/v5.rs | 108 ++++++++++++++++ cumulus/pallets/xcmp-queue/src/mock.rs | 6 +- cumulus/pallets/xcmp-queue/src/tests.rs | 2 +- .../assets/asset-hub-rococo/src/lib.rs | 14 +- .../assets/asset-hub-westend/src/lib.rs | 14 +- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 16 ++- .../bridge-hubs/bridge-hub-westend/src/lib.rs | 14 +- .../collectives-westend/src/lib.rs | 14 +- .../contracts/contracts-rococo/src/lib.rs | 3 +- .../contracts-rococo/src/xcm_config.rs | 11 +- .../coretime/coretime-rococo/src/lib.rs | 14 +- .../coretime/coretime-westend/src/lib.rs | 13 +- .../glutton/glutton-westend/src/lib.rs | 5 +- .../runtimes/people/people-rococo/src/lib.rs | 13 +- .../runtimes/people/people-westend/src/lib.rs | 13 +- .../runtimes/starters/shell/src/lib.rs | 2 +- .../runtimes/testing/penpal/src/lib.rs | 8 +- .../testing/rococo-parachain/src/lib.rs | 8 +- cumulus/primitives/core/src/lib.rs | 8 ++ polkadot/parachain/src/primitives.rs | 14 +- prdoc/pr_3952.prdoc | 35 +++++ .../parachain/runtime/src/configs/mod.rs | 4 +- 26 files changed, 407 insertions(+), 67 deletions(-) create mode 100644 cumulus/pallets/xcmp-queue/src/migration/v5.rs create mode 100644 prdoc/pr_3952.prdoc diff --git a/cumulus/pallets/parachain-system/src/lib.rs b/cumulus/pallets/parachain-system/src/lib.rs index c8e7d1bb30f71..7657dc4555eee 100644 --- a/cumulus/pallets/parachain-system/src/lib.rs +++ b/cumulus/pallets/parachain-system/src/lib.rs @@ -30,7 +30,7 @@ use codec::{Decode, Encode}; use cumulus_primitives_core::{ relay_chain, AbridgedHostConfiguration, ChannelInfo, ChannelStatus, CollationInfo, - GetChannelInfo, InboundDownwardMessage, InboundHrmpMessage, MessageSendError, + GetChannelInfo, InboundDownwardMessage, InboundHrmpMessage, ListChannelInfos, MessageSendError, OutboundHrmpMessage, ParaId, PersistedValidationData, UpwardMessage, UpwardMessageSender, XcmpMessageHandler, XcmpMessageSource, }; @@ -1022,6 +1022,13 @@ impl FeeTracker for Pallet { } } +impl ListChannelInfos for Pallet { + fn outgoing_channels() -> Vec { + let Some(state) = RelevantMessagingState::::get() else { return Vec::new() }; + state.egress_channels.into_iter().map(|(id, _)| id).collect() + } +} + impl GetChannelInfo for Pallet { fn get_channel_status(id: ParaId) -> ChannelStatus { // Note, that we are using `relevant_messaging_state` which may be from the previous diff --git a/cumulus/pallets/parachain-system/src/mock.rs b/cumulus/pallets/parachain-system/src/mock.rs index fe89dfe68c67e..e8d2eb70e2629 100644 --- a/cumulus/pallets/parachain-system/src/mock.rs +++ b/cumulus/pallets/parachain-system/src/mock.rs @@ -122,7 +122,7 @@ impl pallet_message_queue::Config for Test { type Size = u32; type QueueChangeHandler = (); type QueuePausedQuery = (); - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MaxWeight; type IdleMaxServiceWeight = (); diff --git a/cumulus/pallets/xcmp-queue/src/lib.rs b/cumulus/pallets/xcmp-queue/src/lib.rs index cc785b66150e5..5633f05f13bb8 100644 --- a/cumulus/pallets/xcmp-queue/src/lib.rs +++ b/cumulus/pallets/xcmp-queue/src/lib.rs @@ -51,7 +51,7 @@ pub mod weights; pub use weights::WeightInfo; use bounded_collections::BoundedBTreeSet; -use codec::{Decode, DecodeLimit, Encode}; +use codec::{Decode, DecodeLimit, Encode, MaxEncodedLen}; use cumulus_primitives_core::{ relay_chain::BlockNumber as RelayBlockNumber, ChannelStatus, GetChannelInfo, MessageSendError, ParaId, XcmpMessageFormat, XcmpMessageHandler, XcmpMessageSource, @@ -59,7 +59,7 @@ use cumulus_primitives_core::{ use frame_support::{ defensive, defensive_assert, - traits::{EnqueueMessage, EnsureOrigin, Get, QueueFootprint, QueuePausedQuery}, + traits::{Defensive, EnqueueMessage, EnsureOrigin, Get, QueueFootprint, QueuePausedQuery}, weights::{Weight, WeightMeter}, BoundedVec, }; @@ -68,7 +68,7 @@ use polkadot_runtime_common::xcm_sender::PriceForMessageDelivery; use polkadot_runtime_parachains::FeeTracker; use scale_info::TypeInfo; use sp_core::MAX_POSSIBLE_ALLOCATION; -use sp_runtime::{FixedU128, RuntimeDebug, Saturating}; +use sp_runtime::{FixedU128, RuntimeDebug, Saturating, WeakBoundedVec}; use sp_std::prelude::*; use xcm::{latest::prelude::*, VersionedLocation, VersionedXcm, WrapVersion, MAX_XCM_DECODE_DEPTH}; use xcm_builder::InspectMessageQueues; @@ -106,7 +106,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::storage_version(migration::STORAGE_VERSION)] - #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::config] @@ -133,6 +132,25 @@ pub mod pallet { #[pallet::constant] type MaxInboundSuspended: Get; + /// Maximal number of outbound XCMP channels that can have messages queued at the same time. + /// + /// If this is reached, then no further messages can be sent to channels that do not yet + /// have a message queued. This should be set to the expected maximum of outbound channels + /// which is determined by [`Self::ChannelInfo`]. It is important to set this large enough, + /// since otherwise the congestion control protocol will not work as intended and messages + /// may be dropped. This value increases the PoV and should therefore not be picked too + /// high. Governance needs to pay attention to not open more channels than this value. + #[pallet::constant] + type MaxActiveOutboundChannels: Get; + + /// The maximal page size for HRMP message pages. + /// + /// A lower limit can be set dynamically, but this is the hard-limit for the PoV worst case + /// benchmarking. The limit for the size of a message is slightly below this, since some + /// overhead is incurred for encoding the format. + #[pallet::constant] + type MaxPageSize: Get; + /// The origin that is allowed to resume or suspend the XCMP queue. type ControllerOrigin: EnsureOrigin; @@ -277,6 +295,10 @@ pub mod pallet { AlreadySuspended, /// The execution is already resumed. AlreadyResumed, + /// There are too many active outbound channels. + TooManyActiveOutboundChannels, + /// The message is too big. + TooBig, } /// The suspended inbound XCMP channels. All others are not suspended. @@ -298,19 +320,28 @@ pub mod pallet { /// case of the need to send a high-priority signal message this block. /// The bool is true if there is a signal message waiting to be sent. #[pallet::storage] - pub(super) type OutboundXcmpStatus = - StorageValue<_, Vec, ValueQuery>; + pub(super) type OutboundXcmpStatus = StorageValue< + _, + BoundedVec, + ValueQuery, + >; - // The new way of doing it: /// The messages outbound in a given XCMP channel. #[pallet::storage] - pub(super) type OutboundXcmpMessages = - StorageDoubleMap<_, Blake2_128Concat, ParaId, Twox64Concat, u16, Vec, ValueQuery>; + pub(super) type OutboundXcmpMessages = StorageDoubleMap< + _, + Blake2_128Concat, + ParaId, + Twox64Concat, + u16, + WeakBoundedVec, + ValueQuery, + >; /// Any signal messages waiting to be sent. #[pallet::storage] pub(super) type SignalMessages = - StorageMap<_, Blake2_128Concat, ParaId, Vec, ValueQuery>; + StorageMap<_, Blake2_128Concat, ParaId, WeakBoundedVec, ValueQuery>; /// The configuration which controls the dynamics of the outbound queue. #[pallet::storage] @@ -332,15 +363,14 @@ pub mod pallet { StorageMap<_, Twox64Concat, ParaId, FixedU128, ValueQuery, InitialFactor>; } -#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] +#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub enum OutboundState { Ok, Suspended, } /// Struct containing detailed information about the outbound channel. -#[derive(Clone, Eq, PartialEq, Encode, Decode, TypeInfo)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Clone, Eq, PartialEq, Encode, Decode, TypeInfo, RuntimeDebug, MaxEncodedLen)] pub struct OutboundChannelDetails { /// The `ParaId` of the parachain that this channel is connected with. recipient: ParaId, @@ -376,7 +406,7 @@ impl OutboundChannelDetails { } } -#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] +#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub struct QueueConfigData { /// The number of pages which must be in the queue for the other side to be told to suspend /// their sending. @@ -479,7 +509,10 @@ impl Pallet { { details } else { - all_channels.push(OutboundChannelDetails::new(recipient)); + all_channels.try_push(OutboundChannelDetails::new(recipient)).map_err(|e| { + log::error!("Failed to activate HRMP channel: {:?}", e); + MessageSendError::TooManyChannels + })?; all_channels .last_mut() .expect("can't be empty; a new element was just pushed; qed") @@ -504,7 +537,9 @@ impl Pallet { if page.len() + encoded_fragment.len() > max_message_size { return None } - page.extend_from_slice(&encoded_fragment[..]); + for frag in encoded_fragment.iter() { + page.try_push(*frag).ok()?; + } Some(page.len()) }, ) @@ -522,7 +557,10 @@ impl Pallet { new_page.extend_from_slice(&encoded_fragment[..]); let last_page_size = new_page.len(); let number_of_pages = (channel_details.last_index - channel_details.first_index) as u32; - >::insert(recipient, page_index, new_page); + let bounded_page = BoundedVec::::try_from(new_page) + .map_err(|_| MessageSendError::TooBig)?; + let bounded_page = WeakBoundedVec::force_from(bounded_page.into_inner(), None); + >::insert(recipient, page_index, bounded_page); >::put(all_channels); (number_of_pages, last_page_size) }; @@ -544,17 +582,24 @@ impl Pallet { /// Sends a signal to the `dest` chain over XCMP. This is guaranteed to be dispatched on this /// block. - fn send_signal(dest: ParaId, signal: ChannelSignal) { + fn send_signal(dest: ParaId, signal: ChannelSignal) -> Result<(), Error> { let mut s = >::get(); if let Some(details) = s.iter_mut().find(|item| item.recipient == dest) { details.signals_exist = true; } else { - s.push(OutboundChannelDetails::new(dest).with_signals()); + s.try_push(OutboundChannelDetails::new(dest).with_signals()) + .map_err(|_| Error::::TooManyActiveOutboundChannels)?; } - >::mutate(dest, |page| { - *page = (XcmpMessageFormat::Signals, signal).encode(); - }); + + let page = BoundedVec::::try_from( + (XcmpMessageFormat::Signals, signal).encode(), + ) + .map_err(|_| Error::::TooBig)?; + let page = WeakBoundedVec::force_from(page.into_inner(), None); + + >::insert(dest, page); >::put(s); + Ok(()) } fn suspend_channel(target: ParaId) { @@ -564,7 +609,9 @@ impl Pallet { defensive_assert!(ok, "WARNING: Attempt to suspend channel that was not Ok."); details.state = OutboundState::Suspended; } else { - s.push(OutboundChannelDetails::new(target).with_suspended_state()); + if s.try_push(OutboundChannelDetails::new(target).with_suspended_state()).is_err() { + defensive!("Cannot pause channel; too many outbound channels"); + } } }); } @@ -665,18 +712,25 @@ impl OnQueueChanged for Pallet { let suspended = suspended_channels.contains(¶); if suspended && fp.ready_pages <= resume_threshold { - Self::send_signal(para, ChannelSignal::Resume); - - suspended_channels.remove(¶); - >::put(suspended_channels); + if let Err(err) = Self::send_signal(para, ChannelSignal::Resume) { + log::error!("defensive: Could not send resumption signal to inbound channel of sibling {:?}: {:?}; channel remains suspended.", para, err); + } else { + suspended_channels.remove(¶); + >::put(suspended_channels); + } } else if !suspended && fp.ready_pages >= suspend_threshold { log::warn!("XCMP queue for sibling {:?} is full; suspending channel.", para); - Self::send_signal(para, ChannelSignal::Suspend); - if let Err(err) = suspended_channels.try_insert(para) { + if let Err(err) = Self::send_signal(para, ChannelSignal::Suspend) { + // It will retry if `drop_threshold` is not reached, but it could be too late. + log::error!( + "defensive: Could not send suspension signal; future messages may be dropped: {:?}", err + ); + } else if let Err(err) = suspended_channels.try_insert(para) { log::error!("Too many channels suspended; cannot suspend sibling {:?}: {:?}; further messages may be dropped.", para, err); + } else { + >::put(suspended_channels); } - >::put(suspended_channels); } } } @@ -843,7 +897,7 @@ impl XcmpMessageSource for Pallet { // since it's so unlikely then for now we just drop it. defensive!("WARNING: oversize message in queue - dropping"); } else { - result.push((para_id, page)); + result.push((para_id, page.into_inner())); } let max_total_size = match T::ChannelInfo::get_channel_info(para_id) { @@ -891,7 +945,9 @@ impl XcmpMessageSource for Pallet { let pruned = old_statuses_len - statuses.len(); // removing an item from status implies a message being sent, so the result messages must // be no less than the pruned channels. - statuses.rotate_left(result.len().saturating_sub(pruned)); + let _ = statuses.try_rotate_left(result.len().saturating_sub(pruned)).defensive_proof( + "Could not store HRMP channels config. Some HRMP channels may be broken.", + ); >::put(statuses); diff --git a/cumulus/pallets/xcmp-queue/src/migration.rs b/cumulus/pallets/xcmp-queue/src/migration.rs index 1702cd70bc2fb..b64982a893029 100644 --- a/cumulus/pallets/xcmp-queue/src/migration.rs +++ b/cumulus/pallets/xcmp-queue/src/migration.rs @@ -16,6 +16,8 @@ //! A module that is responsible for migration of storage. +pub mod v5; + use crate::{Config, OverweightIndex, Pallet, QueueConfig, QueueConfigData, DEFAULT_POV_SIZE}; use cumulus_primitives_core::XcmpMessageFormat; use frame_support::{ @@ -25,7 +27,7 @@ use frame_support::{ }; /// The in-code storage version. -pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(4); +pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(5); pub const LOG: &str = "runtime::xcmp-queue-migration"; diff --git a/cumulus/pallets/xcmp-queue/src/migration/v5.rs b/cumulus/pallets/xcmp-queue/src/migration/v5.rs new file mode 100644 index 0000000000000..247adab7108fa --- /dev/null +++ b/cumulus/pallets/xcmp-queue/src/migration/v5.rs @@ -0,0 +1,108 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Migrates the storage to version 5. + +use crate::*; +use cumulus_primitives_core::ListChannelInfos; +use frame_support::{pallet_prelude::*, traits::UncheckedOnRuntimeUpgrade}; + +/// Configs needed to run the V5 migration. +pub trait V5Config: Config { + /// List all outbound channels with their target `ParaId` and maximum message size. + type ChannelList: ListChannelInfos; +} + +/// Ensures that the storage migrates cleanly to V5. +/// +/// The migration itself is a no-op, but it checks that none of the `BoundedVec`s would truncate on +/// the next decode after the upgrade was applied. +pub type MigrateV4ToV5 = frame_support::migrations::VersionedMigration< + 4, + 5, + unversioned::UncheckedMigrateV4ToV5, + Pallet, + ::DbWeight, +>; + +// V4 storage aliases +mod v4 { + use super::*; + + #[frame_support::storage_alias] + pub(super) type OutboundXcmpStatus = + StorageValue, Vec, ValueQuery>; + + #[frame_support::storage_alias] + pub(super) type OutboundXcmpMessages = StorageDoubleMap< + Pallet, + Blake2_128Concat, + ParaId, + Twox64Concat, + u16, + Vec, + ValueQuery, + >; + + #[frame_support::storage_alias] + pub(super) type SignalMessages = + StorageMap, Blake2_128Concat, ParaId, Vec, ValueQuery>; +} + +// Private module to hide the migration. +mod unversioned { + /// Please use [`MigrateV4ToV5`] instead. + pub struct UncheckedMigrateV4ToV5(core::marker::PhantomData); +} + +impl UncheckedOnRuntimeUpgrade for unversioned::UncheckedMigrateV4ToV5 { + fn on_runtime_upgrade() -> frame_support::weights::Weight { + Default::default() + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(_: Vec) -> Result<(), sp_runtime::DispatchError> { + // We dont need any front-run protection for this since channels are opened by governance. + ensure!( + v4::OutboundXcmpStatus::::get().len() as u32 <= T::MaxActiveOutboundChannels::get(), + "Too many outbound channels. Close some channels or increase `MaxActiveOutboundChannels`." + ); + + ensure!(T::MaxPageSize::get() >= 16, "Sanity check failed: MaxPageSize too small"); + + // Check if any channels have a too large message max sizes. + let max_msg_len = T::MaxPageSize::get() - XcmpMessageFormat::max_encoded_len() as u32; + for channel in T::ChannelList::outgoing_channels() { + let info = T::ChannelInfo::get_channel_info(channel) + .expect("All listed channels must provide info"); + + if info.max_message_size > max_msg_len { + log::error!( + "Max message size for channel is too large. This means that the V5 \ + migration can be front-run and an attacker could place a large message just right \ + before the migration to make other messages un-decodable. Please either increase \ + `MaxPageSize` or decrease the `max_message_size` for this channel. Channel max: {}, \ + MaxPageSize: {}", + info.max_message_size, + max_msg_len + ); + return Err("Migration can be front-run".into()); + } + } + + Ok(()) + } +} diff --git a/cumulus/pallets/xcmp-queue/src/mock.rs b/cumulus/pallets/xcmp-queue/src/mock.rs index e258576aa3f6d..97121aa78e9ad 100644 --- a/cumulus/pallets/xcmp-queue/src/mock.rs +++ b/cumulus/pallets/xcmp-queue/src/mock.rs @@ -277,7 +277,11 @@ impl Config for Test { type ChannelInfo = MockedChannelInfo; type VersionWrapper = (); type XcmpQueue = EnqueueToLocalStorage>; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = SystemParachainAsSuperuser; type WeightInfo = (); diff --git a/cumulus/pallets/xcmp-queue/src/tests.rs b/cumulus/pallets/xcmp-queue/src/tests.rs index f48e9eec3ac05..7c02059e5a904 100644 --- a/cumulus/pallets/xcmp-queue/src/tests.rs +++ b/cumulus/pallets/xcmp-queue/src/tests.rs @@ -520,7 +520,7 @@ fn hrmp_signals_are_prioritized() { }); // But a signal gets prioritized instead of the messages: - XcmpQueue::send_signal(sibling_para_id.into(), ChannelSignal::Suspend); + assert_ok!(XcmpQueue::send_signal(sibling_para_id.into(), ChannelSignal::Suspend)); let taken = XcmpQueue::take_outbound_messages(130); assert_eq!( diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 0df9b65c714d2..b0df11e1046a3 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -670,7 +670,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; @@ -700,12 +700,21 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type ChannelInfo = ParachainSystem; type VersionWrapper = PolkadotXcm; type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = xcm_config::XcmOriginToTransactDispatchOrigin; type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; } +impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime { + // This must be the same as the `ChannelInfo` from the `Config`: + type ChannelList = ParachainSystem; +} + parameter_types! { pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent; } @@ -980,6 +989,7 @@ pub type Migrations = ( InitStorageVersions, // unreleased cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4, + cumulus_pallet_xcmp_queue::migration::v5::MigrateV4ToV5, pallet_collator_selection::migration::v2::MigrationToV2, // permanent pallet_xcm::migration::MigrateToLatestXcmVersion, diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index b5c3ed5053c4b..062babef18d36 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -669,7 +669,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; @@ -697,13 +697,22 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type VersionWrapper = PolkadotXcm; // Enqueue XCMP messages from siblings for later processing. type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; } +impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime { + // This must be the same as the `ChannelInfo` from the `Config`: + type ChannelList = ParachainSystem; +} + parameter_types! { pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent; } @@ -984,6 +993,7 @@ pub type Migrations = ( DeleteUndecodableStorage, // unreleased cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4, + cumulus_pallet_xcmp_queue::migration::v5::MigrateV4ToV5, // permanent pallet_xcm::migration::MigrateToLatestXcmVersion, ); diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 2a7f46feee695..9043175a701c7 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -148,8 +148,9 @@ pub type Migrations = ( pallet_collator_selection::migration::v2::MigrationToV2, pallet_multisig::migrations::v1::MigrateToV1, InitStorageVersions, - cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4, // unreleased + cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4, + cumulus_pallet_xcmp_queue::migration::v5::MigrateV4ToV5, snowbridge_pallet_system::migration::v0::InitializeOnUpgrade< Runtime, ConstU32, @@ -389,7 +390,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; @@ -417,13 +418,22 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type VersionWrapper = PolkadotXcm; // Enqueue XCMP messages from siblings for later processing. type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; } +impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime { + // This must be the same as the `ChannelInfo` from the `Config`: + type ChannelList = ParachainSystem; +} + parameter_types! { pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent; } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs index 4c467010c7c87..50911b4d780fd 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs @@ -129,6 +129,7 @@ pub type Migrations = ( InitStorageVersions, // unreleased cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4, + cumulus_pallet_xcmp_queue::migration::v5::MigrateV4ToV5, // permanent pallet_xcm::migration::MigrateToLatestXcmVersion, ); @@ -352,7 +353,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; @@ -379,13 +380,22 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type ChannelInfo = ParachainSystem; type VersionWrapper = PolkadotXcm; type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; } +impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime { + // This must be the same as the `ChannelInfo` from the `Config`: + type ChannelList = ParachainSystem; +} + parameter_types! { pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent; } diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs index 35b505d9da6a7..59005d0fa97dd 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs @@ -420,7 +420,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; @@ -448,13 +448,22 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type VersionWrapper = PolkadotXcm; // Enqueue XCMP messages from siblings for later processing. type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = EitherOfDiverse, Fellows>; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; } +impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime { + // This must be the same as the `ChannelInfo` from the `Config`: + type ChannelList = ParachainSystem; +} + parameter_types! { pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent; } @@ -727,6 +736,7 @@ type Migrations = ( pallet_collator_selection::migration::v2::MigrationToV2, // unreleased cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4, + cumulus_pallet_xcmp_queue::migration::v5::MigrateV4ToV5, // permanent pallet_xcm::migration::MigrateToLatestXcmVersion, ); diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs index df39cd811d1fd..85a85e7086cb0 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs @@ -106,6 +106,7 @@ pub type Migrations = ( pallet_contracts::Migration, // unreleased cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4, + cumulus_pallet_xcmp_queue::migration::v5::MigrateV4ToV5, // permanent pallet_xcm::migration::MigrateToLatestXcmVersion, ); @@ -318,7 +319,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs index 8c33710198605..ef5ded1731d0d 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs @@ -284,7 +284,11 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { cumulus_primitives_core::ParaId, parachains_common::message_queue::ParaIdToSibling, >; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = EitherOfDiverse< EnsureRoot, EnsureXcm>, @@ -294,6 +298,11 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; } +impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime { + // This must be the same as the `ChannelInfo` from the `Config`: + type ChannelList = ParachainSystem; +} + parameter_types! { pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent; } diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs index ab925b04eb7c1..4f4935de133bf 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs @@ -110,6 +110,7 @@ pub type UncheckedExtrinsic = pub type Migrations = ( pallet_collator_selection::migration::v2::MigrationToV2, cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4, + cumulus_pallet_xcmp_queue::migration::v5::MigrateV4ToV5, pallet_broker::migration::MigrateV0ToV1, // permanent pallet_xcm::migration::MigrateToLatestXcmVersion, @@ -301,7 +302,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; @@ -341,13 +342,22 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type ChannelInfo = ParachainSystem; type VersionWrapper = PolkadotXcm; type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = RootOrFellows; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; } +impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime { + // This must be the same as the `ChannelInfo` from the `Config`: + type ChannelList = ParachainSystem; +} + pub const PERIOD: u32 = 6 * HOURS; pub const OFFSET: u32 = 0; diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs index 61c7b6e495872..fca1b0e7c6ec4 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs @@ -302,7 +302,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; @@ -342,13 +342,22 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type ChannelInfo = ParachainSystem; type VersionWrapper = PolkadotXcm; type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = RootOrFellows; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; } +impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime { + // This must be the same as the `ChannelInfo` from the `Config`: + type ChannelList = ParachainSystem; +} + pub const PERIOD: u32 = 6 * HOURS; pub const OFFSET: u32 = 0; diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs index 424fa9cb7e726..b4ee0f5ae7108 100644 --- a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs @@ -208,8 +208,9 @@ impl pallet_message_queue::Config for Runtime { >; type Size = u32; type QueueChangeHandler = (); - type QueuePausedQuery = (); // No XCMP queue pallet deployed. - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + // No XCMP queue pallet deployed. + type QueuePausedQuery = (); + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs index 544b2e78a4695..68e34a0e567ea 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs @@ -281,7 +281,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; @@ -308,13 +308,22 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type ChannelInfo = ParachainSystem; type VersionWrapper = PolkadotXcm; type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = RootOrFellows; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; } +impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime { + // This must be the same as the `ChannelInfo` from the `Config`: + type ChannelList = ParachainSystem; +} + pub const PERIOD: u32 = 6 * HOURS; pub const OFFSET: u32 = 0; diff --git a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs index 50c818a20226c..4d838fb9961fe 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs @@ -281,7 +281,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; @@ -308,13 +308,22 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type ChannelInfo = ParachainSystem; type VersionWrapper = PolkadotXcm; type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = RootOrFellows; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; } +impl cumulus_pallet_xcmp_queue::migration::v5::V5Config for Runtime { + // This must be the same as the `ChannelInfo` from the `Config`: + type ChannelList = ParachainSystem; +} + pub const PERIOD: u32 = 6 * HOURS; pub const OFFSET: u32 = 0; diff --git a/cumulus/parachains/runtimes/starters/shell/src/lib.rs b/cumulus/parachains/runtimes/starters/shell/src/lib.rs index a3d1629bbe5eb..7422b580cc3e0 100644 --- a/cumulus/parachains/runtimes/starters/shell/src/lib.rs +++ b/cumulus/parachains/runtimes/starters/shell/src/lib.rs @@ -229,7 +229,7 @@ impl pallet_message_queue::Config for Runtime { // These need to be configured to the XCMP pallet - if it is deployed. type QueueChangeHandler = (); type QueuePausedQuery = (); - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; diff --git a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs index 582154fec6d27..86a8b0f1d9ea0 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs @@ -541,7 +541,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = MessageQueueServiceWeight; @@ -569,7 +569,11 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type VersionWrapper = PolkadotXcm; // Enqueue XCMP messages from siblings for later processing. type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = (); diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs index f22e900ba9efd..b515e8ec5c9c7 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs @@ -317,7 +317,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = (); @@ -542,7 +542,11 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type VersionWrapper = (); // Enqueue XCMP messages from siblings for later processing. type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxInboundSuspended = ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + // Most on-chain HRMP channels are configured to use 102400 bytes of max message size, so we + // need to set the page size larger than that until we reduce the channel size on-chain. + type MaxPageSize = ConstU32<{ 103 * 1024 }>; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = cumulus_pallet_xcmp_queue::weights::SubstrateWeight; diff --git a/cumulus/primitives/core/src/lib.rs b/cumulus/primitives/core/src/lib.rs index 7f7353685657e..29216d5134651 100644 --- a/cumulus/primitives/core/src/lib.rs +++ b/cumulus/primitives/core/src/lib.rs @@ -64,6 +64,8 @@ pub enum MessageSendError { TooBig, /// Some other error. Other, + /// There are too many channels open at once. + TooManyChannels, } impl From for &'static str { @@ -74,6 +76,7 @@ impl From for &'static str { NoChannel => "NoChannel", TooBig => "TooBig", Other => "Other", + TooManyChannels => "TooManyChannels", } } } @@ -135,6 +138,11 @@ pub trait GetChannelInfo { fn get_channel_info(id: ParaId) -> Option; } +/// List all open outgoing channels. +pub trait ListChannelInfos { + fn outgoing_channels() -> Vec; +} + /// Something that should be called when sending an upward message. pub trait UpwardMessageSender { /// Send the given UMP message; return the expected number of blocks before the message will diff --git a/polkadot/parachain/src/primitives.rs b/polkadot/parachain/src/primitives.rs index 5a1efdf898217..2764384363727 100644 --- a/polkadot/parachain/src/primitives.rs +++ b/polkadot/parachain/src/primitives.rs @@ -333,7 +333,19 @@ impl DmpMessageHandler for () { } /// The aggregate XCMP message format. -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo, RuntimeDebug)] +#[derive( + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Encode, + Decode, + TypeInfo, + RuntimeDebug, + MaxEncodedLen, +)] pub enum XcmpMessageFormat { /// Encoded `VersionedXcm` messages, all concatenated. ConcatenatedVersionedXcm, diff --git a/prdoc/pr_3952.prdoc b/prdoc/pr_3952.prdoc new file mode 100644 index 0000000000000..2401adbb76c13 --- /dev/null +++ b/prdoc/pr_3952.prdoc @@ -0,0 +1,35 @@ +title: Storage bound the XCMP queue pallet + +doc: + - audience: Runtime Dev + description: | + Enforce upper limits for the number of active XCMP channels, the number of outgoing XCMP + messages per channel and the number of signals per channel. + + ## Integration + + If you see this error in your try-runtime-cli: + ```pre + Max message size for channel is too large. This means that the V5 migration can be front-run and an + attacker could place a large message just right before the migration to make other messages un-decodable. + Please either increase `MaxPageSize` or decrease the `max_message_size` for this channel. Channel max: + 102400, MaxPageSize: 65535 + ``` + + Then increase the `MaxPageSize` of the `cumulus_pallet_xcmp_queue` to something like this: + ```rust + type MaxPageSize = ConstU32<{ 103 * 1024 }>; + ``` + +migrations: + db: [] + + runtime: + - reference: cumulus_pallet_xcmp_queue::migration::v5::MigrateV4ToV5 + description: A No-OP migration is deployed to ensure that all `BoundedVec`s` still decode as expected. + +crates: + - name: cumulus-pallet-xcmp-queue + bump: major + +host_functions: [] diff --git a/templates/parachain/runtime/src/configs/mod.rs b/templates/parachain/runtime/src/configs/mod.rs index 0aec332feaf65..63e6a67a90638 100644 --- a/templates/parachain/runtime/src/configs/mod.rs +++ b/templates/parachain/runtime/src/configs/mod.rs @@ -221,7 +221,7 @@ impl pallet_message_queue::Config for Runtime { // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: type QueueChangeHandler = NarrowOriginToSibling; type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type HeapSize = sp_core::ConstU32<{ 103 * 1024 }>; type MaxStale = sp_core::ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type IdleMaxServiceWeight = (); @@ -236,6 +236,8 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { // Enqueue XCMP messages from siblings for later processing. type XcmpQueue = TransformOrigin; type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type MaxActiveOutboundChannels = ConstU32<128>; + type MaxPageSize = ConstU32<{ 1 << 16 }>; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = ();