diff --git a/pallets/dmp-queue/src/lib.rs b/pallets/dmp-queue/src/lib.rs index eb6ed6e3f50..5b2cf067694 100644 --- a/pallets/dmp-queue/src/lib.rs +++ b/pallets/dmp-queue/src/lib.rs @@ -89,6 +89,9 @@ pub mod pallet { /// Origin which is allowed to execute overweight messages. type ExecuteOverweightOrigin: EnsureOrigin; + + /// The origin that is allowed to resume or suspend the XCMP queue. + type ControllerOrigin: EnsureOrigin; } /// The configuration. @@ -109,6 +112,10 @@ pub mod pallet { pub(super) type Overweight = StorageMap<_, Blake2_128Concat, OverweightIndex, (RelayBlockNumber, Vec), OptionQuery>; + /// Whether or not the XCMP queue is suspended from executing incoming XCMs or not. + #[pallet::storage] + pub(super) type QueueSuspended = StorageValue<_, bool, ValueQuery>; + #[pallet::error] pub enum Error { /// The message index given is unknown. @@ -154,6 +161,32 @@ pub mod pallet { Self::deposit_event(Event::OverweightServiced(index, used)); Ok(Some(used.saturating_add(1_000_000)).into()) } + + /// Suspends all XCM executions for the XCMP queue, regardless of the sender's origin. + /// + /// - `origin`: Must pass `ControllerOrigin`. + #[pallet::weight(T::DbWeight::get().writes(1))] + pub fn suspend_xcm_execution(origin: OriginFor) -> DispatchResult { + T::ControllerOrigin::ensure_origin(origin)?; + + QueueSuspended::::put(true); + + Ok(()) + } + + /// Resumes all XCM executions for the XCMP queue. + /// + /// Note that this function doesn't change the status of the in/out bound channels. + /// + /// - `origin`: Must pass `ControllerOrigin`. + #[pallet::weight(T::DbWeight::get().writes(1))] + pub fn resume_xcm_execution(origin: OriginFor) -> DispatchResult { + T::ControllerOrigin::ensure_origin(origin)?; + + QueueSuspended::::put(false); + + Ok(()) + } } #[pallet::event] @@ -184,6 +217,11 @@ pub mod pallet { /// /// Returns the weight consumed by executing messages in the queue. fn service_queue(limit: Weight) -> Weight { + let suspended = QueueSuspended::::get(); + if suspended { + return 0 + } + PageIndex::::mutate(|page_index| Self::do_service_queue(limit, page_index)) } @@ -263,6 +301,11 @@ pub mod pallet { iter: impl Iterator)>, limit: Weight, ) -> Weight { + let suspended = QueueSuspended::::get(); + if suspended { + return 0 + } + let mut page_index = PageIndex::::get(); let config = Configuration::::get(); @@ -447,6 +490,7 @@ mod tests { type Event = Event; type XcmExecutor = MockExec; type ExecuteOverweightOrigin = frame_system::EnsureRoot; + type ControllerOrigin = frame_system::EnsureRoot; } pub(crate) fn new_test_ext() -> sp_io::TestExternalities { @@ -786,4 +830,20 @@ mod tests { assert_eq!(pages_queued(), 1); }); } + + #[test] + fn suspend_xcm_execution_works() { + new_test_ext().execute_with(|| { + QueueSuspended::::put(true); + + let incoming = [msg(1000), msg(1001)]; + enqueue(&incoming[..]); + + let weight_used = handle_messages(&incoming, 5000); + + assert_eq!(weight_used, 0); + assert_eq!(take_trace(), Vec::new()); + assert_eq!(pages_queued(), 1); + }); + } } diff --git a/parachain-template/runtime/src/lib.rs b/parachain-template/runtime/src/lib.rs index 79cac58f199..7867a886802 100644 --- a/parachain-template/runtime/src/lib.rs +++ b/parachain-template/runtime/src/lib.rs @@ -532,6 +532,7 @@ impl cumulus_pallet_dmp_queue::Config for Runtime { type Event = Event; type XcmExecutor = XcmExecutor; type ExecuteOverweightOrigin = EnsureRoot; + type ControllerOrigin = EnsureRoot; } parameter_types! { diff --git a/polkadot-parachains/rococo-parachain/src/lib.rs b/polkadot-parachains/rococo-parachain/src/lib.rs index 01d67ca4cb6..3f6411bb2a9 100644 --- a/polkadot-parachains/rococo-parachain/src/lib.rs +++ b/polkadot-parachains/rococo-parachain/src/lib.rs @@ -460,7 +460,8 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { impl cumulus_pallet_dmp_queue::Config for Runtime { type Event = Event; type XcmExecutor = XcmExecutor; - type ExecuteOverweightOrigin = frame_system::EnsureRoot; + type ExecuteOverweightOrigin = EnsureRoot; + type ControllerOrigin = EnsureRoot; } impl cumulus_ping::Config for Runtime { diff --git a/polkadot-parachains/statemine/src/lib.rs b/polkadot-parachains/statemine/src/lib.rs index 0da8de22380..03ec54f99a2 100644 --- a/polkadot-parachains/statemine/src/lib.rs +++ b/polkadot-parachains/statemine/src/lib.rs @@ -604,12 +604,14 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type ChannelInfo = ParachainSystem; type VersionWrapper = PolkadotXcm; type ExecuteOverweightOrigin = EnsureRoot; + type ControllerOrigin = EnsureRoot; } impl cumulus_pallet_dmp_queue::Config for Runtime { type Event = Event; type XcmExecutor = XcmExecutor; type ExecuteOverweightOrigin = EnsureRoot; + type ControllerOrigin = EnsureRoot; } parameter_types! { diff --git a/polkadot-parachains/statemint/src/lib.rs b/polkadot-parachains/statemint/src/lib.rs index 11f9407d88a..9399e906a3a 100644 --- a/polkadot-parachains/statemint/src/lib.rs +++ b/polkadot-parachains/statemint/src/lib.rs @@ -623,6 +623,7 @@ impl cumulus_pallet_dmp_queue::Config for Runtime { type Event = Event; type XcmExecutor = XcmExecutor; type ExecuteOverweightOrigin = EnsureRoot; + type ControllerOrigin = EnsureRoot; } parameter_types! { diff --git a/polkadot-parachains/westmint/src/lib.rs b/polkadot-parachains/westmint/src/lib.rs index 13c17f92305..9c159e97f3f 100644 --- a/polkadot-parachains/westmint/src/lib.rs +++ b/polkadot-parachains/westmint/src/lib.rs @@ -603,6 +603,7 @@ impl cumulus_pallet_dmp_queue::Config for Runtime { type Event = Event; type XcmExecutor = XcmExecutor; type ExecuteOverweightOrigin = EnsureRoot; + type ControllerOrigin = EnsureRoot; } parameter_types! {