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
@@ -22,7 +22,7 @@ use frame_system::RawOrigin;
benchmarks! {
set_config_with_u32 {}: update_resume_threshold(RawOrigin::Root, 100)
set_config_with_weight {}: update_weight_restrict_decay(RawOrigin::Root, 3_000_000)
set_config_with_weight {}: update_weight_restrict_decay(RawOrigin::Root, Weight::from_ref_time(3_000_000))
}
impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
+117 -84
View File
@@ -44,20 +44,18 @@ use cumulus_primitives_core::{
ParaId, XcmpMessageFormat, XcmpMessageHandler, XcmpMessageSource,
};
use frame_support::{
traits::EnsureOrigin,
traits::{EnsureOrigin, Get},
weights::{constants::WEIGHT_REF_TIME_PER_MILLIS, Weight},
};
use polkadot_runtime_common::xcm_sender::ConstantPrice;
use rand_chacha::{
rand_core::{RngCore, SeedableRng},
ChaChaRng,
};
use scale_info::TypeInfo;
use sp_runtime::{traits::Hash, RuntimeDebug};
use sp_runtime::RuntimeDebug;
use sp_std::{convert::TryFrom, prelude::*};
use xcm::{
latest::{prelude::*, Weight as XcmWeight},
VersionedXcm, WrapVersion, MAX_XCM_DECODE_DEPTH,
};
use xcm::{latest::prelude::*, VersionedXcm, WrapVersion, MAX_XCM_DECODE_DEPTH};
use xcm_executor::traits::ConvertOrigin;
pub use pallet::*;
@@ -68,6 +66,12 @@ pub type OverweightIndex = u64;
const LOG_TARGET: &str = "xcmp_queue";
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;
#[frame_support::pallet]
pub mod pallet {
use super::*;
@@ -103,6 +107,9 @@ pub mod pallet {
/// superuser origin.
type ControllerOriginConverter: ConvertOrigin<Self::RuntimeOrigin>;
/// The price for delivering an XCM to a sibling parachain destination.
type PriceForSiblingDelivery: PriceForSiblingDelivery;
/// The weight information of this pallet.
type WeightInfo: WeightInfo;
}
@@ -135,11 +142,11 @@ pub mod pallet {
/// Events:
/// - `OverweightServiced`: On success.
#[pallet::call_index(0)]
#[pallet::weight((Weight::from_ref_time(weight_limit.saturating_add(1_000_000)), DispatchClass::Operational,))]
#[pallet::weight((weight_limit.saturating_add(Weight::from_ref_time(1_000_000)), DispatchClass::Operational))]
pub fn service_overweight(
origin: OriginFor<T>,
index: OverweightIndex,
weight_limit: XcmWeight,
weight_limit: Weight,
) -> DispatchResultWithPostInfo {
T::ExecuteOverweightOrigin::ensure_origin(origin)?;
@@ -150,9 +157,8 @@ pub mod pallet {
&mut data.as_slice(),
)
.map_err(|_| Error::<T>::BadXcm)?;
let used =
Self::handle_xcm_message(sender, sent_at, xcm, Weight::from_ref_time(weight_limit))
.map_err(|_| Error::<T>::WeightOverLimit)?;
let used = Self::handle_xcm_message(sender, sent_at, xcm, weight_limit)
.map_err(|_| Error::<T>::WeightOverLimit)?;
Overweight::<T>::remove(index);
Self::deposit_event(Event::OverweightServiced { index, used });
Ok(Some(used.saturating_add(Weight::from_ref_time(1_000_000))).into())
@@ -234,9 +240,9 @@ pub mod pallet {
/// - `new`: Desired value for `QueueConfigData.threshold_weight`
#[pallet::call_index(6)]
#[pallet::weight((T::WeightInfo::set_config_with_weight(), DispatchClass::Operational,))]
pub fn update_threshold_weight(origin: OriginFor<T>, new: XcmWeight) -> DispatchResult {
pub fn update_threshold_weight(origin: OriginFor<T>, new: Weight) -> DispatchResult {
ensure_root(origin)?;
QueueConfig::<T>::mutate(|data| data.threshold_weight = Weight::from_ref_time(new));
QueueConfig::<T>::mutate(|data| data.threshold_weight = new);
Ok(())
}
@@ -248,14 +254,9 @@ pub mod pallet {
/// - `new`: Desired value for `QueueConfigData.weight_restrict_decay`.
#[pallet::call_index(7)]
#[pallet::weight((T::WeightInfo::set_config_with_weight(), DispatchClass::Operational,))]
pub fn update_weight_restrict_decay(
origin: OriginFor<T>,
new: XcmWeight,
) -> DispatchResult {
pub fn update_weight_restrict_decay(origin: OriginFor<T>, new: Weight) -> DispatchResult {
ensure_root(origin)?;
QueueConfig::<T>::mutate(|data| {
data.weight_restrict_decay = Weight::from_ref_time(new)
});
QueueConfig::<T>::mutate(|data| data.weight_restrict_decay = new);
Ok(())
}
@@ -269,12 +270,10 @@ pub mod pallet {
#[pallet::weight((T::WeightInfo::set_config_with_weight(), DispatchClass::Operational,))]
pub fn update_xcmp_max_individual_weight(
origin: OriginFor<T>,
new: XcmWeight,
new: Weight,
) -> DispatchResult {
ensure_root(origin)?;
QueueConfig::<T>::mutate(|data| {
data.xcmp_max_individual_weight = Weight::from_ref_time(new)
});
QueueConfig::<T>::mutate(|data| data.xcmp_max_individual_weight = new);
Ok(())
}
@@ -284,17 +283,15 @@ pub mod pallet {
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
/// Some XCM was executed ok.
Success { message_hash: Option<T::Hash>, weight: Weight },
Success { message_hash: Option<XcmHash>, weight: Weight },
/// Some XCM failed.
Fail { message_hash: Option<T::Hash>, error: XcmError, weight: Weight },
Fail { message_hash: Option<XcmHash>, error: XcmError, weight: Weight },
/// Bad XCM version used.
BadVersion { message_hash: Option<T::Hash> },
BadVersion { message_hash: Option<XcmHash> },
/// Bad XCM format used.
BadFormat { message_hash: Option<T::Hash> },
/// An upward message was sent to the relay chain.
UpwardMessageSent { message_hash: Option<T::Hash> },
BadFormat { message_hash: Option<XcmHash> },
/// An HRMP message was sent to a sibling parachain.
XcmpMessageSent { message_hash: Option<T::Hash> },
XcmpMessageSent { message_hash: Option<XcmHash> },
/// An XCM exceeded the individual message weight budget.
OverweightEnqueued {
sender: ParaId,
@@ -368,7 +365,7 @@ pub mod pallet {
/// `service_overweight`.
#[pallet::storage]
pub(super) type Overweight<T: Config> =
StorageMap<_, Twox64Concat, OverweightIndex, (ParaId, RelayBlockNumber, Vec<u8>)>;
CountedStorageMap<_, Twox64Concat, OverweightIndex, (ParaId, RelayBlockNumber, Vec<u8>)>;
/// The number of overweight messages ever recorded in `Overweight`. Also doubles as the next
/// available free overweight index.
@@ -623,34 +620,23 @@ impl<T: Config> Pallet<T> {
xcm: VersionedXcm<T::RuntimeCall>,
max_weight: Weight,
) -> Result<Weight, XcmError> {
let hash = Encode::using_encoded(&xcm, T::Hashing::hash);
let hash = xcm.using_encoded(sp_io::hashing::blake2_256);
log::debug!("Processing XCMP-XCM: {:?}", &hash);
let (result, event) = match Xcm::<T::RuntimeCall>::try_from(xcm) {
Ok(xcm) => {
let location = (1, Parachain(sender.into()));
let location = (Parent, Parachain(sender.into()));
match T::XcmExecutor::execute_xcm(location, xcm, max_weight.ref_time()) {
match T::XcmExecutor::execute_xcm(location, xcm, hash, max_weight) {
Outcome::Error(e) => (
Err(e),
Event::Fail { message_hash: Some(hash), error: e, weight: Weight::zero() },
),
Outcome::Complete(w) => (
Ok(Weight::from_ref_time(w)),
Event::Success {
message_hash: Some(hash),
weight: Weight::from_ref_time(w),
},
),
Outcome::Complete(w) =>
(Ok(w), Event::Success { message_hash: Some(hash), weight: w }),
// As far as the caller is concerned, this was dispatched without error, so
// we just report the weight used.
Outcome::Incomplete(w, e) => (
Ok(Weight::from_ref_time(w)),
Event::Fail {
message_hash: Some(hash),
error: e,
weight: Weight::from_ref_time(w),
},
),
Outcome::Incomplete(w, e) =>
(Ok(w), Event::Fail { message_hash: Some(hash), error: e, weight: w }),
}
},
Err(()) =>
@@ -663,6 +649,7 @@ impl<T: Config> Pallet<T> {
fn process_xcmp_message(
sender: ParaId,
(sent_at, format): (RelayBlockNumber, XcmpMessageFormat),
messages_processed: &mut u8,
max_weight: Weight,
max_individual_weight: Weight,
) -> (Weight, bool) {
@@ -672,35 +659,45 @@ impl<T: Config> Pallet<T> {
let mut weight_used = Weight::zero();
match format {
XcmpMessageFormat::ConcatenatedVersionedXcm => {
while !remaining_fragments.is_empty() {
while !remaining_fragments.is_empty() &&
*messages_processed < MAX_MESSAGES_PER_BLOCK
{
last_remaining_fragments = remaining_fragments;
if let Ok(xcm) = VersionedXcm::<T::RuntimeCall>::decode_with_depth_limit(
MAX_XCM_DECODE_DEPTH,
&mut remaining_fragments,
) {
let weight = max_weight - weight_used;
*messages_processed += 1;
match Self::handle_xcm_message(sender, sent_at, xcm, weight) {
Ok(used) => weight_used = weight_used.saturating_add(used),
Err(XcmError::WeightLimitReached(required))
if required > max_individual_weight.ref_time() =>
if required.any_gt(max_individual_weight) =>
{
// overweight - add to overweight queue and continue with message
// execution consuming the message.
let msg_len = last_remaining_fragments
.len()
.saturating_sub(remaining_fragments.len());
let overweight_xcm = last_remaining_fragments[..msg_len].to_vec();
let index = Self::stash_overweight(sender, sent_at, overweight_xcm);
let e = Event::OverweightEnqueued {
sender,
sent_at,
index,
required: Weight::from_ref_time(required),
};
Self::deposit_event(e);
let is_under_limit =
Overweight::<T>::count() < MAX_OVERWEIGHT_MESSAGES;
weight_used.saturating_accrue(T::DbWeight::get().reads(1));
if is_under_limit {
// overweight - add to overweight queue and continue with message
// execution consuming the message.
let msg_len = last_remaining_fragments
.len()
.saturating_sub(remaining_fragments.len());
let overweight_xcm =
last_remaining_fragments[..msg_len].to_vec();
let index =
Self::stash_overweight(sender, sent_at, overweight_xcm);
let e = Event::OverweightEnqueued {
sender,
sent_at,
index,
required,
};
Self::deposit_event(e);
}
},
Err(XcmError::WeightLimitReached(required))
if required <= max_weight.ref_time() =>
if required.all_lte(max_weight) =>
{
// That message didn't get processed this time because of being
// too heavy. We leave it around for next time and bail.
@@ -727,6 +724,7 @@ impl<T: Config> Pallet<T> {
if let Ok(blob) = <Vec<u8>>::decode(&mut remaining_fragments) {
let weight = max_weight - weight_used;
*messages_processed += 1;
match Self::handle_blob_message(sender, sent_at, blob, weight) {
Ok(used) => weight_used = weight_used.saturating_add(used),
Err(true) => {
@@ -804,6 +802,7 @@ impl<T: Config> Pallet<T> {
/// further.
fn service_xcmp_queue(max_weight: Weight) -> Weight {
let suspended = QueueSuspended::<T>::get();
let mut messages_processed = 0;
let mut status = <InboundXcmpStatus<T>>::get(); // <- sorted.
if status.is_empty() {
@@ -832,12 +831,13 @@ impl<T: Config> Pallet<T> {
let mut shuffle_index = 0;
while shuffle_index < shuffled.len() &&
max_weight.saturating_sub(weight_used).all_gte(threshold_weight)
max_weight.saturating_sub(weight_used).all_gte(threshold_weight) &&
messages_processed < MAX_MESSAGES_PER_BLOCK
{
let index = shuffled[shuffle_index];
let sender = status[index].sender;
let sender_origin = T::ControllerOriginConverter::convert_origin(
(1, Parachain(sender.into())),
(Parent, Parachain(sender.into())),
OriginKind::Superuser,
);
let is_controller = sender_origin
@@ -872,6 +872,7 @@ impl<T: Config> Pallet<T> {
let (weight_processed, is_empty) = Self::process_xcmp_message(
sender,
status[index].message_metadata[0],
&mut messages_processed,
weight_remaining,
xcmp_max_individual_weight,
);
@@ -1133,28 +1134,60 @@ impl<T: Config> XcmpMessageSource for Pallet<T> {
}
}
pub trait PriceForSiblingDelivery {
fn price_for_sibling_delivery(id: ParaId, message: &Xcm<()>) -> MultiAssets;
}
impl PriceForSiblingDelivery for () {
fn price_for_sibling_delivery(_: ParaId, _: &Xcm<()>) -> MultiAssets {
MultiAssets::new()
}
}
impl<T: Get<MultiAssets>> PriceForSiblingDelivery for ConstantPrice<T> {
fn price_for_sibling_delivery(_: ParaId, _: &Xcm<()>) -> MultiAssets {
T::get()
}
}
/// Xcm sender for sending to a sibling parachain.
impl<T: Config> SendXcm for Pallet<T> {
fn send_xcm(dest: impl Into<MultiLocation>, msg: Xcm<()>) -> Result<(), SendError> {
let dest = dest.into();
type Ticket = (ParaId, VersionedXcm<()>);
match &dest {
fn validate(
dest: &mut Option<MultiLocation>,
msg: &mut Option<Xcm<()>>,
) -> SendResult<(ParaId, VersionedXcm<()>)> {
let d = dest.take().ok_or(SendError::MissingArgument)?;
match &d {
// An HRMP message for a sibling parachain.
MultiLocation { parents: 1, interior: X1(Parachain(id)) } => {
let versioned_xcm = T::VersionWrapper::wrap_version(&dest, msg)
let xcm = msg.take().ok_or(SendError::MissingArgument)?;
let id = ParaId::from(*id);
let price = T::PriceForSiblingDelivery::price_for_sibling_delivery(id, &xcm);
let versioned_xcm = T::VersionWrapper::wrap_version(&d, xcm)
.map_err(|()| SendError::DestinationUnsupported)?;
let hash = T::Hashing::hash_of(&versioned_xcm);
Self::send_fragment(
(*id).into(),
XcmpMessageFormat::ConcatenatedVersionedXcm,
versioned_xcm,
)
.map_err(|e| SendError::Transport(<&'static str>::from(e)))?;
Self::deposit_event(Event::XcmpMessageSent { message_hash: Some(hash) });
Ok(())
Ok(((id, versioned_xcm), price))
},
// Anything else is unhandled. This includes a message this is meant for us.
_ => Err(SendError::CannotReachDestination(dest, msg)),
_ => {
// Anything else is unhandled. This includes a message that is not meant for us.
// We need to make sure that dest/msg is not consumed here.
*dest = Some(d);
Err(SendError::NotApplicable)
},
}
}
fn deliver((id, xcm): (ParaId, VersionedXcm<()>)) -> Result<XcmHash, SendError> {
let hash = xcm.using_encoded(sp_io::hashing::blake2_256);
match Self::send_fragment(id, XcmpMessageFormat::ConcatenatedVersionedXcm, xcm) {
Ok(_) => {
Self::deposit_event(Event::XcmpMessageSent { message_hash: Some(hash) });
Ok(hash)
},
Err(e) => Err(SendError::Transport(<&'static str>::from(e))),
}
}
}
+17 -5
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(2);
@@ -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>>() == 1 {
weight += migrate_to_v2::<T>();
weight.saturating_accrue(migrate_to_v2::<T>());
StorageVersion::new(2).put::<Pallet<T>>();
weight.saturating_accrue(T::DbWeight::get().writes(1));
}
if StorageVersion::get::<Pallet<T>>() == 2 {
weight.saturating_accrue(migrate_to_v3::<T>());
StorageVersion::new(3).put::<Pallet<T>>();
weight.saturating_accrue(T::DbWeight::get().writes(1));
}
weight
@@ -49,9 +55,9 @@ mod v1 {
pub suspend_threshold: u32,
pub drop_threshold: u32,
pub resume_threshold: u32,
pub threshold_weight: XcmWeight,
pub weight_restrict_decay: XcmWeight,
pub xcmp_max_individual_weight: XcmWeight,
pub threshold_weight: u64,
pub weight_restrict_decay: u64,
pub xcmp_max_individual_weight: u64,
}
impl Default for QueueConfigData {
@@ -98,6 +104,12 @@ pub fn migrate_to_v2<T: Config>() -> Weight {
T::DbWeight::get().reads_writes(1, 1)
}
pub fn migrate_to_v3<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::*;
+20 -8
View File
@@ -18,7 +18,10 @@ use crate as xcmp_queue;
use core::marker::PhantomData;
use cumulus_pallet_parachain_system::AnyRelayNumber;
use cumulus_primitives_core::{IsSystem, ParaId};
use frame_support::{parameter_types, traits::OriginTrait};
use frame_support::{
parameter_types,
traits::{Everything, Nothing, OriginTrait},
};
use frame_system::EnsureRoot;
use sp_core::H256;
use sp_runtime::{
@@ -26,9 +29,7 @@ use sp_runtime::{
traits::{BlakeTwo256, IdentityLookup},
};
use xcm::prelude::*;
use xcm_builder::{
CurrencyAdapter, FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset, ParentIsPreset,
};
use xcm_builder::{CurrencyAdapter, FixedWeightBounds, IsConcrete, NativeAsset, ParentIsPreset};
use xcm_executor::traits::ConvertOrigin;
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
@@ -58,7 +59,7 @@ parameter_types! {
type AccountId = u64;
impl frame_system::Config for Test {
type BaseCallFilter = frame_support::traits::Everything;
type BaseCallFilter = Everything;
type BlockWeights = ();
type BlockLength = ();
type DbWeight = ();
@@ -115,9 +116,10 @@ impl cumulus_pallet_parachain_system::Config for Test {
parameter_types! {
pub const RelayChain: MultiLocation = MultiLocation::parent();
pub Ancestry: MultiLocation = X1(Parachain(1u32.into())).into();
pub UnitWeightCost: u64 = 1_000_000;
pub UniversalLocation: InteriorMultiLocation = X1(Parachain(1u32.into())).into();
pub UnitWeightCost: Weight = Weight::from_parts(1_000_000, 1024);
pub const MaxInstructions: u32 = 100;
pub const MaxAssetsIntoHolding: u32 = 64;
}
/// Means for transacting assets on this chain.
@@ -145,7 +147,7 @@ impl xcm_executor::Config for XcmConfig {
type OriginConverter = ();
type IsReserve = NativeAsset;
type IsTeleporter = NativeAsset;
type LocationInverter = LocationInverter<Ancestry>;
type UniversalLocation = UniversalLocation;
type Barrier = ();
type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
type Trader = ();
@@ -153,6 +155,15 @@ impl xcm_executor::Config for XcmConfig {
type AssetTrap = ();
type AssetClaims = ();
type SubscriptionService = ();
type PalletInstancesInfo = AllPalletsWithSystem;
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
type AssetLocker = ();
type AssetExchanger = ();
type FeeManager = ();
type MessageExporter = ();
type UniversalAliases = Nothing;
type CallDispatcher = RuntimeCall;
type SafeCallFilter = Everything;
}
pub type XcmRouter = (
@@ -193,6 +204,7 @@ impl Config for Test {
type ControllerOrigin = EnsureRoot<AccountId>;
type ControllerOriginConverter = SystemParachainAsSuperuser<RuntimeOrigin>;
type WeightInfo = ();
type PriceForSiblingDelivery = ();
}
pub fn new_test_ext() -> sp_io::TestExternalities {
+108 -8
View File
@@ -46,6 +46,7 @@ fn bad_message_is_handled() {
XcmpQueue::process_xcmp_message(
1000.into(),
(1, format),
&mut 0,
Weight::from_ref_time(10_000_000_000),
Weight::from_ref_time(10_000_000_000),
);
@@ -69,6 +70,7 @@ fn handle_blob_message() {
XcmpQueue::process_xcmp_message(
1000.into(),
(1, format),
&mut 0,
Weight::from_ref_time(10_000_000_000),
Weight::from_ref_time(10_000_000_000),
);
@@ -86,6 +88,7 @@ fn handle_invalid_data() {
XcmpQueue::process_xcmp_message(
1000.into(),
(1, format),
&mut 0,
Weight::from_ref_time(10_000_000_000),
Weight::from_ref_time(10_000_000_000),
);
@@ -96,7 +99,7 @@ fn handle_invalid_data() {
fn service_overweight_unknown() {
new_test_ext().execute_with(|| {
assert_noop!(
XcmpQueue::service_overweight(RuntimeOrigin::root(), 0, 1000),
XcmpQueue::service_overweight(RuntimeOrigin::root(), 0, Weight::from_parts(1000, 1000)),
Error::<Test>::BadOverweightIndex,
);
});
@@ -109,7 +112,7 @@ fn service_overweight_bad_xcm_format() {
Overweight::<Test>::insert(0, (ParaId::from(1000), 0, bad_xcm));
assert_noop!(
XcmpQueue::service_overweight(RuntimeOrigin::root(), 0, 1000),
XcmpQueue::service_overweight(RuntimeOrigin::root(), 0, Weight::from_parts(1000, 1000)),
Error::<Test>::BadXcm
);
});
@@ -187,9 +190,15 @@ fn update_threshold_weight_works() {
new_test_ext().execute_with(|| {
let data: QueueConfigData = <QueueConfig<Test>>::get();
assert_eq!(data.threshold_weight, Weight::from_ref_time(100_000));
assert_ok!(XcmpQueue::update_threshold_weight(RuntimeOrigin::root(), 10_000));
assert_ok!(XcmpQueue::update_threshold_weight(
RuntimeOrigin::root(),
Weight::from_ref_time(10_000)
));
assert_noop!(
XcmpQueue::update_threshold_weight(RuntimeOrigin::signed(5), 10_000_000),
XcmpQueue::update_threshold_weight(
RuntimeOrigin::signed(5),
Weight::from_ref_time(10_000_000),
),
BadOrigin
);
let data: QueueConfigData = <QueueConfig<Test>>::get();
@@ -203,9 +212,15 @@ fn update_weight_restrict_decay_works() {
new_test_ext().execute_with(|| {
let data: QueueConfigData = <QueueConfig<Test>>::get();
assert_eq!(data.weight_restrict_decay, Weight::from_ref_time(2));
assert_ok!(XcmpQueue::update_weight_restrict_decay(RuntimeOrigin::root(), 5));
assert_ok!(XcmpQueue::update_weight_restrict_decay(
RuntimeOrigin::root(),
Weight::from_ref_time(5)
));
assert_noop!(
XcmpQueue::update_weight_restrict_decay(RuntimeOrigin::signed(6), 4),
XcmpQueue::update_weight_restrict_decay(
RuntimeOrigin::signed(6),
Weight::from_ref_time(4),
),
BadOrigin
);
let data: QueueConfigData = <QueueConfig<Test>>::get();
@@ -224,12 +239,12 @@ fn update_xcmp_max_individual_weight() {
);
assert_ok!(XcmpQueue::update_xcmp_max_individual_weight(
RuntimeOrigin::root(),
30u64 * WEIGHT_REF_TIME_PER_MILLIS
Weight::from_ref_time(30u64 * WEIGHT_REF_TIME_PER_MILLIS)
));
assert_noop!(
XcmpQueue::update_xcmp_max_individual_weight(
RuntimeOrigin::signed(3),
10u64 * WEIGHT_REF_TIME_PER_MILLIS
Weight::from_ref_time(10u64 * WEIGHT_REF_TIME_PER_MILLIS)
),
BadOrigin
);
@@ -241,3 +256,88 @@ fn update_xcmp_max_individual_weight() {
);
});
}
/// Validates [`validate`] for required Some(destination) and Some(message)
struct OkFixedXcmHashWithAssertingRequiredInputsSender;
impl OkFixedXcmHashWithAssertingRequiredInputsSender {
const FIXED_XCM_HASH: [u8; 32] = [9; 32];
fn fixed_delivery_asset() -> MultiAssets {
MultiAssets::new()
}
fn expected_delivery_result() -> Result<(XcmHash, MultiAssets), SendError> {
Ok((Self::FIXED_XCM_HASH, Self::fixed_delivery_asset()))
}
}
impl SendXcm for OkFixedXcmHashWithAssertingRequiredInputsSender {
type Ticket = ();
fn validate(
destination: &mut Option<MultiLocation>,
message: &mut Option<Xcm<()>>,
) -> SendResult<Self::Ticket> {
assert!(destination.is_some());
assert!(message.is_some());
Ok(((), OkFixedXcmHashWithAssertingRequiredInputsSender::fixed_delivery_asset()))
}
fn deliver(_: Self::Ticket) -> Result<XcmHash, SendError> {
Ok(Self::FIXED_XCM_HASH)
}
}
#[test]
fn xcmp_queue_does_not_consume_dest_or_msg_on_not_applicable() {
// dummy message
let message = Xcm(vec![Trap(5)]);
// XcmpQueue - check dest is really not applicable
let dest = (Parent, Parent, Parent);
let mut dest_wrapper = Some(dest.clone().into());
let mut msg_wrapper = Some(message.clone());
assert_eq!(
Err(SendError::NotApplicable),
<XcmpQueue as SendXcm>::validate(&mut dest_wrapper, &mut msg_wrapper)
);
// check wrapper were not consumed
assert_eq!(Some(dest.clone().into()), dest_wrapper.take());
assert_eq!(Some(message.clone()), msg_wrapper.take());
// another try with router chain with asserting sender
assert_eq!(
OkFixedXcmHashWithAssertingRequiredInputsSender::expected_delivery_result(),
send_xcm::<(XcmpQueue, OkFixedXcmHashWithAssertingRequiredInputsSender)>(
dest.into(),
message
)
);
}
#[test]
fn xcmp_queue_consumes_dest_and_msg_on_ok_validate() {
// dummy message
let message = Xcm(vec![Trap(5)]);
// XcmpQueue - check dest/msg is valid
let dest = (Parent, X1(Parachain(5555)));
let mut dest_wrapper = Some(dest.clone().into());
let mut msg_wrapper = Some(message.clone());
assert!(<XcmpQueue as SendXcm>::validate(&mut dest_wrapper, &mut msg_wrapper).is_ok());
// check wrapper were consumed
assert_eq!(None, dest_wrapper.take());
assert_eq!(None, msg_wrapper.take());
new_test_ext().execute_with(|| {
// another try with router chain with asserting sender
assert_eq!(
Err(SendError::Transport("NoChannel")),
send_xcm::<(XcmpQueue, OkFixedXcmHashWithAssertingRequiredInputsSender)>(
dest.into(),
message
)
);
});
}