Unverified Commit 0f5e37ce authored by Keith Yeung's avatar Keith Yeung Committed by GitHub
Browse files

Ensure MultiLocation always has a canonical representation (#3404)



* MultiAsset TWO

* Ensure MultiLocation always has a canonical representation

* Remove v1 module

* Draft next MultiAsset API.

* Implement custom encoding/decoding scheme for MultiLocation

* Properly implement IntoIterator for Junctions

* Implement TryFrom<MultiLocation> for Junctions

* Fix spelling mistakes

* Fix tests in xcm-executor

* XCM core builds

* XCM Executor builds

* XCM Builder builds

* Fix xcm-builder tests and compilation

* Make pallet-xcm compile

* Use MultiLocation::default()

* Make polkadot-runtime-common compile

* Make rococo-runtime compile

* Change return type of parent_count to u8

* Change MAX_MULTILOCATION_LENGTH to 255

* Make kusama-runtime compile

* Fix logic in pallet-xcm

* Use MultiLocation::empty()

* Fix logic in location_conversion

* Fix logic in origin_conversion.rs

* Make westend-runtime compile

* Rename prefixes and suffixes variables

* Rename non_parent to interior

* Rename non_parent to interior

* Add test for encode/decode roundtrip and fix decode algorithm

* API changes making their way throughout

* Some TODOs

* Further build fixes

* Rename non_parent/junctions to interior

* Basic compile builds

* First test fixed

* All executor tests fixed

* Typo

* Optimize subsume_assets and add test

* Optimize checked_sub

* XCM Builder first test fixed

* Fix builder tests

* Fix doc test

* Make xcm-simulator compile

* Make xcm-simulator-example compile

* Make spellcheck happy

* cargo fmt

* fix some doc tests

* spelling

* named fields for AllOf

* Fix subtle bug where Null is treated as an identifier

* Add FIXME comment awaiting for const generics eval stabilization

* Update xcm/src/v0/multiasset.rs
Co-authored-by: default avatarAlexander Popiak <alexander.popiak@parity.io>

* Update xcm/src/v0/multiasset.rs
Co-authored-by: default avatarAlexander Popiak <alexander.popiak@parity.io>

* Update xcm/src/v0/multiasset.rs
Co-authored-by: default avatarAlexander Popiak <alexander.popiak@parity.io>

* Update xcm/src/v0/multiasset.rs
Co-authored-by: default avatarAlexander Popiak <alexander.popiak@parity.io>

* Reformat

* Move to XCM version 1

* Spelling

* warnings

* Replace some more v0->v1s

* warnings

* format

* Add max_assets param

* building

* test fixes

* tests

* another test

* final test

* Update rustdocs and add debug_assert where sensible

* Revert debug_assert in const fn len()

* tests

* Rename Null -> Here

* Introduce

* More ergonomics

* More ergonomics

* test fix

* test fixes

* docs

* BuyExecution includes

* Fix XCM extrinsics

* fmt

* Make Vec<MultiAsset>/MultiAssets conversions safe

* More MultiAssets conversion safety

* spelling

* fix doc test

* Apply suggestions from code review
Co-authored-by: default avatarAmar Singh <asinghchrony@protonmail.com>

* Apply suggestions from code review
Co-authored-by: default avatarAmar Singh <asinghchrony@protonmail.com>

* fmt

* Add v0, remove VersionedMultiAsset

* Remove VersionedMultiLocation

* Update xcm/src/v1/order.rs
Co-authored-by: default avatarAmar Singh <asinghchrony@protonmail.com>

* Update xcm/src/v1/mod.rs
Co-authored-by: default avatarAmar Singh <asinghchrony@protonmail.com>

* XCM v0 backwards compatibility

* Full compatibility

* fmt

* Update xcm/pallet-xcm/src/lib.rs

* Update xcm/src/v0/order.rs
Co-authored-by: Shawn Tabrizi's avatarShawn Tabrizi <shawntabrizi@gmail.com>

* Tweaks to versioning system

* Fixes

* fmt

* Fix pallet-xcm tests

* fix

* Substitute with_parent with with_parents_const

* Rename argument name from a to m

* Rename split_last to split_last_interior

* Allow adding multiple parents in MultiLocation

* Rename pop_parent to dec_parent

* Ensure relay chain XCM sender receives a MultiLocation without any parents

* Block only when MultiLocation destination length is 8

* Cargo fmt

* Remove reverse iterators, implement DoubleEndedIterator and add tests

* Fix iter_rev lifetime requirements

* Cargo fmt

* Add an into() method for Junctions for conciseness in const context

* Ensure parent count is 0 while executing who in RelayedFrom

* Appease spellchecker

* Use and_then instead of repeated map_err

* Remove custom codec indices for v1 Junctions

* Add convenience 'contains_parents_only' method to MultiLocation

* Fix merge conflict

* Use more convenience methods

* Remove with_parachain_interior

* Prefer matching against tuple instead of using match guards

* Match against tuple instead of using more match guards

* Update encode/decode test for MultiLocation

* Minor tweaks

* Fixes

* Fixes

* Fixes

* Fix MultiLocation

* Add deprecation note for iter_rev and into_iter_rev

* Update some rustdocs

* cargo fmt

* Fix xcm-executor unit tests

* Fix compilation and unit tests in xcm-builder

* cargo fmt

* Fix tests in xcm-simulator-example

* Publicize MultiLocation fields

* Match on the MultiLocation struct directly in xcm-builder

* Do not dereference undereferenceable types

* Add convenience MultiLocation conversions for tuples

* Use clearer import paths

* Remove unused dependency

* fix junction + response

* Import from latest opaque xcm module

* Update xcm/src/v1/mod.rs

* better comment

* Fix ownership transfer

* Fix merge

* Fix merge

* cargo fmt

* Fix merge

* Fix merge

* Fix integration test

* More readable Parent syntax

* cleanup

* cleanup

* cleanup

* cleanup

* cleanup

* cleanup

* cleanup

* cleanup

* cargo fmt

* Fixes

* Fix doc test
Co-authored-by: default avatarGav Wood <gavin@parity.io>
Co-authored-by: default avatarAlexander Popiak <alexander.popiak@parity.io>
Co-authored-by: default avatarAmar Singh <asinghchrony@protonmail.com>
Co-authored-by: Shawn Tabrizi's avatarShawn Tabrizi <shawntabrizi@gmail.com>
parent d76421c8
Pipeline #152019 passed with stages
in 42 minutes and 7 seconds
......@@ -19,7 +19,7 @@
use parity_scale_codec::Encode;
use runtime_parachains::{configuration, dmp};
use sp_std::marker::PhantomData;
use xcm::opaque::v1::{Error, Junction, MultiLocation, Result, SendXcm, Xcm};
use xcm::opaque::latest::*;
/// XCM sender for relay chain. It only sends downward message.
pub struct ChildParachainRouter<T, W>(PhantomData<(T, W)>);
......@@ -28,21 +28,21 @@ impl<T: configuration::Config + dmp::Config, W: xcm::WrapVersion> SendXcm
for ChildParachainRouter<T, W>
{
fn send_xcm(dest: MultiLocation, msg: Xcm) -> Result {
match &dest {
MultiLocation::X1(Junction::Parachain(id)) => {
match dest {
MultiLocation { parents: 0, interior: Junctions::X1(Junction::Parachain(id)) } => {
// Downward message passing.
let versioned_xcm =
W::wrap_version(&dest, msg).map_err(|()| Error::DestinationUnsupported)?;
let config = <configuration::Pallet<T>>::config();
<dmp::Pallet<T>>::queue_downward_message(
&config,
(*id).into(),
id.into(),
versioned_xcm.encode(),
)
.map_err(Into::<Error>::into)?;
Ok(())
},
_ => Err(Error::CannotReachDestination(dest, msg)),
dest => Err(Error::CannotReachDestination(dest, msg)),
}
}
}
......@@ -1203,12 +1203,12 @@ parameter_types! {
/// The location of the KSM token, from the context of this chain. Since this token is native to this
/// chain, we make it synonymous with it and thus it is the `Here` location, which means "equivalent to
/// the context".
pub const KsmLocation: MultiLocation = MultiLocation::Here;
pub const KsmLocation: MultiLocation = Here.into();
/// The Kusama network ID. This is named.
pub const KusamaNetwork: NetworkId = NetworkId::Kusama;
/// Our XCM location ancestry - i.e. what, if anything, `Parent` means evaluated in our context. Since
/// Kusama is a top-level relay-chain, there is no ancestry.
pub const Ancestry: MultiLocation = MultiLocation::Here;
pub const Ancestry: MultiLocation = Here.into();
/// The check account, which holds any native assets that have been teleported out and not back in (yet).
pub CheckAccount: AccountId = XcmPallet::check_account();
}
......@@ -1265,7 +1265,7 @@ pub type XcmRouter = (
parameter_types! {
pub const Kusama: MultiAssetFilter = Wild(AllOf { fun: WildFungible, id: Concrete(KsmLocation::get()) });
pub const KusamaForStatemint: (MultiAssetFilter, MultiLocation) = (Kusama::get(), X1(Parachain(1000)));
pub const KusamaForStatemint: (MultiAssetFilter, MultiLocation) = (Kusama::get(), Parachain(1000).into());
}
pub type TrustedTeleporters = (xcm_builder::Case<KusamaForStatemint>,);
......
......@@ -583,9 +583,9 @@ impl parachains_paras::Config for Runtime {
}
parameter_types! {
pub const RocLocation: MultiLocation = MultiLocation::Here;
pub const RocLocation: MultiLocation = Here.into();
pub const RococoNetwork: NetworkId = NetworkId::Polkadot;
pub const Ancestry: MultiLocation = MultiLocation::Here;
pub const Ancestry: MultiLocation = Here.into();
pub CheckAccount: AccountId = XcmPallet::check_account();
}
......@@ -625,10 +625,10 @@ pub type XcmRouter = (
parameter_types! {
pub const Rococo: MultiAssetFilter = Wild(AllOf { fun: WildFungible, id: Concrete(RocLocation::get()) });
pub const RococoForTick: (MultiAssetFilter, MultiLocation) = (Rococo::get(), X1(Parachain(100)));
pub const RococoForTrick: (MultiAssetFilter, MultiLocation) = (Rococo::get(), X1(Parachain(110)));
pub const RococoForTrack: (MultiAssetFilter, MultiLocation) = (Rococo::get(), X1(Parachain(120)));
pub const RococoForStatemint: (MultiAssetFilter, MultiLocation) = (Rococo::get(), X1(Parachain(1001)));
pub const RococoForTick: (MultiAssetFilter, MultiLocation) = (Rococo::get(), Parachain(100).into());
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 type TrustedTeleporters = (
xcm_builder::Case<RococoForTick>,
......@@ -640,10 +640,10 @@ pub type TrustedTeleporters = (
parameter_types! {
pub AllowUnpaidFrom: Vec<MultiLocation> =
vec![
X1(Parachain(100)),
X1(Parachain(110)),
X1(Parachain(120)),
X1(Parachain(1001))
Parachain(100).into(),
Parachain(110).into(),
Parachain(120).into(),
Parachain(1001).into(),
];
}
......
......@@ -16,7 +16,7 @@
use frame_support::{parameter_types, traits::Everything, weights::Weight};
use xcm::latest::{
Error as XcmError, Junction::*, MultiAsset, MultiLocation, MultiLocation::*, NetworkId,
Error as XcmError, Junctions::Here, MultiAsset, MultiLocation, NetworkId, Parent,
Result as XcmResult, SendXcm, Xcm,
};
use xcm_builder::{AllowUnpaidExecutionFrom, FixedWeightBounds, SignedToAccountId32};
......@@ -52,7 +52,7 @@ impl TransactAsset for DummyAssetTransactor {
}
fn withdraw_asset(_what: &MultiAsset, _who: &MultiLocation) -> Result<Assets, XcmError> {
let asset: MultiAsset = (X1(Parent), 100_000).into();
let asset: MultiAsset = (Parent, 100_000).into();
Ok(asset.into())
}
}
......@@ -71,7 +71,7 @@ impl WeightTrader for DummyWeightTrader {
pub struct InvertNothing;
impl InvertLocation for InvertNothing {
fn invert_location(_: &MultiLocation) -> MultiLocation {
MultiLocation::Here
Here.into()
}
}
......
......@@ -866,8 +866,8 @@ impl auctions::Config for Runtime {
}
parameter_types! {
pub const WndLocation: MultiLocation = MultiLocation::Here;
pub const Ancestry: MultiLocation = MultiLocation::Here;
pub const WndLocation: MultiLocation = Here.into();
pub const Ancestry: MultiLocation = Here.into();
pub WestendNetwork: NetworkId = NetworkId::Named(b"Westend".to_vec());
pub CheckAccount: AccountId = XcmPallet::check_account();
}
......@@ -908,7 +908,7 @@ pub type XcmRouter = (
parameter_types! {
pub const WestendForWestmint: (MultiAssetFilter, MultiLocation) =
(Wild(AllOf { fun: WildFungible, id: Concrete(WndLocation::get()) }), X1(Parachain(1000)));
(Wild(AllOf { fun: WildFungible, id: Concrete(WndLocation::get()) }), Parachain(1000).into());
}
pub type TrustedTeleporters = (xcm_builder::Case<WestendForWestmint>,);
......
......@@ -102,7 +102,7 @@ pub mod pallet {
UnweighableMessage,
/// The assets to be sent are empty.
Empty,
/// Could not reanchor the assets to declare the fees for the destination chain.
/// Could not re-anchor the assets to declare the fees for the destination chain.
CannotReanchor,
/// Too many assets have been attempted for transfer.
TooManyAssets,
......@@ -306,9 +306,10 @@ pub mod pallet {
dest: MultiLocation,
message: Xcm<()>,
) -> Result<(), XcmError> {
let message = match interior {
MultiLocation::Here => message,
who => Xcm::<()>::RelayedFrom { who, message: Box::new(message) },
let message = if interior.is_here() {
message
} else {
Xcm::<()>::RelayedFrom { who: interior, message: Box::new(message) }
};
log::trace!(target: "xcm::send_xcm", "dest: {:?}, message: {:?}", &dest, &message);
T::XcmRouter::send_xcm(dest, message)
......@@ -384,7 +385,7 @@ where
#[cfg(feature = "runtime-benchmarks")]
fn successful_origin() -> O {
O::from(Origin::Xcm(MultiLocation::Here))
O::from(Origin::Xcm(Here.into()))
}
}
......@@ -393,9 +394,9 @@ where
pub struct XcmPassthrough<Origin>(PhantomData<Origin>);
impl<Origin: From<crate::Origin>> ConvertOrigin<Origin> for XcmPassthrough<Origin> {
fn convert_origin(origin: MultiLocation, kind: OriginKind) -> Result<Origin, MultiLocation> {
match (kind, origin) {
(OriginKind::Xcm, l) => Ok(crate::Origin::Xcm(l).into()),
(_, origin) => Err(origin),
match kind {
OriginKind::Xcm => Ok(crate::Origin::Xcm(origin).into()),
_ => Err(origin),
}
}
}
......@@ -71,7 +71,7 @@ impl SendXcm for TestSendXcm {
pub struct TestSendXcmErrX8;
impl SendXcm for TestSendXcmErrX8 {
fn send_xcm(dest: MultiLocation, msg: Xcm) -> XcmResult {
if let MultiLocation::X8(..) = dest {
if dest.len() == 8 {
Err(XcmError::Undefined)
} else {
SENT_XCM.with(|q| q.borrow_mut().push((dest, msg)));
......@@ -129,9 +129,9 @@ impl pallet_balances::Config for Test {
}
parameter_types! {
pub const RelayLocation: MultiLocation = MultiLocation::Here;
pub const RelayLocation: MultiLocation = Here.into();
pub const AnyNetwork: NetworkId = NetworkId::Any;
pub Ancestry: MultiLocation = MultiLocation::Here;
pub Ancestry: MultiLocation = Here.into();
pub UnitWeightCost: Weight = 1_000;
}
......
......@@ -40,7 +40,7 @@ fn send_works() {
let sender: MultiLocation =
AccountId32 { network: AnyNetwork::get(), id: ALICE.into() }.into();
let message = Xcm::ReserveAssetDeposited {
assets: (X1(Parent), SEND_AMOUNT).into(),
assets: (Parent, SEND_AMOUNT).into(),
effects: vec![
buy_execution((Parent, SEND_AMOUNT), weight),
DepositAsset { assets: All.into(), max_assets: 1, beneficiary: sender.clone() },
......@@ -54,7 +54,7 @@ fn send_works() {
assert_eq!(
sent_xcm(),
vec![(
MultiLocation::Here,
Here.into(),
RelayedFrom { who: sender.clone(), message: Box::new(message.clone()) }
)]
);
......@@ -87,16 +87,7 @@ fn send_fails_when_xcm_router_blocks() {
assert_noop!(
XcmPallet::send(
Origin::signed(ALICE),
Box::new(X8(
Junction::Parent,
Junction::Parent,
Junction::Parent,
Junction::Parent,
Junction::Parent,
Junction::Parent,
Junction::Parent,
Junction::Parent
)),
Box::new(MultiLocation::ancestor(8)),
Box::new(message.clone())
),
crate::Error::<Test>::SendFailure
......@@ -118,7 +109,7 @@ fn teleport_assets_works() {
assert_ok!(XcmPallet::teleport_assets(
Origin::signed(ALICE),
Box::new(RelayLocation::get()),
Box::new(X1(AccountId32 { network: Any, id: BOB.into() })),
Box::new(AccountId32 { network: Any, id: BOB.into() }.into()),
(Here, SEND_AMOUNT).into(),
0,
weight,
......@@ -162,7 +153,7 @@ fn reserve_transfer_assets_works() {
vec![(
Parachain(PARA_ID).into(),
Xcm::ReserveAssetDeposited {
assets: (X1(Parent), SEND_AMOUNT).into(),
assets: (Parent, SEND_AMOUNT).into(),
effects: vec![
buy_execution((Parent, SEND_AMOUNT), weight),
DepositAsset { assets: All.into(), max_assets: 1, beneficiary: dest },
......
......@@ -17,7 +17,7 @@
//! Support data structures for `MultiLocation`, primarily the `Junction` datatype.
use alloc::vec::Vec;
use parity_scale_codec::{self, Decode, Encode};
use parity_scale_codec::{Decode, Encode};
/// A global identifier of an account-bearing consensus system.
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug)]
......@@ -140,10 +140,7 @@ pub enum Junction {
/// Usage will vary widely owing to its generality.
///
/// NOTE: Try to avoid using this and instead use a more specific item.
GeneralIndex {
#[codec(compact)]
id: u128,
},
GeneralIndex(#[codec(compact)] u128),
/// A nondescript datum acting as a key within the context location.
///
/// Usage will vary widely owing to its generality.
......@@ -161,6 +158,23 @@ pub enum Junction {
Plurality { id: BodyId, part: BodyPart },
}
impl From<crate::v1::Junction> for Junction {
fn from(v1: crate::v1::Junction) -> Junction {
use crate::v1::Junction::*;
match v1 {
Parachain(id) => Self::Parachain(id),
AccountId32 { network, id } => Self::AccountId32 { network, id },
AccountIndex64 { network, index } => Self::AccountIndex64 { network, index },
AccountKey20 { network, key } => Self::AccountKey20 { network, key },
PalletInstance(index) => Self::PalletInstance(index),
GeneralIndex(index) => Self::GeneralIndex(index),
GeneralKey(key) => Self::GeneralKey(key),
OnlyChild => Self::OnlyChild,
Plurality { id, part } => Self::Plurality { id, part },
}
}
}
impl Junction {
/// Returns true if this junction is a `Parent` item.
pub fn is_parent(&self) -> bool {
......
......@@ -33,13 +33,14 @@ mod traits;
use super::v1::{Response as Response1, Xcm as Xcm1};
pub use junction::{BodyId, BodyPart, Junction, NetworkId};
pub use multi_asset::{AssetInstance, MultiAsset};
pub use multi_location::MultiLocation;
pub use multi_location::MultiLocation::{self, *};
pub use order::Order;
pub use traits::{Error, ExecuteXcm, Outcome, Result, SendXcm};
/// A prelude for importing all types typically used when interacting with XCM messages.
pub mod prelude {
pub use super::{
junction::{BodyId, Junction::*},
multi_asset::{
AssetInstance::{self, *},
MultiAsset::{self, *},
......@@ -47,9 +48,8 @@ pub mod prelude {
multi_location::MultiLocation::{self, *},
order::Order::{self, *},
traits::{Error as XcmError, ExecuteXcm, Outcome, Result as XcmResult, SendXcm},
BodyId, BodyPart,
Junction::*,
NetworkId, OriginKind,
OriginKind,
Xcm::{self, *},
};
}
......@@ -321,11 +321,12 @@ pub mod opaque {
}
// Convert from a v1 response to a v0 response
impl From<Response1> for Response {
fn from(new_response: Response1) -> Self {
match new_response {
Response1::Assets(assets) => Self::Assets(assets.into()),
}
impl TryFrom<Response1> for Response {
type Error = ();
fn try_from(new_response: Response1) -> result::Result<Self, ()> {
Ok(match new_response {
Response1::Assets(assets) => Self::Assets(assets.try_into()?),
})
}
}
......@@ -335,33 +336,33 @@ impl<Call> TryFrom<Xcm1<Call>> for Xcm<Call> {
use Xcm::*;
Ok(match x {
Xcm1::WithdrawAsset { assets, effects } => WithdrawAsset {
assets: assets.into(),
assets: assets.try_into()?,
effects: effects
.into_iter()
.map(Order::try_from)
.collect::<result::Result<_, _>>()?,
},
Xcm1::ReserveAssetDeposited { assets, effects } => ReserveAssetDeposit {
assets: assets.into(),
assets: assets.try_into()?,
effects: effects
.into_iter()
.map(Order::try_from)
.collect::<result::Result<_, _>>()?,
},
Xcm1::ReceiveTeleportedAsset { assets, effects } => TeleportAsset {
assets: assets.into(),
assets: assets.try_into()?,
effects: effects
.into_iter()
.map(Order::try_from)
.collect::<result::Result<_, _>>()?,
},
Xcm1::QueryResponse { query_id: u64, response } =>
QueryResponse { query_id: u64, response: response.into() },
QueryResponse { query_id: u64, response: response.try_into()? },
Xcm1::TransferAsset { assets, beneficiary } =>
TransferAsset { assets: assets.into(), dest: beneficiary.into() },
TransferAsset { assets: assets.try_into()?, dest: beneficiary.try_into()? },
Xcm1::TransferReserveAsset { assets, dest, effects } => TransferReserveAsset {
assets: assets.into(),
dest: dest.into(),
assets: assets.try_into()?,
dest: dest.try_into()?,
effects: effects
.into_iter()
.map(Order::try_from)
......@@ -375,7 +376,7 @@ impl<Call> TryFrom<Xcm1<Call>> for Xcm<Call> {
Xcm1::Transact { origin_type, require_weight_at_most, call } =>
Transact { origin_type, require_weight_at_most, call: call.into() },
Xcm1::RelayedFrom { who, message } => RelayedFrom {
who: who.into(),
who: who.try_into()?,
message: alloc::boxed::Box::new((*message).try_into()?),
},
})
......
......@@ -17,8 +17,12 @@
//! Cross-Consensus Message format data structures.
use super::MultiLocation;
use crate::v1::{MultiAsset as MultiAsset1, MultiAssetFilter, MultiAssets, WildMultiAsset};
use crate::v1::{MultiAssetFilter, MultiAssets, WildMultiAsset};
use alloc::{vec, vec::Vec};
use core::{
convert::{TryFrom, TryInto},
result,
};
use parity_scale_codec::{self, Decode, Encode};
pub use crate::v1::AssetInstance;
......@@ -290,53 +294,64 @@ impl MultiAsset {
}
}
impl From<MultiAsset1> for MultiAsset {
fn from(a: MultiAsset1) -> MultiAsset {
impl TryFrom<crate::v1::MultiAsset> for MultiAsset {
type Error = ();
fn try_from(m: crate::v1::MultiAsset) -> result::Result<MultiAsset, ()> {
use crate::v1::{AssetId::*, Fungibility::*};
use MultiAsset::*;
match (a.id, a.fun) {
(Concrete(id), Fungible(amount)) => ConcreteFungible { id: id.into(), amount },
Ok(match (m.id, m.fun) {
(Concrete(id), Fungible(amount)) => ConcreteFungible { id: id.try_into()?, amount },
(Concrete(class), NonFungible(instance)) =>
ConcreteNonFungible { class: class.into(), instance },
ConcreteNonFungible { class: class.try_into()?, instance },
(Abstract(id), Fungible(amount)) => AbstractFungible { id, amount },
(Abstract(class), NonFungible(instance)) => AbstractNonFungible { class, instance },
}
})
}
}
impl From<MultiAssets> for Vec<MultiAsset> {
fn from(a: MultiAssets) -> Vec<MultiAsset> {
a.drain().into_iter().map(MultiAsset::from).collect()
impl TryFrom<MultiAssets> for Vec<MultiAsset> {
type Error = ();
fn try_from(m: MultiAssets) -> result::Result<Vec<MultiAsset>, ()> {
m.drain().into_iter().map(MultiAsset::try_from).collect()
}
}
impl From<WildMultiAsset> for MultiAsset {
fn from(a: WildMultiAsset) -> MultiAsset {
impl TryFrom<WildMultiAsset> for MultiAsset {
type Error = ();
fn try_from(m: WildMultiAsset) -> result::Result<MultiAsset, ()> {
use crate::v1::{AssetId::*, WildFungibility::*};
use MultiAsset::*;
match a {
Ok(match m {
WildMultiAsset::All => All,
WildMultiAsset::AllOf { id, fun } => match (id, fun) {
(Concrete(id), Fungible) => AllConcreteFungible { id: id.into() },
(Concrete(class), NonFungible) => AllConcreteNonFungible { class: class.into() },
(Concrete(id), Fungible) => AllConcreteFungible { id: id.try_into()? },
(Concrete(class), NonFungible) =>
AllConcreteNonFungible { class: class.try_into()? },
(Abstract(id), Fungible) => AllAbstractFungible { id },
(Abstract(class), NonFungible) => AllAbstractNonFungible { class },
},
}
})
}
}
impl From<WildMultiAsset> for Vec<MultiAsset> {
fn from(a: WildMultiAsset) -> Vec<MultiAsset> {
vec![a.into()]
impl TryFrom<WildMultiAsset> for Vec<MultiAsset> {
type Error = ();
fn try_from(m: WildMultiAsset) -> result::Result<Vec<MultiAsset>, ()> {
Ok(vec![m.try_into()?])
}
}
impl From<MultiAssetFilter> for Vec<MultiAsset> {
fn from(a: MultiAssetFilter) -> Vec<MultiAsset> {
match a {
MultiAssetFilter::Definite(assets) => assets.into(),
MultiAssetFilter::Wild(wildcard) => wildcard.into(),
impl TryFrom<MultiAssetFilter> for Vec<MultiAsset> {
type Error = ();
fn try_from(m: MultiAssetFilter) -> result::Result<Vec<MultiAsset>, ()> {
match m {
MultiAssetFilter::Definite(assets) => assets.try_into(),
MultiAssetFilter::Wild(wildcard) => wildcard.try_into(),
}
}
}
......
......@@ -16,9 +16,9 @@
//! Cross-Consensus Message format data structures.
use core::{mem, result};
use super::{super::v1::MultiLocation as MultiLocation1, Junction};
use super::Junction;
use crate::v1::MultiLocation as MultiLocation1;
use core::{convert::TryFrom, mem, result};
use parity_scale_codec::{self, Decode, Encode};
/// A relative path between state-bearing consensus systems.
......@@ -696,20 +696,68 @@ impl MultiLocation {
}
}
impl From<MultiLocation1> for MultiLocation {
fn from(old: MultiLocation1) -> Self {
use MultiLocation::*;
match old {
MultiLocation1::Here => Null,
MultiLocation1::X1(j0) => X1(j0),
MultiLocation1::X2(j0, j1) => X2(j0, j1),
MultiLocation1::X3(j0, j1, j2) => X3(j0, j1, j2),
MultiLocation1::X4(j0, j1, j2, j3) => X4(j0, j1, j2, j3),
MultiLocation1::X5(j0, j1, j2, j3, j4) => X5(j0, j1, j2, j3, j4),
MultiLocation1::X6(j0, j1, j2, j3, j4, j5) => X6(j0, j1, j2, j3, j4, j5),
MultiLocation1::X7(j0, j1, j2, j3, j4, j5, j6) => X7(j0, j1, j2, j3, j4, j5, j6),
MultiLocation1::X8(j0, j1, j2, j3, j4, j5, j6, j7) =>
X8(j0, j1, j2, j3, j4, j5, j6, j7),
impl TryFrom<MultiLocation1> for MultiLocation {
type Error = ();
fn try_from(v1: MultiLocation1) -> result::Result<Self, ()> {
use crate::v1::Junctions::*;
let mut res = Self::Null;
for _ in 0..v1.parents {
res.push(Junction::Parent)?;
}
match v1.interior {
Here => Ok(res),
X1(j0) => res.pushed_with(Junction::from(j0)).map_err(|_| ()),
X2(j0, j1) => res
.pushed_with(Junction::from(j0))
.and_then(|res| res.pushed_with(Junction::from(j1)))
.map_err(|_| ()),
X3(j0, j1, j2) => res
.pushed_with(Junction::from(j0))
.and_then(|res| res.pushed_with(Junction::from(j1)))
.and_then(|res| res.pushed_with(Junction::from(j2)))
.map_err(|_| ()),
X4(j0, j1, j2, j3) => res
.pushed_with(Junction::from(j0))
.and_then(|res| res.pushed_with(Junction::from(j1)))
.and_then(|res| res.pushed_with(Junction::from(j2)))
.and_then(|res| res.pushed_with(Junction::from(j3)))
.map_err(|_| ()),
X5(j0, j1, j2, j3, j4) => res
.pushed_with(Junction::from(j0))
.and_then(|res| res.pushed_with(Junction::from(j1)))
.and_then(|res| res.pushed_with(Junction::from(j2)))
.and_then(|res| res.pushed_with(Junction::from(j3)))
.and_then(|res| res.pushed_with(Junction::from(j4)))
.map_err(|_| ()),
X6(j0, j1, j2, j3, j4, j5) => res
.pushed_with(Junction::from(j0))
.and_then(|res| res.pushed_with(Junction::from(j1)))
.and_then(|res| res.pushed_with(Junction::from(j2)))