// Copyright 2020 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 .
//! 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.
#![no_std]
extern crate alloc;
use core::{
convert::{TryFrom, TryInto},
result::Result,
};
use derivative::Derivative;
use parity_scale_codec::{Decode, Encode, Error as CodecError, Input};
pub mod v0;
pub mod v1;
pub mod latest {
pub use super::v1::*;
}
mod double_encoded;
pub use double_encoded::DoubleEncoded;
#[derive(Clone, Eq, PartialEq, Debug)]
pub enum Unsupported {}
impl Encode for Unsupported {}
impl Decode for Unsupported {
fn decode(_: &mut I) -> Result {
Err("Not decodable".into())
}
}
/// A single XCM message, together with its version code.
#[derive(Derivative, Encode, Decode)]
#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))]
#[codec(encode_bound())]
#[codec(decode_bound())]
pub enum VersionedXcm {
V0(v0::Xcm),
V1(v1::Xcm),
}
impl From> for VersionedXcm {
fn from(x: v0::Xcm) -> Self {
VersionedXcm::V0(x)
}
}
impl From> for VersionedXcm {
fn from(x: v1::Xcm) -> Self {
VersionedXcm::V1(x)
}
}
impl TryFrom> for v0::Xcm {
type Error = ();
fn try_from(x: VersionedXcm) -> Result {
match x {
VersionedXcm::V0(x) => Ok(x),
VersionedXcm::V1(x) => x.try_into(),
}
}
}
impl TryFrom> for v1::Xcm {
type Error = ();
fn try_from(x: VersionedXcm) -> Result {
match x {
VersionedXcm::V0(x) => x.try_into(),
VersionedXcm::V1(x) => Ok(x),
}
}
}
/// Convert an `Xcm` datum into a `VersionedXcm`, based on a destination `MultiLocation` which will interpret it.
pub trait WrapVersion {
fn wrap_version(
dest: &latest::MultiLocation,
xcm: impl Into>,
) -> Result, ()>;
}
/// `()` implementation does nothing with the XCM, just sending with whatever version it was authored as.
impl WrapVersion for () {
fn wrap_version(
_: &latest::MultiLocation,
xcm: impl Into>,
) -> Result, ()> {
Ok(xcm.into())
}
}
/// `WrapVersion` implementation which attempts to always convert the XCM to version 0 before wrapping it.
pub struct AlwaysV0;
impl WrapVersion for AlwaysV0 {
fn wrap_version(
_: &latest::MultiLocation,
xcm: impl Into>,
) -> Result, ()> {
Ok(VersionedXcm::::V0(xcm.into().try_into()?))
}
}
/// `WrapVersion` implementation which attempts to always convert the XCM to version 1 before wrapping it.
pub struct AlwaysV1;
impl WrapVersion for AlwaysV1 {
fn wrap_version(
_: &latest::MultiLocation,
xcm: impl Into>,
) -> Result, ()> {
Ok(VersionedXcm::::V1(xcm.into().try_into()?))
}
}
/// `WrapVersion` implementation which attempts to always convert the XCM to the latest version before wrapping it.
pub type AlwaysLatest = AlwaysV1;
/// `WrapVersion` implementation which attempts to always convert the XCM to the release version before wrapping it.
pub type AlwaysRelease = AlwaysV0;
pub mod opaque {
pub mod v0 {
// Everything from v0
pub use crate::v0::*;
// Then override with the opaque types in v0
pub use crate::v0::opaque::{Order, Xcm};
}
pub mod v1 {
// Everything from v1
pub use crate::v1::*;
// Then override with the opaque types in v1
pub use crate::v1::opaque::{Order, Xcm};
}
pub mod latest {
pub use super::v1::*;
}
/// The basic `VersionedXcm` type which just uses the `Vec` as an encoded call.
pub type VersionedXcm = super::VersionedXcm<()>;
}