mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 19:51:02 +00:00
XCM v1 (#2815)
* MultiAsset TWO * Draft next MultiAsset API. * XCM core builds * XCM Executor builds * XCM Builder builds * API changes making their way throughout * Some TODOs * Further build fixes * Basic compile builds * First test fixed * All executor tests fixed * Typo * Optimize subsume_assets and add test * Optimize checked_sub * XCM Builder first test fixed * Fix builder tests * Fix doc test * fix some doc tests * spelling * named fields for AllOf * Update xcm/src/v0/multiasset.rs Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Update xcm/src/v0/multiasset.rs Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Update xcm/src/v0/multiasset.rs Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Update xcm/src/v0/multiasset.rs Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Reformat * Move to XCM version 1 * Spelling * warnings * Replace some more v0->v1s * warnings * format * Add max_assets param * building * test fixes * tests * another test * final test * tests * Rename Null -> Here * Introduce * More ergonomics * More ergonomics * test fix * test fixes * docs * BuyExecution includes * Fix XCM extrinsics * fmt * Make Vec<MultiAsset>/MultiAssets conversions safe * More MultiAssets conversion safety * spelling * fix doc test * Apply suggestions from code review Co-authored-by: Amar Singh <asinghchrony@protonmail.com> * Apply suggestions from code review Co-authored-by: Amar Singh <asinghchrony@protonmail.com> * fmt * Add v0, remove VersionedMultiAsset * Remove VersionedMultiLocation * Update xcm/src/v1/order.rs Co-authored-by: Amar Singh <asinghchrony@protonmail.com> * Update xcm/src/v1/mod.rs Co-authored-by: Amar Singh <asinghchrony@protonmail.com> * XCM v0 backwards compatibility * Full compatibility * fmt * Update xcm/pallet-xcm/src/lib.rs * Update xcm/src/v0/order.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * Tweaks to versioning system * Fixes * fmt * Update xcm/xcm-executor/src/assets.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * Update xcm/xcm-executor/src/assets.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * Grumbles * Update xcm/src/v1/multiasset.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * fmt * Update xcm/src/v1/multiasset.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * Update xcm/src/v1/multiasset.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * Fixes * Formatting Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> Co-authored-by: Amar Singh <asinghchrony@protonmail.com> Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
This commit is contained in:
@@ -0,0 +1,392 @@
|
||||
// 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 1 of the Cross-Consensus Message format data structures.
|
||||
|
||||
use super::v0::Xcm as Xcm0;
|
||||
use crate::DoubleEncoded;
|
||||
use alloc::vec::Vec;
|
||||
use core::{
|
||||
convert::{TryFrom, TryInto},
|
||||
fmt::Debug,
|
||||
result,
|
||||
};
|
||||
use derivative::Derivative;
|
||||
use parity_scale_codec::{self, Decode, Encode};
|
||||
|
||||
mod junction;
|
||||
pub mod multiasset;
|
||||
mod multilocation;
|
||||
mod order;
|
||||
mod traits; // the new multiasset.
|
||||
|
||||
pub use junction::{BodyId, BodyPart, Junction, NetworkId};
|
||||
pub use multiasset::{
|
||||
AssetId, AssetInstance, Fungibility, MultiAsset, MultiAssetFilter, MultiAssets,
|
||||
WildFungibility, WildMultiAsset,
|
||||
};
|
||||
pub use multilocation::MultiLocation;
|
||||
pub use order::Order;
|
||||
pub use traits::{Error, ExecuteXcm, Outcome, Result, SendXcm};
|
||||
|
||||
/// A prelude for importing all types typically used when interacting with XCM messages.
|
||||
pub mod prelude {
|
||||
pub use super::{
|
||||
junction::{
|
||||
BodyId, BodyPart,
|
||||
Junction::*,
|
||||
NetworkId::{self, *},
|
||||
},
|
||||
multiasset::{
|
||||
AssetId::{self, *},
|
||||
AssetInstance::{self, *},
|
||||
Fungibility::{self, *},
|
||||
MultiAsset,
|
||||
MultiAssetFilter::{self, *},
|
||||
MultiAssets,
|
||||
WildFungibility::{self, Fungible as WildFungible, NonFungible as WildNonFungible},
|
||||
WildMultiAsset::{self, *},
|
||||
},
|
||||
multilocation::MultiLocation::{self, *},
|
||||
opaque,
|
||||
order::Order::{self, *},
|
||||
traits::{Error as XcmError, ExecuteXcm, Outcome, Result as XcmResult, SendXcm},
|
||||
OriginKind, Response,
|
||||
Xcm::{self, *},
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: #2841 #XCMENCODE Efficient encodings for MultiAssets, 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 dispatch origin representation for the sender in the
|
||||
/// local runtime framework. For Cumulus/Frame chains this is the `Parachain` or `Relay` origin
|
||||
/// if coming from a chain, though there may be others if the `MultiLocation` XCM origin has a
|
||||
/// primary/native dispatch origin form.
|
||||
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,
|
||||
|
||||
/// Origin should be interpreted as an XCM native origin and the `MultiLocation` should be
|
||||
/// encoded directly in the dispatch origin unchanged. For Cumulus/Frame chains, this will be
|
||||
/// the `pallet_xcm::Origin::Xcm` type.
|
||||
Xcm,
|
||||
}
|
||||
|
||||
/// Response data to a query.
|
||||
#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug)]
|
||||
pub enum Response {
|
||||
/// Some assets.
|
||||
Assets(MultiAssets),
|
||||
}
|
||||
|
||||
/// 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(Derivative, Encode, Decode)]
|
||||
#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))]
|
||||
#[codec(encode_bound())]
|
||||
#[codec(decode_bound())]
|
||||
pub enum Xcm<Call> {
|
||||
/// 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 register.
|
||||
///
|
||||
/// Kind: *Instruction*.
|
||||
///
|
||||
/// Errors:
|
||||
#[codec(index = 0)]
|
||||
WithdrawAsset { assets: MultiAssets, effects: Vec<Order<Call>> },
|
||||
|
||||
/// 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 register.
|
||||
///
|
||||
/// 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:
|
||||
#[codec(index = 1)]
|
||||
ReserveAssetDeposited { assets: MultiAssets, effects: Vec<Order<Call>> },
|
||||
|
||||
/// 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 the Holding Register.
|
||||
///
|
||||
/// - `assets`: The asset(s) that are minted into the Holding Register.
|
||||
/// - `effects`: The order(s) to execute on the Holding Register.
|
||||
///
|
||||
/// Safety: `origin` must be trusted to have irrevocably destroyed the corresponding `assets` prior as a consequence
|
||||
/// of sending this message.
|
||||
///
|
||||
/// Kind: *Trusted Indication*.
|
||||
///
|
||||
/// Errors:
|
||||
#[codec(index = 2)]
|
||||
ReceiveTeleportedAsset { assets: MultiAssets, effects: Vec<Order<Call>> },
|
||||
|
||||
/// Indication of the contents of the holding register 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:
|
||||
#[codec(index = 3)]
|
||||
QueryResponse {
|
||||
#[codec(compact)]
|
||||
query_id: u64,
|
||||
response: Response,
|
||||
},
|
||||
|
||||
/// Withdraw asset(s) (`assets`) from the ownership of `origin` and place equivalent assets under the
|
||||
/// ownership of `beneficiary`.
|
||||
///
|
||||
/// - `assets`: The asset(s) to be withdrawn.
|
||||
/// - `beneficiary`: The new owner for the assets.
|
||||
///
|
||||
/// Safety: No concerns.
|
||||
///
|
||||
/// Kind: *Instruction*.
|
||||
///
|
||||
/// Errors:
|
||||
#[codec(index = 4)]
|
||||
TransferAsset { assets: MultiAssets, beneficiary: MultiLocation },
|
||||
|
||||
/// Withdraw asset(s) (`assets`) from the ownership of `origin` and place equivalent assets under the
|
||||
/// ownership of `dest` within this consensus system (i.e. its sovereign account).
|
||||
///
|
||||
/// Send an onward XCM message to `dest` of `ReserveAssetDeposited` with the given `effects`.
|
||||
///
|
||||
/// - `assets`: The asset(s) to be withdrawn.
|
||||
/// - `dest`: The location whose sovereign account will own the assets and thus the effective beneficiary for the
|
||||
/// assets and the notification target for the reserve asset deposit message.
|
||||
/// - `effects`: The orders that should be contained in the `ReserveAssetDeposited` which is sent onwards to
|
||||
/// `dest`.
|
||||
///
|
||||
/// Safety: No concerns.
|
||||
///
|
||||
/// Kind: *Instruction*.
|
||||
///
|
||||
/// Errors:
|
||||
#[codec(index = 5)]
|
||||
TransferReserveAsset { assets: MultiAssets, dest: MultiLocation, effects: Vec<Order<()>> },
|
||||
|
||||
/// 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.
|
||||
/// - `max_weight`: The weight of `call`; this should be at least the chain's calculated weight and will
|
||||
/// be used in the weight determination arithmetic.
|
||||
/// - `call`: The encoded transaction to be applied.
|
||||
///
|
||||
/// Safety: No concerns.
|
||||
///
|
||||
/// Kind: *Instruction*.
|
||||
///
|
||||
/// Errors:
|
||||
#[codec(index = 6)]
|
||||
Transact { origin_type: OriginKind, require_weight_at_most: u64, call: DoubleEncoded<Call> },
|
||||
|
||||
/// A message to notify about a new incoming HRMP channel. This message is meant to be sent by the
|
||||
/// relay-chain to a para.
|
||||
///
|
||||
/// - `sender`: The sender in the to-be opened channel. Also, the initiator of the channel opening.
|
||||
/// - `max_message_size`: The maximum size of a message proposed by the sender.
|
||||
/// - `max_capacity`: The maximum number of messages that can be queued in the channel.
|
||||
///
|
||||
/// Safety: The message should originate directly from the relay-chain.
|
||||
///
|
||||
/// Kind: *System Notification*
|
||||
#[codec(index = 7)]
|
||||
HrmpNewChannelOpenRequest {
|
||||
#[codec(compact)]
|
||||
sender: u32,
|
||||
#[codec(compact)]
|
||||
max_message_size: u32,
|
||||
#[codec(compact)]
|
||||
max_capacity: u32,
|
||||
},
|
||||
|
||||
/// A message to notify about that a previously sent open channel request has been accepted by
|
||||
/// the recipient. That means that the channel will be opened during the next relay-chain session
|
||||
/// change. This message is meant to be sent by the relay-chain to a para.
|
||||
///
|
||||
/// Safety: The message should originate directly from the relay-chain.
|
||||
///
|
||||
/// Kind: *System Notification*
|
||||
///
|
||||
/// Errors:
|
||||
#[codec(index = 8)]
|
||||
HrmpChannelAccepted {
|
||||
#[codec(compact)]
|
||||
recipient: u32,
|
||||
},
|
||||
|
||||
/// A message to notify that the other party in an open channel decided to close it. In particular,
|
||||
/// `initiator` is going to close the channel opened from `sender` to the `recipient`. The close
|
||||
/// will be enacted at the next relay-chain session change. This message is meant to be sent by
|
||||
/// the relay-chain to a para.
|
||||
///
|
||||
/// Safety: The message should originate directly from the relay-chain.
|
||||
///
|
||||
/// Kind: *System Notification*
|
||||
///
|
||||
/// Errors:
|
||||
#[codec(index = 9)]
|
||||
HrmpChannelClosing {
|
||||
#[codec(compact)]
|
||||
initiator: u32,
|
||||
#[codec(compact)]
|
||||
sender: u32,
|
||||
#[codec(compact)]
|
||||
recipient: u32,
|
||||
},
|
||||
|
||||
/// A message to indicate that the embedded XCM is actually arriving on behalf of some consensus
|
||||
/// location within the origin.
|
||||
///
|
||||
/// Safety: `who` must be an interior location of the context. This basically means that no `Parent`
|
||||
/// junctions are allowed in it. This should be verified at the time of XCM execution.
|
||||
///
|
||||
/// Kind: *Instruction*
|
||||
///
|
||||
/// Errors:
|
||||
#[codec(index = 10)]
|
||||
RelayedFrom { who: MultiLocation, message: alloc::boxed::Box<Xcm<Call>> },
|
||||
}
|
||||
|
||||
impl<Call> Xcm<Call> {
|
||||
pub fn into<C>(self) -> Xcm<C> {
|
||||
Xcm::from(self)
|
||||
}
|
||||
pub fn from<C>(xcm: Xcm<C>) -> Self {
|
||||
use Xcm::*;
|
||||
match xcm {
|
||||
WithdrawAsset { assets, effects } =>
|
||||
WithdrawAsset { assets, effects: effects.into_iter().map(Order::into).collect() },
|
||||
ReserveAssetDeposited { assets, effects } => ReserveAssetDeposited {
|
||||
assets,
|
||||
effects: effects.into_iter().map(Order::into).collect(),
|
||||
},
|
||||
ReceiveTeleportedAsset { assets, effects } => ReceiveTeleportedAsset {
|
||||
assets,
|
||||
effects: effects.into_iter().map(Order::into).collect(),
|
||||
},
|
||||
QueryResponse { query_id: u64, response } => QueryResponse { query_id: u64, response },
|
||||
TransferAsset { assets, beneficiary } => TransferAsset { assets, beneficiary },
|
||||
TransferReserveAsset { assets, dest, effects } =>
|
||||
TransferReserveAsset { assets, dest, effects },
|
||||
HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity } =>
|
||||
HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity },
|
||||
HrmpChannelAccepted { recipient } => HrmpChannelAccepted { recipient },
|
||||
HrmpChannelClosing { initiator, sender, recipient } =>
|
||||
HrmpChannelClosing { initiator, sender, recipient },
|
||||
Transact { origin_type, require_weight_at_most, call } =>
|
||||
Transact { origin_type, require_weight_at_most, call: call.into() },
|
||||
RelayedFrom { who, message } =>
|
||||
RelayedFrom { who, message: alloc::boxed::Box::new((*message).into()) },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod opaque {
|
||||
/// The basic concrete type of `generic::Xcm`, which doesn't make any assumptions about the format of a
|
||||
/// call other than it is pre-encoded.
|
||||
pub type Xcm = super::Xcm<()>;
|
||||
|
||||
pub use super::order::opaque::*;
|
||||
}
|
||||
|
||||
impl<Call> TryFrom<Xcm0<Call>> for Xcm<Call> {
|
||||
type Error = ();
|
||||
fn try_from(old: Xcm0<Call>) -> result::Result<Xcm<Call>, ()> {
|
||||
use Xcm::*;
|
||||
Ok(match old {
|
||||
Xcm0::WithdrawAsset { assets, effects } => WithdrawAsset {
|
||||
assets: assets.try_into()?,
|
||||
effects: effects
|
||||
.into_iter()
|
||||
.map(Order::try_from)
|
||||
.collect::<result::Result<_, _>>()?,
|
||||
},
|
||||
Xcm0::ReserveAssetDeposit { assets, effects } => ReserveAssetDeposited {
|
||||
assets: assets.try_into()?,
|
||||
effects: effects
|
||||
.into_iter()
|
||||
.map(Order::try_from)
|
||||
.collect::<result::Result<_, _>>()?,
|
||||
},
|
||||
Xcm0::TeleportAsset { assets, effects } => ReceiveTeleportedAsset {
|
||||
assets: assets.try_into()?,
|
||||
effects: effects
|
||||
.into_iter()
|
||||
.map(Order::try_from)
|
||||
.collect::<result::Result<_, _>>()?,
|
||||
},
|
||||
Xcm0::QueryResponse { query_id: u64, response } =>
|
||||
QueryResponse { query_id: u64, response },
|
||||
Xcm0::TransferAsset { assets, dest } =>
|
||||
TransferAsset { assets: assets.try_into()?, beneficiary: dest.into() },
|
||||
Xcm0::TransferReserveAsset { assets, dest, effects } => TransferReserveAsset {
|
||||
assets: assets.try_into()?,
|
||||
dest: dest.into(),
|
||||
effects: effects
|
||||
.into_iter()
|
||||
.map(Order::try_from)
|
||||
.collect::<result::Result<_, _>>()?,
|
||||
},
|
||||
Xcm0::HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity } =>
|
||||
HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity },
|
||||
Xcm0::HrmpChannelAccepted { recipient } => HrmpChannelAccepted { recipient },
|
||||
Xcm0::HrmpChannelClosing { initiator, sender, recipient } =>
|
||||
HrmpChannelClosing { initiator, sender, recipient },
|
||||
Xcm0::Transact { origin_type, require_weight_at_most, call } =>
|
||||
Transact { origin_type, require_weight_at_most, call: call.into() },
|
||||
Xcm0::RelayedFrom { who, message } => RelayedFrom {
|
||||
who: who.into(),
|
||||
message: alloc::boxed::Box::new((*message).try_into()?),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user