mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-01 01:01:01 +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,382 @@
|
||||
// Copyright 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/>.
|
||||
|
||||
//! Traits and utilities to help with origin mutation and bridging.
|
||||
|
||||
use frame_support::{ensure, traits::Get};
|
||||
use parity_scale_codec::{Decode, Encode};
|
||||
use sp_std::{convert::TryInto, marker::PhantomData, prelude::*};
|
||||
use xcm::prelude::*;
|
||||
use xcm_executor::traits::{validate_export, ExportXcm};
|
||||
use SendError::*;
|
||||
|
||||
fn ensure_is_remote(
|
||||
universal_local: impl Into<InteriorMultiLocation>,
|
||||
dest: impl Into<MultiLocation>,
|
||||
) -> Result<(NetworkId, InteriorMultiLocation), MultiLocation> {
|
||||
let dest = dest.into();
|
||||
let universal_local = universal_local.into();
|
||||
let local_net = match universal_local.global_consensus() {
|
||||
Ok(x) => x,
|
||||
Err(_) => return Err(dest),
|
||||
};
|
||||
let universal_destination: InteriorMultiLocation = universal_local
|
||||
.into_location()
|
||||
.appended_with(dest)
|
||||
.map_err(|x| x.1)?
|
||||
.try_into()?;
|
||||
let (remote_dest, remote_net) = match universal_destination.split_first() {
|
||||
(d, Some(GlobalConsensus(n))) if n != local_net => (d, n),
|
||||
_ => return Err(dest),
|
||||
};
|
||||
Ok((remote_net, remote_dest))
|
||||
}
|
||||
|
||||
/// Implementation of `SendXcm` which uses the given `ExportXcm` implementation in order to forward
|
||||
/// the message over a bridge.
|
||||
///
|
||||
/// No effort is made to charge for any bridge fees, so this can only be used when it is known
|
||||
/// that the message sending cannot be abused in any way.
|
||||
///
|
||||
/// This is only useful when the local chain has bridging capabilities.
|
||||
pub struct UnpaidLocalExporter<Exporter, UniversalLocation>(
|
||||
PhantomData<(Exporter, UniversalLocation)>,
|
||||
);
|
||||
impl<Exporter: ExportXcm, UniversalLocation: Get<InteriorMultiLocation>> SendXcm
|
||||
for UnpaidLocalExporter<Exporter, UniversalLocation>
|
||||
{
|
||||
type Ticket = Exporter::Ticket;
|
||||
|
||||
fn validate(
|
||||
dest: &mut Option<MultiLocation>,
|
||||
xcm: &mut Option<Xcm<()>>,
|
||||
) -> SendResult<Exporter::Ticket> {
|
||||
let d = dest.take().ok_or(MissingArgument)?;
|
||||
let universal_source = UniversalLocation::get();
|
||||
let devolved = match ensure_is_remote(universal_source, d) {
|
||||
Ok(x) => x,
|
||||
Err(d) => {
|
||||
*dest = Some(d);
|
||||
return Err(NotApplicable)
|
||||
},
|
||||
};
|
||||
let (network, destination) = devolved;
|
||||
let xcm = xcm.take().ok_or(SendError::MissingArgument)?;
|
||||
validate_export::<Exporter>(network, 0, universal_source, destination, xcm)
|
||||
}
|
||||
|
||||
fn deliver(ticket: Exporter::Ticket) -> Result<XcmHash, SendError> {
|
||||
Exporter::deliver(ticket)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ExporterFor {
|
||||
/// Return the locally-routable bridge (if any) capable of forwarding `message` to the
|
||||
/// `remote_location` on the remote `network`, together with the payment which is required.
|
||||
///
|
||||
/// The payment is specified from the local context, not the bridge chain. This is the
|
||||
/// total amount to withdraw in to Holding and should cover both payment for the execution on
|
||||
/// the bridge chain as well as payment for the use of the `ExportMessage` instruction.
|
||||
fn exporter_for(
|
||||
network: &NetworkId,
|
||||
remote_location: &InteriorMultiLocation,
|
||||
message: &Xcm<()>,
|
||||
) -> Option<(MultiLocation, Option<MultiAsset>)>;
|
||||
}
|
||||
|
||||
#[impl_trait_for_tuples::impl_for_tuples(30)]
|
||||
impl ExporterFor for Tuple {
|
||||
fn exporter_for(
|
||||
network: &NetworkId,
|
||||
remote_location: &InteriorMultiLocation,
|
||||
message: &Xcm<()>,
|
||||
) -> Option<(MultiLocation, Option<MultiAsset>)> {
|
||||
for_tuples!( #(
|
||||
if let Some(r) = Tuple::exporter_for(network, remote_location, message) {
|
||||
return Some(r);
|
||||
}
|
||||
)* );
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NetworkExportTable<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Get<Vec<(NetworkId, MultiLocation, Option<MultiAsset>)>>> ExporterFor
|
||||
for NetworkExportTable<T>
|
||||
{
|
||||
fn exporter_for(
|
||||
network: &NetworkId,
|
||||
_: &InteriorMultiLocation,
|
||||
_: &Xcm<()>,
|
||||
) -> Option<(MultiLocation, Option<MultiAsset>)> {
|
||||
T::get().into_iter().find(|(ref j, ..)| j == network).map(|(_, l, p)| (l, p))
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of `SendXcm` which wraps the message inside an `ExportMessage` instruction
|
||||
/// and sends it to a destination known to be able to handle it.
|
||||
///
|
||||
/// No effort is made to make payment to the bridge for its services, so the bridge location
|
||||
/// must have been configured with a barrier rule allowing unpaid execution for this message
|
||||
/// coming from our origin.
|
||||
///
|
||||
/// This is only useful if we have special dispensation by the remote bridges to have the
|
||||
/// `ExportMessage` instruction executed without payment.
|
||||
pub struct UnpaidRemoteExporter<Bridges, Router, UniversalLocation>(
|
||||
PhantomData<(Bridges, Router, UniversalLocation)>,
|
||||
);
|
||||
impl<Bridges: ExporterFor, Router: SendXcm, UniversalLocation: Get<InteriorMultiLocation>> SendXcm
|
||||
for UnpaidRemoteExporter<Bridges, Router, UniversalLocation>
|
||||
{
|
||||
type Ticket = Router::Ticket;
|
||||
|
||||
fn validate(
|
||||
dest: &mut Option<MultiLocation>,
|
||||
xcm: &mut Option<Xcm<()>>,
|
||||
) -> SendResult<Router::Ticket> {
|
||||
let d = dest.ok_or(MissingArgument)?;
|
||||
let devolved = ensure_is_remote(UniversalLocation::get(), d).map_err(|_| NotApplicable)?;
|
||||
let (remote_network, remote_location) = devolved;
|
||||
let xcm = xcm.take().ok_or(MissingArgument)?;
|
||||
let (bridge, maybe_payment) =
|
||||
Bridges::exporter_for(&remote_network, &remote_location, &xcm).ok_or(NotApplicable)?;
|
||||
ensure!(maybe_payment.is_none(), Unroutable);
|
||||
|
||||
// We then send a normal message to the bridge asking it to export the prepended
|
||||
// message to the remote chain. This will only work if the bridge will do the message
|
||||
// export for free. Common-good chains will typically be afforded this.
|
||||
let message =
|
||||
Xcm(vec![ExportMessage { network: remote_network, destination: remote_location, xcm }]);
|
||||
let (v, mut cost) = validate_send::<Router>(bridge, message)?;
|
||||
if let Some(payment) = maybe_payment {
|
||||
cost.push(payment);
|
||||
}
|
||||
Ok((v, cost))
|
||||
}
|
||||
|
||||
fn deliver(validation: Router::Ticket) -> Result<XcmHash, SendError> {
|
||||
Router::deliver(validation)
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of `SendXcm` which wraps the message inside an `ExportMessage` instruction
|
||||
/// and sends it to a destination known to be able to handle it.
|
||||
///
|
||||
/// The `ExportMessage` instruction on the bridge is paid for from the local chain's sovereign
|
||||
/// account on the bridge. The amount paid is determined through the `ExporterFor` trait.
|
||||
pub struct SovereignPaidRemoteExporter<Bridges, Router, UniversalLocation>(
|
||||
PhantomData<(Bridges, Router, UniversalLocation)>,
|
||||
);
|
||||
impl<Bridges: ExporterFor, Router: SendXcm, UniversalLocation: Get<InteriorMultiLocation>> SendXcm
|
||||
for SovereignPaidRemoteExporter<Bridges, Router, UniversalLocation>
|
||||
{
|
||||
type Ticket = Router::Ticket;
|
||||
|
||||
fn validate(
|
||||
dest: &mut Option<MultiLocation>,
|
||||
xcm: &mut Option<Xcm<()>>,
|
||||
) -> SendResult<Router::Ticket> {
|
||||
let d = *dest.as_ref().ok_or(MissingArgument)?;
|
||||
let devolved = ensure_is_remote(UniversalLocation::get(), d).map_err(|_| NotApplicable)?;
|
||||
let (remote_network, remote_location) = devolved;
|
||||
|
||||
let xcm = xcm.take().ok_or(MissingArgument)?;
|
||||
let (bridge, maybe_payment) =
|
||||
Bridges::exporter_for(&remote_network, &remote_location, &xcm).ok_or(NotApplicable)?;
|
||||
|
||||
let local_from_bridge =
|
||||
UniversalLocation::get().invert_target(&bridge).map_err(|_| Unroutable)?;
|
||||
let export_instruction =
|
||||
ExportMessage { network: remote_network, destination: remote_location, xcm };
|
||||
|
||||
let message = Xcm(if let Some(ref payment) = maybe_payment {
|
||||
let fees = payment
|
||||
.clone()
|
||||
.reanchored(&bridge, UniversalLocation::get())
|
||||
.map_err(|_| Unroutable)?;
|
||||
vec![
|
||||
WithdrawAsset(fees.clone().into()),
|
||||
BuyExecution { fees, weight_limit: Unlimited },
|
||||
export_instruction,
|
||||
RefundSurplus,
|
||||
DepositAsset { assets: All.into(), beneficiary: local_from_bridge },
|
||||
]
|
||||
} else {
|
||||
vec![export_instruction]
|
||||
});
|
||||
|
||||
// We then send a normal message to the bridge asking it to export the prepended
|
||||
// message to the remote chain.
|
||||
let (v, mut cost) = validate_send::<Router>(bridge, message)?;
|
||||
if let Some(bridge_payment) = maybe_payment {
|
||||
cost.push(bridge_payment);
|
||||
}
|
||||
Ok((v, cost))
|
||||
}
|
||||
|
||||
fn deliver(ticket: Router::Ticket) -> Result<XcmHash, SendError> {
|
||||
Router::deliver(ticket)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait DispatchBlob {
|
||||
/// Dispatches an incoming blob and returns the unexpectable weight consumed by the dispatch.
|
||||
fn dispatch_blob(blob: Vec<u8>) -> Result<(), DispatchBlobError>;
|
||||
}
|
||||
|
||||
pub trait HaulBlob {
|
||||
/// Sends a blob over some point-to-point link. This will generally be implemented by a bridge.
|
||||
fn haul_blob(blob: Vec<u8>) -> Result<(), HaulBlobError>;
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum HaulBlobError {
|
||||
/// Represents point-to-point link failure with a human-readable explanation of the specific issue is provided.
|
||||
Transport(&'static str),
|
||||
}
|
||||
|
||||
impl From<HaulBlobError> for SendError {
|
||||
fn from(err: HaulBlobError) -> Self {
|
||||
match err {
|
||||
HaulBlobError::Transport(reason) => SendError::Transport(reason),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Encode, Decode)]
|
||||
pub struct BridgeMessage {
|
||||
/// The message destination as a *Universal Location*. This means it begins with a
|
||||
/// `GlobalConsensus` junction describing the network under which global consensus happens.
|
||||
/// If this does not match our global consensus then it's a fatal error.
|
||||
universal_dest: VersionedInteriorMultiLocation,
|
||||
message: VersionedXcm<()>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum DispatchBlobError {
|
||||
Unbridgable,
|
||||
InvalidEncoding,
|
||||
UnsupportedLocationVersion,
|
||||
UnsupportedXcmVersion,
|
||||
RoutingError,
|
||||
NonUniversalDestination,
|
||||
WrongGlobal,
|
||||
}
|
||||
|
||||
pub struct BridgeBlobDispatcher<Router, OurPlace>(PhantomData<(Router, OurPlace)>);
|
||||
impl<Router: SendXcm, OurPlace: Get<InteriorMultiLocation>> DispatchBlob
|
||||
for BridgeBlobDispatcher<Router, OurPlace>
|
||||
{
|
||||
fn dispatch_blob(blob: Vec<u8>) -> Result<(), DispatchBlobError> {
|
||||
let our_universal = OurPlace::get();
|
||||
let our_global =
|
||||
our_universal.global_consensus().map_err(|()| DispatchBlobError::Unbridgable)?;
|
||||
let BridgeMessage { universal_dest, message } =
|
||||
Decode::decode(&mut &blob[..]).map_err(|_| DispatchBlobError::InvalidEncoding)?;
|
||||
let universal_dest: InteriorMultiLocation = universal_dest
|
||||
.try_into()
|
||||
.map_err(|_| DispatchBlobError::UnsupportedLocationVersion)?;
|
||||
// `universal_dest` is the desired destination within the universe: first we need to check
|
||||
// we're in the right global consensus.
|
||||
let intended_global = universal_dest
|
||||
.global_consensus()
|
||||
.map_err(|()| DispatchBlobError::NonUniversalDestination)?;
|
||||
ensure!(intended_global == our_global, DispatchBlobError::WrongGlobal);
|
||||
let dest = universal_dest.relative_to(&our_universal);
|
||||
let message: Xcm<()> =
|
||||
message.try_into().map_err(|_| DispatchBlobError::UnsupportedXcmVersion)?;
|
||||
let _ = send_xcm::<Router>(dest, message).map_err(|_| DispatchBlobError::RoutingError)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HaulBlobExporter<Bridge, BridgedNetwork, Price>(
|
||||
PhantomData<(Bridge, BridgedNetwork, Price)>,
|
||||
);
|
||||
impl<Bridge: HaulBlob, BridgedNetwork: Get<NetworkId>, Price: Get<MultiAssets>> ExportXcm
|
||||
for HaulBlobExporter<Bridge, BridgedNetwork, Price>
|
||||
{
|
||||
type Ticket = (Vec<u8>, XcmHash);
|
||||
|
||||
fn validate(
|
||||
network: NetworkId,
|
||||
_channel: u32,
|
||||
universal_source: &mut Option<InteriorMultiLocation>,
|
||||
destination: &mut Option<InteriorMultiLocation>,
|
||||
message: &mut Option<Xcm<()>>,
|
||||
) -> Result<((Vec<u8>, XcmHash), MultiAssets), SendError> {
|
||||
let bridged_network = BridgedNetwork::get();
|
||||
ensure!(&network == &bridged_network, SendError::NotApplicable);
|
||||
// We don't/can't use the `channel` for this adapter.
|
||||
let dest = destination.take().ok_or(SendError::MissingArgument)?;
|
||||
let universal_dest = match dest.pushed_front_with(GlobalConsensus(bridged_network)) {
|
||||
Ok(d) => d.into(),
|
||||
Err((dest, _)) => {
|
||||
*destination = Some(dest);
|
||||
return Err(SendError::NotApplicable)
|
||||
},
|
||||
};
|
||||
let (local_net, local_sub) = universal_source
|
||||
.take()
|
||||
.ok_or(SendError::MissingArgument)?
|
||||
.split_global()
|
||||
.map_err(|()| SendError::Unroutable)?;
|
||||
let mut inner: Xcm<()> = vec![UniversalOrigin(GlobalConsensus(local_net))].into();
|
||||
if local_sub != Here {
|
||||
inner.inner_mut().push(DescendOrigin(local_sub));
|
||||
}
|
||||
inner
|
||||
.inner_mut()
|
||||
.extend(message.take().ok_or(SendError::MissingArgument)?.into_iter());
|
||||
let message = VersionedXcm::from(inner);
|
||||
let hash = message.using_encoded(sp_io::hashing::blake2_256);
|
||||
let blob = BridgeMessage { universal_dest, message }.encode();
|
||||
Ok(((blob, hash), Price::get()))
|
||||
}
|
||||
|
||||
fn deliver((blob, hash): (Vec<u8>, XcmHash)) -> Result<XcmHash, SendError> {
|
||||
Bridge::haul_blob(blob)?;
|
||||
Ok(hash)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn ensure_is_remote_works() {
|
||||
// A Kusama parachain is remote from the Polkadot Relay.
|
||||
let x = ensure_is_remote(Polkadot, (Parent, Kusama, Parachain(1000)));
|
||||
assert_eq!(x, Ok((Kusama, Parachain(1000).into())));
|
||||
|
||||
// Polkadot Relay is remote from a Kusama parachain.
|
||||
let x = ensure_is_remote((Kusama, Parachain(1000)), (Parent, Parent, Polkadot));
|
||||
assert_eq!(x, Ok((Polkadot, Here)));
|
||||
|
||||
// Our own parachain is local.
|
||||
let x = ensure_is_remote(Polkadot, Parachain(1000));
|
||||
assert_eq!(x, Err(Parachain(1000).into()));
|
||||
|
||||
// Polkadot's parachain is not remote if we are Polkadot.
|
||||
let x = ensure_is_remote(Polkadot, (Parent, Polkadot, Parachain(1000)));
|
||||
assert_eq!(x, Err((Parent, Polkadot, Parachain(1000)).into()));
|
||||
|
||||
// If we don't have a consensus ancestor, then we cannot determine remoteness.
|
||||
let x = ensure_is_remote((), (Parent, Polkadot, Parachain(1000)));
|
||||
assert_eq!(x, Err((Parent, Polkadot, Parachain(1000)).into()));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user