Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

XCM v3: Bridge infrastructure #4681

Merged
merged 65 commits into from
Feb 14, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
665bd6c
XCM bridge infrastructure
gavofyork Oct 30, 2021
535980e
Missing bit of cherry-pick
gavofyork Jan 10, 2022
d4376f1
Revamped XCM proc macros; new NetworkIds
gavofyork Oct 31, 2021
f093c55
Fixes
gavofyork Oct 31, 2021
bb939e8
Formatting
gavofyork Oct 31, 2021
ec2b72d
ExportMessage instruction and config type
gavofyork Oct 31, 2021
6878ed3
Add MessageExporter definitions
gavofyork Oct 31, 2021
270b662
Formatting
gavofyork Oct 31, 2021
bba850d
Missing files
gavofyork Oct 31, 2021
73e4758
Fixes
gavofyork Oct 31, 2021
4bef607
Initial bridging config API
gavofyork Oct 31, 2021
c0edea0
Allow for two-stage XCM execution
gavofyork Nov 2, 2021
128363e
Update xcm/src/v3/mod.rs
gavofyork Nov 2, 2021
4eb42d6
XCM crate building again
gavofyork Jan 10, 2022
08c41fa
Initial bridging primitive
gavofyork Jan 17, 2022
562b08b
Docs
gavofyork Jan 17, 2022
83adc05
Merge branch 'gav-xcm-v3' into gav-xcm-v3-bridging
gavofyork Jan 17, 2022
5ac926a
Docs
gavofyork Jan 18, 2022
b2dc3f1
More work
gavofyork Jan 20, 2022
4d8c9a8
More work
gavofyork Jan 20, 2022
a837427
Merge branch 'master' into gav-xcm-v3
gavofyork Jan 22, 2022
cacaf4c
Merge branch 'gav-xcm-v3' into gav-xcm-v3-bridging
gavofyork Jan 22, 2022
4a8fc7f
Merge branch 'gav-xcm-v3' into gav-xcm-v3-bridging
gavofyork Jan 22, 2022
449fe35
Merge branch 'gav-xcm-v3-bridging' of github.com:paritytech/polkadot …
gavofyork Jan 22, 2022
1723ae9
Make build
gavofyork Jan 22, 2022
30fbd39
WithComputedOrigin and SovereignPaidRemoteExporter
gavofyork Jan 23, 2022
f75c343
Remove TODOs
gavofyork Jan 28, 2022
fc9fa04
Merge remote-tracking branch 'origin/gav-xcm-v3' into gav-xcm-v3-brid…
gavofyork Jan 28, 2022
197ec2e
Merge branch 'gav-xcm-v3' into gav-xcm-v3-bridging
gavofyork Jan 31, 2022
8af0a3a
Slim bridge API and tests.
gavofyork Jan 31, 2022
caf33cb
Fixes
gavofyork Jan 31, 2022
347b32e
More work
gavofyork Feb 2, 2022
8ef2b84
First bridge test passing
gavofyork Feb 2, 2022
b459cfc
Formatting
gavofyork Feb 2, 2022
b2d3fdf
Another test
gavofyork Feb 2, 2022
ca031c2
Next round of bridging tests
gavofyork Feb 2, 2022
870b109
Repot tests
gavofyork Feb 2, 2022
c68bbc8
Cleanups
gavofyork Feb 2, 2022
1724115
Paid bridging
gavofyork Feb 2, 2022
cc9c35f
Formatting
gavofyork Feb 2, 2022
ac24184
Tests
gavofyork Feb 4, 2022
b90d041
Spelling
gavofyork Feb 4, 2022
7310377
Formatting
gavofyork Feb 4, 2022
d5b6f27
Fees and refactoring
gavofyork Feb 4, 2022
6537401
Fixes
gavofyork Feb 4, 2022
f2f844e
Formatting
gavofyork Feb 4, 2022
cfed333
Refactor SendXcm to become two-phase
gavofyork Feb 5, 2022
450f529
Fix tests
gavofyork Feb 5, 2022
7525c01
Refactoring of SendXcm and ExportXcm complete
gavofyork Feb 7, 2022
e715ef2
Formatting
gavofyork Feb 7, 2022
59768bd
Rename CannotReachDestination -> NotApplicable
gavofyork Feb 7, 2022
18f1100
Remove XCM v0
gavofyork Feb 7, 2022
087ac70
Minor grumbles
gavofyork Feb 7, 2022
9c9c38f
Formatting
gavofyork Feb 8, 2022
ca0d360
Formatting
gavofyork Feb 8, 2022
c4bc44a
Merge branch 'gav-xcm-v3-bridging' of github.com:paritytech/polkadot …
gavofyork Feb 8, 2022
3570fb4
Fixes
gavofyork Feb 8, 2022
45a697c
Fixes
gavofyork Feb 8, 2022
e28c84c
Cleanup XCM config
gavofyork Feb 9, 2022
5247473
Fee handling
gavofyork Feb 9, 2022
d68d61d
Merge remote-tracking branch 'origin/gav-xcm-v3' into gav-xcm-v3-brid…
gavofyork Feb 14, 2022
6ef1f0e
Fixes
gavofyork Feb 14, 2022
faa7463
Formatting
gavofyork Feb 14, 2022
ad5c941
Fixes
gavofyork Feb 14, 2022
5ed0737
Bump
gavofyork Feb 14, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Formatting
  • Loading branch information
