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

Make most XCM APIs accept an Into<MultiLocation> where MultiLocation is accepted #3627

Merged
18 commits merged into from
Sep 29, 2021
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
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
3 changes: 2 additions & 1 deletion runtime/common/src/xcm_sender.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ pub struct ChildParachainRouter<T, W>(PhantomData<(T, W)>);
impl<T: configuration::Config + dmp::Config, W: xcm::WrapVersion> SendXcm
for ChildParachainRouter<T, W>
{
fn send_xcm(dest: MultiLocation, msg: Xcm) -> Result {
fn send_xcm(dest: impl Into<MultiLocation>, msg: Xcm) -> Result {
let dest = dest.into();
match dest {
MultiLocation { parents: 0, interior: Junctions::X1(Junction::Parachain(id)) } => {
// Downward message passing.
Expand Down
7 changes: 3 additions & 4 deletions runtime/parachains/src/ump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ impl<XcmExecutor: xcm::latest::ExecuteXcm<C::Call>, C: Config> UmpSink for XcmSi
) -> Result<Weight, (MessageId, Weight)> {
use parity_scale_codec::DecodeLimit;
use xcm::{
latest::{Error as XcmError, Junction, MultiLocation, Xcm},
latest::{Error as XcmError, Junction, Xcm},
VersionedXcm,
};

Expand All @@ -106,9 +106,8 @@ impl<XcmExecutor: xcm::latest::ExecuteXcm<C::Call>, C: Config> UmpSink for XcmSi
Ok(0)
},
Ok(Ok(xcm_message)) => {
let xcm_junction: Junction = Junction::Parachain(origin.into());
let xcm_location: MultiLocation = xcm_junction.into();
let outcome = XcmExecutor::execute_xcm(xcm_location, xcm_message, max_weight);
let xcm_junction = Junction::Parachain(origin.into());
let outcome = XcmExecutor::execute_xcm(xcm_junction, xcm_message, max_weight);
match outcome {
Outcome::Error(XcmError::WeightLimitReached(required)) => Err((id, required)),
outcome => {
Expand Down
2 changes: 1 addition & 1 deletion runtime/test-runtime/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub type LocalOriginToLocation = (

pub struct DoNothingRouter;
impl SendXcm for DoNothingRouter {
fn send_xcm(_dest: MultiLocation, _msg: Xcm<()>) -> XcmResult {
fn send_xcm(_dest: impl Into<MultiLocation>, _msg: Xcm<()>) -> XcmResult {
Ok(())
}
}
Expand Down
14 changes: 10 additions & 4 deletions xcm/pallet-xcm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ pub mod pallet {
message: Box<Xcm<()>>,
) -> DispatchResult {
let origin_location = T::SendXcmOrigin::ensure_origin(origin)?;
let interior =
let interior: Junctions =
origin_location.clone().try_into().map_err(|_| Error::<T>::InvalidOrigin)?;
Self::send_xcm(interior, *dest.clone(), *message.clone()).map_err(|e| match e {
XcmError::CannotReachDestination(..) => Error::<T>::Unreachable,
Expand Down Expand Up @@ -304,10 +304,12 @@ pub mod pallet {
/// Relay an XCM `message` from a given `interior` location in this context to a given `dest`
/// location. A null `dest` is not handled.
pub fn send_xcm(
interior: Junctions,
dest: MultiLocation,
interior: impl Into<Junctions>,
dest: impl Into<MultiLocation>,
message: Xcm<()>,
) -> Result<(), XcmError> {
let interior = interior.into();
let dest = dest.into();
let message = if let Junctions::Here = interior {
message
} else {
Expand Down Expand Up @@ -395,7 +397,11 @@ where
/// this crate's `Origin::Xcm` value.
pub struct XcmPassthrough<Origin>(PhantomData<Origin>);
impl<Origin: From<crate::Origin>> ConvertOrigin<Origin> for XcmPassthrough<Origin> {
fn convert_origin(origin: MultiLocation, kind: OriginKind) -> Result<Origin, MultiLocation> {
fn convert_origin(
origin: impl Into<MultiLocation>,
kind: OriginKind,
) -> Result<Origin, MultiLocation> {
let origin = origin.into();
match kind {
OriginKind::Xcm => Ok(crate::Origin::Xcm(origin).into()),
_ => Err(origin),
Expand Down
7 changes: 4 additions & 3 deletions xcm/pallet-xcm/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,16 @@ pub fn sent_xcm() -> Vec<(MultiLocation, Xcm)> {
/// Sender that never returns error, always sends
pub struct TestSendXcm;
impl SendXcm for TestSendXcm {
fn send_xcm(dest: MultiLocation, msg: Xcm) -> XcmResult {
SENT_XCM.with(|q| q.borrow_mut().push((dest, msg)));
fn send_xcm(dest: impl Into<MultiLocation>, msg: Xcm) -> XcmResult {
SENT_XCM.with(|q| q.borrow_mut().push((dest.into(), msg)));
Ok(())
}
}
/// Sender that returns error if `X8` junction and stops routing
pub struct TestSendXcmErrX8;
impl SendXcm for TestSendXcmErrX8 {
fn send_xcm(dest: MultiLocation, msg: Xcm) -> XcmResult {
fn send_xcm(dest: impl Into<MultiLocation>, msg: Xcm) -> XcmResult {
let dest = dest.into();
if dest.len() == 8 {
Err(XcmError::Undefined)
} else {
Expand Down
12 changes: 6 additions & 6 deletions xcm/src/v1/multilocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,24 +325,24 @@ impl From<Parent> for MultiLocation {
/// A tuple struct which can be converted into a `MultiLocation` of `parents` value 1 with the inner interior.
pub struct ParentThen(Junctions);
impl From<ParentThen> for MultiLocation {
fn from(x: ParentThen) -> Self {
MultiLocation { parents: 1, interior: x.0 }
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.
pub struct Ancestor(u8);
impl From<Ancestor> for MultiLocation {
fn from(x: Ancestor) -> Self {
MultiLocation { parents: x.0, interior: Junctions::Here }
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.
pub struct AncestorThen(u8, Junctions);
impl From<AncestorThen> for MultiLocation {
fn from(x: AncestorThen) -> Self {
MultiLocation { parents: x.0, interior: x.1 }
fn from(AncestorThen(parents, interior): AncestorThen) -> Self {
MultiLocation { parents, interior }
}
}

Expand Down
32 changes: 19 additions & 13 deletions xcm/src/v1/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,12 @@ pub trait ExecuteXcm<Call> {
/// Execute some XCM `message` from `origin` using no more than `weight_limit` weight. The weight limit is
/// a basic hard-limit and the implementation may place further restrictions or requirements on weight and
/// other aspects.
fn execute_xcm(origin: MultiLocation, message: Xcm<Call>, weight_limit: Weight) -> Outcome {
fn execute_xcm(
origin: impl Into<MultiLocation>,
message: Xcm<Call>,
weight_limit: Weight,
) -> Outcome {
let origin = origin.into();
log::debug!(
target: "xcm::execute_xcm",
"origin: {:?}, message: {:?}, weight_limit: {:?}",
Expand All @@ -161,7 +166,7 @@ pub trait ExecuteXcm<Call> {
/// Some amount of `weight_credit` may be provided which, depending on the implementation, may allow
/// execution without associated payment.
fn execute_xcm_in_credit(
origin: MultiLocation,
origin: impl Into<MultiLocation>,
message: Xcm<Call>,
weight_limit: Weight,
weight_credit: Weight,
Expand All @@ -170,7 +175,7 @@ pub trait ExecuteXcm<Call> {

impl<C> ExecuteXcm<C> for () {
fn execute_xcm_in_credit(
_origin: MultiLocation,
_origin: impl Into<MultiLocation>,
_message: Xcm<C>,
_weight_limit: Weight,
_weight_credit: Weight,
Expand All @@ -194,15 +199,16 @@ impl<C> ExecuteXcm<C> for () {
/// /// A sender that only passes the message through and does nothing.
/// struct Sender1;
/// impl SendXcm for Sender1 {
/// fn send_xcm(destination: MultiLocation, message: Xcm<()>) -> Result {
/// return Err(Error::CannotReachDestination(destination, message))
/// fn send_xcm(destination: impl Into<MultiLocation>, message: Xcm<()>) -> Result {
/// return Err(Error::CannotReachDestination(destination.into(), message))
/// }
/// }
///
/// /// A sender that accepts a message that has an X2 junction, otherwise stops the routing.
/// struct Sender2;
/// impl SendXcm for Sender2 {
/// fn send_xcm(destination: MultiLocation, message: Xcm<()>) -> Result {
/// fn send_xcm(destination: impl Into<MultiLocation>, message: Xcm<()>) -> Result {
/// let destination = destination.into();
/// if matches!(destination.interior(), Junctions::X2(j1, j2))
/// && destination.parent_count() == 0
/// {
Expand All @@ -216,7 +222,8 @@ impl<C> ExecuteXcm<C> for () {
/// /// A sender that accepts a message from an X1 parent junction, passing through otherwise.
/// struct Sender3;
/// impl SendXcm for Sender3 {
/// fn send_xcm(destination: MultiLocation, message: Xcm<()>) -> Result {
/// fn send_xcm(destination: impl Into<MultiLocation>, message: Xcm<()>) -> Result {
/// let destination = destination.into();
/// if matches!(destination.interior(), Junctions::Here)
/// && destination.parent_count() == 1
/// {
Expand All @@ -231,17 +238,16 @@ impl<C> ExecuteXcm<C> for () {
/// # fn main() {
/// let call: Vec<u8> = ().encode();
/// let message = Xcm::Transact { origin_type: OriginKind::Superuser, require_weight_at_most: 0, call: call.into() };
/// let destination: MultiLocation = Parent.into();
///
/// assert!(
/// // Sender2 will block this.
/// <(Sender1, Sender2, Sender3) as SendXcm>::send_xcm(destination.clone(), message.clone())
/// <(Sender1, Sender2, Sender3) as SendXcm>::send_xcm(Parent, message.clone())
/// .is_err()
/// );
///
/// assert!(
/// // Sender3 will catch this.
/// <(Sender1, Sender3) as SendXcm>::send_xcm(destination.clone(), message.clone())
/// <(Sender1, Sender3) as SendXcm>::send_xcm(Parent, message.clone())
/// .is_ok()
/// );
/// # }
Expand All @@ -252,19 +258,19 @@ pub trait SendXcm {
/// If it is not a destination which can be reached with this type but possibly could by others, then it *MUST*
/// return `CannotReachDestination`. Any other error will cause the tuple implementation to exit early without
/// trying other type fields.
fn send_xcm(destination: MultiLocation, message: Xcm<()>) -> Result;
fn send_xcm(destination: impl Into<MultiLocation>, message: Xcm<()>) -> Result;
}

#[impl_trait_for_tuples::impl_for_tuples(30)]
impl SendXcm for Tuple {
fn send_xcm(destination: MultiLocation, message: Xcm<()>) -> Result {
fn send_xcm(destination: impl Into<MultiLocation>, message: Xcm<()>) -> Result {
for_tuples!( #(
// we shadow `destination` and `message` in each expansion for the next one.
let (destination, message) = match Tuple::send_xcm(destination, message) {
Err(Error::CannotReachDestination(d, m)) => (d, m),
o @ _ => return o,
};
)* );
Err(Error::CannotReachDestination(destination, message))
Err(Error::CannotReachDestination(destination.into(), message))
}
}
10 changes: 5 additions & 5 deletions xcm/xcm-builder/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ pub fn sent_xcm() -> Vec<(MultiLocation, opaque::Xcm)> {
}
pub struct TestSendXcm;
impl SendXcm for TestSendXcm {
fn send_xcm(dest: MultiLocation, msg: opaque::Xcm) -> XcmResult {
SENT_XCM.with(|q| q.borrow_mut().push((dest, msg)));
fn send_xcm(dest: impl Into<MultiLocation>, msg: opaque::Xcm) -> XcmResult {
SENT_XCM.with(|q| q.borrow_mut().push((dest.into(), msg)));
Ok(())
}
}
Expand Down Expand Up @@ -162,11 +162,11 @@ pub fn to_account(l: MultiLocation) -> Result<u64, MultiLocation> {
pub struct TestOriginConverter;
impl ConvertOrigin<TestOrigin> for TestOriginConverter {
fn convert_origin(
origin: MultiLocation,
origin: impl Into<MultiLocation>,
kind: OriginKind,
) -> Result<TestOrigin, MultiLocation> {
use OriginKind::*;
match (kind, origin) {
match (kind, origin.into()) {
(Superuser, _) => Ok(TestOrigin::Root),
(SovereignAccount, l) => Ok(TestOrigin::Signed(to_account(l)?)),
(Native, MultiLocation { parents: 0, interior: X1(Parachain(id)) }) =>
Expand Down Expand Up @@ -222,7 +222,7 @@ impl OnResponse for TestResponseHandler {
})
}
fn on_response(
_origin: MultiLocation,
_origin: impl Into<MultiLocation>,
query_id: u64,
response: xcm::latest::Response,
) -> Weight {
Expand Down
60 changes: 45 additions & 15 deletions xcm/xcm-builder/src/origin_conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ impl<LocationConverter: Convert<MultiLocation, Origin::AccountId>, Origin: Origi
where
Origin::AccountId: Clone,
{
fn convert_origin(origin: MultiLocation, kind: OriginKind) -> Result<Origin, MultiLocation> {
fn convert_origin(
origin: impl Into<MultiLocation>,
kind: OriginKind,
) -> Result<Origin, MultiLocation> {
let origin = origin.into();
if let OriginKind::SovereignAccount = kind {
let location = LocationConverter::convert(origin)?;
Ok(Origin::signed(location).into())
Expand All @@ -44,7 +48,11 @@ where

pub struct ParentAsSuperuser<Origin>(PhantomData<Origin>);
impl<Origin: OriginTrait> ConvertOrigin<Origin> for ParentAsSuperuser<Origin> {
fn convert_origin(origin: MultiLocation, kind: OriginKind) -> Result<Origin, MultiLocation> {
fn convert_origin(
origin: impl Into<MultiLocation>,
kind: OriginKind,
) -> Result<Origin, MultiLocation> {
let origin = origin.into();
if kind == OriginKind::Superuser && origin.contains_parents_only(1) {
Ok(Origin::root())
} else {
Expand All @@ -57,8 +65,11 @@ pub struct ChildSystemParachainAsSuperuser<ParaId, Origin>(PhantomData<(ParaId,
impl<ParaId: IsSystem + From<u32>, Origin: OriginTrait> ConvertOrigin<Origin>
for ChildSystemParachainAsSuperuser<ParaId, Origin>
{
fn convert_origin(origin: MultiLocation, kind: OriginKind) -> Result<Origin, MultiLocation> {
match (kind, origin) {
fn convert_origin(
origin: impl Into<MultiLocation>,
kind: OriginKind,
) -> Result<Origin, MultiLocation> {
match (kind, origin.into()) {
(
OriginKind::Superuser,
MultiLocation { parents: 0, interior: X1(Junction::Parachain(id)) },
Expand All @@ -72,8 +83,11 @@ pub struct SiblingSystemParachainAsSuperuser<ParaId, Origin>(PhantomData<(ParaId
impl<ParaId: IsSystem + From<u32>, Origin: OriginTrait> ConvertOrigin<Origin>
for SiblingSystemParachainAsSuperuser<ParaId, Origin>
{
fn convert_origin(origin: MultiLocation, kind: OriginKind) -> Result<Origin, MultiLocation> {
match (kind, origin) {
fn convert_origin(
origin: impl Into<MultiLocation>,
kind: OriginKind,
) -> Result<Origin, MultiLocation> {
match (kind, origin.into()) {
(
OriginKind::Superuser,
MultiLocation { parents: 1, interior: X1(Junction::Parachain(id)) },
Expand All @@ -87,8 +101,11 @@ pub struct ChildParachainAsNative<ParachainOrigin, Origin>(PhantomData<(Parachai
impl<ParachainOrigin: From<u32>, Origin: From<ParachainOrigin>> ConvertOrigin<Origin>
for ChildParachainAsNative<ParachainOrigin, Origin>
{
fn convert_origin(origin: MultiLocation, kind: OriginKind) -> Result<Origin, MultiLocation> {
match (kind, origin) {
fn convert_origin(
origin: impl Into<MultiLocation>,
kind: OriginKind,
) -> Result<Origin, MultiLocation> {
match (kind, origin.into()) {
(
OriginKind::Native,
MultiLocation { parents: 0, interior: X1(Junction::Parachain(id)) },
Expand All @@ -104,8 +121,11 @@ pub struct SiblingParachainAsNative<ParachainOrigin, Origin>(
impl<ParachainOrigin: From<u32>, Origin: From<ParachainOrigin>> ConvertOrigin<Origin>
for SiblingParachainAsNative<ParachainOrigin, Origin>
{
fn convert_origin(origin: MultiLocation, kind: OriginKind) -> Result<Origin, MultiLocation> {
match (kind, origin) {
fn convert_origin(
origin: impl Into<MultiLocation>,
kind: OriginKind,
) -> Result<Origin, MultiLocation> {
match (kind, origin.into()) {
(
OriginKind::Native,
MultiLocation { parents: 1, interior: X1(Junction::Parachain(id)) },
Expand All @@ -120,7 +140,11 @@ pub struct RelayChainAsNative<RelayOrigin, Origin>(PhantomData<(RelayOrigin, Ori
impl<RelayOrigin: Get<Origin>, Origin> ConvertOrigin<Origin>
for RelayChainAsNative<RelayOrigin, Origin>
{
fn convert_origin(origin: MultiLocation, kind: OriginKind) -> Result<Origin, MultiLocation> {
fn convert_origin(
origin: impl Into<MultiLocation>,
kind: OriginKind,
) -> Result<Origin, MultiLocation> {
let origin = origin.into();
if kind == OriginKind::Native && origin.contains_parents_only(1) {
Ok(RelayOrigin::get())
} else {
Expand All @@ -135,8 +159,11 @@ impl<Network: Get<NetworkId>, Origin: OriginTrait> ConvertOrigin<Origin>
where
Origin::AccountId: From<[u8; 32]>,
{
fn convert_origin(origin: MultiLocation, kind: OriginKind) -> Result<Origin, MultiLocation> {
match (kind, origin) {
fn convert_origin(
origin: impl Into<MultiLocation>,
kind: OriginKind,
) -> Result<Origin, MultiLocation> {
match (kind, origin.into()) {
(
OriginKind::Native,
MultiLocation { parents: 0, interior: X1(Junction::AccountId32 { id, network }) },
Expand All @@ -153,8 +180,11 @@ impl<Network: Get<NetworkId>, Origin: OriginTrait> ConvertOrigin<Origin>
where
Origin::AccountId: From<[u8; 20]>,
{
fn convert_origin(origin: MultiLocation, kind: OriginKind) -> Result<Origin, MultiLocation> {
match (kind, origin) {
fn convert_origin(
origin: impl Into<MultiLocation>,
kind: OriginKind,
) -> Result<Origin, MultiLocation> {
match (kind, origin.into()) {
(
OriginKind::Native,
MultiLocation { parents: 0, interior: X1(Junction::AccountKey20 { key, network }) },
Expand Down
Loading