Unverified Commit d8d5ce28 authored by Gavin Wood's avatar Gavin Wood Committed by GitHub
Browse files

XCM v2: Scripting, Query responses, Exception handling and Error reporting (#3629)

* Intoduce XCM v2

Also some minor fix for v0/v1

* Minor version cleanup

* Minor version cleanup

* Introduce SendError for XcmSend trait to avoid cycles with having Outcome in Xcm

* comment

* Corrent type

* Docs

* Fix build

* Fixes

* Introduce the basic impl

* Docs

* Add function

* Basic implementation

* Weighed responses and on_report

* Make XCM more script-like

* Remove BuyExecution::orders

* Fixes

* Fixes

* Fixes

* Formatting

* Initial draft and make pallet-xcm build

* fix XCM tests

* Formatting

* Fixes

* Formatting

* spelling

* Fixes

* Fixes

* spelling

* tests for translation

* extra fields to XCM pallet

* Formatting

* Fixes

* spelling

* first integration test

* Another integration test

* Formatting

* fix tests

* all tests

* Fixes

* Fixes

* Formatting

* Fixes

* Fixes

* Formatting

* Bump

* Remove unneeded structuring

* add instruction

* Fixes

* spelling

* Fixes

* Fixes

* Formatting

* Fixes

* Fixes

* Formatting

* Introduce and use VersionedResponse

* Introduce versioning to dispatchables' params

* Fixes

* Formatting

* Rest of merge

* more work

* Formatting

* Basic logic

* Fixes

* Fixes

* Add test

* Fixes

* Formatting

* Fixes

* Fixes

* Fixes

* Nits

* Simplify

* Spelling

* Formatting

* Return weight of unexecuted instructions in case of error as surplus

* Formatting

* Fixes

* Test for instruction count limiting

* Formatting

* Docs
parent 43603f68
Pipeline #154322 passed with stages
in 38 minutes and 39 seconds
......@@ -276,7 +276,7 @@ impl PolkadotTestNode {
function: impl Into<polkadot_test_runtime::Call>,
caller: Sr25519Keyring,
) -> Result<RpcTransactionOutput, RpcTransactionError> {
let extrinsic = construct_extrinsic(&*self.client, function, caller);
let extrinsic = construct_extrinsic(&*self.client, function, caller, 0);
self.rpc_handlers.send_transaction(extrinsic.into()).await
}
......@@ -332,12 +332,12 @@ pub fn construct_extrinsic(
client: &Client,
function: impl Into<polkadot_test_runtime::Call>,
caller: Sr25519Keyring,
nonce: u32,
) -> UncheckedExtrinsic {
let function = function.into();
let current_block_hash = client.info().best_hash;
let current_block = client.info().best_number.saturated_into();
let genesis_block = client.hash(0).unwrap().unwrap();
let nonce = 0;
let period =
BlockHashCount::get().checked_next_power_of_two().map(|c| c / 2).unwrap_or(2) as u64;
let tip = 0;
......@@ -384,5 +384,5 @@ pub fn construct_transfer_extrinsic(
value,
));
construct_extrinsic(client, function, origin)
construct_extrinsic(client, function, origin, 0)
}
......@@ -19,7 +19,7 @@
use parity_scale_codec::Encode;
use runtime_parachains::{configuration, dmp};
use sp_std::marker::PhantomData;
use xcm::opaque::latest::*;
use xcm::latest::prelude::*;
/// XCM sender for relay chain. It only sends downward message.
pub struct ChildParachainRouter<T, W>(PhantomData<(T, W)>);
......@@ -27,22 +27,22 @@ pub struct ChildParachainRouter<T, W>(PhantomData<(T, W)>);
impl<T: configuration::Config + dmp::Config, W: xcm::WrapVersion> SendXcm
for ChildParachainRouter<T, W>
{
fn send_xcm(dest: MultiLocation, msg: Xcm) -> Result {
fn send_xcm(dest: MultiLocation, msg: Xcm<()>) -> SendResult {
match dest {
MultiLocation { parents: 0, interior: Junctions::X1(Junction::Parachain(id)) } => {
MultiLocation { parents: 0, interior: X1(Parachain(id)) } => {
// Downward message passing.
let versioned_xcm =
W::wrap_version(&dest, msg).map_err(|()| Error::DestinationUnsupported)?;
W::wrap_version(&dest, msg).map_err(|()| SendError::DestinationUnsupported)?;
let config = <configuration::Pallet<T>>::config();
<dmp::Pallet<T>>::queue_downward_message(
&config,
id.into(),
versioned_xcm.encode(),
)
.map_err(Into::<Error>::into)?;
.map_err(Into::<SendError>::into)?;
Ok(())
},
dest => Err(Error::CannotReachDestination(dest, msg)),
dest => Err(SendError::CannotReachDestination(dest, msg)),
}
}
}
......@@ -1255,6 +1255,9 @@ type LocalOriginConverter = (
parameter_types! {
/// The amount of weight an XCM operation takes. This is a safe overestimate.
pub const BaseXcmWeight: Weight = 1_000_000_000;
/// Maximum number of instructions in a single XCM fragment. A sanity check against weight
/// calculations getting too crazy.
pub const MaxInstructions: u32 = 100;
}
/// The XCM router. When we want to send an XCM message, we use this type. It amalgamates all of our
......@@ -1290,7 +1293,7 @@ impl xcm_executor::Config for XcmConfig {
type IsTeleporter = TrustedTeleporters;
type LocationInverter = LocationInverter<Ancestry>;
type Barrier = Barrier;
type Weigher = FixedWeightBounds<BaseXcmWeight, Call>;
type Weigher = FixedWeightBounds<BaseXcmWeight, Call, MaxInstructions>;
// The weight trader piggybacks on the existing transaction-fee conversion logic.
type Trader = UsingComponents<WeightToFee, KsmLocation, AccountId, Balances, ToAuthor<Runtime>>;
type ResponseHandler = ();
......@@ -1325,8 +1328,10 @@ impl pallet_xcm::Config for Runtime {
type XcmExecutor = XcmExecutor<XcmConfig>;
type XcmTeleportFilter = Everything;
type XcmReserveTransferFilter = Everything;
type Weigher = FixedWeightBounds<BaseXcmWeight, Call>;
type Weigher = FixedWeightBounds<BaseXcmWeight, Call, MaxInstructions>;
type LocationInverter = LocationInverter<Ancestry>;
type Origin = Origin;
type Call = Call;
}
parameter_types! {
......
......@@ -22,7 +22,7 @@ use frame_support::pallet_prelude::*;
use primitives::v1::{DownwardMessage, Hash, Id as ParaId, InboundDownwardMessage};
use sp_runtime::traits::{BlakeTwo256, Hash as HashT, SaturatedConversion};
use sp_std::{fmt, prelude::*};
use xcm::latest::Error as XcmError;
use xcm::latest::SendError;
pub use pallet::*;
......@@ -33,10 +33,10 @@ pub enum QueueDownwardMessageError {
ExceedsMaxMessageSize,
}
impl From<QueueDownwardMessageError> for XcmError {
impl From<QueueDownwardMessageError> for SendError {
fn from(err: QueueDownwardMessageError) -> Self {
match err {
QueueDownwardMessageError::ExceedsMaxMessageSize => XcmError::ExceedsMaxMessageSize,
QueueDownwardMessageError::ExceedsMaxMessageSize => SendError::ExceedsMaxMessageSize,
}
}
}
......
......@@ -1007,13 +1007,13 @@ impl<T: Config> Pallet<T> {
let notification_bytes = {
use parity_scale_codec::Encode as _;
use xcm::opaque::{v1::Xcm, VersionedXcm};
use xcm::opaque::{latest::prelude::*, VersionedXcm};
VersionedXcm::from(Xcm::HrmpNewChannelOpenRequest {
VersionedXcm::from(Xcm(vec![HrmpNewChannelOpenRequest {
sender: u32::from(origin),
max_capacity: proposed_max_capacity,
max_message_size: proposed_max_message_size,
})
}]))
.encode()
};
if let Err(dmp::QueueDownwardMessageError::ExceedsMaxMessageSize) =
......@@ -1066,9 +1066,9 @@ impl<T: Config> Pallet<T> {
let notification_bytes = {
use parity_scale_codec::Encode as _;
use xcm::opaque::{v1::Xcm, VersionedXcm};
VersionedXcm::from(Xcm::HrmpChannelAccepted { recipient: u32::from(origin) }).encode()
use xcm::opaque::{latest::prelude::*, VersionedXcm};
let xcm = Xcm(vec![HrmpChannelAccepted { recipient: u32::from(origin) }]);
VersionedXcm::from(xcm).encode()
};
if let Err(dmp::QueueDownwardMessageError::ExceedsMaxMessageSize) =
<dmp::Pallet<T>>::queue_downward_message(&config, sender, notification_bytes)
......@@ -1106,13 +1106,13 @@ impl<T: Config> Pallet<T> {
let config = <configuration::Pallet<T>>::config();
let notification_bytes = {
use parity_scale_codec::Encode as _;
use xcm::opaque::{v1::Xcm, VersionedXcm};
use xcm::opaque::{latest::prelude::*, VersionedXcm};
VersionedXcm::from(Xcm::HrmpChannelClosing {
VersionedXcm::from(Xcm(vec![HrmpChannelClosing {
initiator: u32::from(origin),
sender: u32::from(channel_id.sender),
recipient: u32::from(channel_id.recipient),
})
}]))
.encode()
};
let opposite_party =
......
......@@ -631,6 +631,7 @@ parameter_types! {
pub const RococoForTrick: (MultiAssetFilter, MultiLocation) = (Rococo::get(), Parachain(110).into());
pub const RococoForTrack: (MultiAssetFilter, MultiLocation) = (Rococo::get(), Parachain(120).into());
pub const RococoForStatemint: (MultiAssetFilter, MultiLocation) = (Rococo::get(), Parachain(1001).into());
pub const MaxInstructions: u32 = 100;
}
pub type TrustedTeleporters = (
xcm_builder::Case<RococoForTick>,
......@@ -666,7 +667,7 @@ impl xcm_executor::Config for XcmConfig {
type IsTeleporter = TrustedTeleporters;
type LocationInverter = LocationInverter<Ancestry>;
type Barrier = Barrier;
type Weigher = FixedWeightBounds<BaseXcmWeight, Call>;
type Weigher = FixedWeightBounds<BaseXcmWeight, Call, MaxInstructions>;
type Trader = UsingComponents<WeightToFee, RocLocation, AccountId, Balances, ToAuthor<Runtime>>;
type ResponseHandler = ();
}
......@@ -696,8 +697,10 @@ impl pallet_xcm::Config for Runtime {
type XcmExecutor = XcmExecutor<XcmConfig>;
type XcmTeleportFilter = Everything;
type XcmReserveTransferFilter = Everything;
type Weigher = FixedWeightBounds<BaseXcmWeight, Call>;
type Weigher = FixedWeightBounds<BaseXcmWeight, Call, MaxInstructions>;
type LocationInverter = LocationInverter<Ancestry>;
type Origin = Origin;
type Call = Call;
}
impl parachains_session_info::Config for Runtime {}
......
......@@ -495,6 +495,7 @@ impl parachains_ump::Config for Runtime {
parameter_types! {
pub const BaseXcmWeight: frame_support::weights::Weight = 1_000;
pub const AnyNetwork: xcm::latest::NetworkId = xcm::latest::NetworkId::Any;
pub const MaxInstructions: u32 = 100;
}
pub type LocalOriginToLocation = xcm_builder::SignedToAccountId32<Origin, AccountId, AnyNetwork>;
......@@ -506,12 +507,14 @@ impl pallet_xcm::Config for Runtime {
type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin<Origin, LocalOriginToLocation>;
type LocationInverter = xcm_config::InvertNothing;
type SendXcmOrigin = xcm_builder::EnsureXcmOrigin<Origin, LocalOriginToLocation>;
type Weigher = xcm_builder::FixedWeightBounds<BaseXcmWeight, Call>;
type Weigher = xcm_builder::FixedWeightBounds<BaseXcmWeight, Call, MaxInstructions>;
type XcmRouter = xcm_config::DoNothingRouter;
type XcmExecuteFilter = Everything;
type XcmExecutor = xcm_executor::XcmExecutor<xcm_config::XcmConfig>;
type XcmTeleportFilter = Everything;
type XcmReserveTransferFilter = Everything;
type Origin = Origin;
type Call = Call;
}
impl parachains_hrmp::Config for Runtime {
......@@ -524,6 +527,91 @@ impl parachains_scheduler::Config for Runtime {}
impl paras_sudo_wrapper::Config for Runtime {}
impl pallet_test_notifier::Config for Runtime {
type Event = Event;
type Origin = Origin;
type Call = Call;
}
#[frame_support::pallet]
pub mod pallet_test_notifier {
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
use pallet_xcm::{ensure_response, QueryId};
use sp_runtime::DispatchResult;
use xcm::latest::prelude::*;
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);
#[pallet::config]
pub trait Config: frame_system::Config + pallet_xcm::Config {
type Event: IsType<<Self as frame_system::Config>::Event> + From<Event<Self>>;
type Origin: IsType<<Self as frame_system::Config>::Origin>
+ Into<Result<pallet_xcm::Origin, <Self as Config>::Origin>>;
type Call: IsType<<Self as pallet_xcm::Config>::Call> + From<Call<Self>>;
}
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
QueryPrepared(QueryId),
NotifyQueryPrepared(QueryId),
ResponseReceived(MultiLocation, QueryId, Response),
}
#[pallet::error]
pub enum Error<T> {
UnexpectedId,
BadAccountFormat,
}
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::weight(1_000_000)]
pub fn prepare_new_query(origin: OriginFor<T>) -> DispatchResult {
let who = ensure_signed(origin)?;
let id = who
.using_encoded(|mut d| <[u8; 32]>::decode(&mut d))
.map_err(|_| Error::<T>::BadAccountFormat)?;
let qid = pallet_xcm::Pallet::<T>::new_query(
Junction::AccountId32 { network: Any, id }.into(),
100u32.into(),
);
Self::deposit_event(Event::<T>::QueryPrepared(qid));
Ok(())
}
#[pallet::weight(1_000_000)]
pub fn prepare_new_notify_query(origin: OriginFor<T>) -> DispatchResult {
let who = ensure_signed(origin)?;
let id = who
.using_encoded(|mut d| <[u8; 32]>::decode(&mut d))
.map_err(|_| Error::<T>::BadAccountFormat)?;
let call = Call::<T>::notification_received(0, Default::default());
let qid = pallet_xcm::Pallet::<T>::new_notify_query(
Junction::AccountId32 { network: Any, id }.into(),
<T as Config>::Call::from(call),
100u32.into(),
);
Self::deposit_event(Event::<T>::NotifyQueryPrepared(qid));
Ok(())
}
#[pallet::weight(1_000_000)]
pub fn notification_received(
origin: OriginFor<T>,
query_id: QueryId,
response: Response,
) -> DispatchResult {
let responder = ensure_response(<T as Config>::Origin::from(origin))?;
Self::deposit_event(Event::<T>::ResponseReceived(responder, query_id, response));
Ok(())
}
}
}
construct_runtime! {
pub enum Runtime where
Block = Block,
......@@ -573,6 +661,8 @@ construct_runtime! {
ParasDisputes: parachains_disputes::{Pallet, Storage, Event<T>},
Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>},
TestNotifier: pallet_test_notifier::{Pallet, Call, Event<T>},
}
}
......
......@@ -15,10 +15,7 @@
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use frame_support::{parameter_types, traits::Everything, weights::Weight};
use xcm::latest::{
Error as XcmError, Junctions::Here, MultiAsset, MultiLocation, NetworkId, Parent,
Result as XcmResult, SendXcm, Xcm,
};
use xcm::latest::prelude::*;
use xcm_builder::{AllowUnpaidExecutionFrom, FixedWeightBounds, SignedToAccountId32};
use xcm_executor::{
traits::{InvertLocation, TransactAsset, WeightTrader},
......@@ -27,6 +24,7 @@ use xcm_executor::{
parameter_types! {
pub const OurNetwork: NetworkId = NetworkId::Polkadot;
pub const MaxInstructions: u32 = 100;
}
/// Type to convert an `Origin` type value into a `MultiLocation` value which represents an interior location
......@@ -38,7 +36,7 @@ pub type LocalOriginToLocation = (
pub struct DoNothingRouter;
impl SendXcm for DoNothingRouter {
fn send_xcm(_dest: MultiLocation, _msg: Xcm<()>) -> XcmResult {
fn send_xcm(_dest: MultiLocation, _msg: Xcm<()>) -> SendResult {
Ok(())
}
}
......@@ -85,7 +83,7 @@ impl xcm_executor::Config for XcmConfig {
type IsTeleporter = ();
type LocationInverter = InvertNothing;
type Barrier = Barrier;
type Weigher = FixedWeightBounds<super::BaseXcmWeight, super::Call>;
type Weigher = FixedWeightBounds<super::BaseXcmWeight, super::Call, MaxInstructions>;
type Trader = DummyWeightTrader;
type ResponseHandler = ();
type ResponseHandler = super::Xcm;
}
......@@ -912,6 +912,7 @@ pub type XcmRouter = (
parameter_types! {
pub const WestendForWestmint: (MultiAssetFilter, MultiLocation) =
(Wild(AllOf { fun: WildFungible, id: Concrete(WndLocation::get()) }), Parachain(1000).into());
pub const MaxInstructions: u32 = 100;
}
pub type TrustedTeleporters = (xcm_builder::Case<WestendForWestmint>,);
......@@ -935,7 +936,7 @@ impl xcm_executor::Config for XcmConfig {
type IsTeleporter = TrustedTeleporters;
type LocationInverter = LocationInverter<Ancestry>;
type Barrier = Barrier;
type Weigher = FixedWeightBounds<BaseXcmWeight, Call>;
type Weigher = FixedWeightBounds<BaseXcmWeight, Call, MaxInstructions>;
type Trader = UsingComponents<WeightToFee, WndLocation, AccountId, Balances, ToAuthor<Runtime>>;
type ResponseHandler = ();
}
......@@ -958,8 +959,10 @@ impl pallet_xcm::Config for Runtime {
type XcmExecutor = XcmExecutor<XcmConfig>;
type XcmTeleportFilter = Everything;
type XcmReserveTransferFilter = Everything;
type Weigher = FixedWeightBounds<BaseXcmWeight, Call>;
type Weigher = FixedWeightBounds<BaseXcmWeight, Call, MaxInstructions>;
type LocationInverter = LocationInverter<Ancestry>;
type Origin = Origin;
type Call = Call;
}
construct_runtime! {
......
......@@ -108,6 +108,7 @@ inverter/MS
io
IP/S
isn
isolatable
isolate/BG
iterable
jaeger/MS
......@@ -189,6 +190,7 @@ prometheus/MS
provisioner/MS
proxy/DMSG
proxy/G
proxying
PRs
PVF/S
README/MS
......@@ -200,6 +202,7 @@ responder/SM
retriability
reverify
roundtrip/MS
routable
rpc
RPC/MS
runtime/MS
......@@ -231,6 +234,7 @@ taskmanager/MS
TCP
teleport/D
teleport/RG
teleports
teleportation/SM
teleporter/SM
teleporters
......@@ -251,6 +255,7 @@ unordered
unreceived
unreserve
unreserving
unroutable
unservable/B
untrusted
untyped
......
This diff is collapsed.
......@@ -20,13 +20,10 @@ use polkadot_runtime_parachains::origin;
use sp_core::H256;
use sp_runtime::{testing::Header, traits::IdentityLookup, AccountId32};
pub use sp_std::{cell::RefCell, fmt::Debug, marker::PhantomData};
use xcm::{
latest::prelude::*,
opaque::latest::{Error as XcmError, MultiAsset, Result as XcmResult, SendXcm, Xcm},
};
use xcm::latest::prelude::*;
use xcm_builder::{
AccountId32Aliases, AllowTopLevelPaidExecutionFrom, Case, ChildParachainAsNative,
ChildParachainConvertsVia, ChildSystemParachainAsSuperuser,
AccountId32Aliases, AllowKnownQueryResponses, AllowTopLevelPaidExecutionFrom, Case,
ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser,
CurrencyAdapter as XcmCurrencyAdapter, FixedRateOfFungible, FixedWeightBounds, IsConcrete,
LocationInverter, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation,
TakeWeightCredit,
......@@ -40,6 +37,85 @@ pub type Balance = u128;
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
type Block = frame_system::mocking::MockBlock<Test>;
#[frame_support::pallet]
pub mod pallet_test_notifier {
use crate::{ensure_response, QueryId};
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
use sp_runtime::DispatchResult;
use xcm::latest::prelude::*;
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);
#[pallet::config]
pub trait Config: frame_system::Config + crate::Config {
type Event: IsType<<Self as frame_system::Config>::Event> + From<Event<Self>>;
type Origin: IsType<<Self as frame_system::Config>::Origin>
+ Into<Result<crate::Origin, <Self as Config>::Origin>>;
type Call: IsType<<Self as crate::Config>::Call> + From<Call<Self>>;
}
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
QueryPrepared(QueryId),
NotifyQueryPrepared(QueryId),
ResponseReceived(MultiLocation, QueryId, Response),
}
#[pallet::error]
pub enum Error<T> {
UnexpectedId,
BadAccountFormat,
}
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::weight(1_000_000)]
pub fn prepare_new_query(origin: OriginFor<T>) -> DispatchResult {
let who = ensure_signed(origin)?;
let id = who
.using_encoded(|mut d| <[u8; 32]>::decode(&mut d))
.map_err(|_| Error::<T>::BadAccountFormat)?;
let qid = crate::Pallet::<T>::new_query(
Junction::AccountId32 { network: Any, id }.into(),
100u32.into(),
);
Self::deposit_event(Event::<T>::QueryPrepared(qid));
Ok(())
}
#[pallet::weight(1_000_000)]
pub fn prepare_new_notify_query(origin: OriginFor<T>) -> DispatchResult {
let who = ensure_signed(origin)?;
let id = who
.using_encoded(|mut d| <[u8; 32]>::decode(&mut d))
.map_err(|_| Error::<T>::BadAccountFormat)?;
let call = Call::<T>::notification_received(0, Default::default());
let qid = crate::Pallet::<T>::new_notify_query(
Junction::AccountId32 { network: Any, id }.into(),
<T as Config>::Call::from(call),
100u32.into(),
);
Self::deposit_event(Event::<T>::NotifyQueryPrepared(qid));
Ok(())
}
#[pallet::weight(1_000_000)]
pub fn notification_received(
origin: OriginFor<T>,
query_id: QueryId,
response: Response,
) -> DispatchResult {
let responder = ensure_response(<T as Config>::Origin::from(origin))?;
Self::deposit_event(Event::<T>::ResponseReceived(responder, query_id, response));
Ok(())
}
}
}
construct_runtime!(
pub enum Test where
Block = Block,
......@@ -49,20 +125,21 @@ construct_runtime!(
System: frame_system::{Pallet, Call, Storage, Config, Event<T>},
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
ParasOrigin: origin::{Pallet, Origin},
XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event<T>},
XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event<T>, Origin},
TestNotifier: pallet_test_notifier::{Pallet, Call, Event<T>},
}
);
thread_local! {
pub static SENT_XCM: RefCell<Vec<(MultiLocation, Xcm)>> = RefCell::new(Vec::new());
pub static SENT_XCM: RefCell<Vec<(MultiLocation, Xcm<()>)>> = RefCell::new(Vec::new());
}
pub fn sent_xcm() -> Vec<(MultiLocation, Xcm)> {
pub fn sent_xcm() -> Vec<(MultiLocation, Xcm<()>)> {
SENT_XCM.with(|q| (*q.borrow()).clone())
}
/// Sender that never returns error, always sends
pub struct TestSendXcm;
impl SendXcm for TestSendXcm {
fn send_xcm(dest: MultiLocation, msg: Xcm) -> XcmResult {
fn send_xcm(dest: MultiLocation, msg: Xcm<()>) -> SendResult {
SENT_XCM.with(|q| q.borrow_mut().push((dest, msg)));
Ok(())
}
......@@ -70,9 +147,9 @@ impl SendXcm for TestSendXcm {
/// Sender that returns error if `X8` junction and stops routing
pub struct TestSendXcmErrX8;
impl SendXcm for TestSendXcmErrX8 {
fn send_xcm(dest: MultiLocation, msg: Xcm) -> XcmResult {
fn send_xcm(dest: MultiLocation, msg: Xcm<()>) -> SendResult {
if dest.len() == 8 {
Err(XcmError::Undefined)
Err(SendError::Transport("Destination location full"))
} else {
SENT_XCM.with(|q| q.borrow_mut().push((dest, msg)));
Ok(())
......@@ -152,9 +229,14 @@ parameter_types! {
pub const BaseXcmWeight: Weight = 1_000;
pub CurrencyPerSecond: (AssetId, u128) = (Concrete(RelayLocation::get()), 1);
pub TrustedAssets: (MultiAssetFilter, MultiLocation) = (All.into(), Here.into());
pub const MaxInstructions: u32 = 100;
}
pub type Barrier = (TakeWeightCredit, AllowTopLevelPaidExecutionFrom<Everything>);
pub type Barrier = (
TakeWeightCredit,
AllowTopLevelPaidExecutionFrom<Everything>,
AllowKnownQueryResponses<XcmPallet>,
);
pub struct XcmConfig;
impl xcm_executor::Config for XcmConfig {
......@@ -166,9 +248,9 @@ impl xcm_executor::Config for XcmConfig {
type IsTeleporter = Case<TrustedAssets>;
type LocationInverter = LocationInverter<Ancestry>;
type Barrier = Barrier;
type Weigher = FixedWeightBounds<BaseXcmWeight, Call>;
type Weigher = FixedWeightBounds<BaseXcmWeight, Call, MaxInstructions>;
type Trader = FixedRateOfFungible<CurrencyPerSecond, ()>;
type ResponseHandler = ();
type ResponseHandler = XcmPallet;
}