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

XCM v0 #1657

Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
8f6ce0e
Rename XCMP -> Xcmp
gavofyork Aug 25, 2020
6ce0b56
Merge remote-tracking branch 'origin/rococo-branch' into gav-xcmp
gavofyork Aug 26, 2020
4ba8022
WiP: Xcm
gavofyork Aug 29, 2020
7492c3b
Finish up on draft
gavofyork Aug 31, 2020
9658a23
Remove old code, work on getting it all to build.
gavofyork Aug 31, 2020
84d1c55
XCM handler and parachains now build 🎉
gavofyork Aug 31, 2020
0c0796e
Various fixes
gavofyork Sep 4, 2020
a563c53
Fix compilation
bkchr Sep 7, 2020
38656a0
fix tests
shawntabrizi Sep 7, 2020
d8b67f1
Merge branch 'gav-xcmp' of https://github.com/paritytech/polkadot int…
shawntabrizi Sep 7, 2020
9c16e3d
bump parity-scale-codec 1.3.5, fix `dest_` -> `dest`
shawntabrizi Sep 7, 2020
f979fab
remove unused
shawntabrizi Sep 7, 2020
87e2090
Remove defunct code
gavofyork Sep 8, 2020
f672cc6
Merge branch 'gav-xcmp' of github.com:paritytech/polkadot into gav-xcmp
gavofyork Sep 8, 2020
4d2e8d1
Derive `RuntimeDebug` across XCM enums
shawntabrizi Sep 9, 2020
db7aa74
Working
gavofyork Sep 9, 2020
89b3695
More work
gavofyork Sep 9, 2020
3115e1d
Some fixes
bkchr Sep 10, 2020
0dfcd00
Merge branch 'gav-xcmp' into gav-xcmp-working
gavofyork Sep 10, 2020
9dd154b
More work
gavofyork Sep 10, 2020
4163db9
Merge branch 'gav-xcmp-working' of github.com:paritytech/polkadot int…
gavofyork Sep 10, 2020
0566de0
Move interpreter into polkadot, split & repot
gavofyork Sep 10, 2020
a5c0e95
Move interpreter into polkadot, split & repot
gavofyork Sep 10, 2020
fdfabe6
Remove 'static'
gavofyork Sep 10, 2020
fa116b0
Fix toml file
bkchr Sep 10, 2020
10f8641
imports
shawntabrizi Sep 10, 2020
3887848
fix filename
shawntabrizi Sep 10, 2020
b2384b9
some fixes
shawntabrizi Sep 10, 2020
7d158e8
Fix
gavofyork Sep 10, 2020
8743525
Merge branch 'gav-xcmp-working' of github.com:paritytech/polkadot int…
gavofyork Sep 10, 2020
060a337
Fixes
gavofyork Sep 10, 2020
9a4497a
Fixes
gavofyork Sep 10, 2020
ee07247
Fixes
gavofyork Sep 10, 2020
2d9550e
Fixes
gavofyork Sep 10, 2020
3ae493e
Fixes
gavofyork Sep 10, 2020
40a6fb0
Fixes
gavofyork Sep 10, 2020
534b731
Fixes
gavofyork Sep 10, 2020
953a581
Fixes
gavofyork Sep 10, 2020
91f3914
Fixes
gavofyork Sep 10, 2020
ba8bdaa
Fixes
gavofyork Sep 10, 2020
52affef
Fixes
gavofyork Sep 10, 2020
1b1e265
fixes
shawntabrizi Sep 10, 2020
c958d08
Fixes
gavofyork Sep 10, 2020
1a3dc55
remove `frame-system`
shawntabrizi Sep 10, 2020
721a3e9
Fixes
gavofyork Sep 10, 2020
c83ee04
Merge branch 'gav-xcmp-working' of github.com:paritytech/polkadot int…
gavofyork Sep 10, 2020
a6131ae
Fixes
gavofyork Sep 10, 2020
85dee1a
Fixes
gavofyork Sep 10, 2020
4c77f93
fixes for `parachains`
shawntabrizi Sep 10, 2020
22d5321
Merge branch 'gav-xcmp-working' of https://github.com/paritytech/polk…
shawntabrizi Sep 10, 2020
0d37c9b
Fixes
gavofyork Sep 10, 2020
9ccc139
Merge branch 'gav-xcmp-working' of github.com:paritytech/polkadot int…
gavofyork Sep 10, 2020
7a7c958
QueryHolding
gavofyork Sep 10, 2020
a213bd3
`From` instead of `UncheckedFrom`
shawntabrizi Sep 10, 2020
e609000
Initial effort at integrating xcm-executor into Rococo
gavofyork Sep 10, 2020
c25b4b7
Merge branch 'gav-xcmp-working' of github.com:paritytech/polkadot int…
gavofyork Sep 10, 2020
1aeb7c8
Fixes
gavofyork Sep 10, 2020
6080e7b
Fixes
gavofyork Sep 10, 2020
739eeb7
Fixes
gavofyork Sep 10, 2020
9334f62
Fixes
gavofyork Sep 10, 2020
bc01389
Fixes
gavofyork Sep 10, 2020
ec55f0b
Rococo builds! 🎉
gavofyork Sep 10, 2020
6e112c9
Implement Xcm for the unit type
shawntabrizi Sep 10, 2020
b092cd4
Fixes
gavofyork Sep 10, 2020
61a4090
Fixes
gavofyork Sep 10, 2020
7dea1b3
Fixes
gavofyork Sep 10, 2020
758d675
Fixes
gavofyork Sep 10, 2020
aa08941
Fixes
gavofyork Sep 10, 2020
2e8a923
Fixes
gavofyork Sep 10, 2020
3869118
Fixes
gavofyork Sep 11, 2020
eab83fe
Fixes
gavofyork Sep 11, 2020
6565989
Fixes
gavofyork Sep 11, 2020
a388c68
Refactor all the hard logic away.
gavofyork Sep 11, 2020
17a6a16
Fixes
gavofyork Sep 11, 2020
3121739
Fixes
gavofyork Sep 11, 2020
9b39a46
Fixes
gavofyork Sep 11, 2020
3b3ef7c
Broken.
gavofyork Sep 11, 2020
14b36e3
Add `RuntimeDebug` to Assets
shawntabrizi Sep 11, 2020
a6222b2
Fixes
gavofyork Sep 11, 2020
f5143f3
Merge branch 'gav-xcmp' of github.com:paritytech/polkadot into gav-xcmp
gavofyork Sep 11, 2020
87ab207
Fix DepositReserveAsset. Repotting, renaming and docs.
gavofyork Sep 12, 2020
7d572f6
fix networkid export
shawntabrizi Sep 12, 2020
7d1629d
Full docs.
gavofyork Sep 12, 2020
358673b
Merge remote-tracking branch 'origin/gav-xcmp' into gav-xcmp
gavofyork Sep 12, 2020
baa3e74
Polkadot JS Types
shawntabrizi Sep 12, 2020
2ef7c7e
Update types.json
shawntabrizi Sep 12, 2020
f712a36
Fix `RocLocation`
shawntabrizi Sep 12, 2020
b4bc868
Fixes
gavofyork Sep 12, 2020
ccb2c08
Merge branch 'gav-xcmp' of github.com:paritytech/polkadot into gav-xcmp
gavofyork Sep 12, 2020
573df3d
Generate tuples properly.
gavofyork Sep 12, 2020
e19549f
Improve docs
gavofyork Sep 13, 2020
94b96dd
Docs and API tidy
gavofyork Sep 13, 2020
cf02df9
Merge branch 'gav-xcmp' of github.com:paritytech/polkadot into gav-xcmp
gavofyork Sep 13, 2020
a4eeae0
Introduce some error handling (#1709)
shawntabrizi Sep 13, 2020
b60cf99
Fixes
gavofyork Sep 15, 2020
dfa3290
Merge branch 'gav-xcmp' of github.com:paritytech/polkadot into gav-xcmp
gavofyork Sep 15, 2020
3f22946
Fixes
gavofyork Sep 16, 2020
8c86f3f
Fixes
gavofyork Sep 17, 2020
17bacc8
Fixes
gavofyork Sep 17, 2020
e4c31ee
Add result events, logging
gavofyork Sep 17, 2020
33ecb02
Fixes
gavofyork Sep 18, 2020
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
Prev Previous commit
Next Next commit
Initial effort at integrating xcm-executor into Rococo
  • Loading branch information
gavofyork committed Sep 10, 2020
commit e6090001493557306b8ba045eacec782d0bd911f
105 changes: 23 additions & 82 deletions runtime/common/src/parachains.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ use system::{
};
use crate::attestations::{self, IncludedBlocks};
use crate::registrar::Registrar;
use xcm::{VersionedXcm, VersionedMultiLocation, v0::{Xcm, MultiOrigin, MultiAsset, MultiLocation, Junction, Ai}};
use xcm::{VersionedXcm, VersionedMultiLocation, v0::{Xcm, SendXcm, ExecuteXcm, MultiOrigin, MultiAsset, MultiLocation, Junction, Ai}};

// ranges for iteration of general block number don't work, so this
// is a utility to get around that.
Expand Down Expand Up @@ -326,6 +326,9 @@ pub trait Trait: CreateSignedTransaction<Call<Self>> + attestations::Trait + ses

/// A type that converts the opaque hash type to exact one.
type BlockHashConversion: Convert<Self::Hash, primitives::v0::Hash>;

/// The XCM interpreter.
type XcmExecutive: ExecuteXcm;
}

