mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-25 11:45:47 +00:00
XCM docs and tests (#2948)
* WIP * add tests and docs for DoubleEncoded * reformat parent_count * add test for match_and_split * fix append_with docs and add tests * move Parachain enum variant to tuple * Fix stuff * add to append test * simplify match * formatting * format and extend doc comments (including examples) * fix typo * add some doc comments * add test for location inverter * Add more tests/docs * Fix build * matches fungibles * currency adapter. * add more tests for location inverter * extract max length magic number into constant * adapters. * Apply suggestions from code review * Final touches. * Repot and fixes * Remove last todo * Apply suggestions from code review Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Update xcm/xcm-builder/src/barriers.rs Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Update xcm/xcm-builder/src/barriers.rs Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Update xcm/xcm-builder/src/currency_adapter.rs Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Update xcm/xcm-builder/src/filter_asset_location.rs Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Update xcm/xcm-builder/src/matches_fungible.rs Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Update xcm/xcm-executor/src/traits/conversion.rs Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Update xcm/xcm-executor/src/traits/conversion.rs Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Update xcm/xcm-executor/src/traits/transact_asset.rs Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Update xcm/xcm-executor/src/traits/should_execute.rs Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> Co-authored-by: kianenigma <kian@parity.io> Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
This commit is contained in:
@@ -28,8 +28,8 @@ use xcm::v0::{
|
||||
|
||||
pub mod traits;
|
||||
use traits::{
|
||||
TransactAsset, ConvertOrigin, FilterAssetLocation, InvertLocation, WeightBounds, WeightTrader, ShouldExecute,
|
||||
OnResponse
|
||||
TransactAsset, ConvertOrigin, FilterAssetLocation, InvertLocation, WeightBounds, WeightTrader,
|
||||
ShouldExecute, OnResponse
|
||||
};
|
||||
|
||||
mod assets;
|
||||
@@ -37,6 +37,7 @@ pub use assets::{Assets, AssetId};
|
||||
mod config;
|
||||
pub use config::Config;
|
||||
|
||||
/// The XCM executor.
|
||||
pub struct XcmExecutor<Config>(PhantomData<Config>);
|
||||
|
||||
impl<Config: config::Config> ExecuteXcm<Config::Call> for XcmExecutor<Config> {
|
||||
|
||||
@@ -24,6 +24,9 @@ use xcm::v0::{MultiLocation, OriginKind};
|
||||
/// One of `convert`/`convert_ref` and `reverse`/`reverse_ref` MUST be implemented. If possible, implement
|
||||
/// `convert_ref`, since this will never result in a clone. Use `convert` when you definitely need to consume
|
||||
/// the source value.
|
||||
///
|
||||
/// Can be amalgamated into tuples. If any of the tuple elements converts into `Ok(_)` it short circuits. Otherwise returns
|
||||
/// the `Err(_)` of the last failing conversion (or `Err(())` for ref conversions).
|
||||
pub trait Convert<A: Clone, B: Clone> {
|
||||
/// Convert from `value` (of type `A`) into an equivalent value of type `B`, `Err` if not possible.
|
||||
fn convert(value: A) -> Result<B, A> { Self::convert_ref(&value).map_err(|_| value) }
|
||||
@@ -115,7 +118,49 @@ impl<T: Clone + Encode + Decode> Convert<Vec<u8>, T> for Decoded {
|
||||
fn reverse_ref(value: impl Borrow<T>) -> Result<Vec<u8>, ()> { Ok(value.borrow().encode()) }
|
||||
}
|
||||
|
||||
/// A convertor trait for origin types.
|
||||
///
|
||||
/// Can be amalgamated into tuples. If any of the tuple elements returns `Ok(_)`, it short circuits. Else, the `Err(_)`
|
||||
/// of the last tuple item is returned. Each intermediate `Err(_)` might return a different `origin` of type `Origin`
|
||||
/// which is passed to the next convert item.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use xcm::v0::{MultiLocation, Junction, OriginKind};
|
||||
/// # use xcm_executor::traits::ConvertOrigin;
|
||||
/// // A convertor that will bump the para id and pass it to the next one.
|
||||
/// struct BumpParaId;
|
||||
/// impl ConvertOrigin<u32> for BumpParaId {
|
||||
/// fn convert_origin(origin: MultiLocation, _: OriginKind) -> Result<u32, MultiLocation> {
|
||||
/// match origin {
|
||||
/// MultiLocation::X1(Junction::Parachain(id)) => {
|
||||
/// Err(MultiLocation::X1(Junction::Parachain(id + 1)))
|
||||
/// }
|
||||
/// _ => unreachable!()
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// struct AcceptPara7;
|
||||
/// impl ConvertOrigin<u32> for AcceptPara7 {
|
||||
/// fn convert_origin(origin: MultiLocation, _: OriginKind) -> Result<u32, MultiLocation> {
|
||||
/// match origin {
|
||||
/// MultiLocation::X1(Junction::Parachain(id)) if id == 7 => {
|
||||
/// Ok(7)
|
||||
/// }
|
||||
/// _ => Err(origin)
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// # fn main() {
|
||||
/// let origin = MultiLocation::X1(Junction::Parachain(6));
|
||||
/// assert!(
|
||||
/// <(BumpParaId, AcceptPara7) as ConvertOrigin<u32>>::convert_origin(origin, OriginKind::Native)
|
||||
/// .is_ok()
|
||||
/// );
|
||||
/// # }
|
||||
/// ```
|
||||
pub trait ConvertOrigin<Origin> {
|
||||
/// Attempt to convert `origin` to the generic `Origin` whilst consuming it.
|
||||
fn convert_origin(origin: MultiLocation, kind: OriginKind) -> Result<Origin, MultiLocation>;
|
||||
}
|
||||
|
||||
@@ -123,14 +168,17 @@ pub trait ConvertOrigin<Origin> {
|
||||
impl<O> ConvertOrigin<O> for Tuple {
|
||||
fn convert_origin(origin: MultiLocation, kind: OriginKind) -> Result<O, MultiLocation> {
|
||||
for_tuples!( #(
|
||||
let origin = match Tuple::convert_origin(origin, kind) { Err(o) => o, r => return r };
|
||||
let origin = match Tuple::convert_origin(origin, kind) {
|
||||
Err(o) => o,
|
||||
r => return r
|
||||
};
|
||||
)* );
|
||||
Err(origin)
|
||||
}
|
||||
}
|
||||
|
||||
/// Means of inverting a location: given a location which describes a `target` interpreted from the `source`, this
|
||||
/// will provide the corresponding location which describes the `source`
|
||||
/// Means of inverting a location: given a location which describes a `target` interpreted from the
|
||||
/// `source`, this will provide the corresponding location which describes the `source`.
|
||||
pub trait InvertLocation {
|
||||
fn invert_location(l: &MultiLocation) -> MultiLocation;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
use xcm::v0::{MultiAsset, MultiLocation};
|
||||
|
||||
/// Filters assets/location pairs.
|
||||
///
|
||||
/// Can be amalgamated into tuples. If any item returns `true`, it short-circuits, else `false` is returned.
|
||||
pub trait FilterAssetLocation {
|
||||
/// A filter to distinguish between asset/location pairs.
|
||||
fn filter_asset_location(asset: &MultiAsset, origin: &MultiLocation) -> bool;
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright 2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot 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.
|
||||
|
||||
// Polkadot 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/>.
|
||||
|
||||
use xcm::v0::{MultiAsset, Error as XcmError};
|
||||
use sp_std::result;
|
||||
|
||||
/// Errors associated with [`MatchesFungibles`] operation.
|
||||
pub enum Error {
|
||||
/// Asset not found.
|
||||
AssetNotFound,
|
||||
/// `MultiLocation` to `AccountId` conversion failed.
|
||||
AccountIdConversionFailed,
|
||||
/// `u128` amount to currency `Balance` conversion failed.
|
||||
AmountToBalanceConversionFailed,
|
||||
/// `MultiLocation` to `AssetId` conversion failed.
|
||||
AssetIdConversionFailed,
|
||||
}
|
||||
|
||||
impl From<Error> for XcmError {
|
||||
fn from(e: Error) -> Self {
|
||||
use XcmError::FailedToTransactAsset;
|
||||
match e {
|
||||
Error::AssetNotFound => FailedToTransactAsset("AssetNotFound"),
|
||||
Error::AccountIdConversionFailed => FailedToTransactAsset("AccountIdConversionFailed"),
|
||||
Error::AmountToBalanceConversionFailed => FailedToTransactAsset("AmountToBalanceConversionFailed"),
|
||||
Error::AssetIdConversionFailed => FailedToTransactAsset("AssetIdConversionFailed"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait MatchesFungibles<AssetId, Balance> {
|
||||
fn matches_fungibles(a: &MultiAsset) -> result::Result<(AssetId, Balance), Error>;
|
||||
}
|
||||
|
||||
#[impl_trait_for_tuples::impl_for_tuples(30)]
|
||||
impl<
|
||||
AssetId: Clone,
|
||||
Balance: Clone,
|
||||
> MatchesFungibles<AssetId, Balance> for Tuple {
|
||||
fn matches_fungibles(a: &MultiAsset) -> result::Result<(AssetId, Balance), Error> {
|
||||
for_tuples!( #(
|
||||
match Tuple::matches_fungibles(a) { o @ Ok(_) => return o, _ => () }
|
||||
)* );
|
||||
Err(Error::AssetNotFound)
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,8 @@ mod filter_asset_location;
|
||||
pub use filter_asset_location::{FilterAssetLocation};
|
||||
mod matches_fungible;
|
||||
pub use matches_fungible::{MatchesFungible};
|
||||
mod matches_fungibles;
|
||||
pub use matches_fungibles::{MatchesFungibles, Error};
|
||||
mod on_response;
|
||||
pub use on_response::OnResponse;
|
||||
mod should_execute;
|
||||
|
||||
@@ -17,8 +17,11 @@
|
||||
use xcm::v0::{Response, MultiLocation};
|
||||
use frame_support::weights::Weight;
|
||||
|
||||
/// Define what needs to be done upon receiving a query response.
|
||||
pub trait OnResponse {
|
||||
/// Returns `true` if we are expecting a response from `origin` for query `query_id`.
|
||||
fn expecting_response(origin: &MultiLocation, query_id: u64) -> bool;
|
||||
/// Handler for receiving a `response` from `origin` relating to `query_id`.
|
||||
fn on_response(origin: MultiLocation, query_id: u64, response: Response) -> Weight;
|
||||
}
|
||||
impl OnResponse for () {
|
||||
|
||||
@@ -19,18 +19,21 @@ use xcm::v0::{Xcm, MultiLocation};
|
||||
use frame_support::weights::Weight;
|
||||
|
||||
/// Trait to determine whether the execution engine should actually execute a given XCM.
|
||||
///
|
||||
/// Can be amalgamated into a tuple to have multiple trials. If any of the tuple elements returns `Ok()`, the
|
||||
/// execution stops. Else, `Err(_)` is returned if all elements reject the message.
|
||||
pub trait ShouldExecute {
|
||||
/// Returns `true` if the given `message` may be executed.
|
||||
///
|
||||
/// - `origin`: The origin (sender) of the message.
|
||||
/// - `top_level`: `true`` indicates the initial XCM coming from the `origin`, `false` indicates an embedded
|
||||
/// XCM executed internally as part of another message or an `Order`.
|
||||
/// - `top_level`: `true` indicates the initial XCM coming from the `origin`, `false` indicates an embedded XCM
|
||||
/// executed internally as part of another message or an `Order`.
|
||||
/// - `message`: The message itself.
|
||||
/// - `shallow_weight`: The weight of the non-negotiable execution of the message. This does not include any
|
||||
/// embedded XCMs sat behind mechanisms like `BuyExecution` which would need to answer for their own weight.
|
||||
/// - `weight_credit`: The pre-established amount of weight that the system has determined this message
|
||||
/// may utilise in its execution. Typically non-zero only because of prior fee payment, but could
|
||||
/// in principle be due to other factors.
|
||||
/// - `weight_credit`: The pre-established amount of weight that the system has determined this message may utilise
|
||||
/// in its execution. Typically non-zero only because of prior fee payment, but could in principle be due to other
|
||||
/// factors.
|
||||
fn should_execute<Call>(
|
||||
origin: &MultiLocation,
|
||||
top_level: bool,
|
||||
@@ -51,7 +54,7 @@ impl ShouldExecute for Tuple {
|
||||
) -> Result<(), ()> {
|
||||
for_tuples!( #(
|
||||
match Tuple::should_execute(origin, top_level, message, shallow_weight, weight_credit) {
|
||||
o @ Ok(()) => return o,
|
||||
Ok(()) => return Ok(()),
|
||||
_ => (),
|
||||
}
|
||||
)* );
|
||||
|
||||
@@ -20,9 +20,11 @@ use crate::Assets;
|
||||
|
||||
/// Facility for asset transacting.
|
||||
///
|
||||
/// This should work with as many asset/location combinations as possible. Locations to support may include non-
|
||||
/// account locations such as a `MultiLocation::X1(Junction::Parachain)`. Different chains may handle them in
|
||||
/// different ways.
|
||||
/// This should work with as many asset/location combinations as possible. Locations to support may include non-account
|
||||
/// locations such as a `MultiLocation::X1(Junction::Parachain)`. Different chains may handle them in different ways.
|
||||
///
|
||||
/// Can be amalgamated as a tuple of items that implement this trait. In such executions, if any of the transactors
|
||||
/// returns `Ok(())`, then it will short circuit. Else, execution is passed to the next transactor.
|
||||
pub trait TransactAsset {
|
||||
/// Ensure that `check_in` will result in `Ok`.
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user