XCM v3 Companion (#697)

* Fixes

* Undiener

* Undiener

* Undiener

* Lockfile

* Changes for send returning hash

* Include message ID as params to execute_xcm

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Companion fixes

* Formatting

* Fixes

* Formatting

* Bump

* Bump

* Fixes

* Formatting

* Make the price of UMP/XCMP message sending configurable

* cargo fmt

* Remove InvertLocation

* Formatting

* Use ConstantPrice from polkadot-runtime-common

* Fix naming

* cargo fmt

* Fixes

* Fixes

* Fixes

* Add CallDispatcher

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Remove unused import

* Remove unused import

* XCMv3 fixes (#1710)

* Fixes XCMv3 related
Fixes XCMv3 (removed query_holding)
Fixes XCMv3 - should use _depositable_count?
Fixes XCMv3 - removed TrustedReserve
Fixes - missing weights for statemine/statemint/westmint
[DO-NOT-CHERRY-PICK] tmp return query_holding to aviod conficts to master
Fixes - missing functions for pallet_xcm_benchmarks::generic::Config
Fixes for XCMv3 benchmarking
Fix xcm - removed query_holding

* ".git/.scripts/bench-bot.sh" xcm statemine assets pallet_xcm_benchmarks::generic

* ".git/.scripts/bench-bot.sh" xcm statemint assets pallet_xcm_benchmarks::generic

* ".git/.scripts/bench-bot.sh" xcm westmint assets pallet_xcm_benchmarks::generic

* Fix imports

* Avoid consuming XCM message for NotApplicable scenario (#1787)

* Avoid consuming message for NotApplicable scenario

* Avoid consuming message for NotApplicable scenario tests

* Add 10 message processing limit to DMP queue

* Add 10 message limit to XCMP queue

* Always increment the message_processed count whenever a message is processed

* Fix formatting

* Set an upper limit to the overweight message DMP queue

* Add upper limit to XCMP overweight message queue

* Fix for missing weight for `fn unpaid_execution()`

* Fix - usage of `messages_processed`

* Fixes

* Fixes

* Fixes

* cargo fmt

* Fixes

* Fixes

* Fixes

* Fixes

* Remove unused import

* Fixes for gav-xcm-v3 (#1835)

* Fix for FungiblesAdapter - trait changes: Contains -> AssetChecking

* Fix for missing weight for `fn unpaid_execution()`

* Used NonLocalMint for all NonZeroIssuance

* Fix

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Fix tests

* Fixes

* Add SafeCallFilter

* Add missing config items

* Add TODO

* Use () as the PriceForParentDelivery

* Fixes

* Fixes

* Fixes

* Fixes

* Update transact_origin to transact_origin_and_runtime_call

* Add ReachableDest config item to XCM pallet

* Update SafeCallFilter to allow remark_with_event in runtime benchmarks

* cargo fmt

* Update substrate

* Fix worst_case_holding

* Fix DMQ queue unit tests

* Remove unused label

* cargo fmt

* Actually process incoming XCMs

* Fixes

* Fixes

* Fixes

* Fixes - return back Weightless

* Added measured benchmarks for `pallet_xcm` (#1968)

* Fix

Fix

Fix

* Fix

* Fixes for transact benchmark

* Fixes add pallet_xcm to benchmarks

* Revert remark_with_event

* ".git/.scripts/bench-bot.sh" xcm statemine assets pallet_xcm_benchmarks::generic

* Fixes

* TMP

* Fix for reserve_asset_deposited

* ".git/.scripts/bench-bot.sh" pallet statemine assets pallet_xcm

* Fix

* ".git/.scripts/bench-bot.sh" pallet statemint assets pallet_xcm

* Fix

* ".git/.scripts/bench-bot.sh" pallet westmint assets pallet_xcm

* Fix westmint

* ".git/.scripts/bench-bot.sh" xcm statemine assets pallet_xcm_benchmarks::generic

* Fix

* ".git/.scripts/bench-bot.sh" xcm westmint assets pallet_xcm_benchmarks::generic

* ".git/.scripts/bench-bot.sh" xcm statemint assets pallet_xcm_benchmarks::generic

* ".git/.scripts/bench-bot.sh" pallet collectives-polkadot collectives pallet_xcm

* Fix for collectives

* ".git/.scripts/bench-bot.sh" pallet bridge-hub-kusama bridge-hubs pallet_xcm

* ".git/.scripts/bench-bot.sh" pallet bridge-hub-rococo bridge-hubs pallet_xcm

* Fixes for bridge-hubs

* Fixes - return back Weightless

* Fix - removed MigrateToTrackInactive for contracts-rococo

Co-authored-by: command-bot <>

* cargo fmt

* Fix benchmarks

* Bko gav xcm v3 (#1993)

* Fix

* ".git/.scripts/bench-bot.sh" xcm statemint assets pallet_xcm_benchmarks::fungible

* ".git/.scripts/bench-bot.sh" xcm statemine assets pallet_xcm_benchmarks::fungible

* ".git/.scripts/bench-bot.sh" xcm westmint assets pallet_xcm_benchmarks::fungible

* ".git/.scripts/bench-bot.sh" xcm statemine assets pallet_xcm_benchmarks::generic

* ".git/.scripts/bench-bot.sh" xcm statemint assets pallet_xcm_benchmarks::generic

* ".git/.scripts/bench-bot.sh" xcm westmint assets pallet_xcm_benchmarks::generic

* ".git/.scripts/bench-bot.sh" pallet statemine assets pallet_xcm

* ".git/.scripts/bench-bot.sh" pallet westmint assets pallet_xcm

* ".git/.scripts/bench-bot.sh" pallet statemint assets pallet_xcm

* ".git/.scripts/bench-bot.sh" pallet collectives-polkadot collectives pallet_xcm

* ".git/.scripts/bench-bot.sh" pallet bridge-hub-kusama bridge-hubs pallet_xcm

* ".git/.scripts/bench-bot.sh" pallet bridge-hub-rococo bridge-hubs pallet_xcm

Co-authored-by: command-bot <>

* Change AllowUnpaidExecutionFrom to be explicit

* xcm-v3 benchmarks, weights, fixes for bridge-hubs (#2035)

* Dumy weights to get compile

* Change UniversalLocation according to https://github.com/paritytech/polkadot/pull/4097 (Location Inversion Removed)

* Fix bridge-hubs weights

* ".git/.scripts/bench-bot.sh" pallet statemine assets pallet_xcm

* ".git/.scripts/bench-bot.sh" pallet statemint assets pallet_xcm

* ".git/.scripts/bench-bot.sh" pallet collectives-polkadot collectives pallet_xcm

* ".git/.scripts/bench-bot.sh" pallet westmint assets pallet_xcm

* ".git/.scripts/bench-bot.sh" xcm bridge-hub-kusama bridge-hubs pallet_xcm_benchmarks::generic

* ".git/.scripts/bench-bot.sh" xcm bridge-hub-kusama bridge-hubs pallet_xcm_benchmarks::fungible

* ".git/.scripts/bench-bot.sh" pallet bridge-hub-kusama bridge-hubs pallet_xcm

* ".git/.scripts/bench-bot.sh" pallet bridge-hub-rococo bridge-hubs pallet_xcm

* ".git/.scripts/bench-bot.sh" xcm bridge-hub-rococo bridge-hubs pallet_xcm_benchmarks::fungible

* ".git/.scripts/bench-bot.sh" xcm bridge-hub-rococo bridge-hubs pallet_xcm_benchmarks::generic

* Change NetworkId to Option<NetworkId>

Co-authored-by: command-bot <>
Co-authored-by: Keith Yeung <kungfukeith11@gmail.com>

* Add event for showing the hash of an UMP sent message (#1228)

* Add UpwardMessageSent event in parachain-system

* additional fixes

* Message Id

* Fix errors from merge

* fmt

* more fmt

* Remove todo

* more formatting

* Fixes

* Fixes

* Fixes

* Fixes

* Allow explicit unpaid executions from the relay chains for system parachains (#2060)

* Allow explicit unpaid executions from the relay chains for system parachains

* Put origin-filtering barriers into WithComputedOrigin

* Use ConstU32<8>

* Small nits

* formatting

* cargo fmt

* Allow receiving XCMs from any relay chain plurality

* Fixes

* update lockfile for {"polkadot", "substrate"}

* Update polkadot

* Add runtime-benchmarks feature

Co-authored-by: Keith Yeung <kungfukeith11@gmail.com>
Co-authored-by: Branislav Kontur <bkontur@gmail.com>
Co-authored-by: girazoki <gorka.irazoki@gmail.com>
Co-authored-by: parity-processbot <>
This commit is contained in:
Gavin Wood
2023-01-17 06:26:34 -03:00
committed by GitHub
parent a714040a0d
commit 3a459e8fcf
73 changed files with 4328 additions and 1487 deletions
+167 -92
View File
@@ -33,13 +33,16 @@ pub use pallet::*;
use scale_info::TypeInfo;
use sp_runtime::RuntimeDebug;
use sp_std::{convert::TryFrom, prelude::*};
use xcm::{
latest::{prelude::*, Weight as XcmWeight},
VersionedXcm, MAX_XCM_DECODE_DEPTH,
};
use xcm::{latest::prelude::*, VersionedXcm, MAX_XCM_DECODE_DEPTH};
const DEFAULT_POV_SIZE: u64 = 64 * 1024; // 64 KB
// Maximum amount of messages to process per block. This is a temporary measure until we properly
// account for proof size weights.
const MAX_MESSAGES_PER_BLOCK: u8 = 10;
// Maximum amount of messages that can exist in the overweight queue at any given time.
const MAX_OVERWEIGHT_MESSAGES: u32 = 1000;
#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
pub struct ConfigData {
/// The maximum amount of weight any individual message may consume. Messages above this weight
@@ -119,8 +122,13 @@ pub mod pallet {
/// The overweight messages.
#[pallet::storage]
pub(super) type Overweight<T> =
StorageMap<_, Blake2_128Concat, OverweightIndex, (RelayBlockNumber, Vec<u8>), OptionQuery>;
pub(super) type Overweight<T> = CountedStorageMap<
_,
Blake2_128Concat,
OverweightIndex,
(RelayBlockNumber, Vec<u8>),
OptionQuery,
>;
#[pallet::error]
pub enum Error<T> {
@@ -145,30 +153,18 @@ pub mod pallet {
#[pallet::call]
impl<T: Config> Pallet<T> {
/// Service a single overweight message.
///
/// - `origin`: Must pass `ExecuteOverweightOrigin`.
/// - `index`: The index of the overweight message to service.
/// - `weight_limit`: The amount of weight that message execution may take.
///
/// Errors:
/// - `Unknown`: Message of `index` is unknown.
/// - `OverLimit`: Message execution may use greater than `weight_limit`.
///
/// Events:
/// - `OverweightServiced`: On success.
#[pallet::call_index(0)]
#[pallet::weight(Weight::from_ref_time(weight_limit.saturating_add(1_000_000)))]
#[pallet::weight(weight_limit.saturating_add(Weight::from_ref_time(1_000_000)))]
pub fn service_overweight(
origin: OriginFor<T>,
index: OverweightIndex,
weight_limit: XcmWeight,
weight_limit: Weight,
) -> DispatchResultWithPostInfo {
T::ExecuteOverweightOrigin::ensure_origin(origin)?;
let (sent_at, data) = Overweight::<T>::get(index).ok_or(Error::<T>::Unknown)?;
let weight_used =
Self::try_service_message(Weight::from_ref_time(weight_limit), sent_at, &data[..])
.map_err(|_| Error::<T>::OverLimit)?;
let weight_used = Self::try_service_message(weight_limit, sent_at, &data[..])
.map_err(|_| Error::<T>::OverLimit)?;
Overweight::<T>::remove(index);
Self::deposit_event(Event::OverweightServiced { overweight_index: index, weight_used });
Ok(Some(weight_used.saturating_add(Weight::from_ref_time(1_000_000))).into())
@@ -201,16 +197,29 @@ pub mod pallet {
///
/// Returns the weight consumed by executing messages in the queue.
fn service_queue(limit: Weight) -> Weight {
PageIndex::<T>::mutate(|page_index| Self::do_service_queue(limit, page_index))
let mut messages_processed = 0;
PageIndex::<T>::mutate(|page_index| {
Self::do_service_queue(limit, page_index, &mut messages_processed)
})
}
/// Exactly equivalent to `service_queue` but expects a mutable `page_index` to be passed
/// in and any changes stored.
fn do_service_queue(limit: Weight, page_index: &mut PageIndexData) -> Weight {
fn do_service_queue(
limit: Weight,
page_index: &mut PageIndexData,
messages_processed: &mut u8,
) -> Weight {
let mut used = Weight::zero();
while page_index.begin_used < page_index.end_used {
let page = Pages::<T>::take(page_index.begin_used);
for (i, &(sent_at, ref data)) in page.iter().enumerate() {
if *messages_processed >= MAX_MESSAGES_PER_BLOCK {
// Exceeded block message limit - put the remaining messages back and bail
Pages::<T>::insert(page_index.begin_used, &page[i..]);
return used
}
*messages_processed += 1;
match Self::try_service_message(limit.saturating_sub(used), sent_at, &data[..])
{
Ok(w) => used += w,
@@ -257,12 +266,12 @@ pub mod pallet {
Ok(Weight::zero())
},
Ok(Ok(x)) => {
let outcome = T::XcmExecutor::execute_xcm(Parent, x, limit.ref_time());
let outcome = T::XcmExecutor::execute_xcm(Parent, x, message_id, limit);
match outcome {
Outcome::Error(XcmError::WeightLimitReached(required)) =>
Err((message_id, Weight::from_ref_time(required))),
Err((message_id, required)),
outcome => {
let weight_used = Weight::from_ref_time(outcome.weight_used());
let weight_used = outcome.weight_used();
Self::deposit_event(Event::ExecutedDownward { message_id, outcome });
Ok(weight_used)
},
@@ -280,11 +289,12 @@ pub mod pallet {
iter: impl Iterator<Item = (RelayBlockNumber, Vec<u8>)>,
limit: Weight,
) -> Weight {
let mut messages_processed = 0;
let mut page_index = PageIndex::<T>::get();
let config = Configuration::<T>::get();
// First try to use `max_weight` to service the current queue.
let mut used = Self::do_service_queue(limit, &mut page_index);
let mut used = Self::do_service_queue(limit, &mut page_index, &mut messages_processed);
// Then if the queue is empty, use the weight remaining to service the incoming messages
// and once we run out of weight, place them in the queue.
@@ -297,15 +307,21 @@ pub mod pallet {
};
for (i, (sent_at, data)) in iter.enumerate() {
if messages_processed >= MAX_MESSAGES_PER_BLOCK {
break
}
if maybe_enqueue_page.is_none() {
// We're not currently enqueuing - try to execute inline.
let remaining_weight = limit.saturating_sub(used);
messages_processed += 1;
match Self::try_service_message(remaining_weight, sent_at, &data[..]) {
Ok(consumed) => used += consumed,
Err((message_id, required_weight)) =>
// Too much weight required right now.
{
if required_weight.any_gt(config.max_individual) {
let is_under_limit = Overweight::<T>::count() < MAX_OVERWEIGHT_MESSAGES;
used.saturating_accrue(T::DbWeight::get().reads(1));
if required_weight.any_gt(config.max_individual) && is_under_limit {
// overweight - add to overweight queue and continue with
// message execution.
let overweight_index = page_index.overweight_count;
@@ -367,7 +383,7 @@ mod tests {
};
use sp_version::RuntimeVersion;
use std::cell::RefCell;
use xcm::latest::{MultiLocation, OriginKind, Weight as XCMWeight};
use xcm::latest::{MultiLocation, OriginKind};
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
type Block = frame_system::mocking::MockBlock<Test>;
@@ -442,28 +458,58 @@ mod tests {
})
}
pub enum Weightless {}
impl PreparedMessage for Weightless {
fn weight_of(&self) -> Weight {
unreachable!()
}
}
pub struct MockExec;
impl ExecuteXcm<RuntimeCall> for MockExec {
type Prepared = Weightless;
fn prepare(_message: Xcm) -> Result<Self::Prepared, Xcm> {
unreachable!()
}
fn execute(
_origin: impl Into<MultiLocation>,
_pre: Weightless,
_hash: XcmHash,
_weight_credit: Weight,
) -> Outcome {
unreachable!()
}
fn execute_xcm_in_credit(
_origin: impl Into<MultiLocation>,
message: Xcm,
weight_limit: XCMWeight,
_credit: XCMWeight,
_hash: XcmHash,
weight_limit: Weight,
_weight_credit: Weight,
) -> Outcome {
let o = match (message.0.len(), &message.0.first()) {
(1, Some(Transact { require_weight_at_most, .. })) => {
if *require_weight_at_most <= weight_limit {
if require_weight_at_most.all_lte(weight_limit) {
Outcome::Complete(*require_weight_at_most)
} else {
Outcome::Error(XcmError::WeightLimitReached(*require_weight_at_most))
}
},
// use 1000 to decide that it's not supported.
_ => Outcome::Incomplete(1000.min(weight_limit), XcmError::Unimplemented),
_ => Outcome::Incomplete(
Weight::from_parts(1000, 1000).min(weight_limit),
XcmError::Unimplemented,
),
};
TRACE.with(|q| q.borrow_mut().push((message, o.clone())));
o
}
fn charge_fees(_location: impl Into<MultiLocation>, _fees: MultiAssets) -> XcmResult {
Err(XcmError::Unimplemented)
}
}
impl Config for Test {
@@ -498,20 +544,23 @@ mod tests {
DmpQueue::handle_dmp_messages(iter, limit)
}
fn msg(weight: XCMWeight) -> Xcm {
fn msg(weight: u64) -> Xcm {
Xcm(vec![Transact {
origin_type: OriginKind::Native,
require_weight_at_most: weight,
origin_kind: OriginKind::Native,
require_weight_at_most: Weight::from_parts(weight, weight),
call: Vec::new().into(),
}])
}
fn msg_complete(weight: XCMWeight) -> (Xcm, Outcome) {
(msg(weight), Outcome::Complete(weight))
fn msg_complete(weight: u64) -> (Xcm, Outcome) {
(msg(weight), Outcome::Complete(Weight::from_parts(weight, weight)))
}
fn msg_limit_reached(weight: XCMWeight) -> (Xcm, Outcome) {
(msg(weight), Outcome::Error(XcmError::WeightLimitReached(weight)))
fn msg_limit_reached(weight: u64) -> (Xcm, Outcome) {
(
msg(weight),
Outcome::Error(XcmError::WeightLimitReached(Weight::from_parts(weight, weight))),
)
}
fn pages_queued() -> PageCounter {
@@ -531,7 +580,7 @@ mod tests {
#[test]
fn basic_setup_works() {
new_test_ext().execute_with(|| {
let weight_used = handle_messages(&[], Weight::from_ref_time(1000));
let weight_used = handle_messages(&[], Weight::from_parts(1000, 1000));
assert_eq!(weight_used, Weight::zero());
assert_eq!(take_trace(), Vec::new());
assert!(queue_is_empty());
@@ -542,8 +591,8 @@ mod tests {
fn service_inline_complete_works() {
new_test_ext().execute_with(|| {
let incoming = vec![msg(1000), msg(1001)];
let weight_used = handle_messages(&incoming, Weight::from_ref_time(2500));
assert_eq!(weight_used, Weight::from_ref_time(2001));
let weight_used = handle_messages(&incoming, Weight::from_parts(2500, 2500));
assert_eq!(weight_used, Weight::from_parts(2001, 2001));
assert_eq!(take_trace(), vec![msg_complete(1000), msg_complete(1001)]);
assert!(queue_is_empty());
});
@@ -554,8 +603,8 @@ mod tests {
new_test_ext().execute_with(|| {
let enqueued = vec![msg(1000), msg(1001), msg(1002)];
enqueue(&enqueued);
let weight_used = handle_messages(&[], Weight::from_ref_time(2500));
assert_eq!(weight_used, Weight::from_ref_time(2001));
let weight_used = handle_messages(&[], Weight::from_parts(2500, 2500));
assert_eq!(weight_used, Weight::from_parts(2001, 2001));
assert_eq!(
take_trace(),
vec![msg_complete(1000), msg_complete(1001), msg_limit_reached(1002),]
@@ -567,7 +616,7 @@ mod tests {
fn enqueue_works() {
new_test_ext().execute_with(|| {
let incoming = vec![msg(1000), msg(1001), msg(1002)];
let weight_used = handle_messages(&incoming, Weight::from_ref_time(999));
let weight_used = handle_messages(&incoming, Weight::from_parts(999, 999));
assert_eq!(weight_used, Weight::zero());
assert_eq!(
PageIndex::<Test>::get(),
@@ -576,15 +625,15 @@ mod tests {
assert_eq!(Pages::<Test>::get(0).len(), 3);
assert_eq!(take_trace(), vec![msg_limit_reached(1000)]);
let weight_used = handle_messages(&[], Weight::from_ref_time(2500));
assert_eq!(weight_used, Weight::from_ref_time(2001));
let weight_used = handle_messages(&[], Weight::from_parts(2500, 2500));
assert_eq!(weight_used, Weight::from_parts(2001, 2001));
assert_eq!(
take_trace(),
vec![msg_complete(1000), msg_complete(1001), msg_limit_reached(1002),]
);
let weight_used = handle_messages(&[], Weight::from_ref_time(2500));
assert_eq!(weight_used, Weight::from_ref_time(1002));
let weight_used = handle_messages(&[], Weight::from_parts(2500, 2500));
assert_eq!(weight_used, Weight::from_parts(1002, 1002));
assert_eq!(take_trace(), vec![msg_complete(1002),]);
assert!(queue_is_empty());
});
@@ -594,14 +643,14 @@ mod tests {
fn service_inline_then_enqueue_works() {
new_test_ext().execute_with(|| {
let incoming = vec![msg(1000), msg(1001), msg(1002)];
let weight_used = handle_messages(&incoming, Weight::from_ref_time(1500));
assert_eq!(weight_used, Weight::from_ref_time(1000));
let weight_used = handle_messages(&incoming, Weight::from_parts(1500, 1500));
assert_eq!(weight_used, Weight::from_parts(1000, 1000));
assert_eq!(pages_queued(), 1);
assert_eq!(Pages::<Test>::get(0).len(), 2);
assert_eq!(take_trace(), vec![msg_complete(1000), msg_limit_reached(1001),]);
let weight_used = handle_messages(&[], Weight::from_ref_time(2500));
assert_eq!(weight_used, Weight::from_ref_time(2003));
let weight_used = handle_messages(&[], Weight::from_parts(2500, 2500));
assert_eq!(weight_used, Weight::from_parts(2003, 2003));
assert_eq!(take_trace(), vec![msg_complete(1001), msg_complete(1002),]);
assert!(queue_is_empty());
});
@@ -613,8 +662,8 @@ mod tests {
let enqueued = vec![msg(1000), msg(1001)];
let incoming = vec![msg(1002), msg(1003)];
enqueue(&enqueued);
let weight_used = handle_messages(&incoming, Weight::from_ref_time(5000));
assert_eq!(weight_used, Weight::from_ref_time(4006));
let weight_used = handle_messages(&incoming, Weight::from_parts(5000, 5000));
assert_eq!(weight_used, Weight::from_parts(4006, 4006));
assert_eq!(
take_trace(),
vec![
@@ -634,19 +683,19 @@ mod tests {
let enqueued = vec![msg(1000), msg(10001)];
let incoming = vec![msg(1002), msg(1003)];
enqueue(&enqueued);
let weight_used = handle_messages(&incoming, Weight::from_ref_time(5000));
assert_eq!(weight_used, Weight::from_ref_time(1000));
let weight_used = handle_messages(&incoming, Weight::from_parts(5000, 5000));
assert_eq!(weight_used, Weight::from_parts(1000, 1000));
assert_eq!(take_trace(), vec![msg_complete(1000), msg_limit_reached(10001),]);
assert_eq!(pages_queued(), 2);
// 5000 is not enough to process the 10001 blocker, so nothing happens.
let weight_used = handle_messages(&[], Weight::from_ref_time(5000));
let weight_used = handle_messages(&[], Weight::from_parts(5000, 5000));
assert_eq!(weight_used, Weight::zero());
assert_eq!(take_trace(), vec![msg_limit_reached(10001),]);
// 20000 is now enough to process everything.
let weight_used = handle_messages(&[], Weight::from_ref_time(20000));
assert_eq!(weight_used, Weight::from_ref_time(12006));
let weight_used = handle_messages(&[], Weight::from_parts(20000, 20000));
assert_eq!(weight_used, Weight::from_parts(12006, 12006));
assert_eq!(
take_trace(),
vec![msg_complete(10001), msg_complete(1002), msg_complete(1003),]
@@ -661,8 +710,8 @@ mod tests {
let enqueued = vec![msg(1000), msg(1001)];
let incoming = vec![msg(10002), msg(1003)];
enqueue(&enqueued);
let weight_used = handle_messages(&incoming, Weight::from_ref_time(5000));
assert_eq!(weight_used, Weight::from_ref_time(2001));
let weight_used = handle_messages(&incoming, Weight::from_parts(5000, 5000));
assert_eq!(weight_used, Weight::from_parts(2001, 2001));
assert_eq!(
take_trace(),
vec![msg_complete(1000), msg_complete(1001), msg_limit_reached(10002),]
@@ -670,8 +719,8 @@ mod tests {
assert_eq!(pages_queued(), 1);
// 20000 is now enough to process everything.
let weight_used = handle_messages(&[], Weight::from_ref_time(20000));
assert_eq!(weight_used, Weight::from_ref_time(11005));
let weight_used = handle_messages(&[], Weight::from_parts(20000, 20000));
assert_eq!(weight_used, Weight::from_parts(11005, 11005));
assert_eq!(take_trace(), vec![msg_complete(10002), msg_complete(1003),]);
assert!(queue_is_empty());
});
@@ -683,8 +732,8 @@ mod tests {
let enqueued = vec![msg(1000), msg(1001)];
let incoming = vec![msg(1002), msg(10003)];
enqueue(&enqueued);
let weight_used = handle_messages(&incoming, Weight::from_ref_time(5000));
assert_eq!(weight_used, Weight::from_ref_time(3003));
let weight_used = handle_messages(&incoming, Weight::from_parts(5000, 5000));
assert_eq!(weight_used, Weight::from_parts(3003, 3003));
assert_eq!(
take_trace(),
vec![
@@ -697,8 +746,8 @@ mod tests {
assert_eq!(pages_queued(), 1);
// 20000 is now enough to process everything.
let weight_used = handle_messages(&[], Weight::from_ref_time(20000));
assert_eq!(weight_used, Weight::from_ref_time(10003));
let weight_used = handle_messages(&[], Weight::from_parts(20000, 20000));
assert_eq!(weight_used, Weight::from_parts(10003, 10003));
assert_eq!(take_trace(), vec![msg_complete(10003),]);
assert!(queue_is_empty());
});
@@ -709,20 +758,20 @@ mod tests {
new_test_ext().execute_with(|| {
let enqueued = vec![msg(1000), msg(1001)];
enqueue(&enqueued);
let weight_used = handle_messages(&vec![msg(1002)], Weight::from_ref_time(1500));
assert_eq!(weight_used, Weight::from_ref_time(1000));
let weight_used = handle_messages(&vec![msg(1002)], Weight::from_parts(1500, 1500));
assert_eq!(weight_used, Weight::from_parts(1000, 1000));
assert_eq!(take_trace(), vec![msg_complete(1000), msg_limit_reached(1001),]);
assert_eq!(pages_queued(), 2);
assert_eq!(PageIndex::<Test>::get().begin_used, 0);
let weight_used = handle_messages(&vec![msg(1003)], Weight::from_ref_time(1500));
assert_eq!(weight_used, Weight::from_ref_time(1001));
let weight_used = handle_messages(&vec![msg(1003)], Weight::from_parts(1500, 1500));
assert_eq!(weight_used, Weight::from_parts(1001, 1001));
assert_eq!(take_trace(), vec![msg_complete(1001), msg_limit_reached(1002),]);
assert_eq!(pages_queued(), 2);
assert_eq!(PageIndex::<Test>::get().begin_used, 1);
let weight_used = handle_messages(&vec![msg(1004)], Weight::from_ref_time(1500));
assert_eq!(weight_used, Weight::from_ref_time(1002));
let weight_used = handle_messages(&vec![msg(1004)], Weight::from_parts(1500, 1500));
assert_eq!(weight_used, Weight::from_parts(1002, 1002));
assert_eq!(take_trace(), vec![msg_complete(1002), msg_limit_reached(1003),]);
assert_eq!(pages_queued(), 2);
assert_eq!(PageIndex::<Test>::get().begin_used, 2);
@@ -733,11 +782,13 @@ mod tests {
fn overweight_should_not_block_queue() {
new_test_ext().execute_with(|| {
// Set the overweight threshold to 9999.
Configuration::<Test>::put(ConfigData { max_individual: Weight::from_ref_time(9999) });
Configuration::<Test>::put(ConfigData {
max_individual: Weight::from_parts(9999, 9999),
});
let incoming = vec![msg(1000), msg(10001), msg(1002)];
let weight_used = handle_messages(&incoming, Weight::from_ref_time(2500));
assert_eq!(weight_used, Weight::from_ref_time(2002));
let weight_used = handle_messages(&incoming, Weight::from_parts(2500, 2500));
assert_eq!(weight_used, Weight::from_parts(2002, 2002));
assert!(queue_is_empty());
assert_eq!(
take_trace(),
@@ -752,40 +803,64 @@ mod tests {
fn overweights_should_be_manually_executable() {
new_test_ext().execute_with(|| {
// Set the overweight threshold to 9999.
Configuration::<Test>::put(ConfigData { max_individual: Weight::from_ref_time(9999) });
Configuration::<Test>::put(ConfigData {
max_individual: Weight::from_parts(9999, 9999),
});
let incoming = vec![msg(10000)];
let weight_used = handle_messages(&incoming, Weight::from_ref_time(2500));
let weight_used = handle_messages(&incoming, Weight::from_parts(2500, 2500));
assert_eq!(weight_used, Weight::zero());
assert_eq!(take_trace(), vec![msg_limit_reached(10000)]);
assert_eq!(overweights(), vec![0]);
assert_noop!(
DmpQueue::service_overweight(RuntimeOrigin::signed(1), 0, 20000),
DmpQueue::service_overweight(
RuntimeOrigin::signed(1),
0,
Weight::from_parts(20000, 20000)
),
BadOrigin
);
assert_noop!(
DmpQueue::service_overweight(RuntimeOrigin::root(), 1, 20000),
DmpQueue::service_overweight(
RuntimeOrigin::root(),
1,
Weight::from_parts(20000, 20000)
),
Error::<Test>::Unknown
);
assert_noop!(
DmpQueue::service_overweight(RuntimeOrigin::root(), 0, 9999),
DmpQueue::service_overweight(
RuntimeOrigin::root(),
0,
Weight::from_parts(9999, 9999)
),
Error::<Test>::OverLimit
);
assert_eq!(take_trace(), vec![msg_limit_reached(10000)]);
let base_weight = super::Call::<Test>::service_overweight { index: 0, weight_limit: 0 }
.get_dispatch_info()
.weight;
let base_weight =
super::Call::<Test>::service_overweight { index: 0, weight_limit: Weight::zero() }
.get_dispatch_info()
.weight;
use frame_support::dispatch::GetDispatchInfo;
let info = DmpQueue::service_overweight(RuntimeOrigin::root(), 0, 20000).unwrap();
let info = DmpQueue::service_overweight(
RuntimeOrigin::root(),
0,
Weight::from_parts(20000, 20000),
)
.unwrap();
let actual_weight = info.actual_weight.unwrap();
assert_eq!(actual_weight, base_weight + Weight::from_ref_time(10000));
assert_eq!(actual_weight, base_weight + Weight::from_parts(10000, 10000));
assert_eq!(take_trace(), vec![msg_complete(10000)]);
assert!(overweights().is_empty());
assert_noop!(
DmpQueue::service_overweight(RuntimeOrigin::root(), 0, 20000),
DmpQueue::service_overweight(
RuntimeOrigin::root(),
0,
Weight::from_parts(20000, 20000)
),
Error::<Test>::Unknown
);
});
@@ -798,8 +873,8 @@ mod tests {
enqueue(&vec![msg(1002), msg(1003)]);
enqueue(&vec![msg(1004), msg(1005)]);
let weight_used = DmpQueue::on_idle(1, Weight::from_ref_time(6000));
assert_eq!(weight_used, Weight::from_ref_time(5010));
let weight_used = DmpQueue::on_idle(1, Weight::from_parts(6000, 6000));
assert_eq!(weight_used, Weight::from_parts(5010, 5010));
assert_eq!(
take_trace(),
vec![
+19 -3
View File
@@ -22,7 +22,6 @@ use frame_support::{
traits::StorageVersion,
weights::{constants::WEIGHT_REF_TIME_PER_MILLIS, Weight},
};
use xcm::latest::Weight as XcmWeight;
/// The current storage version.
pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
@@ -33,8 +32,15 @@ pub fn migrate_to_latest<T: Config>() -> Weight {
let mut weight = T::DbWeight::get().reads(1);
if StorageVersion::get::<Pallet<T>>() == 0 {
weight += migrate_to_v1::<T>();
weight.saturating_accrue(migrate_to_v1::<T>());
StorageVersion::new(1).put::<Pallet<T>>();
weight.saturating_accrue(T::DbWeight::get().writes(1));
}
if StorageVersion::get::<Pallet<T>>() == 1 {
weight.saturating_accrue(migrate_to_v2::<T>());
StorageVersion::new(2).put::<Pallet<T>>();
weight.saturating_accrue(T::DbWeight::get().writes(1));
}
weight
@@ -46,7 +52,7 @@ mod v0 {
#[derive(Decode, Encode, Debug)]
pub struct ConfigData {
pub max_individual: XcmWeight,
pub max_individual: u64,
}
impl Default for ConfigData {
@@ -78,6 +84,16 @@ pub fn migrate_to_v1<T: Config>() -> Weight {
T::DbWeight::get().reads_writes(1, 1)
}
/// Migrates `Overweight` so that it initializes the storage map's counter.
///
/// NOTE: Only use this function if you know what you're doing. Default to using
/// `migrate_to_latest`.
pub fn migrate_to_v2<T: Config>() -> Weight {
let overweight_messages = <Pallet<T> as Store>::Overweight::initialize_counter() as u64;
T::DbWeight::get().reads_writes(overweight_messages, 1)
}
#[cfg(test)]
mod tests {
use super::*;