gavofyork committed Feb 7, 2022
commit e715ef258a566af10296de4458fc5705f8ee1621
16 changes: 12 additions & 4 deletions runtime/common/src/xcm_sender.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@

use parity_scale_codec::Encode;
use primitives::v1::Id as ParaId;
use runtime_parachains::{configuration::{self, HostConfiguration}, dmp};
use sp_std::{prelude::*, marker::PhantomData};
use runtime_parachains::{
configuration::{self, HostConfiguration},
dmp,
};
use sp_std::{marker::PhantomData, prelude::*};
use xcm::prelude::*;
use SendError::*;

Expand All @@ -31,7 +34,10 @@ impl<T: configuration::Config + dmp::Config, W: xcm::WrapVersion> SendXcm
{
type OptionTicket = Option<(HostConfiguration<T::BlockNumber>, ParaId, Vec<u8>)>;

fn validate(dest: &mut Option<MultiLocation>, msg: &mut Option<Xcm<()>>) -> SendResult<(HostConfiguration<T::BlockNumber>, ParaId, Vec<u8>)> {
fn validate(
dest: &mut Option<MultiLocation>,
msg: &mut Option<Xcm<()>>,
) -> SendResult<(HostConfiguration<T::BlockNumber>, ParaId, Vec<u8>)> {
let d = dest.take().ok_or(MissingArgument)?;
let id = if let MultiLocation { parents: 0, interior: X1(Parachain(id)) } = &d {
*id
Expand All @@ -51,7 +57,9 @@ impl<T: configuration::Config + dmp::Config, W: xcm::WrapVersion> SendXcm
Ok(((config, para, blob), MultiAssets::new()))
}

fn deliver((config, para, blob): (HostConfiguration<T::BlockNumber>, ParaId, Vec<u8>)) -> Result<(), SendError> {
fn deliver(
(config, para, blob): (HostConfiguration<T::BlockNumber>, ParaId, Vec<u8>),
) -> Result<(), SendError> {
<dmp::Pallet<T>>::queue_downward_message(&config, para, blob)
.map_err(|_| SendError::Transport(&"Error placing into DMP queue"))
}
Expand Down
4 changes: 3 additions & 1 deletion xcm/pallet-xcm-benchmarks/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ impl xcm::opaque::latest::SendXcm for DevNull {
fn validate(_: &mut Option<MultiLocation>, _: &mut Option<Xcm<()>>) -> SendResult<()> {
Ok(((), MultiAssets::new()))
}
fn deliver(_: ()) -> Result<(), SendError> { Ok(()) }
fn deliver(_: ()) -> Result<(), SendError> {
Ok(())
}
}

impl xcm_executor::traits::OnResponse for DevNull {
Expand Down
10 changes: 5 additions & 5 deletions xcm/src/v3/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ pub use multilocation::{
Ancestor, AncestorThen, InteriorMultiLocation, MultiLocation, Parent, ParentThen,
};
pub use traits::{
Error, ExecuteXcm, Outcome, PreparedMessage, Result, SendError,
SendResult, SendXcm, Weight, send_xcm, validate_send, Unwrappable,
send_xcm, validate_send, Error, ExecuteXcm, Outcome, PreparedMessage, Result, SendError,
SendResult, SendXcm, Unwrappable, Weight,
};
// These parts of XCM v2 are unchanged in XCM v3, and are re-imported here.
pub use super::v2::{BodyId, BodyPart, OriginKind, WeightLimit};
Expand Down Expand Up @@ -165,7 +165,7 @@ impl<Call> From<Xcm<Call>> for Vec<Instruction<Call>> {
pub mod prelude {
mod contents {
pub use super::super::{
Ancestor, AncestorThen,
send_xcm, validate_send, Ancestor, AncestorThen,
AssetId::{self, *},
AssetInstance::{self, *},
BodyId, BodyPart, Error as XcmError, ExecuteXcm,
Expand All @@ -179,8 +179,8 @@ pub mod prelude {
MultiAssets, MultiLocation,
NetworkId::{self, *},
OriginKind, Outcome, PalletInfo, Parent, ParentThen, PreparedMessage, QueryId,
QueryResponseInfo, Response, Result as XcmResult, SendError,
SendResult, SendXcm, send_xcm, validate_send, Unwrappable,
QueryResponseInfo, Response, Result as XcmResult, SendError, SendResult, SendXcm,
Unwrappable,
WeightLimit::{self, *},
WildFungibility::{self, Fungible as WildFungible, NonFungible as WildNonFungible},
WildMultiAsset::{self, *},
Expand Down
37 changes: 26 additions & 11 deletions xcm/src/v3/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,9 +326,15 @@ pub trait Unwrappable {

impl<T> Unwrappable for Option<T> {
type Inner = T;
fn none() -> Self { None }
fn some(i: Self::Inner) -> Self { Some(i) }
fn take(self) -> Option<Self::Inner> { self }
fn none() -> Self {
None
}
fn some(i: Self::Inner) -> Self {
Some(i)
}
fn take(self) -> Option<Self::Inner> {
self
}
}

/// Utility for sending an XCM message.
Expand Down Expand Up @@ -421,19 +427,20 @@ pub trait SendXcm {
) -> SendResult<<Self::OptionTicket as Unwrappable>::Inner>;

/// Actually carry out the delivery operation for a previously validated message sending.
fn deliver(ticket: <Self::OptionTicket as Unwrappable>::Inner) -> result::Result<(), SendError>;
fn deliver(ticket: <Self::OptionTicket as Unwrappable>::Inner)
-> result::Result<(), SendError>;
}

#[impl_trait_for_tuples::impl_for_tuples(30)]
impl SendXcm for Tuple {
type OptionTicket = Option<( for_tuples!{ #( Tuple::OptionTicket ),* } )>;
type OptionTicket = Option<(for_tuples! { #( Tuple::OptionTicket ),* })>;

fn validate(
destination: &mut Option<MultiLocation>,
message: &mut Option<Xcm<()>>,
) -> SendResult<( for_tuples!{ #( Tuple::OptionTicket ),* } )> {
) -> SendResult<(for_tuples! { #( Tuple::OptionTicket ),* })> {
let mut maybe_cost: Option<MultiAssets> = None;
let one_ticket: ( for_tuples!{ #( Tuple::OptionTicket ),* } ) = ( for_tuples!{ #(
let one_ticket: (for_tuples! { #( Tuple::OptionTicket ),* }) = (for_tuples! { #(
if maybe_cost.is_some() {
<Tuple::OptionTicket as Unwrappable>::none()
} else {
Expand All @@ -446,15 +453,17 @@ impl SendXcm for Tuple {
},
}
}
),* } );
),* });
if let Some(cost) = maybe_cost {
Ok((one_ticket, cost))
} else {
Err(SendError::CannotReachDestination)
}
}

fn deliver(one_ticket: <Self::OptionTicket as Unwrappable>::Inner) -> result::Result<(), SendError> {
fn deliver(
one_ticket: <Self::OptionTicket as Unwrappable>::Inner,
) -> result::Result<(), SendError> {
for_tuples!( #(
if let Some(validated) = one_ticket.Tuple.take() {
return Tuple::deliver(validated);
Expand All @@ -466,7 +475,10 @@ impl SendXcm for Tuple {

/// Convenience function for using a `SendXcm` implementation. Just interprets the `dest` and wraps
/// both in `Some` before passing them as as mutable references into `T::send_xcm`.
pub fn validate_send<T: SendXcm>(dest: MultiLocation, msg: Xcm<()>) -> SendResult<<T::OptionTicket as Unwrappable>::Inner> {
pub fn validate_send<T: SendXcm>(
dest: MultiLocation,
msg: Xcm<()>,
) -> SendResult<<T::OptionTicket as Unwrappable>::Inner> {
T::validate(&mut Some(dest), &mut Some(msg))
}

Expand All @@ -478,7 +490,10 @@ pub fn validate_send<T: SendXcm>(dest: MultiLocation, msg: Xcm<()>) -> SendResul
///
/// Generally you'll want to validate and get the price first to ensure that the sender can pay it
/// before actually doing the delivery.
pub fn send_xcm<T: SendXcm>(dest: MultiLocation, msg: Xcm<()>) -> result::Result<MultiAssets, SendError> {
pub fn send_xcm<T: SendXcm>(
dest: MultiLocation,
msg: Xcm<()>,
) -> result::Result<MultiAssets, SendError> {
let (ticket, price) = T::validate(&mut Some(dest), &mut Some(msg))?;
T::deliver(ticket)?;
Ok(price)
Expand Down
5 changes: 4 additions & 1 deletion xcm/xcm-builder/src/bridging_tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ use crate::{mock::*, universal_exports::*};
use frame_support::{parameter_types, traits::Get};
use std::{cell::RefCell, marker::PhantomData};
use xcm::prelude::*;
use xcm_executor::{XcmExecutor, traits::{validate_export, export_xcm}};
use xcm_executor::{
traits::{export_xcm, validate_export},
XcmExecutor,
};
use SendError::*;

mod local_para_para;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ type LocalRouter = (LocalInnerRouter, LocalBridgingRouter);
#[test]
fn sending_to_bridged_chain_works() {
let msg = Xcm(vec![Trap(1)]);
assert_eq!(send_xcm::<LocalRouter>((Parent, Remote::get(), Parachain(1)).into(), msg), Ok(MultiAssets::new()));
assert_eq!(
send_xcm::<LocalRouter>((Parent, Remote::get(), Parachain(1)).into(), msg),
Ok(MultiAssets::new())
);
assert_eq!(TheBridge::service(), 1);
assert_eq!(
take_received_remote_messages(),
Expand Down
5 changes: 4 additions & 1 deletion xcm/xcm-builder/src/bridging_tests/remote_relay_relay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ type LocalRouter = (LocalInnerRouter, LocalBridgeRouter);
#[test]
fn sending_to_bridged_chain_works() {
let msg = Xcm(vec![Trap(1)]);
assert_eq!(send_xcm::<LocalRouter>((Parent, Parent, Remote::get()).into(), msg), Ok(MultiAssets::new()));
assert_eq!(
send_xcm::<LocalRouter>((Parent, Parent, Remote::get()).into(), msg),
Ok(MultiAssets::new())
);
assert_eq!(TheBridge::service(), 1);
assert_eq!(
take_received_remote_messages(),
Expand Down
2 changes: 1 addition & 1 deletion xcm/xcm-builder/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ impl ExportXcm for TestMessageExporter {
*dest = Some(d);
*msg = Some(m);
Err(e)
}
},
}
}
fn deliver(tuple: (NetworkId, u32, InteriorMultiLocation, Xcm<()>)) -> Result<(), SendError> {
Expand Down
25 changes: 17 additions & 8 deletions xcm/xcm-builder/src/universal_exports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ 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::{ExportXcm, validate_export};
use xcm_executor::traits::{validate_export, ExportXcm};
use SendError::*;

fn ensure_is_remote(
Expand Down Expand Up @@ -61,7 +61,10 @@ impl<Exporter: ExportXcm, Ancestry: Get<InteriorMultiLocation>> SendXcm
{
type OptionTicket = Exporter::OptionTicket;

fn validate(dest: &mut Option<MultiLocation>, xcm: &mut Option<Xcm<()>>) -> SendResult<<Exporter::OptionTicket as Unwrappable>::Inner> {
fn validate(
dest: &mut Option<MultiLocation>,
xcm: &mut Option<Xcm<()>>,
) -> SendResult<<Exporter::OptionTicket as Unwrappable>::Inner> {
let d = dest.take().ok_or(MissingArgument)?;
let devolved = match ensure_is_remote(Ancestry::get(), d) {
Ok(x) => x,
Expand Down Expand Up @@ -167,8 +170,9 @@ impl<Bridges: ExporterFor, Router: SendXcm, Ancestry: Get<InteriorMultiLocation>
}
exported.inner_mut().extend(xcm.take().ok_or(MissingArgument)?.into_iter());

let (bridge, maybe_payment) = Bridges::exporter_for(&remote_network, &remote_location, &exported)
.ok_or(CannotReachDestination)?;
let (bridge, maybe_payment) =
Bridges::exporter_for(&remote_network, &remote_location, &exported)
.ok_or(CannotReachDestination)?;
ensure!(maybe_payment.is_none(), Unroutable);

// We then send a normal message to the bridge asking it to export the prepended
Expand Down Expand Up @@ -225,16 +229,19 @@ impl<Bridges: ExporterFor, Router: SendXcm, Ancestry: Get<InteriorMultiLocation>
}
exported.inner_mut().extend(xcm.take().ok_or(MissingArgument)?.into_iter());

let (bridge, maybe_payment) = Bridges::exporter_for(&remote_network, &remote_location, &exported)
.ok_or(CannotReachDestination)?;
let (bridge, maybe_payment) =
Bridges::exporter_for(&remote_network, &remote_location, &exported)
.ok_or(CannotReachDestination)?;

let local_from_bridge =
MultiLocation::from(Ancestry::get()).inverted(&bridge).map_err(|_| Unroutable)?;
let export_instruction =
ExportMessage { network: remote_network, destination: remote_location, xcm: exported };

let message = Xcm(if let Some(ref payment) = maybe_payment {
let fees = payment.clone().reanchored(&bridge, &Ancestry::get().into())
let fees = payment
.clone()
.reanchored(&bridge, &Ancestry::get().into())
.map_err(|_| Unroutable)?;
vec![
WithdrawAsset(fees.clone().into()),
Expand Down Expand Up @@ -318,7 +325,9 @@ impl<Router: SendXcm, OurPlace: Get<InteriorMultiLocation>> DispatchBlob
}
}

pub struct HaulBlobExporter<Bridge, BridgedNetwork, Price>(PhantomData<(Bridge, BridgedNetwork, Price)>);
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>
{
Expand Down
9 changes: 5 additions & 4 deletions xcm/xcm-executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ use xcm::latest::prelude::*;

pub mod traits;
use traits::{
ClaimAssets, ConvertOrigin, DropAssets, FilterAssetLocation, OnResponse,
ShouldExecute, TransactAsset, UniversalLocation, VersionChangeNotifier, WeightBounds,
validate_export, WeightTrader, ExportXcm,
validate_export, ClaimAssets, ConvertOrigin, DropAssets, ExportXcm, FilterAssetLocation,
OnResponse, ShouldExecute, TransactAsset, UniversalLocation, VersionChangeNotifier,
WeightBounds, WeightTrader,
};

mod assets;
Expand Down Expand Up @@ -597,7 +597,8 @@ impl<Config: config::Config> XcmExecutor<Config> {
// Hash identifies the lane on the exporter which we use. We use the pairwise
// combination of the origin and destination to ensure origin/destination pairs will
// generally have their own lanes.
let (ticket, fee) = validate_export::<Config::MessageExporter>(network, channel, destination, xcm)?;
let (ticket, fee) =
validate_export::<Config::MessageExporter>(network, channel, destination, xcm)?;
self.holding.try_take(fee.into()).map_err(|_| XcmError::NotHoldingFees)?;
Config::MessageExporter::deliver(ticket)?;
Ok(())
Expand Down
8 changes: 4 additions & 4 deletions xcm/xcm-executor/src/traits/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,16 @@ pub trait ExportXcm {

#[impl_trait_for_tuples::impl_for_tuples(30)]
impl ExportXcm for Tuple {
type OptionTicket = Option<( for_tuples!{ #( Tuple::OptionTicket ),* } )>;
type OptionTicket = Option<(for_tuples! { #( Tuple::OptionTicket ),* })>;

fn validate(
network: NetworkId,
channel: u32,
destination: &mut Option<InteriorMultiLocation>,
message: &mut Option<Xcm<()>>,
) -> SendResult<( for_tuples!{ #( Tuple::OptionTicket ),* } )> {
) -> SendResult<(for_tuples! { #( Tuple::OptionTicket ),* })> {
let mut maybe_cost: Option<MultiAssets> = None;
let one_ticket: ( for_tuples!{ #( Tuple::OptionTicket ),* } ) = ( for_tuples!{ #(
let one_ticket: (for_tuples! { #( Tuple::OptionTicket ),* }) = (for_tuples! { #(
if maybe_cost.is_some() {
<Tuple::OptionTicket as Unwrappable>::none()
} else {
Expand All @@ -68,7 +68,7 @@ impl ExportXcm for Tuple {
},
}
}
),* } );
),* });
if let Some(cost) = maybe_cost {
Ok((one_ticket, cost))
} else {
Expand Down
2 changes: 1 addition & 1 deletion xcm/xcm-executor/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub use conversion::{
mod drop_assets;
pub use drop_assets::{ClaimAssets, DropAssets};
mod export;
pub use export::{export_xcm, ExportXcm, validate_export};
pub use export::{export_xcm, validate_export, ExportXcm};
mod filter_asset_location;
pub use filter_asset_location::FilterAssetLocation;
mod matches_fungible;
Expand Down