diff --git a/cumulus/pallets/xcmp-queue/src/benchmarking.rs b/cumulus/pallets/xcmp-queue/src/benchmarking.rs index 1efa302c207f..270d8d881466 100644 --- a/cumulus/pallets/xcmp-queue/src/benchmarking.rs +++ b/cumulus/pallets/xcmp-queue/src/benchmarking.rs @@ -46,8 +46,10 @@ benchmarks! { set_config_with_weight {}: update_weight_restrict_decay(RawOrigin::Root, Weight::from_parts(3_000_000, 0)) service_deferred { let m in 1..T::MaxDeferredMessages::get(); + let b in 1..T::MaxBucketsProcessed::get(); let max_messages = m as usize; + let max_processed = b as u16; let para_id = ParaId::from(999); let xcm = construct_xcm::(); @@ -56,7 +58,6 @@ benchmarks! { // We set `deferred_to` to the current relay block number to make sure that the messages are serviced. let deferred_message = DeferredMessage { sent_at: relay_block, deferred_to: relay_block, sender: para_id, xcm }; let deferred_xcm_messages = vec![deferred_message.clone(); max_messages]; - let max_processed = T::MaxBucketsProcessed::get() as u16; for i in 0..max_processed { crate::Pallet::::inject_deferred_messages(para_id, (relay_block, i), deferred_xcm_messages.clone().try_into().unwrap()); assert_eq!(crate::Pallet::::messages_deferred_to(para_id, (relay_block, i)).len(), max_messages); @@ -70,7 +71,7 @@ benchmarks! { assert!(crate::Pallet::::update_xcmp_max_individual_weight(RawOrigin::Root.into(), weight).is_ok()); // account for the reads induced by trying to execute all `max_messages` let weight_limit = weight.saturating_add(T::DbWeight::get().reads_writes((max_processed as usize * max_messages) as u64, 0)); - } :_(RawOrigin::Root, weight_limit, para_id) + } :_(RawOrigin::Root, weight_limit, para_id, max_processed as u32) verify { assert_eq!(crate::Pallet::::messages_deferred_to(para_id, (relay_block, 0)).len(), 0); diff --git a/cumulus/pallets/xcmp-queue/src/lib.rs b/cumulus/pallets/xcmp-queue/src/lib.rs index 395365471340..f56609d9cd12 100644 --- a/cumulus/pallets/xcmp-queue/src/lib.rs +++ b/cumulus/pallets/xcmp-queue/src/lib.rs @@ -330,31 +330,7 @@ pub mod pallet { Ok(()) } - /// This extrinsic executes deferred messages up to the specified `weight_limit` and the current relay chain block number. - /// - /// - `origin`: Must pass `ExecuteDeferredOrigin`. - /// - `weight_limit`: Maximum weight budget for deferred message execution. - /// - `para_id`: The queue to service. - #[pallet::call_index(9)] - #[pallet::weight((weight_limit.saturating_add(T::WeightInfo::service_deferred(T::MaxDeferredMessages::get())), DispatchClass::Operational))] - pub fn service_deferred( - origin: OriginFor, - weight_limit: Weight, - para_id: ParaId, - ) -> DispatchResultWithPostInfo { - T::ExecuteDeferredOrigin::ensure_origin(origin)?; - - let relay_block_number = T::RelayChainBlockNumberProvider::current_block_number(); - let QueueConfigData { xcmp_max_individual_weight, .. } = QueueConfig::::get(); - - let weight_used = Self::service_deferred_queue( - para_id, - weight_limit, - relay_block_number, - xcmp_max_individual_weight, - ); - Ok(Some(weight_used.saturating_add(T::WeightInfo::service_deferred(T::MaxDeferredMessages::get()))).into()) - } + // 9 and 10 are deprecated /// This extrinsic discards all deferred messages that match the given parameters. /// @@ -458,6 +434,35 @@ pub mod pallet { Ok(()) } + + /// This extrinsic executes deferred messages up to the specified `weight_limit` and the current relay chain block number. + /// + /// - `origin`: Must pass `ExecuteDeferredOrigin`. + /// - `weight_limit`: Maximum weight budget for deferred message execution. + /// - `para_id`: The queue to service. + /// - `max_processed`: The maximum number of buckets to process. + #[pallet::call_index(15)] + #[pallet::weight((weight_limit.saturating_add(T::WeightInfo::service_deferred(T::MaxDeferredMessages::get(), *max_processed)), DispatchClass::Operational))] + pub fn service_deferred( + origin: OriginFor, + weight_limit: Weight, + para_id: ParaId, + max_processed: u32, + ) -> DispatchResultWithPostInfo { + T::ExecuteDeferredOrigin::ensure_origin(origin)?; + + let relay_block_number = T::RelayChainBlockNumberProvider::current_block_number(); + let QueueConfigData { xcmp_max_individual_weight, .. } = QueueConfig::::get(); + + let weight_used = Self::service_deferred_queue( + para_id, + weight_limit, + relay_block_number, + xcmp_max_individual_weight, + max_processed as usize, + ); + Ok(Some(weight_used.saturating_add(T::WeightInfo::service_deferred(T::MaxDeferredMessages::get(), max_processed))).into()) + } } #[pallet::event] @@ -1175,12 +1180,18 @@ impl Pallet { let (sent_at, format) = status[index].message_metadata[0]; - - let weight_used_for_queue = if T::WeightInfo::service_deferred(T::MaxDeferredMessages::get()).any_gte(weight_remaining) { + let max_processed = T::MaxBucketsProcessed::get(); + let weight_used_for_queue = if T::WeightInfo::service_deferred(T::MaxDeferredMessages::get(), max_processed).any_gte(weight_remaining) { Weight::zero() } else { - T::WeightInfo::service_deferred(T::MaxDeferredMessages::get()).saturating_add( - Self::service_deferred_queue(sender, weight_remaining, sent_at, xcmp_max_individual_weight)) + T::WeightInfo::service_deferred(T::MaxDeferredMessages::get(), max_processed).saturating_add( + Self::service_deferred_queue( + sender, + weight_remaining, + sent_at, + xcmp_max_individual_weight, + max_processed as usize, + )) }; let weight_remaining = weight_remaining.saturating_sub(weight_used_for_queue); @@ -1241,7 +1252,8 @@ impl Pallet { } let mut keys = DeferredIndices::::iter_keys(); let mut processed_all_queues = false; - let service_queue_weight = T::WeightInfo::service_deferred(T::MaxDeferredMessages::get()); + let service_queue_weight = T::WeightInfo::service_deferred( + T::MaxDeferredMessages::get(), T::MaxBucketsProcessed::get()); while !processed_all_queues && max_weight.all_gt(weight_used.saturating_add(service_queue_weight)) { if let Some(sender) = keys.next() { weight_used.saturating_accrue(service_queue_weight); @@ -1250,6 +1262,7 @@ impl Pallet { max_weight.saturating_sub(weight_used), relay_chain_block_number, max_individual_weight, + T::MaxBucketsProcessed::get() as usize, )); } else { processed_all_queues = true; @@ -1265,6 +1278,7 @@ impl Pallet { max_weight: Weight, up_to_relay_block_number: RelayBlockNumber, max_individual_weight: Weight, + max_processed: usize, ) -> Weight { if QueueSuspended::::get() || DeferredQueueSuspended::::get() { return Weight::zero(); @@ -1275,7 +1289,7 @@ impl Pallet { let indices_to_process = indices.range((Included(&(0, 0)), Included(&(up_to_relay_block_number, u16::MAX)))); let mut processed = BTreeSet::new(); - for index in indices_to_process.take(T::MaxBucketsProcessed::get() as usize) { + for index in indices_to_process.take(max_processed) { if weight_used.any_gte(max_weight) { break; } diff --git a/cumulus/pallets/xcmp-queue/src/tests.rs b/cumulus/pallets/xcmp-queue/src/tests.rs index 4de0b599fa4b..5b46273313b0 100644 --- a/cumulus/pallets/xcmp-queue/src/tests.rs +++ b/cumulus/pallets/xcmp-queue/src/tests.rs @@ -466,7 +466,7 @@ fn service_deferred_should_execute_deferred_messages() { RelayBlockNumberProviderMock::set(7); //Act - assert_ok!(XcmpQueue::service_deferred(RuntimeOrigin::root(), Weight::MAX, para_id)); + assert_ok!(XcmpQueue::service_deferred(RuntimeOrigin::root(), Weight::MAX, para_id, ::MaxBucketsProcessed::get())); //Assert assert_eq!(create_bounded_btreeset([].into_iter()), DeferredIndices::::get(para_id)); @@ -531,7 +531,7 @@ fn service_deferred_should_store_unprocessed_messages() { RelayBlockNumberProviderMock::set(7); //Act - assert_ok!(XcmpQueue::service_deferred(RuntimeOrigin::root(), Weight::MAX, para_id)); + assert_ok!(XcmpQueue::service_deferred(RuntimeOrigin::root(), Weight::MAX, para_id, ::MaxBucketsProcessed::get())); //Assert assert_deferred_messages!(para_id, (8, 0), vec![Some(msg_not_to_process)]); @@ -566,7 +566,7 @@ fn service_deferred_should_fail_when_called_with_wrong_origin() { //Act and assert assert_noop!( - XcmpQueue::service_deferred(RuntimeOrigin::signed(100), Weight::MAX, para_id), + XcmpQueue::service_deferred(RuntimeOrigin::signed(100), Weight::MAX, para_id, ::MaxBucketsProcessed::get()), BadOrigin ); }); @@ -584,7 +584,10 @@ fn service_deferred_queues_should_pass_overweight_messages_to_overweight_queue() let low_max_individual_weight = Weight::from_parts(100, 1); let low_max_weight = low_max_individual_weight.saturating_add( - ::WeightInfo::service_deferred(::MaxDeferredMessages::get())); + ::WeightInfo::service_deferred( + ::MaxDeferredMessages::get(), + ::MaxBucketsProcessed::get(), + )); assert!(FixedWeigher::weight(&mut xcm).unwrap().any_gt(low_max_weight)); let versioned_xcm = VersionedXcm::from(xcm); let para_id = ParaId::from(999); @@ -628,7 +631,10 @@ fn service_deferred_queues_should_stop_processing_when_weight_limit_is_reached_f let low_max_weight = FixedWeigher::weight(&mut xcm) .unwrap() .saturating_add( - ::WeightInfo::service_deferred(::MaxDeferredMessages::get())); + ::WeightInfo::service_deferred( + ::MaxDeferredMessages::get(), + ::MaxBucketsProcessed::get(), + )); let versioned_xcm = VersionedXcm::from(xcm); let para_id = ParaId::from(999); let second_para_id = ParaId::from(1000); @@ -687,7 +693,10 @@ fn service_deferred_queues_should_stop_processing_when_weight_limit_is_reached_f let low_max_weight = FixedWeigher::weight(&mut xcm) .unwrap() .saturating_add( - ::WeightInfo::service_deferred(::MaxDeferredMessages::get())); + ::WeightInfo::service_deferred( + ::MaxDeferredMessages::get(), + ::MaxBucketsProcessed::get(), + )); let versioned_xcm = VersionedXcm::from(xcm); let para_id = ParaId::from(999); let mut xcmp_message = Vec::new(); diff --git a/cumulus/pallets/xcmp-queue/src/weights.rs b/cumulus/pallets/xcmp-queue/src/weights.rs index e7ff28cb0215..c3a9c70cb19e 100644 --- a/cumulus/pallets/xcmp-queue/src/weights.rs +++ b/cumulus/pallets/xcmp-queue/src/weights.rs @@ -26,7 +26,7 @@ use sp_std::marker::PhantomData; pub trait WeightInfo { fn set_config_with_u32() -> Weight; fn set_config_with_weight() -> Weight; - fn service_deferred(m: u32) -> Weight; + fn service_deferred(m: u32, b: u32) -> Weight; fn discard_deferred_bucket(m: u32) -> Weight; fn discard_deferred_individual(m: u32) -> Weight; fn try_place_in_deferred_queue(m: u32) -> Weight; @@ -65,7 +65,7 @@ impl WeightInfo for SubstrateWeight { // Proof Skipped: XcmpQueue OverweightCount (max_values: Some(1), max_size: None, mode: Measured) // Storage: XcmpQueue Overweight (r:100 w:100) // Proof Skipped: XcmpQueue Overweight (max_values: None, max_size: None, mode: Measured) - fn service_deferred(m: u32) -> Weight { + fn service_deferred(m: u32, b: u32) -> Weight { Weight::from_parts(221_105_465_000 as u64, 0) .saturating_add(T::DbWeight::get().reads(107 as u64)) .saturating_add(T::DbWeight::get().writes(104 as u64)) @@ -126,7 +126,7 @@ impl WeightInfo for () { // Proof Skipped: XcmpQueue OverweightCount (max_values: Some(1), max_size: None, mode: Measured) // Storage: XcmpQueue Overweight (r:100 w:100) // Proof Skipped: XcmpQueue Overweight (max_values: None, max_size: None, mode: Measured) - fn service_deferred(m: u32) -> Weight { + fn service_deferred(m: u32, b: u32) -> Weight { Weight::from_parts(221_105_465_000 as u64, 0) .saturating_add(RocksDbWeight::get().reads(107 as u64)) .saturating_add(RocksDbWeight::get().writes(104 as u64))