mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-16 23:41:02 +00:00
XCM v3 (#4097)
* cargo fmt * Create benchmarks for XCM instructions introduced in v3 (#4564) * Create benchmarks for BurnAsset and ExpectAsset * Add benchmarks for ExpectOrigin and ExpectError * Add benchmarks for QueryPallet and ExpectPallet * Add benchmarks for ReportTransactStatus and ClearTransactStatus * cargo fmt * Use AllPalletsWithSystem in mocks * Update XCM generic benchmarks for westend * Remove default impls for some XCM weight functions * Fix compilation error * Add weight_args helper attribute * Remove manually written XcmWeightInfo * Parse trailing comma * Revert "Add weight_args helper attribute" This reverts commit 3b7c47a6182e1b9227036c38b406d494c3fcf6fd. * Fixes * Fixes * XCM v3: Introduce querier field into `QueryReponse` (#4732) * Introduce querier field into QueryReponse * Convert &Option<MultiLocation> to Option<&MultiLocation> &Option<T> is almost always never quite useful, most of the time it still gets converted to an Option<&T> via `as_ref`, so we should simply make functions that accept Option<&T> instead. * Fix tests * cargo fmt * Fix benchmarks * Appease spellchecker * Fix test * Fix tests * Fix test * Fix mock * Fixes * Fix tests * Add test for response queriers * Update xcm/pallet-xcm/src/lib.rs * Test for non-existence of querier Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * Fixes * Fixes * Add `starts_with` function to `MultiLocation` and `Junctions` (#4835) * add matches_prefix function to MultiLocation and Junctions * rename matches_prefix to starts_with * remove unnecessary main in doc comment Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Make use of starts_with in match_and_split Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * XCM v3: Bridge infrastructure (#4681) * XCM bridge infrastructure * Missing bit of cherry-pick * Revamped XCM proc macros; new NetworkIds * Fixes * Formatting * ExportMessage instruction and config type * Add MessageExporter definitions * Formatting * Missing files * Fixes * Initial bridging config API * Allow for two-stage XCM execution * Update xcm/src/v3/mod.rs Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * XCM crate building again * Initial bridging primitive * Docs * Docs * More work * More work * Merge branch 'gav-xcm-v3' into gav-xcm-v3-bridging * Make build * WithComputedOrigin and SovereignPaidRemoteExporter * Remove TODOs * Slim bridge API and tests. * Fixes * More work * First bridge test passing * Formatting * Another test * Next round of bridging tests * Repot tests * Cleanups * Paid bridging * Formatting * Tests * Spelling * Formatting * Fees and refactoring * Fixes * Formatting * Refactor SendXcm to become two-phase * Fix tests * Refactoring of SendXcm and ExportXcm complete * Formatting * Rename CannotReachDestination -> NotApplicable * Remove XCM v0 * Minor grumbles * Formatting * Formatting * Fixes * Fixes * Cleanup XCM config * Fee handling * Fixes * Formatting * Fixes * Bump Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * Bump Substrate * XCM v3: `ExchangeAsset` and Remote-locking (#4945) * Asset Exchange and Locks * Make sure XCM typers impl MaxEncodedLen * Basic implementation for locks * Bump Substrate * Missing files * Use new API * Introduce instruction * Big refactor * Docs * Remove deprecated struct * Remove deprecated struct * Repot XCM builder tests * ExchangeAsset test * Exchange tests * Locking tests * Locking tests * Fixes and tests * Fixes * Formatting * Spelling * Add simulator test for remote locking * Fix tests * Bump * XCM v3: Support for non-fungibles (#4950) * NFT support and a test * New files. * Integration tests for sending NFTs * Formatting * Broken Cargo features * Use 2021 edition * Fixes * Formatting * Formatting * Update xcm/xcm-builder/src/asset_conversion.rs Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * Update xcm/xcm-builder/src/nonfungibles_adapter.rs Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * Update xcm/xcm-executor/src/lib.rs Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * Fixes * Fixes * Fixes * Formatting * Fixes Co-authored-by: Bastian Köcher <info@kchr.de> Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * XCM v3: Context & ID hash (#4756) * send_xcm returns message hash * cargo fmt * Create topic register and instructions * Fix weights * Use tabs * Sketch out XcmContext * Fix doc test * Add the XCM context as a parameter to executor trait fns * Fixes * Add XcmContext parameter * Revert adding context as an arg to SendXcm trait methods * Revert adding context argument to ConvertOrigin trait methods * cargo fmt * Do not change the API of XcmExecutor::execute * Fixes * Fixes * Fixes * Fixes * Remove convenience method * Fixes * Fixes * cargo fmt * Fixes * Add benchmarks for XCM topic instructions * cargo run --quiet --profile=production --features=runtime-benchmarks -- benchmark --chain=westend-dev --steps=50 --repeat=20 --pallet=pallet_xcm_benchmarks::generic --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --header=./file_header.txt --template=./xcm/pallet-xcm-benchmarks/template.hbs --output=./runtime/westend/src/weights/xcm/pallet_xcm_benchmarks_generic.rs * Remove context argument on FilterAssetLocation * Fixes * Remove unused import * Fixes * Fixes * Fixes * Accept XCM hash parameter in ExecuteXcm trait methods * cargo fmt * Properly enable sp-io/std * Fixes * default-features = false * Fixes * Fixes * Fixes * Make XcmContext optional in withdraw_asset * Fixes * Fixes * Fixes * Modify tests to check for the correct XCM hash * Small refactor * cargo fmt * Check for expected hash in xcm-builder unit tests * Add doc comment for the optionality of the XCM context in withdraw_asset * Update xcm/src/v3/traits.rs * Update xcm/src/v3/traits.rs * Store XcmContext and avoid rebuilding * Use ref for XcmContext * Formatting * Fix incorrect hash CC @KiChjang * Refactor and make clear fake hashes * Fixes * Fixes * Fixes * Fix broken hashing * Docs * Fixes * Fixes * Fixes * Formatting * Fixes * Fixes * Fixes * Remove unknowable hash * Formatting * Use message hash for greater identifiability * Formatting * Fixes * Formatting Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> Co-authored-by: Parity Bot <admin@parity.io> * Fixes * Fixes * Fixes * Fixes * Formatting * Fixes * Formatting * Fixes * Fixes * Formatting * Formatting * Remove horrible names * Bump * Remove InvertLocation trait (#5092) * Remove InvertLocation trait * Remove unneeded functions * Formatting * Fixes * Remove XCMv1 (#5094) * Remove XCMv1 * Remove XCMv1 * Formatting * Fixes * Fixes * Formatting * derive serialize/deserialize for xcm primitives (#5036) * derive serialize/deserialize for xcm primitives * derive serialize/deserialize for xcm primitives * update v3 * update v2 Co-authored-by: Gav Wood <gavin@parity.io> * Update lock * Fixes * Add benchmarks for the ExchangeAsset instruction * `AliasOrigin` instruction stub (#5122) * AliasOrigin instruction stub * Fixes * Fixes * Update substrate * Fixes * Ensure same array length before using copy_from_slice * Fixes * Add benchmarks for the UniversalOrigin instruction * Remove unused import * Remove unused import * Add benchmarks for SetFeesMode instruction * Add benchmarks for asset (un)locking instructions * Leave AliasOrigin unbenchmarked * Fixes after merge * cargo fmt * Fixes * Fixes * Set TrustedReserves to None on both Kusama and Westend * Remove extraneous reserve_asset_deposited benchmark * Fix universal_origin benchmark * cargo run --quiet --profile=production --features=runtime-benchmarks -- benchmark pallet --chain=westend-dev --steps=50 --repeat=20 --pallet=pallet_xcm_benchmarks::generic --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --header=./file_header.txt --template=./xcm/pallet-xcm-benchmarks/template.hbs --output=./runtime/westend/src/weights/xcm/pallet_xcm_benchmarks_generic.rs * Don't rely on skipped benchmark functions * Fixes * cargo run --quiet --profile=production --features=runtime-benchmarks -- benchmark pallet --chain=kusama-dev --steps=50 --repeat=20 --pallet=pallet_xcm_benchmarks::generic --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --header=./file_header.txt --template=./xcm/pallet-xcm-benchmarks/template.hbs --output=./runtime/kusama/src/weights/xcm/pallet_xcm_benchmarks_generic.rs * Fix unused variables * Fixes * Spelling * Fixes * Fix codec index of VersionedXcm * Allows to customize how calls are dispatched from XCM (#5657) * CallDispatcher trait * fmt * unused import * fix test-runtime * remove JustDispatch type * fix typo in test-runtime * missing CallDispatcher * more missing CallDispatcher * Update comment `NoteAssetLocked` -> `NoteUnlockable` * Fixes * Fixes * Adjust MultiAssets weights based on new wild card variants * Fixes * Fixes * Fixes * Fixes * Fixes * Some late fixes for XCMv3 (#5237) * Maximise chances that trapped assets can be reclaimed * Do origin check as part of ExportMessage for security * Formatting * Fixes * Cleanup export XCM APIs * Formatting * Update xcm/src/v3/junctions.rs * UnpaidExecution instruction and associated barrier. * Tighten barriers (ClearOrigin/QueryResponse) * Allow only 1 ClearOrigin instruction in AllowTopLevelPaidExecutionFrom * Bi-directional teleport accounting * Revert other fix * Build fixes] * Tests build * Benchmark fixes Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * Update Substrate * Re-export `pub` stuff from universal_exports.rs + removed unecessary clone (#6145) * Re-export `pub` stuff from universal_exports.rs * Removed unnecessary clone * Use 2D weights in XCM v3 (#6134) * Depend upon sp-core instead of sp-runtime * Make sp-io a dev-dependency * Use 2D weights in XCM v3 * cargo fmt * Add XCM pallet migration to runtimes * Use from_parts * cargo fmt * Fixes * cargo fmt * Remove XCMWeight import * Fixes * Fixes * Fixes * Fixes * Use translate in migration * Increase max upward message size in tests * Fix doc test * Remove most uses of from_ref_time * cargo fmt * Fixes * Fixes * Add extrinsic benchmarking to XCM pallet * cargo fmt * Fixes * Use old syntax * cargo fmt * Fixes * Remove hardcoded weights * Add XCM pallet to benchmarks * Use successful origin * Fix weird type parameter compilation issue * Fixes * ".git/.scripts/bench-bot.sh" runtime westend-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime rococo-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime kusama-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime polkadot-dev pallet_xcm * Use benchmarked XCM pallet weights * Fixes * Fixes * Use override instead of skip * Fixes * Fixes * Fixes * Fixes * ".git/.scripts/bench-bot.sh" runtime polkadot-dev pallet_xcm * Fixes * ".git/.scripts/bench-bot.sh" runtime polkadot-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime westend-dev pallet_xcm Co-authored-by: command-bot <> * Replace Weight::MAX with 100b weight units * Add test to ensure all_gte in barriers is correct * Update xcm/src/v3/junction.rs Co-authored-by: asynchronous rob <rphmeier@gmail.com> * Add more weight tests * cargo fmt * Create thread_local in XCM executor to limit recursion depth (#6304) * Create thread_local in XCM executor to limit recursion depth * Add unit test for recursion limit * Fix statefulness in tests * Remove panic * Use defer and environmental macro * Fix the implementation * Use nicer interface * Change ThisNetwork to AnyNetwork * Move recursion check up to top level * cargo fmt * Update comment Co-authored-by: Bastian Köcher <info@kchr.de> * Add upper limit on the number of overweight messages in the queue (#6298) * Add upper limit on the number of ovwerweight messages in the queue * Add newline * Introduce whitelist for Transact and limit UMP processing to 10 messages per block (#6280) * Add SafeCallFilter to XcmConfig * Limit UMP to receive 10 messages every block * Place 10 message limit on processing instead of receiving * Always increment the message_processed count whenever a message is processed * Add as_derivative to the Transact whitelist * cargo fmt * Fixes * Update xcm/xcm-builder/src/universal_exports.rs Co-authored-by: Branislav Kontur <bkontur@gmail.com> * Fixes * Fixes * Remove topic register and instead use the topic field in XcmContext * Derive some common traits for DispatchBlobError * Fixes * cargo fmt * Fixes * Fixes * Fix comments * Fixes * Introduce WithOriginFilter and apply it as the CallDispatcher for runtimes * Fixes * Appease clippy and fixes * Fixes * Fix more clippy issues * Fixes * ".git/.scripts/bench-bot.sh" runtime polkadot-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime westend-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime westend-dev pallet_xcm * Add benchmark function for ExportMessage * Fix comment * Add upper limit to DownwardMessageQueues size * Add max size check for queue in can_queue_downward_message * Fixes * Make Transact runtime call configurable * Return Weight::MAX when there is no successful send XCM origin * Update substrate * Fixes * Fixes * Remove ExportMessage benchmark * Remove assertion on Transact instruction benchmark * Make reachable destination configurable in XCM pallet benchmarks * Fixes * Fixes * Remove cfg attribute in fuzzer * Fixes * Remove cfg attribute for XCM pallet in test runtime * Fixes * Use ReachableDest where possible * Fixes * Add benchmark for UnpaidExecution * Update substrate * Ensure benchmark functions pass filters * Add runtime-benchmarks feature to fuzzer * Ensure FixedRateOfFungible accounts for proof size weights * cargo fmt * Whitelist remark_with_event when runtime-benchmarks feature is enabled * Use remark_with_event for Transact benchmarks * Fix Cargo.lock * Allow up to 3 DescendOrigin instructions before UnpaidExecution * cargo fmt * Edit code comment * Check check_origin for unpaid execution privilege * Fixes * Small nits for xcm-v3 (#6408) * Add possibility to skip benchmark for export_message * ".git/.scripts/bench-bot.sh" xcm westend-dev pallet_xcm_benchmarks::generic * Revert * ".git/.scripts/bench-bot.sh" xcm westend-dev pallet_xcm_benchmarks::generic * Add HaulBlobError to `fn haul_blob` * ".git/.scripts/bench-bot.sh" xcm westend-dev pallet_xcm_benchmarks::generic Co-authored-by: command-bot <> * Revert changes to UnpaidExecution * Change AllowUnpaidExecutionFrom to be explicit * Fix log text * cargo fmt * Add benchmarks for XCM pallet version migration (#6448) * Add benchmarks for XCM pallet version migration * cargo fmt * Fixes * Fixes * Fixes * ".git/.scripts/bench-bot.sh" runtime westend-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime kusama-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime rococo-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime polkadot-dev pallet_xcm * Fix benchmarks * Fix benchmarks * ".git/.scripts/bench-bot.sh" runtime westend-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime kusama-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime rococo-dev pallet_xcm * ".git/.scripts/bench-bot.sh" runtime polkadot-dev pallet_xcm Co-authored-by: command-bot <> * Merge remote-tracking branch 'origin/master' into gav-xcm-v3 * Fixes * Fix comments (#6470) * Specify Ethereum networks by their chain id (#6286) Co-authored-by: Squirrel <gilescope@gmail.com> * Use for Kusama * Use WithComputedOrigin for Polkadot, Rococo and Westend * Update lock * Fix warning * Update xcm/pallet-xcm/src/tests.rs Co-authored-by: Squirrel <gilescope@gmail.com> * Update runtime/parachains/src/ump/migration.rs Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update xcm/pallet-xcm/src/migration.rs Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fixes * cargo fmt * Typo * Update xcm/src/v3/mod.rs Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Docs * Docs * Docs * Docs * Docs * Update xcm/src/v3/multiasset.rs Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Add tests for MultiAssets::from_sorted_and_deduplicated * Fail gracefully when same instance NFTs are detected during push * Update Substrate to fix benchmarks * Apply suggestions from code review * Update runtime/kusama/src/xcm_config.rs * Rename arguments * Attempt to fix benchmark * ".git/.scripts/commands/bench/bench.sh" runtime polkadot-dev runtime_parachains::ump * Use actual weights for UMP pallet in Polkadot * ".git/.scripts/commands/bench/bench.sh" runtime kusama-dev runtime_parachains::ump * ".git/.scripts/commands/bench/bench.sh" runtime westend-dev runtime_parachains::ump * ".git/.scripts/commands/bench/bench.sh" runtime rococo-dev runtime_parachains::ump Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> Co-authored-by: Bastian Köcher <info@kchr.de> Co-authored-by: Parity Bot <admin@parity.io> Co-authored-by: stanly-johnson <stanlyjohnson@outlook.com> Co-authored-by: nanocryk <6422796+nanocryk@users.noreply.github.com> Co-authored-by: Branislav Kontur <bkontur@gmail.com> Co-authored-by: asynchronous rob <rphmeier@gmail.com> Co-authored-by: command-bot <> Co-authored-by: Vincent Geddes <vincent.geddes@hey.com> Co-authored-by: Squirrel <gilescope@gmail.com> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
This commit is contained in:
@@ -0,0 +1,710 @@
|
||||
// Copyright 2020-2021 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/>.
|
||||
|
||||
//! XCM `MultiLocation` datatype.
|
||||
|
||||
use super::{Junction, Junctions};
|
||||
use crate::{v2::MultiLocation as OldMultiLocation, VersionedMultiLocation};
|
||||
use core::{
|
||||
convert::{TryFrom, TryInto},
|
||||
result,
|
||||
};
|
||||
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
|
||||
use scale_info::TypeInfo;
|
||||
|
||||
/// 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 an integer number of parents specifying the number of times to
|
||||
/// "escape" upwards into the containing consensus system and then a number of *junctions*, each
|
||||
/// diving down and specifying some interior portion of state (which may be considered a
|
||||
/// "sub-consensus" system).
|
||||
///
|
||||
/// This specific `MultiLocation` implementation uses a `Junctions` datatype which is a Rust `enum`
|
||||
/// in order to make pattern matching easier. There are occasions where it is important to ensure
|
||||
/// that a value is strictly an interior location, in those cases, `Junctions` may be used.
|
||||
///
|
||||
/// The `MultiLocation` value of `Null` simply refers to the interpreting consensus system.
|
||||
#[derive(
|
||||
Copy, Clone, Decode, Encode, Eq, PartialEq, Ord, PartialOrd, Debug, TypeInfo, MaxEncodedLen,
|
||||
)]
|
||||
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct MultiLocation {
|
||||
/// The number of parent junctions at the beginning of this `MultiLocation`.
|
||||
pub parents: u8,
|
||||
/// The interior (i.e. non-parent) junctions that this `MultiLocation` contains.
|
||||
pub interior: Junctions,
|
||||
}
|
||||
|
||||
impl Default for MultiLocation {
|
||||
fn default() -> Self {
|
||||
Self { parents: 0, interior: Junctions::Here }
|
||||
}
|
||||
}
|
||||
|
||||
/// A relative location which is constrained to be an interior location of the context.
|
||||
///
|
||||
/// See also `MultiLocation`.
|
||||
pub type InteriorMultiLocation = Junctions;
|
||||
|
||||
impl MultiLocation {
|
||||
/// Creates a new `MultiLocation` with the given number of parents and interior junctions.
|
||||
pub fn new(parents: u8, interior: impl Into<Junctions>) -> MultiLocation {
|
||||
MultiLocation { parents, interior: interior.into() }
|
||||
}
|
||||
|
||||
/// Consume `self` and return the equivalent `VersionedMultiLocation` value.
|
||||
pub const fn into_versioned(self) -> VersionedMultiLocation {
|
||||
VersionedMultiLocation::V3(self)
|
||||
}
|
||||
|
||||
/// Creates a new `MultiLocation` with 0 parents and a `Here` interior.
|
||||
///
|
||||
/// The resulting `MultiLocation` can be interpreted as the "current consensus system".
|
||||
pub const fn here() -> MultiLocation {
|
||||
MultiLocation { parents: 0, interior: Junctions::Here }
|
||||
}
|
||||
|
||||
/// Creates a new `MultiLocation` which evaluates to the parent context.
|
||||
pub const fn parent() -> MultiLocation {
|
||||
MultiLocation { parents: 1, interior: Junctions::Here }
|
||||
}
|
||||
|
||||
/// Creates a new `MultiLocation` which evaluates to the grand parent context.
|
||||
pub const fn grandparent() -> MultiLocation {
|
||||
MultiLocation { parents: 2, interior: Junctions::Here }
|
||||
}
|
||||
|
||||
/// Creates a new `MultiLocation` with `parents` and an empty (`Here`) interior.
|
||||
pub const fn ancestor(parents: u8) -> MultiLocation {
|
||||
MultiLocation { parents, interior: Junctions::Here }
|
||||
}
|
||||
|
||||
/// Whether the `MultiLocation` has no parents and has a `Here` interior.
|
||||
pub const fn is_here(&self) -> bool {
|
||||
self.parents == 0 && self.interior.len() == 0
|
||||
}
|
||||
|
||||
/// Remove the `NetworkId` value in any interior `Junction`s.
|
||||
pub fn remove_network_id(&mut self) {
|
||||
self.interior.remove_network_id();
|
||||
}
|
||||
|
||||
/// Return a reference to the interior field.
|
||||
pub fn interior(&self) -> &Junctions {
|
||||
&self.interior
|
||||
}
|
||||
|
||||
/// Return a mutable reference to the interior field.
|
||||
pub fn interior_mut(&mut self) -> &mut Junctions {
|
||||
&mut self.interior
|
||||
}
|
||||
|
||||
/// Returns the number of `Parent` junctions at the beginning of `self`.
|
||||
pub const fn parent_count(&self) -> u8 {
|
||||
self.parents
|
||||
}
|
||||
|
||||
/// Returns boolean indicating whether `self` contains only the specified amount of
|
||||
/// parents and no interior junctions.
|
||||
pub const fn contains_parents_only(&self, count: u8) -> bool {
|
||||
matches!(self.interior, Junctions::Here) && self.parents == count
|
||||
}
|
||||
|
||||
/// Returns the number of parents and junctions in `self`.
|
||||
pub const fn len(&self) -> usize {
|
||||
self.parent_count() as usize + self.interior.len()
|
||||
}
|
||||
|
||||
/// Returns the first interior junction, or `None` if the location is empty or contains only
|
||||
/// parents.
|
||||
pub fn first_interior(&self) -> Option<&Junction> {
|
||||
self.interior.first()
|
||||
}
|
||||
|
||||
/// Returns last junction, or `None` if the location is empty or contains only parents.
|
||||
pub fn last(&self) -> Option<&Junction> {
|
||||
self.interior.last()
|
||||
}
|
||||
|
||||
/// Splits off the first interior 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_interior(self) -> (MultiLocation, Option<Junction>) {
|
||||
let MultiLocation { parents, interior: junctions } = self;
|
||||
let (suffix, first) = junctions.split_first();
|
||||
let multilocation = MultiLocation { parents, interior: suffix };
|
||||
(multilocation, first)
|
||||
}
|
||||
|
||||
/// Splits off the last interior junction, returning the remaining prefix (first item in tuple)
|
||||
/// and the last element (second item in tuple) or `None` if it was empty or if `self` only
|
||||
/// contains parents.
|
||||
pub fn split_last_interior(self) -> (MultiLocation, Option<Junction>) {
|
||||
let MultiLocation { parents, interior: junctions } = self;
|
||||
let (prefix, last) = junctions.split_last();
|
||||
let multilocation = MultiLocation { parents, interior: prefix };
|
||||
(multilocation, last)
|
||||
}
|
||||
|
||||
/// Mutates `self`, suffixing its interior junctions with `new`. Returns `Err` with `new` in
|
||||
/// case of overflow.
|
||||
pub fn push_interior(&mut self, new: impl Into<Junction>) -> result::Result<(), Junction> {
|
||||
self.interior.push(new)
|
||||
}
|
||||
|
||||
/// Mutates `self`, prefixing its interior junctions with `new`. Returns `Err` with `new` in
|
||||
/// case of overflow.
|
||||
pub fn push_front_interior(
|
||||
&mut self,
|
||||
new: impl Into<Junction>,
|
||||
) -> result::Result<(), Junction> {
|
||||
self.interior.push_front(new)
|
||||
}
|
||||
|
||||
/// Consumes `self` and returns a `MultiLocation` suffixed with `new`, or an `Err` with theoriginal value of
|
||||
/// `self` in case of overflow.
|
||||
pub fn pushed_with_interior(
|
||||
self,
|
||||
new: impl Into<Junction>,
|
||||
) -> result::Result<Self, (Self, Junction)> {
|
||||
match self.interior.pushed_with(new) {
|
||||
Ok(i) => Ok(MultiLocation { interior: i, parents: self.parents }),
|
||||
Err((i, j)) => Err((MultiLocation { interior: i, parents: self.parents }, j)),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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_interior(
|
||||
self,
|
||||
new: impl Into<Junction>,
|
||||
) -> result::Result<Self, (Self, Junction)> {
|
||||
match self.interior.pushed_front_with(new) {
|
||||
Ok(i) => Ok(MultiLocation { interior: i, parents: self.parents }),
|
||||
Err((i, j)) => Err((MultiLocation { interior: i, parents: self.parents }, j)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the junction at index `i`, or `None` if the location is a parent or if the location
|
||||
/// does not contain that many elements.
|
||||
pub fn at(&self, i: usize) -> Option<&Junction> {
|
||||
let num_parents = self.parents as usize;
|
||||
if i < num_parents {
|
||||
return None
|
||||
}
|
||||
self.interior.at(i - num_parents)
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the junction at index `i`, or `None` if the location is a
|
||||
/// parent or if it doesn't contain that many elements.
|
||||
pub fn at_mut(&mut self, i: usize) -> Option<&mut Junction> {
|
||||
let num_parents = self.parents as usize;
|
||||
if i < num_parents {
|
||||
return None
|
||||
}
|
||||
self.interior.at_mut(i - num_parents)
|
||||
}
|
||||
|
||||
/// Decrements the parent count by 1.
|
||||
pub fn dec_parent(&mut self) {
|
||||
self.parents = self.parents.saturating_sub(1);
|
||||
}
|
||||
|
||||
/// Removes the first interior junction from `self`, returning it
|
||||
/// (or `None` if it was empty or if `self` contains only parents).
|
||||
pub fn take_first_interior(&mut self) -> Option<Junction> {
|
||||
self.interior.take_first()
|
||||
}
|
||||
|
||||
/// Removes the last element from `interior`, returning it (or `None` if it was empty or if
|
||||
/// `self` only contains parents).
|
||||
pub fn take_last(&mut self) -> Option<Junction> {
|
||||
self.interior.take_last()
|
||||
}
|
||||
|
||||
/// Ensures that `self` has the same number of parents as `prefix`, its junctions begins with
|
||||
/// the junctions of `prefix` and that it has a single `Junction` item following.
|
||||
/// If so, returns a reference to this `Junction` item.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use xcm::v3::{Junctions::*, Junction::*, MultiLocation};
|
||||
/// # fn main() {
|
||||
/// let mut m = MultiLocation::new(1, X2(PalletInstance(3), OnlyChild));
|
||||
/// assert_eq!(
|
||||
/// m.match_and_split(&MultiLocation::new(1, X1(PalletInstance(3)))),
|
||||
/// Some(&OnlyChild),
|
||||
/// );
|
||||
/// assert_eq!(m.match_and_split(&MultiLocation::new(1, Here)), None);
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn match_and_split(&self, prefix: &MultiLocation) -> Option<&Junction> {
|
||||
if self.parents != prefix.parents {
|
||||
return None
|
||||
}
|
||||
self.interior.match_and_split(&prefix.interior)
|
||||
}
|
||||
|
||||
pub fn starts_with(&self, prefix: &MultiLocation) -> bool {
|
||||
self.parents == prefix.parents && self.interior.starts_with(&prefix.interior)
|
||||
}
|
||||
|
||||
/// Mutate `self` so that it is suffixed with `suffix`.
|
||||
///
|
||||
/// Does not modify `self` and returns `Err` with `suffix` in case of overflow.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use xcm::v3::{Junctions::*, Junction::*, MultiLocation, Parent};
|
||||
/// # fn main() {
|
||||
/// let mut m: MultiLocation = (Parent, Parachain(21), 69u64).into();
|
||||
/// assert_eq!(m.append_with((Parent, PalletInstance(3))), Ok(()));
|
||||
/// assert_eq!(m, MultiLocation::new(1, X2(Parachain(21), PalletInstance(3))));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn append_with(&mut self, suffix: impl Into<Self>) -> Result<(), Self> {
|
||||
let prefix = core::mem::replace(self, suffix.into());
|
||||
match self.prepend_with(prefix) {
|
||||
Ok(()) => Ok(()),
|
||||
Err(prefix) => Err(core::mem::replace(self, prefix)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Consume `self` and return its value suffixed with `suffix`.
|
||||
///
|
||||
/// Returns `Err` with the original value of `self` and `suffix` in case of overflow.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use xcm::v3::{Junctions::*, Junction::*, MultiLocation, Parent};
|
||||
/// # fn main() {
|
||||
/// let mut m: MultiLocation = (Parent, Parachain(21), 69u64).into();
|
||||
/// let r = m.appended_with((Parent, PalletInstance(3))).unwrap();
|
||||
/// assert_eq!(r, MultiLocation::new(1, X2(Parachain(21), PalletInstance(3))));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn appended_with(mut self, suffix: impl Into<Self>) -> Result<Self, (Self, Self)> {
|
||||
match self.append_with(suffix) {
|
||||
Ok(()) => Ok(self),
|
||||
Err(suffix) => Err((self, suffix)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Mutate `self` so that it is prefixed with `prefix`.
|
||||
///
|
||||
/// Does not modify `self` and returns `Err` with `prefix` in case of overflow.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use xcm::v3::{Junctions::*, Junction::*, MultiLocation, Parent};
|
||||
/// # fn main() {
|
||||
/// let mut m: MultiLocation = (Parent, Parent, PalletInstance(3)).into();
|
||||
/// assert_eq!(m.prepend_with((Parent, Parachain(21), OnlyChild)), Ok(()));
|
||||
/// assert_eq!(m, MultiLocation::new(1, X1(PalletInstance(3))));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn prepend_with(&mut self, prefix: impl Into<Self>) -> Result<(), Self> {
|
||||
// prefix self (suffix)
|
||||
// P .. P I .. I p .. p i .. i
|
||||
let mut prefix = prefix.into();
|
||||
let prepend_interior = prefix.interior.len().saturating_sub(self.parents as usize);
|
||||
let final_interior = self.interior.len().saturating_add(prepend_interior);
|
||||
if final_interior > super::junctions::MAX_JUNCTIONS {
|
||||
return Err(prefix)
|
||||
}
|
||||
let suffix_parents = (self.parents as usize).saturating_sub(prefix.interior.len());
|
||||
let final_parents = (prefix.parents as usize).saturating_add(suffix_parents);
|
||||
if final_parents > 255 {
|
||||
return Err(prefix)
|
||||
}
|
||||
|
||||
// cancel out the final item on the prefix interior for one of the suffix's parents.
|
||||
while self.parents > 0 && prefix.take_last().is_some() {
|
||||
self.dec_parent();
|
||||
}
|
||||
|
||||
// now we have either removed all suffix's parents or prefix interior.
|
||||
// this means we can combine the prefix's and suffix's remaining parents/interior since
|
||||
// we know that with at least one empty, the overall order will be respected:
|
||||
// prefix self (suffix)
|
||||
// P .. P (I) p .. p i .. i => P + p .. (no I) i
|
||||
// -- or --
|
||||
// P .. P I .. I (p) i .. i => P (no p) .. I + i
|
||||
|
||||
self.parents = self.parents.saturating_add(prefix.parents);
|
||||
for j in prefix.interior.into_iter().rev() {
|
||||
self.push_front_interior(j)
|
||||
.expect("final_interior no greater than MAX_JUNCTIONS; qed");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Consume `self` and return its value prefixed with `prefix`.
|
||||
///
|
||||
/// Returns `Err` with the original value of `self` and `prefix` in case of overflow.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use xcm::v3::{Junctions::*, Junction::*, MultiLocation, Parent};
|
||||
/// # fn main() {
|
||||
/// let m: MultiLocation = (Parent, Parent, PalletInstance(3)).into();
|
||||
/// let r = m.prepended_with((Parent, Parachain(21), OnlyChild)).unwrap();
|
||||
/// assert_eq!(r, MultiLocation::new(1, X1(PalletInstance(3))));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn prepended_with(mut self, prefix: impl Into<Self>) -> Result<Self, (Self, Self)> {
|
||||
match self.prepend_with(prefix) {
|
||||
Ok(()) => Ok(self),
|
||||
Err(prefix) => Err((self, prefix)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Mutate `self` so that it represents the same location from the point of view of `target`.
|
||||
/// The context of `self` is provided as `context`.
|
||||
///
|
||||
/// Does not modify `self` in case of overflow.
|
||||
pub fn reanchor(
|
||||
&mut self,
|
||||
target: &MultiLocation,
|
||||
context: InteriorMultiLocation,
|
||||
) -> Result<(), ()> {
|
||||
// TODO: https://github.com/paritytech/polkadot/issues/4489 Optimize this.
|
||||
|
||||
// 1. Use our `context` to figure out how the `target` would address us.
|
||||
let inverted_target = context.invert_target(target)?;
|
||||
|
||||
// 2. Prepend `inverted_target` to `self` to get self's location from the perspective of
|
||||
// `target`.
|
||||
self.prepend_with(inverted_target).map_err(|_| ())?;
|
||||
|
||||
// 3. Given that we know some of `target` context, ensure that any parents in `self` are
|
||||
// strictly needed.
|
||||
self.simplify(target.interior());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Consume `self` and return a new value representing the same location from the point of view
|
||||
/// of `target`. The context of `self` is provided as `context`.
|
||||
///
|
||||
/// Returns the original `self` in case of overflow.
|
||||
pub fn reanchored(
|
||||
mut self,
|
||||
target: &MultiLocation,
|
||||
context: InteriorMultiLocation,
|
||||
) -> Result<Self, Self> {
|
||||
match self.reanchor(target, context) {
|
||||
Ok(()) => Ok(self),
|
||||
Err(()) => Err(self),
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove any unneeded parents/junctions in `self` based on the given context it will be
|
||||
/// interpreted in.
|
||||
pub fn simplify(&mut self, context: &Junctions) {
|
||||
if context.len() < self.parents as usize {
|
||||
// Not enough context
|
||||
return
|
||||
}
|
||||
while self.parents > 0 {
|
||||
let maybe = context.at(context.len() - (self.parents as usize));
|
||||
match (self.interior.first(), maybe) {
|
||||
(Some(i), Some(j)) if i == j => {
|
||||
self.interior.take_first();
|
||||
self.parents -= 1;
|
||||
},
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<OldMultiLocation> for MultiLocation {
|
||||
type Error = ();
|
||||
fn try_from(x: OldMultiLocation) -> result::Result<Self, ()> {
|
||||
Ok(MultiLocation { parents: x.parents, interior: x.interior.try_into()? })
|
||||
}
|
||||
}
|
||||
|
||||
/// A unit struct which can be converted into a `MultiLocation` of `parents` value 1.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||
pub struct Parent;
|
||||
impl From<Parent> for MultiLocation {
|
||||
fn from(_: Parent) -> Self {
|
||||
MultiLocation { parents: 1, interior: Junctions::Here }
|
||||
}
|
||||
}
|
||||
|
||||
/// A tuple struct which can be converted into a `MultiLocation` of `parents` value 1 with the inner interior.
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||
pub struct ParentThen(pub Junctions);
|
||||
impl From<ParentThen> for MultiLocation {
|
||||
fn from(ParentThen(interior): ParentThen) -> Self {
|
||||
MultiLocation { parents: 1, interior }
|
||||
}
|
||||
}
|
||||
|
||||
/// A unit struct which can be converted into a `MultiLocation` of the inner `parents` value.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||
pub struct Ancestor(pub u8);
|
||||
impl From<Ancestor> for MultiLocation {
|
||||
fn from(Ancestor(parents): Ancestor) -> Self {
|
||||
MultiLocation { parents, interior: Junctions::Here }
|
||||
}
|
||||
}
|
||||
|
||||
/// A unit struct which can be converted into a `MultiLocation` of the inner `parents` value and the inner interior.
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||
pub struct AncestorThen<Interior>(pub u8, pub Interior);
|
||||
impl<Interior: Into<Junctions>> From<AncestorThen<Interior>> for MultiLocation {
|
||||
fn from(AncestorThen(parents, interior): AncestorThen<Interior>) -> Self {
|
||||
MultiLocation { parents, interior: interior.into() }
|
||||
}
|
||||
}
|
||||
|
||||
xcm_procedural::impl_conversion_functions_for_multilocation_v3!();
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::v3::prelude::*;
|
||||
use parity_scale_codec::{Decode, Encode};
|
||||
|
||||
#[test]
|
||||
fn conversion_works() {
|
||||
let x: MultiLocation = Parent.into();
|
||||
assert_eq!(x, MultiLocation { parents: 1, interior: Here });
|
||||
// let x: MultiLocation = (Parent,).into();
|
||||
// assert_eq!(x, MultiLocation { parents: 1, interior: Here });
|
||||
// let x: MultiLocation = (Parent, Parent).into();
|
||||
// assert_eq!(x, MultiLocation { parents: 2, interior: Here });
|
||||
let x: MultiLocation = (Parent, Parent, OnlyChild).into();
|
||||
assert_eq!(x, MultiLocation { parents: 2, interior: OnlyChild.into() });
|
||||
let x: MultiLocation = OnlyChild.into();
|
||||
assert_eq!(x, MultiLocation { parents: 0, interior: OnlyChild.into() });
|
||||
let x: MultiLocation = (OnlyChild,).into();
|
||||
assert_eq!(x, MultiLocation { parents: 0, interior: OnlyChild.into() });
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simplify_basic_works() {
|
||||
let mut location: MultiLocation =
|
||||
(Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into();
|
||||
let context = X2(Parachain(1000), PalletInstance(42));
|
||||
let expected = GeneralIndex(69).into();
|
||||
location.simplify(&context);
|
||||
assert_eq!(location, expected);
|
||||
|
||||
let mut location: MultiLocation = (Parent, PalletInstance(42), GeneralIndex(69)).into();
|
||||
let context = X1(PalletInstance(42));
|
||||
let expected = GeneralIndex(69).into();
|
||||
location.simplify(&context);
|
||||
assert_eq!(location, expected);
|
||||
|
||||
let mut location: MultiLocation = (Parent, PalletInstance(42), GeneralIndex(69)).into();
|
||||
let context = X2(Parachain(1000), PalletInstance(42));
|
||||
let expected = GeneralIndex(69).into();
|
||||
location.simplify(&context);
|
||||
assert_eq!(location, expected);
|
||||
|
||||
let mut location: MultiLocation =
|
||||
(Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into();
|
||||
let context = X3(OnlyChild, Parachain(1000), PalletInstance(42));
|
||||
let expected = GeneralIndex(69).into();
|
||||
location.simplify(&context);
|
||||
assert_eq!(location, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simplify_incompatible_location_fails() {
|
||||
let mut location: MultiLocation =
|
||||
(Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into();
|
||||
let context = X3(Parachain(1000), PalletInstance(42), GeneralIndex(42));
|
||||
let expected =
|
||||
(Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into();
|
||||
location.simplify(&context);
|
||||
assert_eq!(location, expected);
|
||||
|
||||
let mut location: MultiLocation =
|
||||
(Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into();
|
||||
let context = X1(Parachain(1000));
|
||||
let expected =
|
||||
(Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into();
|
||||
location.simplify(&context);
|
||||
assert_eq!(location, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reanchor_works() {
|
||||
let mut id: MultiLocation = (Parent, Parachain(1000), GeneralIndex(42)).into();
|
||||
let context = Parachain(2000).into();
|
||||
let target = (Parent, Parachain(1000)).into();
|
||||
let expected = GeneralIndex(42).into();
|
||||
id.reanchor(&target, context).unwrap();
|
||||
assert_eq!(id, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_and_decode_works() {
|
||||
let m = MultiLocation {
|
||||
parents: 1,
|
||||
interior: X2(Parachain(42), AccountIndex64 { network: None, index: 23 }),
|
||||
};
|
||||
let encoded = m.encode();
|
||||
assert_eq!(encoded, [1, 2, 0, 168, 2, 0, 92].to_vec());
|
||||
let decoded = MultiLocation::decode(&mut &encoded[..]);
|
||||
assert_eq!(decoded, Ok(m));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn match_and_split_works() {
|
||||
let m = MultiLocation {
|
||||
parents: 1,
|
||||
interior: X2(Parachain(42), AccountIndex64 { network: None, index: 23 }),
|
||||
};
|
||||
assert_eq!(m.match_and_split(&MultiLocation { parents: 1, interior: Here }), None);
|
||||
assert_eq!(
|
||||
m.match_and_split(&MultiLocation { parents: 1, interior: X1(Parachain(42)) }),
|
||||
Some(&AccountIndex64 { network: None, index: 23 })
|
||||
);
|
||||
assert_eq!(m.match_and_split(&m), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn append_with_works() {
|
||||
let acc = AccountIndex64 { network: None, index: 23 };
|
||||
let mut m = MultiLocation { parents: 1, interior: X1(Parachain(42)) };
|
||||
assert_eq!(m.append_with(X2(PalletInstance(3), acc.clone())), Ok(()));
|
||||
assert_eq!(
|
||||
m,
|
||||
MultiLocation {
|
||||
parents: 1,
|
||||
interior: X3(Parachain(42), PalletInstance(3), acc.clone())
|
||||
}
|
||||
);
|
||||
|
||||
// cannot append to create overly long multilocation
|
||||
let acc = AccountIndex64 { network: None, index: 23 };
|
||||
let m = MultiLocation {
|
||||
parents: 254,
|
||||
interior: X5(Parachain(42), OnlyChild, OnlyChild, OnlyChild, OnlyChild),
|
||||
};
|
||||
let suffix: MultiLocation = (PalletInstance(3), acc.clone(), OnlyChild, OnlyChild).into();
|
||||
assert_eq!(m.clone().append_with(suffix.clone()), Err(suffix));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prepend_with_works() {
|
||||
let mut m = MultiLocation {
|
||||
parents: 1,
|
||||
interior: X2(Parachain(42), AccountIndex64 { network: None, index: 23 }),
|
||||
};
|
||||
assert_eq!(m.prepend_with(MultiLocation { parents: 1, interior: X1(OnlyChild) }), Ok(()));
|
||||
assert_eq!(
|
||||
m,
|
||||
MultiLocation {
|
||||
parents: 1,
|
||||
interior: X2(Parachain(42), AccountIndex64 { network: None, index: 23 })
|
||||
}
|
||||
);
|
||||
|
||||
// cannot prepend to create overly long multilocation
|
||||
let mut m = MultiLocation { parents: 254, interior: X1(Parachain(42)) };
|
||||
let prefix = MultiLocation { parents: 2, interior: Here };
|
||||
assert_eq!(m.prepend_with(prefix.clone()), Err(prefix));
|
||||
|
||||
let prefix = MultiLocation { parents: 1, interior: Here };
|
||||
assert_eq!(m.prepend_with(prefix), Ok(()));
|
||||
assert_eq!(m, MultiLocation { parents: 255, interior: X1(Parachain(42)) });
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn double_ended_ref_iteration_works() {
|
||||
let m = X3(Parachain(1000), Parachain(3), PalletInstance(5));
|
||||
let mut iter = m.iter();
|
||||
|
||||
let first = iter.next().unwrap();
|
||||
assert_eq!(first, &Parachain(1000));
|
||||
let third = iter.next_back().unwrap();
|
||||
assert_eq!(third, &PalletInstance(5));
|
||||
let second = iter.next_back().unwrap();
|
||||
assert_eq!(iter.next(), None);
|
||||
assert_eq!(iter.next_back(), None);
|
||||
assert_eq!(second, &Parachain(3));
|
||||
|
||||
let res = Here
|
||||
.pushed_with(first.clone())
|
||||
.unwrap()
|
||||
.pushed_with(second.clone())
|
||||
.unwrap()
|
||||
.pushed_with(third.clone())
|
||||
.unwrap();
|
||||
assert_eq!(m, res);
|
||||
|
||||
// make sure there's no funny business with the 0 indexing
|
||||
let m = Here;
|
||||
let mut iter = m.iter();
|
||||
|
||||
assert_eq!(iter.next(), None);
|
||||
assert_eq!(iter.next_back(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn conversion_from_other_types_works() {
|
||||
use crate::v2;
|
||||
use core::convert::TryInto;
|
||||
|
||||
fn takes_multilocation<Arg: Into<MultiLocation>>(_arg: Arg) {}
|
||||
|
||||
takes_multilocation(Parent);
|
||||
takes_multilocation(Here);
|
||||
takes_multilocation(X1(Parachain(42)));
|
||||
takes_multilocation((Ancestor(255), PalletInstance(8)));
|
||||
takes_multilocation((Ancestor(5), Parachain(1), PalletInstance(3)));
|
||||
takes_multilocation((Ancestor(2), Here));
|
||||
takes_multilocation(AncestorThen(
|
||||
3,
|
||||
X2(Parachain(43), AccountIndex64 { network: None, index: 155 }),
|
||||
));
|
||||
takes_multilocation((Parent, AccountId32 { network: None, id: [0; 32] }));
|
||||
takes_multilocation((Parent, Here));
|
||||
takes_multilocation(ParentThen(X1(Parachain(75))));
|
||||
takes_multilocation([Parachain(100), PalletInstance(3)]);
|
||||
|
||||
assert_eq!(
|
||||
v2::MultiLocation::from(v2::Junctions::Here).try_into(),
|
||||
Ok(MultiLocation::here())
|
||||
);
|
||||
assert_eq!(v2::MultiLocation::from(v2::Parent).try_into(), Ok(MultiLocation::parent()));
|
||||
assert_eq!(
|
||||
v2::MultiLocation::from((v2::Parent, v2::Parent, v2::Junction::GeneralIndex(42u128),))
|
||||
.try_into(),
|
||||
Ok(MultiLocation { parents: 2, interior: X1(GeneralIndex(42u128)) }),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user