Skip to content
  • Oliver Tale-Yazdi's avatar
    Use `Message Queue` as DMP and XCMP dispatch queue (#1246) · e1c033eb
    Oliver Tale-Yazdi authored
    
    
    (imported from https://github.com/paritytech/cumulus/pull/2157)
    
    ## Changes
    
    This MR refactores the XCMP, Parachains System and DMP pallets to use
    the [MessageQueue](https://github.com/paritytech/substrate/pull/12485)
    for delayed execution of incoming messages. The DMP pallet is entirely
    replaced by the MQ and thereby removed. This allows for PoV-bounded
    execution and resolves a number of issues that stem from the current
    work-around.
    
    All System Parachains adopt this change.  
    The most important changes are in `primitives/core/src/lib.rs`,
    `parachains/common/src/process_xcm_message.rs`,
    `pallets/parachain-system/src/lib.rs`, `pallets/xcmp-queue/src/lib.rs`
    and the runtime configs.
    
    ### DMP Queue Pallet
    
    The pallet got removed and its logic refactored into parachain-system.
    Overweight message management can be done directly through the MQ
    pallet.
    
    Final undeployment migrations are provided by
    `cumulus_pallet_dmp_queue::UndeployDmpQueue` and `DeleteDmpQueue` that
    can be configured with an aux config trait like:
    
    ```rust
    parameter_types! {
    	pub const DmpQueuePalletName: &'static str = \"DmpQueue\" < CHANGE ME;
    	pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent;
    }
    
    impl cumulus_pallet_dmp_queue::MigrationConfig for Runtime {
    	type PalletName = DmpQueuePalletName;
    	type DmpHandler = frame_support::traits::EnqueueWithOrigin<MessageQueue, RelayOrigin>;
    	type DbWeight = <Runtime as frame_system::Config>::DbWeight;
    }
    
    // And adding them to your Migrations tuple:
    pub type Migrations = (
    	...
    	cumulus_pallet_dmp_queue::UndeployDmpQueue<Runtime>,
    	cumulus_pallet_dmp_queue::DeleteDmpQueue<Runtime>,
    );
    ```
    
    ### XCMP Queue pallet
    
    Removed all dispatch queue functionality. Incoming XCMP messages are now
    either: Immediately handled if they are Signals, enqueued into the MQ
    pallet otherwise.
    
    New config items for the XCMP queue pallet:
    ```rust
    /// The actual queue implementation that retains the messages for later processing.
    type XcmpQueue: EnqueueMessage<ParaId>;
    
    /// How a XCM over HRMP from a sibling parachain should be processed.
    type XcmpProcessor: ProcessMessage<Origin = ParaId>;
    
    /// The maximal number of suspended XCMP channels at the same time.
    #[pallet::constant]
    type MaxInboundSuspended: Get<u32>;
    ```
    
    How to configure those:
    
    ```rust
    // Use the MessageQueue pallet to store messages for later processing. The `TransformOrigin` is needed since
    // the MQ pallet itself operators on `AggregateMessageOrigin` but we want to enqueue `ParaId`s.
    type XcmpQueue = TransformOrigin<MessageQueue, AggregateMessageOrigin, ParaId, ParaIdToSibling>;
    
    // Process XCMP messages from siblings. This is type-safe to only accept `ParaId`s. They will be dispatched
    // with origin `Junction::Sibling(…)`.
    type XcmpProcessor = ProcessFromSibling<
    	ProcessXcmMessage<
    		AggregateMessageOrigin,
    		xcm_executor::XcmExecutor<xcm_config::XcmConfig>,
    		RuntimeCall,
    	>,
    >;
    
    // Not really important what to choose here. Just something larger than the maximal number of channels.
    type MaxInboundSuspended = sp_core::ConstU32<1_000>;
    ```
    
    The `InboundXcmpStatus` storage item was replaced by
    `InboundXcmpSuspended` since it now only tracks inbound queue suspension
    and no message indices anymore.
    
    Now only sends the most recent channel `Signals`, as all prio ones are
    out-dated anyway.
    
    ### Parachain System pallet
    
    For `DMP` messages instead of forwarding them to the `DMP` pallet, it
    now pushes them to the configured `DmpQueue`. The message processing
    which was triggered in `set_validation_data` is now being done by the MQ
    pallet `on_initialize`.
    
    XCMP messages are still handed off to the `XcmpMessageHandler`
    (XCMP-Queue pallet) - no change here.
    
    New config items for the parachain system pallet:
    ```rust
    /// Queues inbound downward messages for delayed processing. 
    ///
    /// Analogous to the `XcmpQueue` of the XCMP queue pallet.
    type DmpQueue: EnqueueMessage<AggregateMessageOrigin>;
    ``` 
    
    How to configure:
    ```rust
    /// Use the MQ pallet to store DMP messages for delayed processing.
    type DmpQueue = MessageQueue;
    ``` 
    
    ## Message Flow
    
    The flow of messages on the parachain side. Messages come in from the
    left via the `Validation Data` and finally end up at the `Xcm Executor`
    on the right.
    
    ![Untitled
    (1)](https://github.com/paritytech/cumulus/assets/10380170/6cf8b377-88c9-4aed-96df-baace266e04d)
    
    ## Further changes
    
    - Bumped the default suspension, drop and resume thresholds in
    `QueueConfigData::default()`.
    - `XcmpQueue::{suspend_xcm_execution, resume_xcm_execution}` errors when
    they would be a noop.
    - Properly validate the `QueueConfigData` before setting it.
    - Marked weight files as auto-generated so they wont auto-expand in the
    MR files view.
    - Move the `hypothetical` asserts to `frame_support` under the name
    `experimental_hypothetically`
    
    Questions:
    - [ ] What about the ugly `#[cfg(feature = \"runtime-benchmarks\")]` in
    the runtimes? Not sure how to best fix. Just having them like this makes
    tests fail that rely on the real message processor when the feature is
    enabled.
    - [ ] Need a good weight for `MessageQueueServiceWeight`. The scheduler
    already takes 80% so I put it to 10% but that is quite low.
    
    TODO:
    - [x] Remove c&p code after
    https://github.com/paritytech/polkadot/pull/6271
    - [x] Use `HandleMessage` once it is public in Substrate
    - [x] fix `runtime-benchmarks` feature
    https://github.com/paritytech/polkadot/pull/6966
    - [x] Benchmarks
    - [x] Tests
    - [ ] Migrate `InboundXcmpStatus` to `InboundXcmpSuspended`
    - [x] Possibly cleanup Migrations (DMP+XCMP)
    - [x] optional: create `TransformProcessMessageOrigin` in Substrate and
    replace `ProcessFromSibling`
    - [ ] Rerun weights on ref HW
    
    ---------
    
    Signed-off-by: default avatarOliver Tale-Yazdi <[email protected]>
    Co-authored-by: default avatarLiam Aharon <[email protected]>
    Co-authored-by: default avatarjoe petrowski <[email protected]>
    Co-authored-by: default avatarKian Paimani <[email protected]>
    Co-authored-by: command-bot <>
    e1c033eb