mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 19:51:05 +00:00
Add the XCM primitives crate. (#1760)
Co-authored-by: Gavin Wood <gavin@parity.io> Co-authored-by: Gavin Wood <gavin@parity.io>
This commit is contained in:
Generated
+11
-4
@@ -4340,9 +4340,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parity-scale-codec"
|
name = "parity-scale-codec"
|
||||||
version = "1.3.4"
|
version = "1.3.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "34d38aeaffc032ec69faa476b3caaca8d4dd7f3f798137ff30359e5c7869ceb6"
|
checksum = "7c740e5fbcb6847058b40ac7e5574766c6388f585e184d769910fe0d3a2ca861"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec 0.5.1",
|
"arrayvec 0.5.1",
|
||||||
"bitvec",
|
"bitvec",
|
||||||
@@ -4353,9 +4353,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parity-scale-codec-derive"
|
name = "parity-scale-codec-derive"
|
||||||
version = "1.2.1"
|
version = "1.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cd20ff7e0399b274a5f5bb37b712fccb5b3a64b9128200d1c3cc40fe709cb073"
|
checksum = "198db82bb1c18fc00176004462dd809b2a6d851669550aa17af6dacd21ae0c14"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2 1.0.18",
|
"proc-macro2 1.0.18",
|
||||||
@@ -10016,6 +10016,13 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "xcm"
|
||||||
|
version = "0.8.22"
|
||||||
|
dependencies = [
|
||||||
|
"parity-scale-codec",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yamux"
|
name = "yamux"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ members = [
|
|||||||
"statement-table",
|
"statement-table",
|
||||||
"service",
|
"service",
|
||||||
"validation",
|
"validation",
|
||||||
|
"xcm",
|
||||||
|
|
||||||
"node/collation-generation",
|
"node/collation-generation",
|
||||||
"node/core/av-store",
|
"node/core/av-store",
|
||||||
|
|||||||
@@ -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" ] }
|
||||||
@@ -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),
|
||||||
|
}
|
||||||
@@ -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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
// 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/>.
|
||||||
|
|
||||||
|
//! Cross-Consensus Message format data structures.
|
||||||
|
|
||||||
|
use core::{result, convert::TryFrom};
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
|
use codec::{self, Encode, Decode};
|
||||||
|
use super::{MultiLocation, VersionedMultiAsset};
|
||||||
|
|
||||||
|
/// A general identifier for an instance of a non-fungible asset class.
|
||||||
|
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug)]
|
||||||
|
pub enum AssetInstance {
|
||||||
|
/// Undefined - used if the NFA class has only one instance.
|
||||||
|
Undefined,
|
||||||
|
|
||||||
|
/// A compact index. Technically this could be greater than u128, but this implementation supports only
|
||||||
|
/// values up to `2**128 - 1`.
|
||||||
|
Index { #[codec(compact)] id: u128 },
|
||||||
|
|
||||||
|
/// A 4-byte fixed-length datum.
|
||||||
|
Array4([u8; 4]),
|
||||||
|
|
||||||
|
/// An 8-byte fixed-length datum.
|
||||||
|
Array8([u8; 8]),
|
||||||
|
|
||||||
|
/// A 16-byte fixed-length datum.
|
||||||
|
Array16([u8; 16]),
|
||||||
|
|
||||||
|
/// A 32-byte fixed-length datum.
|
||||||
|
Array32([u8; 32]),
|
||||||
|
|
||||||
|
/// An arbitrary piece of data. Use only when necessary.
|
||||||
|
Blob(Vec<u8>),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A single general identifier for an asset.
|
||||||
|
///
|
||||||
|
/// Represents both fungible and non-fungible assets. May only be used to represent a single asset class.
|
||||||
|
///
|
||||||
|
/// Wildcards may or may not be allowed by the interpreting context.
|
||||||
|
///
|
||||||
|
/// Assets classes may be identified in one of two ways: either an abstract identifier or a concrete identifier.
|
||||||
|
/// Implementations may support only one of these. A single asset may be referenced from multiple asset identifiers,
|
||||||
|
/// though will tend to have only a single *preferred* identifier.
|
||||||
|
///
|
||||||
|
/// ### Abstract identifiers
|
||||||
|
///
|
||||||
|
/// Abstract identifiers are absolute identifiers that represent a notional asset which can exist within multiple
|
||||||
|
/// consensus systems. These tend to be simpler to deal with since their broad meaning is unchanged regardless stay
|
||||||
|
/// of the consensus system in which it is interpreted.
|
||||||
|
///
|
||||||
|
/// However, in the attempt to provide uniformity across consensus systems, they may conflate different instantiations
|
||||||
|
/// of some notional asset (e.g. the reserve asset and a local reserve-backed derivative of it) under the same name,
|
||||||
|
/// leading to confusion. It also implies that one notional asset is accounted for locally in only one way. This may
|
||||||
|
/// not be the case, e.g. where there are multiple bridge instances each providing a bridged "BTC" token yet none
|
||||||
|
/// being fungible between the others.
|
||||||
|
///
|
||||||
|
/// Since they are meant to be absolute and universal, a global registry is needed to ensure that name collisions
|
||||||
|
/// do not occur.
|
||||||
|
///
|
||||||
|
/// An abstract identifier is represented as a simple variable-size byte string. As of writing, no global registry
|
||||||
|
/// exists and no proposals have been put forth for asset labeling.
|
||||||
|
///
|
||||||
|
/// ### Concrete identifiers
|
||||||
|
///
|
||||||
|
/// Concrete identifiers are *relative identifiers* that specifically identify a single asset through its location in
|
||||||
|
/// a consensus system relative to the context interpreting. Use of a `MultiLocation` ensures that similar but non
|
||||||
|
/// fungible variants of the same underlying asset can be properly distinguished, and obviates the need for any kind
|
||||||
|
/// of central registry.
|
||||||
|
///
|
||||||
|
/// The limitation is that the asset identifier cannot be trivially copied between consensus
|
||||||
|
/// systems and must instead be "re-anchored" whenever being moved to a new consensus system, using the two systems'
|
||||||
|
/// relative paths.
|
||||||
|
///
|
||||||
|
/// Throughout XCM, messages are authored such that *when interpreted from the receiver's point of view* they will
|
||||||
|
/// have the desired meaning/effect. This means that relative paths should always by constructed to be read from the
|
||||||
|
/// point of view of the receiving system, *which may be have a completely different meaning in the authoring system*.
|
||||||
|
///
|
||||||
|
/// Concrete identifiers are the preferred way of identifying an asset since they are entirely unambiguous.
|
||||||
|
///
|
||||||
|
/// A concrete identifier is represented by a `MultiLocation`. If a system has an unambiguous primary asset (such as
|
||||||
|
/// Bitcoin with BTC or Ethereum with ETH), then it will conventionally be identified as the chain itself. Alternative
|
||||||
|
/// and more specific ways of referring to an asset within a system include:
|
||||||
|
///
|
||||||
|
/// - `<chain>/PalletInstance(<id>)` for a Frame chain with a single-asset pallet instance (such as an instance of the
|
||||||
|
/// Balances pallet).
|
||||||
|
/// - `<chain>/PalletInstance(<id>)/GeneralIndex(<index>)` for a Frame chain with an indexed multi-asset pallet
|
||||||
|
/// instance (such as an instance of the Assets pallet).
|
||||||
|
/// - `<chain>/AccountId32` for an ERC-20-style single-asset smart-contract on a Frame-based contracts chain.
|
||||||
|
/// - `<chain>/AccountKey20` for an ERC-20-style single-asset smart-contract on an Ethereum-like chain.
|
||||||
|
///
|
||||||
|
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug)]
|
||||||
|
pub enum MultiAsset {
|
||||||
|
/// No assets. Rarely used.
|
||||||
|
None,
|
||||||
|
|
||||||
|
/// All assets. Typically used for the subset of assets to be used for an `Order`, and in that context means
|
||||||
|
/// "all assets currently in holding".
|
||||||
|
All,
|
||||||
|
|
||||||
|
/// All fungible assets. Typically used for the subset of assets to be used for an `Order`, and in that context
|
||||||
|
/// means "all fungible assets currently in holding".
|
||||||
|
AllFungible,
|
||||||
|
|
||||||
|
/// All non-fungible assets. Typically used for the subset of assets to be used for an `Order`, and in that
|
||||||
|
/// context means "all non-fungible assets currently in holding".
|
||||||
|
AllNonFungible,
|
||||||
|
|
||||||
|
/// All fungible assets of a given abstract asset `id`entifier.
|
||||||
|
AllAbstractFungible { id: Vec<u8> },
|
||||||
|
|
||||||
|
/// All non-fungible assets of a given abstract asset `class`.
|
||||||
|
AllAbstractNonFungible { class: Vec<u8> },
|
||||||
|
|
||||||
|
/// All fungible assets of a given concrete asset `id`entifier.
|
||||||
|
AllConcreteFungible { id: MultiLocation },
|
||||||
|
|
||||||
|
/// All non-fungible assets of a given concrete asset `class`.
|
||||||
|
AllConcreteNonFungible { class: MultiLocation },
|
||||||
|
|
||||||
|
/// Some specific `amount` of the fungible asset identified by an abstract `id`.
|
||||||
|
AbstractFungible { id: Vec<u8>, #[codec(compact)] amount: u128 },
|
||||||
|
|
||||||
|
/// Some specific `instance` of the non-fungible asset whose `class` is identified abstractly.
|
||||||
|
AbstractNonFungible { class: Vec<u8>, instance: AssetInstance },
|
||||||
|
|
||||||
|
/// Some specific `amount` of the fungible asset identified by an concrete `id`.
|
||||||
|
ConcreteFungible { id: MultiLocation, #[codec(compact)] amount: u128 },
|
||||||
|
|
||||||
|
/// Some specific `instance` of the non-fungible asset whose `class` is identified concretely.
|
||||||
|
ConcreteNonFungible { class: MultiLocation, instance: AssetInstance },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<MultiAsset> for VersionedMultiAsset {
|
||||||
|
fn from(x: MultiAsset) -> Self {
|
||||||
|
VersionedMultiAsset::V0(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<VersionedMultiAsset> for MultiAsset {
|
||||||
|
type Error = ();
|
||||||
|
fn try_from(x: VersionedMultiAsset) -> result::Result<Self, ()> {
|
||||||
|
match x {
|
||||||
|
VersionedMultiAsset::V0(x) => Ok(x),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,393 @@
|
|||||||
|
// 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/>.
|
||||||
|
|
||||||
|
//! Cross-Consensus Message format data structures.
|
||||||
|
|
||||||
|
use core::{result, mem, convert::TryFrom};
|
||||||
|
|
||||||
|
use codec::{self, Encode, Decode};
|
||||||
|
use super::Junction;
|
||||||
|
use crate::VersionedMultiLocation;
|
||||||
|
|
||||||
|
/// A relative path between state-bearing consensus systems.
|
||||||
|
///
|
||||||
|
/// A location in a consensus system is defined as an *isolatable state machine* held within global consensus. The
|
||||||
|
/// location in question need not have a sophisticated consensus algorithm of its own; a single account within
|
||||||
|
/// Ethereum, for example, could be considered a location.
|
||||||
|
///
|
||||||
|
/// A very-much non-exhaustive list of types of location include:
|
||||||
|
/// - A (normal, layer-1) block chain, e.g. the Bitcoin mainnet or a parachain.
|
||||||
|
/// - A layer-0 super-chain, e.g. the Polkadot Relay chain.
|
||||||
|
/// - A layer-2 smart contract, e.g. an ERC-20 on Ethereum.
|
||||||
|
/// - A logical functional component of a chain, e.g. a single instance of a pallet on a Frame-based Substrate chain.
|
||||||
|
/// - An account.
|
||||||
|
///
|
||||||
|
/// A `MultiLocation` is a *relative identifier*, meaning that it can only be used to define the relative path
|
||||||
|
/// between two locations, and cannot generally be used to refer to a location universally. It is comprised of a
|
||||||
|
/// number of *junctions*, each morphing the previous location, either diving down into one of its internal locations,
|
||||||
|
/// called a *sub-consensus*, or going up into its parent location. Correct `MultiLocation` values must have all
|
||||||
|
/// `Parent` junctions as a prefix to all *sub-consensus* junctions.
|
||||||
|
///
|
||||||
|
/// This specific `MultiLocation` implementation uses a Rust `enum` in order to make pattern matching easier.
|
||||||
|
///
|
||||||
|
/// The `MultiLocation` value of `Null` simply refers to the interpreting consensus system.
|
||||||
|
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug)]
|
||||||
|
pub enum MultiLocation {
|
||||||
|
/// The interpreting consensus system.
|
||||||
|
Null,
|
||||||
|
/// A relative path comprising one junction.
|
||||||
|
X1(Junction),
|
||||||
|
/// A relative path comprising two junctions.
|
||||||
|
X2(Junction, Junction),
|
||||||
|
/// A relative path comprising three junctions.
|
||||||
|
X3(Junction, Junction, Junction),
|
||||||
|
/// A relative path comprising four junctions.
|
||||||
|
X4(Junction, Junction, Junction, Junction),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Junction> for MultiLocation {
|
||||||
|
fn from(x: Junction) -> Self {
|
||||||
|
MultiLocation::X1(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<()> for MultiLocation {
|
||||||
|
fn from(_: ()) -> Self {
|
||||||
|
MultiLocation::Null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<(Junction,)> for MultiLocation {
|
||||||
|
fn from(x: (Junction,)) -> Self {
|
||||||
|
MultiLocation::X1(x.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<(Junction, Junction)> for MultiLocation {
|
||||||
|
fn from(x: (Junction, Junction)) -> Self {
|
||||||
|
MultiLocation::X2(x.0, x.1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<(Junction, Junction, Junction)> for MultiLocation {
|
||||||
|
fn from(x: (Junction, Junction, Junction)) -> Self {
|
||||||
|
MultiLocation::X3(x.0, x.1, x.2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<(Junction, Junction, Junction, Junction)> for MultiLocation {
|
||||||
|
fn from(x: (Junction, Junction, Junction, Junction)) -> Self {
|
||||||
|
MultiLocation::X4(x.0, x.1, x.2, x.3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<[Junction; 0]> for MultiLocation {
|
||||||
|
fn from(_: [Junction; 0]) -> Self {
|
||||||
|
MultiLocation::Null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<[Junction; 1]> for MultiLocation {
|
||||||
|
fn from(x: [Junction; 1]) -> Self {
|
||||||
|
let [x0] = x;
|
||||||
|
MultiLocation::X1(x0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<[Junction; 2]> for MultiLocation {
|
||||||
|
fn from(x: [Junction; 2]) -> Self {
|
||||||
|
let [x0, x1] = x;
|
||||||
|
MultiLocation::X2(x0, x1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<[Junction; 3]> for MultiLocation {
|
||||||
|
fn from(x: [Junction; 3]) -> Self {
|
||||||
|
let [x0, x1, x2] = x;
|
||||||
|
MultiLocation::X3(x0, x1, x2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<[Junction; 4]> for MultiLocation {
|
||||||
|
fn from(x: [Junction; 4]) -> Self {
|
||||||
|
let [x0, x1, x2, x3] = x;
|
||||||
|
MultiLocation::X4(x0, x1, x2, x3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MultiLocationIterator(MultiLocation);
|
||||||
|
impl Iterator for MultiLocationIterator {
|
||||||
|
type Item = Junction;
|
||||||
|
fn next(&mut self) -> Option<Junction> {
|
||||||
|
self.0.take_first()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MultiLocationReverseIterator(MultiLocation);
|
||||||
|
impl Iterator for MultiLocationReverseIterator {
|
||||||
|
type Item = Junction;
|
||||||
|
fn next(&mut self) -> Option<Junction> {
|
||||||
|
self.0.take_last()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MultiLocationRefIterator<'a>(&'a MultiLocation, usize);
|
||||||
|
impl<'a> Iterator for MultiLocationRefIterator<'a> {
|
||||||
|
type Item = &'a Junction;
|
||||||
|
fn next(&mut self) -> Option<&'a Junction> {
|
||||||
|
let result = self.0.at(self.1);
|
||||||
|
self.1 += 1;
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MultiLocationReverseRefIterator<'a>(&'a MultiLocation, usize);
|
||||||
|
impl<'a> Iterator for MultiLocationReverseRefIterator<'a> {
|
||||||
|
type Item = &'a Junction;
|
||||||
|
fn next(&mut self) -> Option<&'a Junction> {
|
||||||
|
self.1 += 1;
|
||||||
|
self.0.at(self.0.len().checked_sub(self.1)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MultiLocation {
|
||||||
|
/// Returns first junction, or `None` if the location is empty.
|
||||||
|
pub fn first(&self) -> Option<&Junction> {
|
||||||
|
match &self {
|
||||||
|
MultiLocation::Null => None,
|
||||||
|
MultiLocation::X1(ref a) => Some(a),
|
||||||
|
MultiLocation::X2(ref a, ..) => Some(a),
|
||||||
|
MultiLocation::X3(ref a, ..) => Some(a),
|
||||||
|
MultiLocation::X4(ref a, ..) => Some(a),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns last junction, or `None` if the location is empty.
|
||||||
|
pub fn last(&self) -> Option<&Junction> {
|
||||||
|
match &self {
|
||||||
|
MultiLocation::Null => None,
|
||||||
|
MultiLocation::X1(ref a) => Some(a),
|
||||||
|
MultiLocation::X2(.., ref a) => Some(a),
|
||||||
|
MultiLocation::X3(.., ref a) => Some(a),
|
||||||
|
MultiLocation::X4(.., ref a) => Some(a),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Splits off the first junction, returning the remaining suffix (first item in tuple) and the first element
|
||||||
|
/// (second item in tuple) or `None` if it was empty.
|
||||||
|
pub fn split_first(self) -> (MultiLocation, Option<Junction>) {
|
||||||
|
match self {
|
||||||
|
MultiLocation::Null => (MultiLocation::Null, None),
|
||||||
|
MultiLocation::X1(a) => (MultiLocation::Null, Some(a)),
|
||||||
|
MultiLocation::X2(a, b) => (MultiLocation::X1(b), Some(a)),
|
||||||
|
MultiLocation::X3(a, b, c) => (MultiLocation::X2(b, c), Some(a)),
|
||||||
|
MultiLocation::X4(a, b, c ,d) => (MultiLocation::X3(b, c, d), Some(a)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Splits off the last junction, returning the remaining prefix (first item in tuple) and the last element
|
||||||
|
/// (second item in tuple) or `None` if it was empty.
|
||||||
|
pub fn split_last(self) -> (MultiLocation, Option<Junction>) {
|
||||||
|
match self {
|
||||||
|
MultiLocation::Null => (MultiLocation::Null, None),
|
||||||
|
MultiLocation::X1(a) => (MultiLocation::Null, Some(a)),
|
||||||
|
MultiLocation::X2(a, b) => (MultiLocation::X1(a), Some(b)),
|
||||||
|
MultiLocation::X3(a, b, c) => (MultiLocation::X2(a, b), Some(c)),
|
||||||
|
MultiLocation::X4(a, b, c ,d) => (MultiLocation::X3(a, b, c), Some(d)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Removes the first element from `self`, returning it (or `None` if it was empty).
|
||||||
|
pub fn take_first(&mut self) -> Option<Junction> {
|
||||||
|
let mut d = MultiLocation::Null;
|
||||||
|
mem::swap(&mut *self, &mut d);
|
||||||
|
let (tail, head) = d.split_first();
|
||||||
|
*self = tail;
|
||||||
|
head
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Removes the last element from `self`, returning it (or `None` if it was empty).
|
||||||
|
pub fn take_last(&mut self) -> Option<Junction> {
|
||||||
|
let mut d = MultiLocation::Null;
|
||||||
|
mem::swap(&mut *self, &mut d);
|
||||||
|
let (head, tail) = d.split_last();
|
||||||
|
*self = head;
|
||||||
|
tail
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Consumes `self` and returns a `MultiLocation` suffixed with `new`, or an `Err` with the original value of
|
||||||
|
/// `self` in case of overflow.
|
||||||
|
pub fn pushed_with(self, new: Junction) -> result::Result<Self, Self> {
|
||||||
|
Ok(match self {
|
||||||
|
MultiLocation::Null => MultiLocation::X1(new),
|
||||||
|
MultiLocation::X1(a) => MultiLocation::X2(a, new),
|
||||||
|
MultiLocation::X2(a, b) => MultiLocation::X3(a, b, new),
|
||||||
|
MultiLocation::X3(a, b, c) => MultiLocation::X4(a, b, c, new),
|
||||||
|
s => Err(s)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Consumes `self` and returns a `MultiLocation` prefixed with `new`, or an `Err` with the original value of
|
||||||
|
/// `self` in case of overflow.
|
||||||
|
pub fn pushed_front_with(self, new: Junction) -> result::Result<Self, Self> {
|
||||||
|
Ok(match self {
|
||||||
|
MultiLocation::Null => MultiLocation::X1(new),
|
||||||
|
MultiLocation::X1(a) => MultiLocation::X2(new, a),
|
||||||
|
MultiLocation::X2(a, b) => MultiLocation::X3(new, a, b),
|
||||||
|
MultiLocation::X3(a, b, c) => MultiLocation::X4(new, a, b, c),
|
||||||
|
s => Err(s)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the number of junctions in `self`.
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
match &self {
|
||||||
|
MultiLocation::Null => 0,
|
||||||
|
MultiLocation::X1(..) => 1,
|
||||||
|
MultiLocation::X2(..) => 2,
|
||||||
|
MultiLocation::X3(..) => 3,
|
||||||
|
MultiLocation::X4(..) => 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the junction at index `i`, or `None` if the location doesn't contain that many elements.
|
||||||
|
pub fn at(&self, i: usize) -> Option<&Junction> {
|
||||||
|
Some(match (i, &self) {
|
||||||
|
(0, MultiLocation::X1(ref a)) => a,
|
||||||
|
(0, MultiLocation::X2(ref a, ..)) => a,
|
||||||
|
(0, MultiLocation::X3(ref a, ..)) => a,
|
||||||
|
(0, MultiLocation::X4(ref a, ..)) => a,
|
||||||
|
(1, MultiLocation::X2(_, ref a)) => a,
|
||||||
|
(1, MultiLocation::X3(_, ref a, ..)) => a,
|
||||||
|
(1, MultiLocation::X4(_, ref a, ..)) => a,
|
||||||
|
(2, MultiLocation::X3(_, _, ref a)) => a,
|
||||||
|
(2, MultiLocation::X4(_, _, ref a, ..)) => a,
|
||||||
|
(3, MultiLocation::X4(_, _, _, ref a)) => a,
|
||||||
|
_ => return None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a mutable reference to the junction at index `i`, or `None` if the location doesn't contain that many
|
||||||
|
/// elements.
|
||||||
|
pub fn at_mut(&mut self, i: usize) -> Option<&mut Junction> {
|
||||||
|
Some(match (i, self) {
|
||||||
|
(0, MultiLocation::X1(ref mut a)) => a,
|
||||||
|
(0, MultiLocation::X2(ref mut a, ..)) => a,
|
||||||
|
(0, MultiLocation::X3(ref mut a, ..)) => a,
|
||||||
|
(0, MultiLocation::X4(ref mut a, ..)) => a,
|
||||||
|
(1, MultiLocation::X2(_, ref mut a)) => a,
|
||||||
|
(1, MultiLocation::X3(_, ref mut a, ..)) => a,
|
||||||
|
(1, MultiLocation::X4(_, ref mut a, ..)) => a,
|
||||||
|
(2, MultiLocation::X3(_, _, ref mut a)) => a,
|
||||||
|
(2, MultiLocation::X4(_, _, ref mut a, ..)) => a,
|
||||||
|
(3, MultiLocation::X4(_, _, _, ref mut a)) => a,
|
||||||
|
_ => return None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a reference iterator over the junctions.
|
||||||
|
pub fn iter(&self) -> MultiLocationRefIterator {
|
||||||
|
MultiLocationRefIterator(&self, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a reference iterator over the junctions in reverse.
|
||||||
|
pub fn iter_rev(&self) -> MultiLocationReverseRefIterator {
|
||||||
|
MultiLocationReverseRefIterator(&self, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Consumes `self` and returns an iterator over the junctions.
|
||||||
|
pub fn into_iter(self) -> MultiLocationIterator {
|
||||||
|
MultiLocationIterator(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Consumes `self` and returns an iterator over the junctions in reverse.
|
||||||
|
pub fn into_iter_rev(self) -> MultiLocationReverseIterator {
|
||||||
|
MultiLocationReverseIterator(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mutates `self`, suffixing it with `new`. Returns `Err` in case of overflow.
|
||||||
|
pub fn push(&mut self, new: Junction) -> result::Result<(), ()> {
|
||||||
|
let mut n = MultiLocation::Null;
|
||||||
|
mem::swap(&mut *self, &mut n);
|
||||||
|
match n.pushed_with(new) {
|
||||||
|
Ok(result) => { *self = result; Ok(()) }
|
||||||
|
Err(old) => { *self = old; Err(()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Mutates `self`, prefixing it with `new`. Returns `Err` in case of overflow.
|
||||||
|
pub fn push_front(&mut self, new: Junction) -> result::Result<(), ()> {
|
||||||
|
let mut n = MultiLocation::Null;
|
||||||
|
mem::swap(&mut *self, &mut n);
|
||||||
|
match n.pushed_front_with(new) {
|
||||||
|
Ok(result) => { *self = result; Ok(()) }
|
||||||
|
Err(old) => { *self = old; Err(()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the number of `Parent` junctions at the beginning of `self`.
|
||||||
|
pub fn parent_count(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
MultiLocation::X4(Junction::Parent, Junction::Parent, Junction::Parent, Junction::Parent) => 4,
|
||||||
|
MultiLocation::X4(Junction::Parent, Junction::Parent, Junction::Parent, ..) => 3,
|
||||||
|
MultiLocation::X3(Junction::Parent, Junction::Parent, Junction::Parent) => 3,
|
||||||
|
MultiLocation::X4(Junction::Parent, Junction::Parent, ..) => 2,
|
||||||
|
MultiLocation::X3(Junction::Parent, Junction::Parent, ..) => 2,
|
||||||
|
MultiLocation::X2(Junction::Parent, Junction::Parent) => 2,
|
||||||
|
MultiLocation::X4(Junction::Parent, ..) => 1,
|
||||||
|
MultiLocation::X3(Junction::Parent, ..) => 1,
|
||||||
|
MultiLocation::X2(Junction::Parent, ..) => 1,
|
||||||
|
MultiLocation::X1(Junction::Parent) => 1,
|
||||||
|
_ => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mutate `self` so that it is prefixed with `prefix`. The correct normalised form is returned, removing any
|
||||||
|
/// internal `Parent`s.
|
||||||
|
///
|
||||||
|
/// Does not modify `self` and returns `Err` with `prefix` in case of overflow.
|
||||||
|
pub fn prepend_with(&mut self, prefix: MultiLocation) -> Result<(), MultiLocation> {
|
||||||
|
let self_parents = self.parent_count();
|
||||||
|
let prefix_rest = prefix.len() - prefix.parent_count();
|
||||||
|
let skipped = self_parents.min(prefix_rest);
|
||||||
|
if self.len() + prefix.len() - 2 * skipped > 4 {
|
||||||
|
return Err(prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut prefix = prefix;
|
||||||
|
while match (prefix.last(), self.first()) {
|
||||||
|
(Some(x), Some(Junction::Parent)) if x != &Junction::Parent => {
|
||||||
|
prefix.take_last();
|
||||||
|
self.take_first();
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
} {}
|
||||||
|
|
||||||
|
for j in prefix.into_iter_rev() {
|
||||||
|
self.push_front(j).expect("len + prefix minus 2*skipped is less than 4; qed");
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<MultiLocation> for VersionedMultiLocation {
|
||||||
|
fn from(x: MultiLocation) -> Self {
|
||||||
|
VersionedMultiLocation::V0(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<VersionedMultiLocation> for MultiLocation {
|
||||||
|
type Error = ();
|
||||||
|
fn try_from(x: VersionedMultiLocation) -> result::Result<Self, ()> {
|
||||||
|
match x {
|
||||||
|
VersionedMultiLocation::V0(x) => Ok(x),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
// 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 alloc::vec::Vec;
|
||||||
|
use codec::{self, Encode, Decode};
|
||||||
|
use super::{MultiAsset, MultiLocation};
|
||||||
|
|
||||||
|
/// An instruction to be executed on some or all of the assets in holding, used by asset-related XCM messages.
|
||||||
|
#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug)]
|
||||||
|
pub enum Order {
|
||||||
|
/// Do nothing. Not generally used.
|
||||||
|
Null,
|
||||||
|
|
||||||
|
/// Remove the asset(s) (`assets`) from holding and place equivalent assets under the ownership of `dest` within
|
||||||
|
/// this consensus system.
|
||||||
|
///
|
||||||
|
/// - `assets`: The asset(s) to remove from holding.
|
||||||
|
/// - `dest`: The new owner for the assets.
|
||||||
|
///
|
||||||
|
/// Errors:
|
||||||
|
DepositAsset { assets: Vec<MultiAsset>, dest: MultiLocation },
|
||||||
|
|
||||||
|
/// Remove the asset(s) (`assets`) from holding and place equivalent assets under the ownership of `dest` within
|
||||||
|
/// this consensus system.
|
||||||
|
///
|
||||||
|
/// Send an onward XCM message to `dest` of `ReserveAssetDeposit` with the
|
||||||
|
///
|
||||||
|
/// - `assets`: The asset(s) to remove from holding.
|
||||||
|
/// - `dest`: The new owner for the assets.
|
||||||
|
/// - `effects`: The orders that should be contained in the `ReserveAssetDeposit` which is sent onwards to
|
||||||
|
/// `dest.
|
||||||
|
///
|
||||||
|
/// Errors:
|
||||||
|
DepositReserveAsset { assets: Vec<MultiAsset>, dest: MultiLocation, effects: Vec<Order> },
|
||||||
|
|
||||||
|
/// Remove the asset(s) (`give`) from holding and replace them with alternative assets.
|
||||||
|
///
|
||||||
|
/// The minimum amount of assets to be received into holding for the order not to fail may be stated.
|
||||||
|
///
|
||||||
|
/// - `give`: The asset(s) to remove from holding.
|
||||||
|
/// - `receive`: The minimum amount of assets(s) which `give` should be exchanged for. The meaning of wildcards
|
||||||
|
/// is undefined and they should be not be used.
|
||||||
|
///
|
||||||
|
/// Errors:
|
||||||
|
ExchangeAsset { give: Vec<MultiAsset>, receive: Vec<MultiAsset> },
|
||||||
|
|
||||||
|
/// Remove the asset(s) (`assets`) from holding and send a `WithdrawAsset` XCM message to a reserve location.
|
||||||
|
///
|
||||||
|
/// - `assets`: The asset(s) to remove from holding.
|
||||||
|
/// - `reserve`: A valid location that acts as a reserve for all asset(s) in `assets`. The sovereign account
|
||||||
|
/// of this consensus system *on the reserve location* will have appropriate assets withdrawn and `effects` will
|
||||||
|
/// be executed on them. There will typically be only one valid location on any given asset/chain combination.
|
||||||
|
/// - `effects`: The orders to execute on the assets once withdrawn *on the reserve location*.
|
||||||
|
///
|
||||||
|
/// Errors:
|
||||||
|
InitiateReserveWithdraw { assets: Vec<MultiAsset>, reserve: MultiLocation, effects: Vec<Order> },
|
||||||
|
|
||||||
|
/// Remove the asset(s) (`assets`) from holding and send a `TeleportAsset` XCM message to a destination location.
|
||||||
|
///
|
||||||
|
/// - `assets`: The asset(s) to remove from holding.
|
||||||
|
/// - `destination`: A valid location that has a bi-lateral teleportation arrangement.
|
||||||
|
/// - `effects`: The orders to execute on the assets once arrived *on the destination location*.
|
||||||
|
///
|
||||||
|
/// Errors:
|
||||||
|
InitiateTeleport { assets: Vec<MultiAsset>, dest: MultiLocation, effects: Vec<Order> },
|
||||||
|
|
||||||
|
/// Send a `Balances` XCM message with the `assets` value equal to the holding contents, or a portion thereof.
|
||||||
|
///
|
||||||
|
/// - `query_id`: An identifier that will be replicated into the returned XCM message.
|
||||||
|
/// - `dest`: A valid destination for the returned XCM message. This may be limited to the current origin.
|
||||||
|
/// - `assets`: A filter for the assets that should be reported back. The assets reported back will be, asset-
|
||||||
|
/// wise, *the lesser of this value and the holding account*. No wildcards will be used when reporting assets
|
||||||
|
/// back.
|
||||||
|
///
|
||||||
|
/// Errors:
|
||||||
|
QueryHolding { #[codec(compact)] query_id: u64, dest: MultiLocation, assets: Vec<MultiAsset> },
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
// 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/>.
|
||||||
|
|
||||||
|
//! Cross-Consensus Message format data structures.
|
||||||
|
|
||||||
|
use core::result;
|
||||||
|
use codec::{Encode, Decode};
|
||||||
|
|
||||||
|
use super::{MultiLocation, Xcm};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, Ord, PartialOrd, Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
Undefined,
|
||||||
|
Unimplemented,
|
||||||
|
UnhandledXcmVersion,
|
||||||
|
UnhandledXcmMessage,
|
||||||
|
UnhandledEffect,
|
||||||
|
EscalationOfPrivilege,
|
||||||
|
UntrustedReserveLocation,
|
||||||
|
UntrustedTeleportLocation,
|
||||||
|
DestinationBufferOverflow,
|
||||||
|
CannotReachDestination,
|
||||||
|
MultiLocationFull,
|
||||||
|
FailedToDecode,
|
||||||
|
BadOrigin,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<()> for Error {
|
||||||
|
fn from(_: ()) -> Self {
|
||||||
|
Self::Undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Result = result::Result<(), Error>;
|
||||||
|
|
||||||
|
pub trait ExecuteXcm {
|
||||||
|
fn execute_xcm(origin: MultiLocation, msg: Xcm) -> Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExecuteXcm for () {
|
||||||
|
fn execute_xcm(_origin: MultiLocation, _msg: Xcm) -> Result {
|
||||||
|
Err(Error::Unimplemented)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait SendXcm {
|
||||||
|
fn send_xcm(dest: MultiLocation, msg: Xcm) -> Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SendXcm for () {
|
||||||
|
fn send_xcm(_dest: MultiLocation, _msg: Xcm) -> Result {
|
||||||
|
Err(Error::Unimplemented)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user