/// Origin for the parachains module.
Expand Down Expand Up @@ -808,6 +811,21 @@ fn make_sorted_duties(duty: &[Chain]) -> Vec<(usize, ParaId)> {
sorted_duties
}

impl<T: Trait> SendXcm for Module<T> {
fn send_xcm(dest: MultiLocation, msg: xcm::v0::Xcm) -> xcm::v0::XcmResult {
if let MultiLocation::X1(Junction::Parachain{ id }) = dest {
let downward_queue_count = DownwardMessageQueue::decode_len(id).unwrap_or(0);
if downward_queue_count >= MAX_DOWNWARD_QUEUE_COUNT {
return Err(()) // Destination buffer overflow.
}
DownwardMessageQueue::append(id, msg.encode());
Ok(())
} else {
return Err(()) // Cannot reach destination.
}
}
}

impl<T: Trait> Module<T> {
/// Initialize the state of a new parachain/parathread.
pub fn initialize_para(
Expand Down Expand Up @@ -932,89 +950,12 @@ impl<T: Trait> Module<T> {
/// Dispatch some messages from a parachain.
fn dispatch_message(from: ParaId, data: &[u8]) {
use sp_std::convert::TryFrom;
let origin: MultiLocation = Junction::Parachain { id: from }.into();
match VersionedXcm::decode(&mut &data[..]).map(Xcm::try_from) {
Ok(Ok(Xcm::ForwardToParachain { id, inner })) => {
let id = ParaId::from(id);
let downward_queue_count = DownwardMessageQueue::decode_len(id).unwrap_or(0);
if downward_queue_count >= MAX_DOWNWARD_QUEUE_COUNT {
return
}
let msg = VersionedXcm::from(Xcm::ForwardedFromParachain{ id: from.into(), inner });
DownwardMessageQueue::append(id, msg.encode());
},
Ok(Ok(Xcm::Transact{ origin_type, call })) => {
if let Ok(message_call) = <T as Trait>::Call::decode(&mut &call[..]) {
let origin: <T as Trait>::Origin = match origin_type {
MultiOrigin::SovereignAccount => system::RawOrigin::Signed(from.into_account()).into(),
MultiOrigin::Native => Origin::Parachain(from).into(),
MultiOrigin::Superuser if from.is_system() => system::RawOrigin::Root.into(),
_ => return,
};
let _ok = message_call.dispatch(origin).is_ok();
// Not much to do with the result as it is. It's up to the parachain to ensure that the
// message makes sense.
}
},
Ok(Ok(Xcm::ReserveAssetTransfer { assets, dest, effects })) => {
if assets.is_empty() { return };
// TODO: Handle multiple assets. This is just a hack to make it work for 1 asset.
let asset = assets[0].clone();
let amount = match asset {
MultiAsset::ConcreteFungible { id: MultiLocation::Null, amount} => amount,
_ => return, // Bail as we don't support being a reserve for this asset.
};
let (onward_asset, dest) = match dest {
// Only destination we support for reserve asset transfers is into a parachain.
MultiLocation::X1(Junction::Parachain { id }) => {
let destid = ParaId::from(id);
let destaccount = destid.into_account();
if T::ParachainCurrency::transfer_out(from, &destaccount, amount, AllowDeath).is_err() {
return
}
// The onward asset, since it's the Relay-chain's native currency, is identified as
// the chain itself (from our context, it's therefore `Null`). From the parachain's context,
// it is identified as `Parent`.
(MultiAsset::ConcreteFungible { id: Junction::Parent.into(), amount }, destid)
},
_ => return,
};
let msg = VersionedXcm::from(Xcm::ReserveAssetCredit { assets: vec![onward_asset], effects }).encode();
DownwardMessageQueue::append(dest, msg);
},
Ok(Ok(Xcm::WithdrawAsset { assets, effects })) => {
if assets.is_empty() || effects.is_empty() { return };
// TODO: Handle multiple assets. This is just a hack to make it work for 1 asset.
let asset = assets[0].clone();
let amount = match asset {
MultiAsset::ConcreteFungible { id: MultiLocation::Null, amount} => amount,
_ => return, // Bail as we don't support being a reserve for this asset.
};
// TODO: Handle multiple effects. This is just a hack to make it work for 1 effect.
let effect = effects[0].clone();
match effect {
// Only effect we support for now is a straight wildcard deposit into an AccountId32.
// TODO: Consider caring about the `network`.
Ai::DepositAsset { assets, dest: MultiLocation::X1(Junction::AccountId32 { id, .. }) } => {
if assets.is_empty() { return };
// TODO: Handle multiple assets. This is just a hack to make it work for 1 asset.
let asset = assets[0].clone();
match asset {
MultiAsset::All => {
let dest = match T::AccountId::decode(&mut &id[..]) {
Ok(x) => x,
Err(_) => return,
};
if T::ParachainCurrency::transfer_out(from, &dest, amount, AllowDeath).is_err() {
return
}
},
_ => return,
}
}
_ => return,
}
Ok(Ok(xcm)) => {
// TODO: handle error.
let _ = T::XcmExecutive::execute_xcm(origin.clone(), xcm);
},
Ok(Ok(_)) => (), // Unhandled XCM message type.
Ok(Err(_)) => (), // Unsupported XCM version.
Err(_) => (), // Bad format (can't decode).
}
Expand Down
5 changes: 5 additions & 0 deletions runtime/rococo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ runtime-common = { package = "polkadot-runtime-common", path = "../common", defa
primitives = { package = "polkadot-primitives", path = "../../primitives", default-features = false }
polkadot-parachain = { path = "../../parachain", default-features = false }

xcm = { path = "../../xcm", default-features = false }
xcm-executor = { path = "../../xcm/xcm-executor", default-features = false }

[dev-dependencies]
libsecp256k1 = "0.3.2"
tiny-keccak = "1.5.0"
Expand Down Expand Up @@ -149,6 +152,8 @@ std = [
"sp-staking/std",
"randomness-collective-flip/std",
"runtime-common/std",
"xcm/std",
"xcm-executor/std",
]
runtime-benchmarks = [
"runtime-common/runtime-benchmarks",
Expand Down
63 changes: 63 additions & 0 deletions runtime/rococo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,67 @@ parameter_types! {
pub const SlashPeriod: BlockNumber = 7 * DAYS;
}

parameter_types! {
const RocLocation: MultiLocation = MultiLocation::X1(Junction::Parent);
}

pub type LocalAssetTransactor =
CurrencyAdapter<
// Use this currency:
balances::Module::<T, DefaultInstance>,
// Use this currency when it is a fungible asset matching the given location or name:
(IsConcrete<RocLocation>),
// Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:
// TODO: This will need some ParaId::into_account() magic.
AccountId32Punner<T::AccountId>,
// Our chain's account ID type (we can't get away without mentioning it explicitly):
T::AccountId,
>;

use polkadot_parachain::primitives::{AccountIdConversion, Id as ParaId};
use xcm::v0::{MultiLocation, Junction};
use sp_core::crypto::UncheckedInto;
impl AccountIdConversion<AccountId> for MultiLocation {
fn into_account(&self) -> AccountId {
match self {
MultiLocation::X1(Junction::Parachain { id }) => ParaId::from(id).into_account(),
MultiLocation::X1(Junction::AccountId32 { id }) => id.unchecked_into(),
x => ("multilocation", x).using_encoded(sp_io::hashing::blake2_256).unchecked_into(),
}
}

fn try_from_account(a: AccountId) -> Option<Self> {
if let Some(id) = ParaId::try_from_account(a) {
return Some(Junction::Parachain { id: id.into() })
}
Some(Junction::AccountId32 { id: a.into() })
}
}

pub struct LocalOriginConverter;
impl OriginConverter<Origin> for LocalOriginConverter {
fn convert_origin(origin: MultiLocation, kind: MultiOrigin) -> Result<Origin, xcm::v0::Error> {
Ok(match (kind, origin) {
(MultiOrigin::SovereignAccount, origin) => system::RawOrigin::Signed(origin.into_account()).into(),
(MultiOrigin::Native, MultiLocation::X1(Junction::Parachain { id })) => parachains::Origin::Parachain(id).into(),
(MultiOrigin::Native, MultiLocation::X1(Junction::AccountId32 { id })) => system::RawOrigin::Signed(id).into(),
(MultiOrigin::Superuser, MultiLocation::X1(Junction::Parachain { id })) if ParaId::from(id).is_system()
=> system::RawOrigin::Root.into(),
_ => Err(())?,
})
}
}

pub struct XcmExecutorConfig;
impl xcm_executor::Config for XcmExecutorConfig {
type Call = Call;
type XcmSender = Parachains;
type AssetTransactor = LocalAssetTransactor;
type OriginConverter = LocalOriginConverter;
type IsReserve = ();
type IsTeleporter = ();
}

impl parachains::Trait for Runtime {
type AuthorityId = primitives::v0::fisherman::FishermanAppCrypto;
type Origin = Origin;
Expand All @@ -419,6 +480,8 @@ impl parachains::Trait for Runtime {
type IdentificationTuple = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, Vec<u8>)>>::IdentificationTuple;
type ReportOffence = Offences;
type BlockHashConversion = sp_runtime::traits::Identity;

type XcmExecutive = XcmExecutor<XcmExecutorConfig>;
}

/// Submits a transaction with the node's public and signature type. Adheres to the signed extension
Expand Down
63 changes: 56 additions & 7 deletions xcm/src/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,25 @@

//! Cross-Consensus Message format data structures.

use sp_std::{boxed::Box, vec::Vec, convert::TryFrom};
use sp_std::{result, boxed::Box, vec::Vec, convert::TryFrom};
use sp_runtime::RuntimeDebug;
use codec::{self, Encode, Decode};
use super::{VersionedXcm, VersionedMultiLocation, VersionedMultiAsset};

pub type XcmError = ();
pub type XcmResult = Result<(), XcmError>;
pub type Error = ();
pub type Result = result::Result<(), Error>;

#[deprecated]
pub type XcmError = Error;
#[deprecated]
pub type XcmResult = Result;

pub trait ExecuteXcm {
fn execute_xcm(origin: MultiLocation, msg: Xcm) -> XcmResult;
fn execute_xcm(origin: MultiLocation, msg: Xcm) -> Result;
}

pub trait SendXcm {
fn send_xcm(dest: MultiLocation, msg: Xcm) -> XcmResult;
fn send_xcm(dest: MultiLocation, msg: Xcm) -> Result;
}

/// Basically just the XCM (more general) version of `ParachainDispatchOrigin`.
Expand Down Expand Up @@ -95,6 +100,33 @@ impl MultiLocation {
s => Err(s)?,
})
}
pub fn into_iter(self) -> impl Iterator<Item=Junction> {
match self {
MultiLocation::Null => None,
MultiLocation::X1(a) => Some(a),
MultiLocation::X2(a, b) => Some(a).chain(Some(b)),
MultiLocation::X3(a, b, c) => Some(a).chain(Some(b)).chain(Some(c)),
MultiLocation::X4(a, b, c, d) => Some(a).chain(Some(b)).chain(Some(c)).chain(Some(d)),
}
}

pub fn push(&mut self, new: Junction) -> Result<(), ()> {
let mut n = MultiLocation::Null;
sp_std::mem::swap(&mut *self, &mut n);
match n.pushed_with(new) {
Ok(result) => { *self = result; Ok(()) }
Err(old) => { *self = old; Err(()) }
}
}

/// Returns partial result as error in case of failure (e.g. because out of space).
pub fn appended_with(self, new: MultiLocation) -> Result<Self, Self> {
let mut result= self;
for j in new.into_iter() {
result = result.pushed_with(j)?;
}
Ok(result)
}
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug)]
Expand All @@ -119,6 +151,23 @@ impl From<Junction> for MultiLocation {
}
}

impl Junction {
fn is_sub_consensus(&self) -> bool {
match self {
Junction::Parent => false,

Junction::Parachain { .. } |
Junction::OpaqueRemark(..) |
Junction::AccountId32 { .. } |
Junction::AccountIndex64 { .. } |
Junction::AccountKey20 { .. } |
Junction::PalletInstance { .. } |
Junction::GeneralIndex { .. } |
Junction::GeneralKey(..) => true,
}
}
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug)]
pub enum AssetInstance {
Undefined,
Expand Down Expand Up @@ -176,8 +225,8 @@ pub enum Xcm {
Balances { #[codec(compact)] query_id: u64, assets: MultiAssets },
Transact { origin_type: MultiOrigin, call: Vec<u8> },
// these won't be staying here for long. only v0 parachains with HRMP.
ForwardToParachain { id: u32, inner: Box<VersionedXcm> },
ForwardedFromParachain { id: u32, inner: Box<VersionedXcm> },
RelayToParachain { id: u32, inner: Box<VersionedXcm> },
RelayedFrom { superorigin: MultiLocation, inner: Box<VersionedXcm> },
}

impl From<Xcm> for VersionedXcm {
Expand Down
6 changes: 6 additions & 0 deletions xcm/xcm-executor/src/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ impl From<Vec<MultiAsset>> for Assets {
}
}

impl From<Assets> for Vec<MultiAsset> {
fn from(a: Assets) -> Self {
a.into_assets_iter().collect()
}
}

impl Assets {
pub fn into_assets_iter(self) -> impl Iterator<Item=MultiAsset> {
let fungible = self.fungible.into_iter()
Expand Down
3 changes: 3 additions & 0 deletions xcm/xcm-executor/src/currency_adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ use frame_support::traits::{ExistenceRequirement::AllowDeath, WithdrawReason};
use crate::traits::{MatchesFungible, PunnFromLocation, TransactAsset};
use sp_std::{convert::TryInto, marker::PhantomData};

// TODO: Will need some way of punning a `Junction::Parachain` into the sovereign parachain account.
// Right now it only works with `Junction::AccountId32`.

pub struct CurrencyAdapter<Currency, Matcher, AccountIdConverter, AccountId>(
PhantomData<Currency>,
PhantomData<Matcher>,
Expand Down
22 changes: 19 additions & 3 deletions xcm/xcm-executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#![cfg_attr(not(feature = "std"), no_std)]

use sp_std::{marker::PhantomData, convert::TryInto};
use frame_support::dispatch::Dispatchable;
use frame_support::{ensure, dispatch::Dispatchable};
use codec::Decode;
use xcm::v0::{Xcm, Ai, ExecuteXcm, SendXcm, XcmResult, MultiLocation, Junction};

Expand All @@ -37,8 +37,13 @@ pub struct XcmExecutor<Config>(PhantomData<Config>);
impl<Config: config::Config> ExecuteXcm for XcmExecutor<Config> {
fn execute_xcm(origin: MultiLocation, msg: Xcm) -> XcmResult {
let (mut holding, effects) = match (origin.clone(), msg) {
(origin, Xcm::ForwardedFromParachain { id, inner }) => {
let new_origin = origin.pushed_with(Junction::Parachain { id }).map_err(|_| ())?;
(origin, Xcm::RelayedFrom { superorigin, inner }) => {
// We ensure that it doesn't contain any `Parent` Junctions which would imply a privilege escalation.
let mut new_origin = origin;
for j in superorigin.into_iter() {
ensure!(j.is_sub_consensus(), ());
new_origin.push(j).map_err(|_| ())?;
}
return Self::execute_xcm(new_origin, (*inner).try_into()?)
}
(origin, Xcm::WithdrawAsset { assets, effects }) => {
Expand Down Expand Up @@ -84,6 +89,17 @@ impl<Config: config::Config> ExecuteXcm for XcmExecutor<Config> {
// message makes sense.
return Ok(());
}
(origin, Xcm::RelayToParachain { id, inner }) => {
let msg = Xcm::RelayedFrom { superorigin: origin, inner }.into();
Config::XcmSender::send_xcm(Junction::Parachain { id }.into(), msg)
},
(origin, Xcm::ReserveAssetTransfer { mut assets, dest, effects }) => {
for asset in assets.iter_mut() {
*asset = Config::AssetTransactor::transfer_asset(asset, &origin, &dest)?;
}
let msg = Xcm::ReserveAssetCredit { assets, effects }.into();
Config::XcmSender::send_xcm(dest, msg)
},
_ => Err(())?, // Unhandled XCM message.
};

Expand Down
Loading