Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Tweaks to XCM for Benchmarking #4283

Merged
merged 3 commits into from
Nov 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions xcm/pallet-xcm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1261,6 +1261,12 @@ pub mod pallet {
VersionNotifyTargets::<T>::remove(XCM_VERSION, LatestVersionedMultiLocation(dest));
Ok(())
}

/// Return true if a location is subscribed to XCM version changes.
fn is_subscribed(dest: &MultiLocation) -> bool {
let versioned_dest = LatestVersionedMultiLocation(dest);
VersionNotifyTargets::<T>::contains_key(XCM_VERSION, versioned_dest)
}
}

impl<T: Config> DropAssets for Pallet<T> {
Expand Down
3 changes: 3 additions & 0 deletions xcm/xcm-builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ mod mock;
#[cfg(test)]
mod tests;

#[cfg(feature = "std")]
pub mod test_utils;

mod location_conversion;
pub use location_conversion::{
Account32Hash, AccountId32Aliases, AccountKey20Aliases, ChildParachainConvertsVia,
Expand Down
54 changes: 1 addition & 53 deletions xcm/xcm-builder/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.

use crate::barriers::AllowSubscriptionsFrom;
use crate::{barriers::AllowSubscriptionsFrom, test_utils::*};
pub use crate::{
AllowKnownQueryResponses, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom,
FixedRateOfFungible, FixedWeightBounds, LocationInverter, TakeWeightCredit,
Expand All @@ -36,7 +36,6 @@ pub use sp_std::{
marker::PhantomData,
};
pub use xcm::latest::prelude::*;
use xcm_executor::traits::{ClaimAssets, DropAssets, VersionChangeNotifier};
pub use xcm_executor::{
traits::{ConvertOrigin, FilterAssetLocation, InvertLocation, OnResponse, TransactAsset},
Assets, Config,
Expand Down Expand Up @@ -273,57 +272,6 @@ pub type TestBarrier = (
AllowSubscriptionsFrom<IsInVec<AllowSubsFrom>>,
);

parameter_types! {
pub static TrappedAssets: Vec<(MultiLocation, MultiAssets)> = vec![];
}

pub struct TestAssetTrap;

impl DropAssets for TestAssetTrap {
fn drop_assets(origin: &MultiLocation, assets: Assets) -> Weight {
let mut t: Vec<(MultiLocation, MultiAssets)> = TrappedAssets::get();
t.push((origin.clone(), assets.into()));
TrappedAssets::set(t);
5
}
}

impl ClaimAssets for TestAssetTrap {
fn claim_assets(origin: &MultiLocation, ticket: &MultiLocation, what: &MultiAssets) -> bool {
let mut t: Vec<(MultiLocation, MultiAssets)> = TrappedAssets::get();
if let (0, X1(GeneralIndex(i))) = (ticket.parents, &ticket.interior) {
if let Some((l, a)) = t.get(*i as usize) {
if l == origin && a == what {
t.swap_remove(*i as usize);
TrappedAssets::set(t);
return true
}
}
}
false
}
}

parameter_types! {
pub static SubscriptionRequests: Vec<(MultiLocation, Option<(QueryId, u64)>)> = vec![];
}
pub struct TestSubscriptionService;

impl VersionChangeNotifier for TestSubscriptionService {
fn start(location: &MultiLocation, query_id: QueryId, max_weight: u64) -> XcmResult {
let mut r = SubscriptionRequests::get();
r.push((location.clone(), Some((query_id, max_weight))));
SubscriptionRequests::set(r);
Ok(())
}
fn stop(location: &MultiLocation) -> XcmResult {
let mut r = SubscriptionRequests::get();
r.push((location.clone(), None));
SubscriptionRequests::set(r);
Ok(())
}
}

pub struct TestConfig;
impl Config for TestConfig {
type Call = TestCall;
Expand Down
83 changes: 83 additions & 0 deletions xcm/xcm-builder/src/test_utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright 2020 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.

// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.

// Shared test utilities and implementations for the XCM Builder.

use frame_support::{dispatch::Weight, parameter_types};
use sp_std::vec::Vec;
pub use xcm::latest::prelude::*;
use xcm_executor::traits::{ClaimAssets, DropAssets, VersionChangeNotifier};
pub use xcm_executor::{
traits::{ConvertOrigin, FilterAssetLocation, InvertLocation, OnResponse, TransactAsset},
Assets, Config,
};

parameter_types! {
pub static SubscriptionRequests: Vec<(MultiLocation, Option<(QueryId, u64)>)> = vec![];
}

pub struct TestSubscriptionService;

impl VersionChangeNotifier for TestSubscriptionService {
fn start(location: &MultiLocation, query_id: QueryId, max_weight: u64) -> XcmResult {
let mut r = SubscriptionRequests::get();
r.push((location.clone(), Some((query_id, max_weight))));
SubscriptionRequests::set(r);
Ok(())
}
fn stop(location: &MultiLocation) -> XcmResult {
let mut r = SubscriptionRequests::get();
r.retain(|(l, _q)| l != location);
r.push((location.clone(), None));
SubscriptionRequests::set(r);
Ok(())
}
fn is_subscribed(location: &MultiLocation) -> bool {
let r = SubscriptionRequests::get();
r.iter().any(|(l, q)| l == location && q.is_some())
}
}

parameter_types! {
pub static TrappedAssets: Vec<(MultiLocation, MultiAssets)> = vec![];
}

pub struct TestAssetTrap;

impl DropAssets for TestAssetTrap {
fn drop_assets(origin: &MultiLocation, assets: Assets) -> Weight {
let mut t: Vec<(MultiLocation, MultiAssets)> = TrappedAssets::get();
t.push((origin.clone(), assets.into()));
TrappedAssets::set(t);
5
}
}

impl ClaimAssets for TestAssetTrap {
fn claim_assets(origin: &MultiLocation, ticket: &MultiLocation, what: &MultiAssets) -> bool {
let mut t: Vec<(MultiLocation, MultiAssets)> = TrappedAssets::get();
if let (0, X1(GeneralIndex(i))) = (ticket.parents, &ticket.interior) {
if let Some((l, a)) = t.get(*i as usize) {
if l == origin && a == what {
t.swap_remove(*i as usize);
TrappedAssets::set(t);
return true
}
}
}
false
}
}
2 changes: 1 addition & 1 deletion xcm/xcm-builder/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.

use super::{mock::*, *};
use super::{mock::*, test_utils::*, *};
use frame_support::{assert_err, weights::constants::WEIGHT_PER_SECOND};
use xcm::latest::prelude::*;
use xcm_executor::{traits::*, Config, XcmExecutor};
Expand Down
46 changes: 26 additions & 20 deletions xcm/xcm-executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,26 +139,7 @@ impl<Config: config::Config> ExecuteXcm<Config::Call> for XcmExecutor<Config> {
}
}

vm.refund_surplus();
drop(vm.trader);

let mut weight_used = xcm_weight.saturating_sub(vm.total_surplus);

if !vm.holding.is_empty() {
log::trace!(target: "xcm::execute_xcm_in_credit", "Trapping assets in holding register: {:?} (original_origin: {:?})", vm.holding, vm.original_origin);
let trap_weight = Config::AssetTrap::drop_assets(&vm.original_origin, vm.holding);
weight_used.saturating_accrue(trap_weight);
};

match vm.error {
None => Outcome::Complete(weight_used),
// TODO: #2841 #REALWEIGHT We should deduct the cost of any instructions following
// the error which didn't end up being executed.
Some((_i, e)) => {
log::debug!(target: "xcm::execute_xcm_in_credit", "Execution errored at {:?}: {:?} (original_origin: {:?})", _i, e, vm.original_origin);
Outcome::Incomplete(weight_used, e)
},
}
vm.post_execute(xcm_weight)
}
}

Expand Down Expand Up @@ -228,6 +209,31 @@ impl<Config: config::Config> XcmExecutor<Config> {
result
}

/// Execute any final operations after having executed the XCM message.
/// This includes refunding surplus weight, trapping extra holding funds, and returning any errors during execution.
pub fn post_execute(mut self, xcm_weight: Weight) -> Outcome {
shawntabrizi marked this conversation as resolved.
Show resolved Hide resolved
self.refund_surplus();
drop(self.trader);

let mut weight_used = xcm_weight.saturating_sub(self.total_surplus);

if !self.holding.is_empty() {
log::trace!(target: "xcm::execute_xcm_in_credit", "Trapping assets in holding register: {:?} (original_origin: {:?})", self.holding, self.original_origin);
let trap_weight = Config::AssetTrap::drop_assets(&self.original_origin, self.holding);
weight_used.saturating_accrue(trap_weight);
};

match self.error {
None => Outcome::Complete(weight_used),
// TODO: #2841 #REALWEIGHT We should deduct the cost of any instructions following
// the error which didn't end up being executed.
Some((_i, e)) => {
log::debug!(target: "xcm::execute_xcm_in_credit", "Execution errored at {:?}: {:?} (original_origin: {:?})", _i, e, self.original_origin);
Outcome::Incomplete(weight_used, e)
},
}
}

/// Remove the registered error handler and return it. Do not refund its weight.
fn take_error_handler(&mut self) -> Xcm<Config::Call> {
let mut r = Xcm::<Config::Call>(vec![]);
Expand Down
6 changes: 6 additions & 0 deletions xcm/xcm-executor/src/traits/on_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ pub trait VersionChangeNotifier {
/// Stop notifying `location` should the XCM change. Returns an error if there is no existing
/// notification set up.
fn stop(location: &MultiLocation) -> XcmResult;

/// Return true if a location is subscribed to XCM version changes.
fn is_subscribed(location: &MultiLocation) -> bool;
}

impl VersionChangeNotifier for () {
Expand All @@ -67,4 +70,7 @@ impl VersionChangeNotifier for () {
fn stop(_: &MultiLocation) -> XcmResult {
Err(XcmError::Unimplemented)
}
fn is_subscribed(_: &MultiLocation) -> bool {
false
}
}