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

Commit

Permalink
Add the XCM primitives crate. (#1760)
Browse files Browse the repository at this point in the history
Co-authored-by: Gavin Wood <gavin@parity.io>

Co-authored-by: Gavin Wood <gavin@parity.io>
  • Loading branch information
pepyakin and gavofyork authored Sep 28, 2020
1 parent db64485 commit ec55686
Show file tree
Hide file tree
Showing 10 changed files with 1,058 additions and 4 deletions.
15 changes: 11 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ members = [
"statement-table",
"service",
"validation",
"xcm",

"node/collation-generation",
"node/core/av-store",
Expand Down
9 changes: 9 additions & 0 deletions xcm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "xcm"
version = "0.8.22"
authors = ["Parity Technologies x<admin@parity.io>"]
description = "The basic XCM datastructures."
edition = "2018"

[dependencies]
codec = { package = "parity-scale-codec", version = "1.3.5", default-features = false, features = [ "derive" ] }
46 changes: 46 additions & 0 deletions xcm/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// 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 <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.
#![no_std]
extern crate alloc;

use codec::{Encode, Decode};

pub mod v0;

/// A single XCM message, together with its version code.
#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug)]
pub enum VersionedXcm {
V0(v0::Xcm),
}

/// A versioned multi-location, a relative location of a cross-consensus system identifier.
#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug)]
pub enum VersionedMultiLocation {
V0(v0::MultiLocation),
}

/// A versioned multi-asset, an identifier for an asset within a consensus system.
#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug)]
pub enum VersionedMultiAsset {
V0(v0::MultiAsset),
}
101 changes: 101 additions & 0 deletions xcm/src/v0/junction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// Copyright 2020 Parity Technologies (UK) Ltd.
// This file is part of Cumulus.

// 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.

//! Support datastructures for `MultiLocation`, primarily the `Junction` datatype.
use alloc::vec::Vec;
use codec::{self, Encode, Decode};

/// A global identifier of an account-bearing consensus system.
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug)]
pub enum NetworkId {
/// Unidentified/any.
Any,
/// Some named network.
Named(Vec<u8>),
/// The Polkadot Relay chain
Polkadot,
/// Kusama.
Kusama,
}

/// A single item in a path to describe the relative location of a consensus system.
///
/// Each item assumes a pre-existing location as its context and is defined in terms of it.
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug)]
pub enum Junction {
/// The consensus system of which the context is a member and state-wise super-set.
///
/// NOTE: This item is *not* a sub-consensus item: a consensus system may not identify itself trustlessly as
/// a location that includes this junction.
Parent,
/// An indexed parachain belonging to and operated by the context.
///
/// Generally used when the context is a Polkadot Relay-chain.
Parachain { #[codec(compact)] id: u32 },
/// A 32-byte identifier for an account of a specific network that is respected as a sovereign endpoint within
/// the context.
///
/// Generally used when the context is a Substrate-based chain.
AccountId32 { network: NetworkId, id: [u8; 32] },
/// An 8-byte index for an account of a specific network that is respected as a sovereign endpoint within
/// the context.
///
/// May be used when the context is a Frame-based chain and includes e.g. an indices pallet.
AccountIndex64 { network: NetworkId, #[codec(compact)] index: u64 },
/// A 20-byte identifier for an account of a specific network that is respected as a sovereign endpoint within
/// the context.
///
/// May be used when the context is an Ethereum or Bitcoin chain or smart-contract.
AccountKey20 { network: NetworkId, key: [u8; 20] },
/// An instanced, indexed pallet that forms a constituent part of the context.
///
/// Generally used when the context is a Frame-based chain.
PalletInstance { id: u8 },
/// A non-descript index within the context location.
///
/// 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 },
/// A nondescript datum acting as a key within the context location.
///
/// Usage will vary widely owing to its generality.
///
/// NOTE: Try to avoid using this and instead use a more specific item.
GeneralKey(Vec<u8>),
/// The unambiguous child.
///
/// Not currently used except as a fallback when deriving ancestry.
OnlyChild,
}

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

Junction::Parachain { .. } |
Junction::AccountId32 { .. } |
Junction::AccountIndex64 { .. } |
Junction::AccountKey20 { .. } |
Junction::PalletInstance { .. } |
Junction::GeneralIndex { .. } |
Junction::GeneralKey(..) |
Junction::OnlyChild => true,
}
}
}
176 changes: 176 additions & 0 deletions xcm/src/v0/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
// Copyright 2020 Parity Technologies (UK) Ltd.
// This file is part of Cumulus.

// 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.

//! Version 0 of the Cross-Consensus Message format data structures.
use core::{result, convert::TryFrom};
use alloc::{boxed::Box, vec::Vec};

use codec::{self, Encode, Decode};
use super::{VersionedXcm, VersionedMultiAsset};

mod junction;
mod multi_asset;
mod multi_location;
mod order;
mod traits;
pub use junction::{Junction, NetworkId};
pub use multi_asset::{MultiAsset, AssetInstance};
pub use multi_location::MultiLocation;
pub use order::Order;
pub use traits::{Error, Result, SendXcm, ExecuteXcm};

