Skip to content
lib.rs 16.5 KiB
Newer Older
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Polkadot.

// Substrate 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.

// Substrate 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/>.

//! Cross-Consensus Message format data structures.

// NOTE, this crate is meant to be used in many different environments, notably wasm, but not
// necessarily related to FRAME or even Substrate.
//
// Hence, `no_std` rather than sp-runtime.
#![cfg_attr(not(feature = "std"), no_std)]

extern crate alloc;

Gavin Wood's avatar
Gavin Wood committed
use derivative::Derivative;
Gavin Wood's avatar
Gavin Wood committed
use parity_scale_codec::{Decode, Encode, Error as CodecError, Input, MaxEncodedLen};
Gavin Wood's avatar
Gavin Wood committed
pub mod v3;
Francisco Aguirre's avatar
Francisco Aguirre committed
pub mod v4;
Gavin Wood's avatar
Gavin Wood committed

pub mod lts {
Francisco Aguirre's avatar
Francisco Aguirre committed
	pub use super::v4::*;
Gavin Wood's avatar
Gavin Wood committed
}
Gavin Wood's avatar
Gavin Wood committed

pub mod latest {
Francisco Aguirre's avatar
Francisco Aguirre committed
	pub use super::v4::*;
Gavin Wood's avatar
Gavin Wood committed
}
Gavin Wood's avatar
Gavin Wood committed
mod double_encoded;
pub use double_encoded::DoubleEncoded;

/// Maximum nesting level for XCM decoding.
pub const MAX_XCM_DECODE_DEPTH: u32 = 8;

/// A version of XCM.
pub type Version = u32;

Gavin Wood's avatar
Gavin Wood committed
#[derive(Clone, Eq, PartialEq, Debug)]
pub enum Unsupported {}
impl Encode for Unsupported {}
impl Decode for Unsupported {
	fn decode<I: Input>(_: &mut I) -> Result<Self, CodecError> {
		Err("Not decodable".into())
	}
}

/// Attempt to convert `self` into a particular version of itself.
pub trait IntoVersion: Sized {
	/// Consume `self` and return same value expressed in some particular `version` of XCM.
	fn into_version(self, version: Version) -> Result<Self, ()>;

	/// Consume `self` and return same value expressed the latest version of XCM.
	fn into_latest(self) -> Result<Self, ()> {
		self.into_version(latest::VERSION)
	}
}

Gavin Wood's avatar
Gavin Wood committed
pub trait TryAs<T> {
	fn try_as(&self) -> Result<&T, ()>;
}

macro_rules! versioned_type {
	($(#[$attr:meta])* pub enum $n:ident {
		$(#[$index3:meta])+
Gavin Wood's avatar
Gavin Wood committed
		V3($v3:ty),
Francisco Aguirre's avatar
Francisco Aguirre committed
		$(#[$index4:meta])+
		V4($v4:ty),
Gavin Wood's avatar
Gavin Wood committed
	}) => {
		#[derive(Derivative, Encode, Decode, TypeInfo)]
		#[derivative(
			Clone(bound = ""),
			Eq(bound = ""),
			PartialEq(bound = ""),
			Debug(bound = "")
		)]
		#[codec(encode_bound())]
		#[codec(decode_bound())]
		#[scale_info(replace_segment("staging_xcm", "xcm"))]
Gavin Wood's avatar
Gavin Wood committed
		$(#[$attr])*
		pub enum $n {
Gavin Wood's avatar
Gavin Wood committed
			V3($v3),
Francisco Aguirre's avatar
Francisco Aguirre committed
			$(#[$index4])*
			V4($v4),
Gavin Wood's avatar
Gavin Wood committed
		impl $n {
			pub fn try_as<T>(&self) -> Result<&T, ()> where Self: TryAs<T> {
				<Self as TryAs<T>>::try_as(&self)
			}
Gavin Wood's avatar
Gavin Wood committed
		impl TryAs<$v3> for $n {
			fn try_as(&self) -> Result<&$v3, ()> {
				match &self {
					Self::V3(ref x) => Ok(x),
Francisco Aguirre's avatar
Francisco Aguirre committed
					_ => Err(()),
				}
			}
		}
		impl TryAs<$v4> for $n {
			fn try_as(&self) -> Result<&$v4, ()> {
				match &self {
					Self::V4(ref x) => Ok(x),
					_ => Err(()),
Gavin Wood's avatar
Gavin Wood committed
				}
			}
Gavin Wood's avatar
Gavin Wood committed
		impl IntoVersion for $n {
			fn into_version(self, n: Version) -> Result<Self, ()> {
				Ok(match n {
					3 => Self::V3(self.try_into()?),
Francisco Aguirre's avatar
Francisco Aguirre committed
					4 => Self::V4(self.try_into()?),
Gavin Wood's avatar
Gavin Wood committed
					_ => return Err(()),
				})
			}
Francisco Aguirre's avatar
Francisco Aguirre committed
		impl From<$v3> for $n {
			fn from(x: $v3) -> Self {
Gavin Wood's avatar
Gavin Wood committed
				$n::V3(x.into())
			}
Francisco Aguirre's avatar
Francisco Aguirre committed
		impl From<$v4> for $n {
			fn from(x: $v4) -> Self {
				$n::V4(x.into())
			}
		}
Gavin Wood's avatar
Gavin Wood committed
		impl TryFrom<$n> for $v3 {
			type Error = ();
			fn try_from(x: $n) -> Result<Self, ()> {
				use $n::*;
				match x {
					V3(x) => Ok(x),
Francisco Aguirre's avatar
Francisco Aguirre committed
					V4(x) => x.try_into(),
				}
			}
		}
		impl TryFrom<$n> for $v4 {
			type Error = ();
			fn try_from(x: $n) -> Result<Self, ()> {
				use $n::*;
				match x {
					V3(x) => x.try_into().map_err(|_| ()),
					V4(x) => Ok(x),
Gavin Wood's avatar
Gavin Wood committed
				}
			}
		}
		impl MaxEncodedLen for $n {
			fn max_encoded_len() -> usize {
				<$v3>::max_encoded_len()
			}
		}
	};
Gavin Wood's avatar
Gavin Wood committed
	($(#[$attr:meta])* pub enum $n:ident {
Gavin Wood's avatar
Gavin Wood committed
		V2($v2:ty),
Gavin Wood's avatar
Gavin Wood committed
		V3($v3:ty),
Francisco Aguirre's avatar
Francisco Aguirre committed
		$(#[$index4:meta])+
		V4($v4:ty),
Gavin Wood's avatar
Gavin Wood committed
	}) => {
		#[derive(Derivative, Encode, Decode, TypeInfo)]
		#[derivative(
			Clone(bound = ""),
			Eq(bound = ""),
			PartialEq(bound = ""),
			Debug(bound = "")
		)]
		#[codec(encode_bound())]
		#[codec(decode_bound())]
		#[scale_info(replace_segment("staging_xcm", "xcm"))]
Gavin Wood's avatar
Gavin Wood committed
		$(#[$attr])*
		pub enum $n {
Gavin Wood's avatar
Gavin Wood committed
			V2($v2),
Gavin Wood's avatar
Gavin Wood committed
			V3($v3),
Francisco Aguirre's avatar
Francisco Aguirre committed
			$(#[$index4])*
			V4($v4),
Gavin Wood's avatar
Gavin Wood committed
		impl $n {
			pub fn try_as<T>(&self) -> Result<&T, ()> where Self: TryAs<T> {
				<Self as TryAs<T>>::try_as(&self)
			}
		}
		impl TryAs<$v2> for $n {
			fn try_as(&self) -> Result<&$v2, ()> {
				match &self {
					Self::V2(ref x) => Ok(x),
					_ => Err(()),
				}
			}
		}
		impl TryAs<$v3> for $n {
			fn try_as(&self) -> Result<&$v3, ()> {
				match &self {
					Self::V3(ref x) => Ok(x),
					_ => Err(()),
				}
			}
		}
Francisco Aguirre's avatar
Francisco Aguirre committed
		impl TryAs<$v4> for $n {
			fn try_as(&self) -> Result<&$v4, ()> {
				match &self {
					Self::V4(ref x) => Ok(x),
					_ => Err(()),
				}
			}
		}
Gavin Wood's avatar
Gavin Wood committed
		impl IntoVersion for $n {
			fn into_version(self, n: Version) -> Result<Self, ()> {
				Ok(match n {
					1 | 2 => Self::V2(self.try_into()?),
					3 => Self::V3(self.try_into()?),
Francisco Aguirre's avatar
Francisco Aguirre committed
					4 => Self::V4(self.try_into()?),
Gavin Wood's avatar
Gavin Wood committed
					_ => return Err(()),
				})
			}
		}
		impl From<$v2> for $n {
			fn from(x: $v2) -> Self {
				$n::V2(x)
			}
		}
Francisco Aguirre's avatar
Francisco Aguirre committed
		impl<T: Into<$v4>> From<T> for $n {
Gavin Wood's avatar
Gavin Wood committed
			fn from(x: T) -> Self {
Francisco Aguirre's avatar
Francisco Aguirre committed
				$n::V4(x.into())
Gavin Wood's avatar
Gavin Wood committed
			}
		}
		impl TryFrom<$n> for $v2 {
			type Error = ();
			fn try_from(x: $n) -> Result<Self, ()> {
				use $n::*;
				match x {
					V2(x) => Ok(x),
					V3(x) => x.try_into(),
Francisco Aguirre's avatar
Francisco Aguirre committed
					V4(x) => {
						let v3: $v3 = x.try_into().map_err(|_| ())?;
						v3.try_into()
					},
Gavin Wood's avatar
Gavin Wood committed
				}
			}
		}
		impl TryFrom<$n> for $v3 {
			type Error = ();
			fn try_from(x: $n) -> Result<Self, ()> {
				use $n::*;
				match x {
					V2(x) => x.try_into(),
					V3(x) => Ok(x),
Francisco Aguirre's avatar
Francisco Aguirre committed
					V4(x) => x.try_into().map_err(|_| ()),
				}
			}
		}
		impl TryFrom<$n> for $v4 {
			type Error = ();
			fn try_from(x: $n) -> Result<Self, ()> {
				use $n::*;
				match x {
					V2(x) => {
						let v3: $v3 = x.try_into().map_err(|_| ())?;
						v3.try_into().map_err(|_| ())
					},
					V3(x) => x.try_into().map_err(|_| ()),
					V4(x) => Ok(x),
Gavin Wood's avatar
Gavin Wood committed
				}
			}
		}
		impl MaxEncodedLen for $n {
			fn max_encoded_len() -> usize {
				<$v3>::max_encoded_len()
			}
		}
	};
Gavin Wood's avatar
Gavin Wood committed
versioned_type! {
Francisco Aguirre's avatar
Francisco Aguirre committed
	/// A single version's `AssetId` value, together with its version code.
Gavin Wood's avatar
Gavin Wood committed
	pub enum VersionedAssetId {
Gavin Wood's avatar
Gavin Wood committed
		V3(v3::AssetId),
Francisco Aguirre's avatar
Francisco Aguirre committed
		#[codec(index = 4)]
		V4(v4::AssetId),
Gavin Wood's avatar
Gavin Wood committed
	}
Gavin Wood's avatar
Gavin Wood committed
versioned_type! {
	/// A single version's `Response` value, together with its version code.
	pub enum VersionedResponse {
Gavin Wood's avatar
Gavin Wood committed
		V2(v2::Response),
Gavin Wood's avatar
Gavin Wood committed
		V3(v3::Response),
Francisco Aguirre's avatar
Francisco Aguirre committed
		#[codec(index = 4)]
		V4(v4::Response),
versioned_type! {
	/// A single `NetworkId` value, together with its version code.
	pub enum VersionedNetworkId {
		#[codec(index = 2)]
		V2(v2::NetworkId),
		#[codec(index = 3)]
		V3(v3::NetworkId),
Francisco Aguirre's avatar
Francisco Aguirre committed
		#[codec(index = 4)]
		V4(v4::NetworkId),
	}
}

versioned_type! {
	/// A single `Junction` value, together with its version code.
	pub enum VersionedJunction {
		#[codec(index = 2)]
		V2(v2::Junction),
		#[codec(index = 3)]
		V3(v3::Junction),
Francisco Aguirre's avatar
Francisco Aguirre committed
		#[codec(index = 4)]
		V4(v4::Junction),
Gavin Wood's avatar
Gavin Wood committed
versioned_type! {
Francisco Aguirre's avatar
Francisco Aguirre committed
	/// A single `Location` value, together with its version code.
Gavin Wood's avatar
Gavin Wood committed
	#[derive(Ord, PartialOrd)]
Francisco Aguirre's avatar
Francisco Aguirre committed
	pub enum VersionedLocation {
		#[codec(index = 1)] // v2 is same as v1 and therefore re-using the v1 index
Gavin Wood's avatar
Gavin Wood committed
		V2(v2::MultiLocation),
Gavin Wood's avatar
Gavin Wood committed
		V3(v3::MultiLocation),
Francisco Aguirre's avatar
Francisco Aguirre committed
		#[codec(index = 4)]
		V4(v4::Location),
Francisco Aguirre's avatar
Francisco Aguirre committed
#[deprecated(note = "Use `VersionedLocation` instead")]
pub type VersionedMultiLocation = VersionedLocation;

Gavin Wood's avatar
Gavin Wood committed
versioned_type! {
Francisco Aguirre's avatar
Francisco Aguirre committed
	/// A single `InteriorLocation` value, together with its version code.
	pub enum VersionedInteriorLocation {
		#[codec(index = 2)] // while this is same as v1::Junctions, VersionedInteriorLocation is introduced in v3
Gavin Wood's avatar
Gavin Wood committed
		V2(v2::InteriorMultiLocation),
Gavin Wood's avatar
Gavin Wood committed
		V3(v3::InteriorMultiLocation),
Francisco Aguirre's avatar
Francisco Aguirre committed
		#[codec(index = 4)]
		V4(v4::InteriorLocation),
Francisco Aguirre's avatar
Francisco Aguirre committed
#[deprecated(note = "Use `VersionedInteriorLocation` instead")]
pub type VersionedInteriorMultiLocation = VersionedInteriorLocation;

Gavin Wood's avatar
Gavin Wood committed
versioned_type! {
Francisco Aguirre's avatar
Francisco Aguirre committed
	/// A single `Asset` value, together with its version code.
	pub enum VersionedAsset {
		#[codec(index = 1)] // v2 is same as v1 and therefore re-using the v1 index
Gavin Wood's avatar
Gavin Wood committed
		V2(v2::MultiAsset),
Gavin Wood's avatar
Gavin Wood committed
		V3(v3::MultiAsset),
Francisco Aguirre's avatar
Francisco Aguirre committed
		#[codec(index = 4)]
		V4(v4::Asset),
Francisco Aguirre's avatar
Francisco Aguirre committed
#[deprecated(note = "Use `VersionedAsset` instead")]
pub type VersionedMultiAsset = VersionedAsset;

Gavin Wood's avatar
Gavin Wood committed
versioned_type! {
	/// A single `MultiAssets` value, together with its version code.
Francisco Aguirre's avatar
Francisco Aguirre committed
	pub enum VersionedAssets {
		#[codec(index = 1)] // v2 is same as v1 and therefore re-using the v1 index
Gavin Wood's avatar
Gavin Wood committed
		V2(v2::MultiAssets),
Gavin Wood's avatar
Gavin Wood committed
		V3(v3::MultiAssets),
Francisco Aguirre's avatar
Francisco Aguirre committed
		#[codec(index = 4)]
		V4(v4::Assets),
Francisco Aguirre's avatar
Francisco Aguirre committed
#[deprecated(note = "Use `VersionedAssets` instead")]
pub type VersionedMultiAssets = VersionedAssets;

/// A single XCM message, together with its version code.
#[derive(Derivative, Encode, Decode, TypeInfo)]
#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))]
Gavin Wood's avatar
Gavin Wood committed
#[codec(encode_bound())]
#[codec(decode_bound())]
#[scale_info(bounds(), skip_type_params(RuntimeCall))]
#[scale_info(replace_segment("staging_xcm", "xcm"))]
pub enum VersionedXcm<RuntimeCall> {
Gavin Wood's avatar
Gavin Wood committed
	#[codec(index = 2)]
	V2(v2::Xcm<RuntimeCall>),
Gavin Wood's avatar
Gavin Wood committed
	#[codec(index = 3)]
	V3(v3::Xcm<RuntimeCall>),
Francisco Aguirre's avatar
Francisco Aguirre committed
	#[codec(index = 4)]
	V4(v4::Xcm<RuntimeCall>),
Gavin Wood's avatar
Gavin Wood committed
}

impl<C> IntoVersion for VersionedXcm<C> {
	fn into_version(self, n: Version) -> Result<Self, ()> {
		Ok(match n {
			2 => Self::V2(self.try_into()?),
Gavin Wood's avatar
Gavin Wood committed
			3 => Self::V3(self.try_into()?),
Francisco Aguirre's avatar
Francisco Aguirre committed
			4 => Self::V4(self.try_into()?),
impl<RuntimeCall> From<v2::Xcm<RuntimeCall>> for VersionedXcm<RuntimeCall> {
	fn from(x: v2::Xcm<RuntimeCall>) -> Self {
Gavin Wood's avatar
Gavin Wood committed
impl<RuntimeCall> From<v3::Xcm<RuntimeCall>> for VersionedXcm<RuntimeCall> {
	fn from(x: v3::Xcm<RuntimeCall>) -> Self {
		VersionedXcm::V3(x)
Gavin Wood's avatar
Gavin Wood committed
	}
}

Francisco Aguirre's avatar
Francisco Aguirre committed
impl<RuntimeCall> From<v4::Xcm<RuntimeCall>> for VersionedXcm<RuntimeCall> {
	fn from(x: v4::Xcm<RuntimeCall>) -> Self {
		VersionedXcm::V4(x)
	}
}

Gavin Wood's avatar
Gavin Wood committed
impl<RuntimeCall> TryFrom<VersionedXcm<RuntimeCall>> for v2::Xcm<RuntimeCall> {
Gavin Wood's avatar
Gavin Wood committed
	type Error = ();
	fn try_from(x: VersionedXcm<RuntimeCall>) -> Result<Self, ()> {
Gavin Wood's avatar
Gavin Wood committed
			V2(x) => Ok(x),
			V3(x) => x.try_into(),
Francisco Aguirre's avatar
Francisco Aguirre committed
			V4(x) => {
				let v3: v3::Xcm<RuntimeCall> = x.try_into()?;
				v3.try_into()
			},
Gavin Wood's avatar
Gavin Wood committed
impl<Call> TryFrom<VersionedXcm<Call>> for v3::Xcm<Call> {
Gavin Wood's avatar
Gavin Wood committed
	fn try_from(x: VersionedXcm<Call>) -> Result<Self, ()> {
Gavin Wood's avatar
Gavin Wood committed
		match x {
Gavin Wood's avatar
Gavin Wood committed
			V2(x) => x.try_into(),
			V3(x) => Ok(x),
Francisco Aguirre's avatar
Francisco Aguirre committed
			V4(x) => x.try_into(),
		}
	}
}

impl<Call> TryFrom<VersionedXcm<Call>> for v4::Xcm<Call> {
	type Error = ();
	fn try_from(x: VersionedXcm<Call>) -> Result<Self, ()> {
		use VersionedXcm::*;
		match x {
			V2(x) => {
				let v3: v3::Xcm<Call> = x.try_into()?;
				v3.try_into()
			},
			V3(x) => x.try_into(),
			V4(x) => Ok(x),
Francisco Aguirre's avatar
Francisco Aguirre committed
/// Convert an `Xcm` datum into a `VersionedXcm`, based on a destination `Location` which will
Gavin Wood's avatar
Gavin Wood committed
pub trait WrapVersion {
	fn wrap_version<RuntimeCall>(
Francisco Aguirre's avatar
Francisco Aguirre committed
		dest: &latest::Location,
		xcm: impl Into<VersionedXcm<RuntimeCall>>,
	) -> Result<VersionedXcm<RuntimeCall>, ()>;
Gavin Wood's avatar
Gavin Wood committed
}

/// Check and return the `Version` that should be used for the `Xcm` datum for the destination
/// `Location`, which will interpret it.
Francisco Aguirre's avatar
Francisco Aguirre committed
	fn get_version_for(dest: &latest::Location) -> Option<Version>;
/// `()` implementation does nothing with the XCM, just sending with whatever version it was
/// authored as.
Gavin Wood's avatar
Gavin Wood committed
impl WrapVersion for () {
	fn wrap_version<RuntimeCall>(
Francisco Aguirre's avatar
Francisco Aguirre committed
		_: &latest::Location,
		xcm: impl Into<VersionedXcm<RuntimeCall>>,
	) -> Result<VersionedXcm<RuntimeCall>, ()> {
Gavin Wood's avatar
Gavin Wood committed
		Ok(xcm.into())
	}
}

/// `WrapVersion` implementation which attempts to always convert the XCM to version 2 before
/// wrapping it.
Gavin Wood's avatar
Gavin Wood committed
pub struct AlwaysV2;
impl WrapVersion for AlwaysV2 {
	fn wrap_version<RuntimeCall>(
Francisco Aguirre's avatar
Francisco Aguirre committed
		_: &latest::Location,
		xcm: impl Into<VersionedXcm<RuntimeCall>>,
	) -> Result<VersionedXcm<RuntimeCall>, ()> {
Gavin Wood's avatar
Gavin Wood committed
		Ok(VersionedXcm::<RuntimeCall>::V2(xcm.into().try_into()?))
Gavin Wood's avatar
Gavin Wood committed
	}
}
impl GetVersion for AlwaysV2 {
Francisco Aguirre's avatar
Francisco Aguirre committed
	fn get_version_for(_dest: &latest::Location) -> Option<Version> {
Gavin Wood's avatar
Gavin Wood committed

/// `WrapVersion` implementation which attempts to always convert the XCM to version 3 before
/// wrapping it.
Gavin Wood's avatar
Gavin Wood committed
pub struct AlwaysV3;
impl WrapVersion for AlwaysV3 {
	fn wrap_version<Call>(
Francisco Aguirre's avatar
Francisco Aguirre committed
		_: &latest::Location,
Gavin Wood's avatar
Gavin Wood committed
		xcm: impl Into<VersionedXcm<Call>>,
	) -> Result<VersionedXcm<Call>, ()> {
		Ok(VersionedXcm::<Call>::V3(xcm.into().try_into()?))
impl GetVersion for AlwaysV3 {
Francisco Aguirre's avatar
Francisco Aguirre committed
	fn get_version_for(_dest: &latest::Location) -> Option<Version> {
Francisco Aguirre's avatar
Francisco Aguirre committed
/// `WrapVersion` implementation which attempts to always convert the XCM to version 3 before
/// wrapping it.
pub struct AlwaysV4;
impl WrapVersion for AlwaysV4 {
	fn wrap_version<Call>(
		_: &latest::Location,
		xcm: impl Into<VersionedXcm<Call>>,
	) -> Result<VersionedXcm<Call>, ()> {
		Ok(VersionedXcm::<Call>::V4(xcm.into().try_into()?))
	}
}
impl GetVersion for AlwaysV4 {
	fn get_version_for(_dest: &latest::Location) -> Option<Version> {
		Some(v4::VERSION)
	}
}

Gavin Wood's avatar
Gavin Wood committed
/// `WrapVersion` implementation which attempts to always convert the XCM to the latest version
/// before wrapping it.
Francisco Aguirre's avatar
Francisco Aguirre committed
pub type AlwaysLatest = AlwaysV4;
Gavin Wood's avatar
Gavin Wood committed

Gavin Wood's avatar
Gavin Wood committed
/// `WrapVersion` implementation which attempts to always convert the XCM to the most recent Long-
/// Term-Support version before wrapping it.
Francisco Aguirre's avatar
Francisco Aguirre committed
pub type AlwaysLts = AlwaysV4;
Gavin Wood's avatar
Gavin Wood committed

pub mod prelude {
	pub use super::{
Francisco Aguirre's avatar
Francisco Aguirre committed
		latest::prelude::*, AlwaysLatest, AlwaysLts, AlwaysV2, AlwaysV3, AlwaysV4, GetVersion,
		IntoVersion, Unsupported, Version as XcmVersion, VersionedAsset, VersionedAssetId,
		VersionedAssets, VersionedInteriorLocation, VersionedLocation, VersionedResponse,
Gavin Wood's avatar
Gavin Wood committed
		VersionedXcm, WrapVersion,
Gavin Wood's avatar
Gavin Wood committed
pub mod opaque {
Gavin Wood's avatar
Gavin Wood committed
		// Everything from v2
		pub use crate::v2::*;
		// Then override with the opaque types in v2
		pub use crate::v2::opaque::{Instruction, Xcm};
	}
Gavin Wood's avatar
Gavin Wood committed
	pub mod v3 {
		// Everything from v3
		pub use crate::v3::*;
		// Then override with the opaque types in v3
		pub use crate::v3::opaque::{Instruction, Xcm};
	}
Francisco Aguirre's avatar
Francisco Aguirre committed
	pub mod v4 {
		// Everything from v4
		pub use crate::v4::*;
		// Then override with the opaque types in v4
		pub use crate::v4::opaque::{Instruction, Xcm};
	}
Gavin Wood's avatar
Gavin Wood committed

	pub mod latest {
Francisco Aguirre's avatar
Francisco Aguirre committed
		pub use super::v4::*;
Gavin Wood's avatar
Gavin Wood committed
	}

	pub mod lts {
Francisco Aguirre's avatar
Francisco Aguirre committed
		pub use super::v4::*;
Gavin Wood's avatar
Gavin Wood committed
	}
Gavin Wood's avatar
Gavin Wood committed

Denis_P's avatar
Denis_P committed
	/// The basic `VersionedXcm` type which just uses the `Vec<u8>` as an encoded call.
Gavin Wood's avatar
Gavin Wood committed
	pub type VersionedXcm = super::VersionedXcm<()>;
Gavin Wood's avatar
Gavin Wood committed
#[test]
fn conversion_works() {
	use latest::prelude::*;
Francisco Aguirre's avatar
Francisco Aguirre committed
	let assets: Assets = (Here, 1u128).into();
	let _: VersionedAssets = assets.into();
}

#[test]
fn size_limits() {
	extern crate std;

	let mut test_failed = false;
	macro_rules! check_sizes {
        ($(($kind:ty, $expected:expr),)+) => {
            $({
                let s = core::mem::size_of::<$kind>();
                // Since the types often affect the size of other types in which they're included
                // it is more convenient to check multiple types at the same time and only fail
                // the test at the end. For debugging it's also useful to print out all of the sizes,
                // even if they're within the expected range.
                if s > $expected {
                    test_failed = true;
                    std::eprintln!(
                        "assertion failed: size of '{}' is {} (which is more than the expected {})",
                        stringify!($kind),
                        s,
                        $expected
                    );
                } else {
                    std::println!(
                        "type '{}' is of size {} which is within the expected {}",
                        stringify!($kind),
                        s,
                        $expected
                    );
                }
            })+
        }
    }

	check_sizes! {
		(crate::latest::Instruction<()>, 112),
		(crate::latest::Asset, 80),
		(crate::latest::Location, 24),
		(crate::latest::AssetId, 40),
		(crate::latest::Junctions, 16),
		(crate::latest::Junction, 88),
		(crate::latest::Response, 40),
		(crate::latest::AssetInstance, 48),
Francisco Aguirre's avatar
Francisco Aguirre committed
		(crate::latest::NetworkId, 48),
		(crate::latest::BodyId, 32),
		(crate::latest::Assets, 24),
		(crate::latest::BodyPart, 12),
	}
	assert!(!test_failed);
Gavin Wood's avatar
Gavin Wood committed
}