// TODO: Efficient encodings for Vec<MultiAsset>, Vec<Order>, using initial byte values 128+ to encode the number of
// items in the vector.

/// Basically just the XCM (more general) version of `ParachainDispatchOrigin`.
#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, Debug)]
pub enum OriginKind {
/// Origin should just be the native origin for the sender. For Cumulus/Frame chains this is
/// the `Parachain` origin.
Native,

/// Origin should just be the standard account-based origin with the sovereign account of
/// the sender. For Cumulus/Frame chains, this is the `Signed` origin.
SovereignAccount,

/// Origin should be the super-user. For Cumulus/Frame chains, this is the `Root` origin.
/// This will not usually be an available option.
Superuser,
}

/// Cross-Consensus Message: A message from one consensus system to another.
///
/// Consensus systems that may send and receive messages include blockchains and smart contracts.
///
/// All messages are delivered from a known *origin*, expressed as a `MultiLocation`.
///
/// This is the inner XCM format and is version-sensitive. Messages are typically passed using the outer
/// XCM format, known as `VersionedXcm`.
#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug)]
pub enum Xcm {
/// Withdraw asset(s) (`assets`) from the ownership of `origin` and place them into `holding`. Execute the
/// orders (`effects`).
///
/// - `assets`: The asset(s) to be withdrawn into holding.
/// - `effects`: The order(s) to execute on the holding account.
///
/// Kind: *Instruction*.
///
/// Errors:
WithdrawAsset { assets: Vec<MultiAsset>, effects: Vec<Order> },

/// Asset(s) (`assets`) have been received into the ownership of this system on the `origin` system.
///
/// Some orders are given (`effects`) which should be executed once the corresponding derivative assets have
/// been placed into `holding`.
///
/// - `assets`: The asset(s) that are minted into holding.
/// - `effects`: The order(s) to execute on the holding account.
///
/// Safety: `origin` must be trusted to have received and be storing `assets` such that they may later be
/// withdrawn should this system send a corresponding message.
///
/// Kind: *Trusted Indication*.
///
/// Errors:
ReserveAssetDeposit { assets: Vec<MultiAsset>, effects: Vec<Order> },

/// Asset(s) (`assets`) have been destroyed on the `origin` system and equivalent assets should be
/// created on this system.
///
/// Some orders are given (`effects`) which should be executed once the corresponding derivative assets have
/// been placed into `holding`.
///
/// - `assets`: The asset(s) that are minted into holding.
/// - `effects`: The order(s) to execute on the holding account.
///
/// Safety: `origin` must be trusted to have irrevocably destroyed the `assets` prior as a consequence of
/// sending this message.
///
/// Kind: *Trusted Indication*.
///
/// Errors:
TeleportAsset { assets: Vec<MultiAsset>, effects: Vec<Order> },

/// Indication of the contents of the holding account corresponding to the `QueryHolding` order of `query_id`.
///
/// - `query_id`: The identifier of the query that resulted in this message being sent.
/// - `assets`: The message content.
///
/// Safety: No concerns.
///
/// Kind: *Information*.
///
/// Errors:
Balances { #[codec(compact)] query_id: u64, assets: Vec<MultiAsset> },

/// Apply the encoded transaction `call`, whose dispatch-origin should be `origin` as expressed by the kind
/// of origin `origin_type`.
///
/// - `origin_type`: The means of expressing the message origin as a dispatch origin.
/// - `call`: The encoded transaction to be applied.
///
/// Safety: No concerns.
///
/// Kind: *Instruction*.
///
/// Errors:
Transact { origin_type: OriginKind, call: Vec<u8> },

/// Relay an inner message (`inner`) to a locally reachable destination ID `dest`.
///
/// The message sent to the destination will be wrapped into a `RelayedFrom` message, with the
/// `superorigin` being this location.
///
/// - `dest: MultiLocation`: The location of the to be relayed into. This may never contain `Parent`, and
/// it must be immediately reachable from the interpreting context.
/// - `inner: VersionedXcm`: The message to be wrapped and relayed.
///
/// Safety: No concerns.
///
/// Kind: *Instruction*.
///
/// Errors:
RelayTo { dest: MultiLocation, inner: Box<VersionedXcm> },

/// A message (`inner`) was sent to `origin` from `superorigin` with the intention of being relayed.
///
/// - `superorigin`: The location of the `inner` message origin, **relative to `origin`**.
/// - `inner`: The message sent by the super origin.
///
/// Safety: `superorigin` must express a sub-consensus only; it may *NEVER* contain a `Parent` junction.
///
/// Kind: *Trusted Indication*.
///
/// Errors:
RelayedFrom { superorigin: MultiLocation, inner: Box<VersionedXcm> },
}

impl From<Xcm> for VersionedXcm {
fn from(x: Xcm) -> Self {
VersionedXcm::V0(x)
}
}

impl TryFrom<VersionedXcm> for Xcm {
type Error = ();
fn try_from(x: VersionedXcm) -> result::Result<Self, ()> {
match x {
VersionedXcm::V0(x) => Ok(x),
}
}
}
Loading

0 comments on commit ec55686

Please sign in to comment.