diff --git a/Cargo.lock b/Cargo.lock index f555a51c5d4b..20c74f92afb0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10689,9 +10689,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.5.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cfdffd972d76b22f3d7f81c8be34b2296afd3a25e0a547bd9abe340a4dbbe97" +checksum = "b569c32c806ec3abdf3b5869fb8bf1e0d275a7c1c9b0b05603d9464632649edf" dependencies = [ "bitvec", "cfg-if", @@ -10703,9 +10703,9 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61fa974aea2d63dd18a4ec3a49d59af9f34178c73a4f56d2f18205628d00681e" +checksum = "53012eae69e5aa5c14671942a5dd47de59d4cdcff8532a6dd0e081faf1119482" dependencies = [ "proc-macro-crate", "proc-macro2", diff --git a/runtime/common/src/xcm_sender.rs b/runtime/common/src/xcm_sender.rs index 3654c44010e9..431c7180668a 100644 --- a/runtime/common/src/xcm_sender.rs +++ b/runtime/common/src/xcm_sender.rs @@ -79,7 +79,7 @@ impl>, ) -> SendResult<(HostConfiguration, ParaId, Vec)> { let d = dest.take().ok_or(MissingArgument)?; - let id = if let MultiLocation { parents: 0, interior: X1(Parachain(id)) } = &d { + let id = if let (0, [Parachain(id)]) = d.unpack() { *id } else { *dest = Some(d); diff --git a/runtime/kusama/src/lib.rs b/runtime/kusama/src/lib.rs index 57659f81cbdb..c091fba49e9c 100644 --- a/runtime/kusama/src/lib.rs +++ b/runtime/kusama/src/lib.rs @@ -2055,7 +2055,7 @@ sp_api::impl_runtime_apis! { } parameter_types! { - pub const TrustedTeleporter: Option<(MultiLocation, MultiAsset)> = Some(( + pub TrustedTeleporter: Option<(MultiLocation, MultiAsset)> = Some(( Statemine::get(), MultiAsset { fun: Fungible(1 * UNITS), id: Concrete(TokenLocation::get()) }, )); diff --git a/runtime/kusama/src/xcm_config.rs b/runtime/kusama/src/xcm_config.rs index 1806a06066dd..9e17b1dd8caa 100644 --- a/runtime/kusama/src/xcm_config.rs +++ b/runtime/kusama/src/xcm_config.rs @@ -22,7 +22,7 @@ use super::{ XcmPallet, }; use frame_support::{ - match_types, parameter_types, + parameter_types, traits::{Contains, Everything, Nothing}, weights::Weight, }; @@ -126,19 +126,20 @@ pub type XcmRouter = ( parameter_types! { pub const Ksm: MultiAssetFilter = Wild(AllOf { fun: WildFungible, id: Concrete(TokenLocation::get()) }); - pub const Statemine: MultiLocation = Parachain(1000).into_location(); - pub const Encointer: MultiLocation = Parachain(1001).into_location(); - pub const KsmForStatemine: (MultiAssetFilter, MultiLocation) = (Ksm::get(), Statemine::get()); - pub const KsmForEncointer: (MultiAssetFilter, MultiLocation) = (Ksm::get(), Encointer::get()); + pub Statemine: MultiLocation = Parachain(1000).into_location(); + pub Encointer: MultiLocation = Parachain(1001).into_location(); + pub KsmForStatemine: (MultiAssetFilter, MultiLocation) = (Ksm::get(), Statemine::get()); + pub KsmForEncointer: (MultiAssetFilter, MultiLocation) = (Ksm::get(), Encointer::get()); pub const MaxAssetsIntoHolding: u32 = 64; } pub type TrustedTeleporters = (xcm_builder::Case, xcm_builder::Case); -match_types! { - pub type OnlyParachains: impl Contains = { - MultiLocation { parents: 0, interior: X1(Parachain(_)) } - }; +pub struct OnlyParachains; +impl Contains for OnlyParachains { + fn contains(loc: &MultiLocation) -> bool { + matches!(loc.unpack(), (0, [Parachain(_)])) + } } /// The barriers one of which must be passed for an XCM message to be executed. diff --git a/runtime/polkadot/src/xcm_config.rs b/runtime/polkadot/src/xcm_config.rs index d154959781f9..dfb50ad41d35 100644 --- a/runtime/polkadot/src/xcm_config.rs +++ b/runtime/polkadot/src/xcm_config.rs @@ -22,7 +22,7 @@ use super::{ TransactionByteFee, WeightToFee, XcmPallet, }; use frame_support::{ - match_types, parameter_types, + parameter_types, traits::{Contains, Everything, Nothing}, weights::Weight, }; @@ -56,7 +56,7 @@ parameter_types! { /// The Polkadot network ID. This is named. pub const ThisNetwork: NetworkId = NetworkId::Polkadot; /// Our location in the universe of consensus systems. - pub const UniversalLocation: InteriorMultiLocation = X1(GlobalConsensus(ThisNetwork::get())); + pub UniversalLocation: InteriorMultiLocation = [GlobalConsensus(ThisNetwork::get())].into(); /// The Checking Account, which holds any native assets that have been teleported out and not back in (yet). pub CheckAccount: AccountId = XcmPallet::check_account(); /// The Checking Account along with the indication that the local chain is able to mint tokens. @@ -134,9 +134,9 @@ pub type XcmRouter = ( parameter_types! { pub const Dot: MultiAssetFilter = Wild(AllOf { fun: WildFungible, id: Concrete(TokenLocation::get()) }); - pub const DotForStatemint: (MultiAssetFilter, MultiLocation) = (Dot::get(), Parachain(STATEMINT_ID).into_location()); - pub const CollectivesLocation: MultiLocation = Parachain(COLLECTIVES_ID).into_location(); - pub const DotForCollectives: (MultiAssetFilter, MultiLocation) = (Dot::get(), CollectivesLocation::get()); + pub DotForStatemint: (MultiAssetFilter, MultiLocation) = (Dot::get(), Parachain(STATEMINT_ID).into_location()); + pub CollectivesLocation: MultiLocation = Parachain(COLLECTIVES_ID).into_location(); + pub DotForCollectives: (MultiAssetFilter, MultiLocation) = (Dot::get(), CollectivesLocation::get()); pub const MaxAssetsIntoHolding: u32 = 64; } @@ -144,14 +144,21 @@ parameter_types! { pub type TrustedTeleporters = (xcm_builder::Case, xcm_builder::Case); -match_types! { - pub type OnlyParachains: impl Contains = { - MultiLocation { parents: 0, interior: X1(Parachain(_)) } - }; - pub type CollectivesOrFellows: impl Contains = { - MultiLocation { parents: 0, interior: X1(Parachain(COLLECTIVES_ID)) } | - MultiLocation { parents: 0, interior: X2(Parachain(COLLECTIVES_ID), Plurality { id: BodyId::Technical, .. }) } - }; +pub struct OnlyParachains; +impl Contains for OnlyParachains { + fn contains(loc: &MultiLocation) -> bool { + matches!(loc.unpack(), (0, [Parachain(_)])) + } +} + +pub struct CollectivesOrFellows; +impl Contains for CollectivesOrFellows { + fn contains(loc: &MultiLocation) -> bool { + matches!(loc.unpack(), |(0, [Parachain(COLLECTIVES_ID)])| ( + 0, + [Parachain(COLLECTIVES_ID), Plurality { id: BodyId::Technical, .. }] + )) + } } /// The barriers one of which must be passed for an XCM message to be executed. diff --git a/runtime/rococo/src/lib.rs b/runtime/rococo/src/lib.rs index 0f2c63e22a6e..0fb02a219182 100644 --- a/runtime/rococo/src/lib.rs +++ b/runtime/rococo/src/lib.rs @@ -2061,11 +2061,11 @@ sp_api::impl_runtime_apis! { } parameter_types! { - pub const TrustedTeleporter: Option<(MultiLocation, MultiAsset)> = Some(( + pub TrustedTeleporter: Option<(MultiLocation, MultiAsset)> = Some(( Statemine::get(), MultiAsset { fun: Fungible(1 * UNITS), id: Concrete(TokenLocation::get()) }, )); - pub const TrustedReserve: Option<(MultiLocation, MultiAsset)> = Some(( + pub TrustedReserve: Option<(MultiLocation, MultiAsset)> = Some(( Statemine::get(), MultiAsset { fun: Fungible(1 * UNITS), id: Concrete(TokenLocation::get()) }, )); diff --git a/runtime/rococo/src/xcm_config.rs b/runtime/rococo/src/xcm_config.rs index 4bf3cb3181ea..b7abf38cf389 100644 --- a/runtime/rococo/src/xcm_config.rs +++ b/runtime/rococo/src/xcm_config.rs @@ -21,7 +21,7 @@ use super::{ Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, TransactionByteFee, WeightToFee, XcmPallet, }; use frame_support::{ - match_types, parameter_types, + parameter_types, traits::{Contains, Everything, Nothing}, weights::Weight, }; @@ -45,7 +45,7 @@ use xcm_builder::{ use xcm_executor::{traits::WithOriginFilter, XcmExecutor}; parameter_types! { - pub const TokenLocation: MultiLocation = Here.into_location(); + pub TokenLocation: MultiLocation = Here.into_location(); pub const ThisNetwork: NetworkId = NetworkId::Rococo; pub UniversalLocation: InteriorMultiLocation = ThisNetwork::get().into(); pub CheckAccount: AccountId = XcmPallet::check_account(); @@ -105,19 +105,19 @@ pub type XcmRouter = ( ); parameter_types! { - pub const Roc: MultiAssetFilter = Wild(AllOf { fun: WildFungible, id: Concrete(TokenLocation::get()) }); - pub const Statemine: MultiLocation = Parachain(1000).into_location(); - pub const Contracts: MultiLocation = Parachain(1002).into_location(); - pub const Encointer: MultiLocation = Parachain(1003).into_location(); - pub const Tick: MultiLocation = Parachain(100).into_location(); - pub const Trick: MultiLocation = Parachain(110).into_location(); - pub const Track: MultiLocation = Parachain(120).into_location(); - pub const RocForTick: (MultiAssetFilter, MultiLocation) = (Roc::get(), Tick::get()); - pub const RocForTrick: (MultiAssetFilter, MultiLocation) = (Roc::get(), Trick::get()); - pub const RocForTrack: (MultiAssetFilter, MultiLocation) = (Roc::get(), Track::get()); - pub const RocForStatemine: (MultiAssetFilter, MultiLocation) = (Roc::get(), Statemine::get()); - pub const RocForContracts: (MultiAssetFilter, MultiLocation) = (Roc::get(), Contracts::get()); - pub const RocForEncointer: (MultiAssetFilter, MultiLocation) = (Roc::get(), Encointer::get()); + pub Roc: MultiAssetFilter = Wild(AllOf { fun: WildFungible, id: Concrete(TokenLocation::get()) }); + pub Statemine: MultiLocation = Parachain(1000).into_location(); + pub Contracts: MultiLocation = Parachain(1002).into_location(); + pub Encointer: MultiLocation = Parachain(1003).into_location(); + pub Tick: MultiLocation = Parachain(100).into_location(); + pub Trick: MultiLocation = Parachain(110).into_location(); + pub Track: MultiLocation = Parachain(120).into_location(); + pub RocForTick: (MultiAssetFilter, MultiLocation) = (Roc::get(), Tick::get()); + pub RocForTrick: (MultiAssetFilter, MultiLocation) = (Roc::get(), Trick::get()); + pub RocForTrack: (MultiAssetFilter, MultiLocation) = (Roc::get(), Track::get()); + pub RocForStatemine: (MultiAssetFilter, MultiLocation) = (Roc::get(), Statemine::get()); + pub RocForContracts: (MultiAssetFilter, MultiLocation) = (Roc::get(), Contracts::get()); + pub RocForEncointer: (MultiAssetFilter, MultiLocation) = (Roc::get(), Encointer::get()); pub const MaxInstructions: u32 = 100; pub const MaxAssetsIntoHolding: u32 = 64; } @@ -130,10 +130,11 @@ pub type TrustedTeleporters = ( xcm_builder::Case, ); -match_types! { - pub type OnlyParachains: impl Contains = { - MultiLocation { parents: 0, interior: X1(Parachain(_)) } - }; +pub struct OnlyParachains; +impl Contains for OnlyParachains { + fn contains(loc: &MultiLocation) -> bool { + matches!(loc.unpack(), (0, [Parachain(_)])) + } } /// The barriers one of which must be passed for an XCM message to be executed. diff --git a/runtime/westend/src/lib.rs b/runtime/westend/src/lib.rs index 538900f83a78..42dec37245fd 100644 --- a/runtime/westend/src/lib.rs +++ b/runtime/westend/src/lib.rs @@ -1802,7 +1802,7 @@ sp_api::impl_runtime_apis! { } parameter_types! { - pub const TrustedTeleporter: Option<(MultiLocation, MultiAsset)> = Some(( + pub TrustedTeleporter: Option<(MultiLocation, MultiAsset)> = Some(( Westmint::get(), MultiAsset { fun: Fungible(1 * UNITS), id: Concrete(TokenLocation::get()) }, )); diff --git a/runtime/westend/src/xcm_config.rs b/runtime/westend/src/xcm_config.rs index 7e37d227a677..6a3f1f4bbca4 100644 --- a/runtime/westend/src/xcm_config.rs +++ b/runtime/westend/src/xcm_config.rs @@ -90,11 +90,11 @@ pub type XcmRouter = ( ); parameter_types! { - pub const Westmint: MultiLocation = Parachain(1000).into_location(); - pub const Collectives: MultiLocation = Parachain(1001).into_location(); + pub Westmint: MultiLocation = Parachain(1000).into_location(); + pub Collectives: MultiLocation = Parachain(1001).into_location(); pub const Wnd: MultiAssetFilter = Wild(AllOf { fun: WildFungible, id: Concrete(TokenLocation::get()) }); - pub const WndForWestmint: (MultiAssetFilter, MultiLocation) = (Wnd::get(), Westmint::get()); - pub const WndForCollectives: (MultiAssetFilter, MultiLocation) = (Wnd::get(), Collectives::get()); + pub WndForWestmint: (MultiAssetFilter, MultiLocation) = (Wnd::get(), Westmint::get()); + pub WndForCollectives: (MultiAssetFilter, MultiLocation) = (Wnd::get(), Collectives::get()); pub const MaxInstructions: u32 = 100; pub const MaxAssetsIntoHolding: u32 = 64; } diff --git a/xcm/Cargo.toml b/xcm/Cargo.toml index e2a123a16680..9cd63dcf6bbd 100644 --- a/xcm/Cargo.toml +++ b/xcm/Cargo.toml @@ -13,7 +13,7 @@ log = { version = "0.4.17", default-features = false } parity-scale-codec = { version = "3.4.0", default-features = false, features = [ "derive", "max-encoded-len" ] } scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } sp-weights = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -serde = { version = "1.0.136", optional = true, features = ["derive"] } +serde = { version = "1.0.136", optional = true, features = ["derive", "rc"] } xcm-procedural = { path = "procedural" } [dev-dependencies] diff --git a/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs b/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs index 382434ea1c28..edf365b059f3 100644 --- a/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs +++ b/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs @@ -167,7 +167,7 @@ impl crate::Config for Test { type AccountIdConverter = AccountIdConverter; fn valid_destination() -> Result { let valid_destination: MultiLocation = - X1(AccountId32 { network: None, id: [0u8; 32] }).into(); + [AccountId32 { network: None, id: [0u8; 32] }].into(); Ok(valid_destination) } @@ -183,14 +183,14 @@ pub type TrustedTeleporters = (xcm_builder::Case,); parameter_types! { pub const CheckingAccount: Option<(u64, MintLocation)> = Some((100, MintLocation::Local)); - pub const ChildTeleporter: MultiLocation = Parachain(1000).into_location(); - pub const TrustedTeleporter: Option<(MultiLocation, MultiAsset)> = Some(( + pub ChildTeleporter: MultiLocation = Parachain(1000).into_location(); + pub TrustedTeleporter: Option<(MultiLocation, MultiAsset)> = Some(( ChildTeleporter::get(), MultiAsset { id: Concrete(Here.into_location()), fun: Fungible(100) }, )); - pub const TeleportConcreteFungible: (MultiAssetFilter, MultiLocation) = + pub TeleportConcreteFungible: (MultiAssetFilter, MultiLocation) = (Wild(AllOf { fun: WildFungible, id: Concrete(Here.into_location()) }), ChildTeleporter::get()); - pub const ReserveConcreteFungible: (MultiAssetFilter, MultiLocation) = + pub ReserveConcreteFungible: (MultiAssetFilter, MultiLocation) = (Wild(AllOf { fun: WildFungible, id: Concrete(Here.into_location()) }), ChildTeleporter::get()); } diff --git a/xcm/pallet-xcm-benchmarks/src/generic/benchmarking.rs b/xcm/pallet-xcm-benchmarks/src/generic/benchmarking.rs index b10c924529ba..475dad41506a 100644 --- a/xcm/pallet-xcm-benchmarks/src/generic/benchmarking.rs +++ b/xcm/pallet-xcm-benchmarks/src/generic/benchmarking.rs @@ -156,7 +156,7 @@ benchmarks! { descend_origin { let mut executor = new_executor::(Default::default()); - let who = X2(OnlyChild, OnlyChild); + let who = Junctions::from([OnlyChild, OnlyChild]); let instruction = Instruction::DescendOrigin(who.clone()); let xcm = Xcm(vec![instruction]); } : { @@ -493,7 +493,7 @@ benchmarks! { } verify { use frame_support::traits::Get; let universal_location = ::UniversalLocation::get(); - assert_eq!(executor.origin(), &Some(X1(alias).relative_to(&universal_location))); + assert_eq!(executor.origin(), &Some(Junctions::from([alias]).relative_to(&universal_location))); } export_message { diff --git a/xcm/pallet-xcm-benchmarks/src/generic/mock.rs b/xcm/pallet-xcm-benchmarks/src/generic/mock.rs index df6e7713b8a9..bb156843fd47 100644 --- a/xcm/pallet-xcm-benchmarks/src/generic/mock.rs +++ b/xcm/pallet-xcm-benchmarks/src/generic/mock.rs @@ -178,7 +178,7 @@ impl generic::Config for Test { fn claimable_asset() -> Result<(MultiLocation, MultiLocation, MultiAssets), BenchmarkError> { let assets: MultiAssets = (Concrete(Here.into()), 100).into(); - let ticket = MultiLocation { parents: 0, interior: X1(GeneralIndex(0)) }; + let ticket = MultiLocation { parents: 0, interior: [GeneralIndex(0)].into() }; Ok((Default::default(), ticket, assets)) } diff --git a/xcm/pallet-xcm-benchmarks/src/mock.rs b/xcm/pallet-xcm-benchmarks/src/mock.rs index 5cb7dc8f4df5..970280c565a0 100644 --- a/xcm/pallet-xcm-benchmarks/src/mock.rs +++ b/xcm/pallet-xcm-benchmarks/src/mock.rs @@ -49,8 +49,8 @@ impl xcm_executor::traits::OnResponse for DevNull { pub struct AccountIdConverter; impl xcm_executor::traits::Convert for AccountIdConverter { fn convert(ml: MultiLocation) -> Result { - match ml { - MultiLocation { parents: 0, interior: X1(Junction::AccountId32 { id, .. }) } => + match ml.unpack() { + (0, [Junction::AccountId32 { id, .. }]) => Ok(::decode(&mut &*id.to_vec()).unwrap()), _ => Err(ml), } diff --git a/xcm/pallet-xcm/src/benchmarking.rs b/xcm/pallet-xcm/src/benchmarking.rs index aca4bd1fb3fa..86210a0ef26d 100644 --- a/xcm/pallet-xcm/src/benchmarking.rs +++ b/xcm/pallet-xcm/src/benchmarking.rs @@ -111,7 +111,7 @@ benchmarks! { let loc = T::ReachableDest::get().ok_or( BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)), )?; - let versioned_loc: VersionedMultiLocation = loc.into(); + let versioned_loc: VersionedMultiLocation = loc.clone().into(); let _ = Pallet::::request_version_notify(loc); }: _(RawOrigin::Root, Box::new(versioned_loc)) diff --git a/xcm/pallet-xcm/src/lib.rs b/xcm/pallet-xcm/src/lib.rs index 16766b7ab90f..e3471dd1222b 100644 --- a/xcm/pallet-xcm/src/lib.rs +++ b/xcm/pallet-xcm/src/lib.rs @@ -787,11 +787,11 @@ pub mod pallet { ) -> DispatchResult { let origin_location = T::SendXcmOrigin::ensure_origin(origin)?; let interior: Junctions = - origin_location.try_into().map_err(|_| Error::::InvalidOrigin)?; + origin_location.clone().try_into().map_err(|_| Error::::InvalidOrigin)?; let dest = MultiLocation::try_from(*dest).map_err(|()| Error::::BadVersion)?; let message: Xcm<()> = (*message).try_into().map_err(|()| Error::::BadVersion)?; - Self::send_xcm(interior, dest, message.clone()).map_err(Error::::from)?; + Self::send_xcm(interior, dest.clone(), message.clone()).map_err(Error::::from)?; Self::deposit_event(Event::Sent(origin_location, dest, message)); Ok(()) } @@ -803,8 +803,8 @@ pub mod pallet { /// with all fees taken as needed from the asset. /// /// - `origin`: Must be capable of withdrawing the `assets` and executing XCM. - /// - `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send - /// from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain. + /// - `dest`: Destination context for the assets. Will typically be `[Parent, Parachain(..)]` to send + /// from parachain to parachain, or `[Parachain(..)]` to send from relay to parachain. /// - `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be /// an `AccountId32` value. /// - `assets`: The assets to be withdrawn. The first item should be the currency used to to pay the fee on the @@ -851,8 +851,8 @@ pub mod pallet { /// with all fees taken as needed from the asset. /// /// - `origin`: Must be capable of withdrawing the `assets` and executing XCM. - /// - `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send - /// from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain. + /// - `dest`: Destination context for the assets. Will typically be `[Parent, Parachain(..)]` to send + /// from parachain to parachain, or `[Parachain(..)]` to send from relay to parachain. /// - `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be /// an `AccountId32` value. /// - `assets`: The assets to be withdrawn. This should include the assets used to pay the fee on the @@ -1024,8 +1024,8 @@ pub mod pallet { /// at risk. /// /// - `origin`: Must be capable of withdrawing the `assets` and executing XCM. - /// - `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send - /// from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain. + /// - `dest`: Destination context for the assets. Will typically be `[Parent, Parachain(..)]` to send + /// from parachain to parachain, or `[Parachain(..)]` to send from relay to parachain. /// - `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be /// an `AccountId32` value. /// - `assets`: The assets to be withdrawn. This should include the assets used to pay the fee on the @@ -1075,8 +1075,8 @@ pub mod pallet { /// at risk. /// /// - `origin`: Must be capable of withdrawing the `assets` and executing XCM. - /// - `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send - /// from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain. + /// - `dest`: Destination context for the assets. Will typically be `[Parent, Parachain(..)]` to send + /// from parachain to parachain, or `[Parachain(..)]` to send from relay to parachain. /// - `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be /// an `AccountId32` value. /// - `assets`: The assets to be withdrawn. The first item should be the currency used to to pay the fee on the @@ -1160,7 +1160,7 @@ impl Pallet { .get(fee_asset_item as usize) .ok_or(Error::::Empty)? .clone() - .reanchored(&dest, context) + .reanchored(&dest, &context) .map_err(|_| Error::::CannotReanchor)?; let max_assets = assets.len() as u32; let assets: MultiAssets = assets.into(); @@ -1172,7 +1172,10 @@ impl Pallet { ReserveAssetDeposited(assets.clone()), ClearOrigin, BuyExecution { fees, weight_limit: Limited(Weight::zero()) }, - DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary }, + DepositAsset { + assets: Wild(AllCounted(max_assets)), + beneficiary: beneficiary.clone(), + }, ]); // use local weight for remote message and hope for the best. let remote_weight = T::Weigher::weight(&mut remote_message) @@ -1220,7 +1223,7 @@ impl Pallet { .get(fee_asset_item as usize) .ok_or(Error::::Empty)? .clone() - .reanchored(&dest, context) + .reanchored(&dest, &context) .map_err(|_| Error::::CannotReanchor)?; let max_assets = assets.len() as u32; let assets: MultiAssets = assets.into(); @@ -1232,7 +1235,10 @@ impl Pallet { ReceiveTeleportedAsset(assets.clone()), ClearOrigin, BuyExecution { fees, weight_limit: Limited(Weight::zero()) }, - DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary }, + DepositAsset { + assets: Wild(AllCounted(max_assets)), + beneficiary: beneficiary.clone(), + }, ]); // use local weight for remote message and hope for the best. let remote_weight = T::Weigher::weight(&mut remote_message) @@ -1328,7 +1334,7 @@ impl Pallet { let response = Response::Version(xcm_version); let message = Xcm(vec![QueryResponse { query_id, response, max_weight, querier: None }]); - let event = match send_xcm::(new_key, message) { + let event = match send_xcm::(new_key.clone(), message) { Ok((_hash, cost)) => { let value = (query_id, max_weight, xcm_version); VersionNotifyTargets::::insert(XCM_VERSION, key, value); @@ -1377,7 +1383,7 @@ impl Pallet { max_weight, querier: None, }]); - let event = match send_xcm::(new_key, message) { + let event = match send_xcm::(new_key.clone(), message) { Ok((_hash, cost)) => { VersionNotifyTargets::::insert( XCM_VERSION, @@ -1403,7 +1409,7 @@ impl Pallet { /// Request that `dest` informs us of its version. pub fn request_version_notify(dest: impl Into) -> XcmResult { let dest = dest.into(); - let versioned_dest = VersionedMultiLocation::from(dest); + let versioned_dest = VersionedMultiLocation::from(dest.clone()); let already = VersionNotifiers::::contains_key(XCM_VERSION, &versioned_dest); ensure!(!already, XcmError::InvalidLocation); let query_id = QueryCounter::::mutate(|q| { @@ -1413,7 +1419,7 @@ impl Pallet { }); // TODO #3735: Correct weight. let instruction = SubscribeVersion { query_id, max_response_weight: Weight::zero() }; - let (_hash, cost) = send_xcm::(dest, Xcm(vec![instruction]))?; + let (_hash, cost) = send_xcm::(dest.clone(), Xcm(vec![instruction]))?; Self::deposit_event(Event::VersionNotifyRequested(dest, cost)); VersionNotifiers::::insert(XCM_VERSION, &versioned_dest, query_id); let query_status = @@ -1428,7 +1434,7 @@ impl Pallet { let versioned_dest = LatestVersionedMultiLocation(&dest); let query_id = VersionNotifiers::::take(XCM_VERSION, versioned_dest) .ok_or(XcmError::InvalidLocation)?; - let (_hash, cost) = send_xcm::(dest, Xcm(vec![UnsubscribeVersion]))?; + let (_hash, cost) = send_xcm::(dest.clone(), Xcm(vec![UnsubscribeVersion]))?; Self::deposit_event(Event::VersionNotifyUnrequested(dest, cost)); Queries::::remove(query_id); Ok(()) @@ -1445,7 +1451,7 @@ impl Pallet { let interior = interior.into(); let dest = dest.into(); let maybe_fee_payer = if interior != Junctions::Here { - message.0.insert(0, DescendOrigin(interior)); + message.0.insert(0, DescendOrigin(interior.clone())); Some(interior.into()) } else { None @@ -1602,7 +1608,7 @@ impl Pallet { "XCM version is unknown for destination: {:?}", dest, ); - let versioned_dest = VersionedMultiLocation::from(*dest); + let versioned_dest = VersionedMultiLocation::from(dest.clone()); VersionDiscoveryQueue::::mutate(|q| { if let Some(index) = q.iter().position(|i| &i.0 == &versioned_dest) { // exists - just bump the count. @@ -1619,7 +1625,7 @@ impl Pallet { /// - the `assets` are not known on this chain; /// - the `assets` cannot be withdrawn with that location as the Origin. fn charge_fees(location: MultiLocation, assets: MultiAssets) -> DispatchResult { - T::XcmExecutor::charge_fees(location, assets.clone()) + T::XcmExecutor::charge_fees(location.clone(), assets.clone()) .map_err(|_| Error::::FeesNotMet)?; Self::deposit_event(Event::FeesPaid(location, assets)); Ok(()) @@ -1859,8 +1865,8 @@ impl VersionChangeNotifier for Pallet { let xcm_version = T::AdvertisedXcmVersion::get(); let response = Response::Version(xcm_version); let instruction = QueryResponse { query_id, response, max_weight, querier: None }; - let (_hash, cost) = send_xcm::(*dest, Xcm(vec![instruction]))?; - Self::deposit_event(Event::::VersionNotifyStarted(*dest, cost)); + let (_hash, cost) = send_xcm::(dest.clone(), Xcm(vec![instruction]))?; + Self::deposit_event(Event::::VersionNotifyStarted(dest.clone(), cost)); let value = (query_id, max_weight, xcm_version); VersionNotifyTargets::::insert(XCM_VERSION, versioned_dest, value); @@ -1889,7 +1895,7 @@ impl DropAssets for Pallet { let versioned = VersionedMultiAssets::from(MultiAssets::from(assets)); let hash = BlakeTwo256::hash_of(&(&origin, &versioned)); AssetTraps::::mutate(hash, |n| *n += 1); - Self::deposit_event(Event::AssetsTrapped(hash, *origin, versioned)); + Self::deposit_event(Event::AssetsTrapped(hash, origin.clone(), versioned)); // TODO #3735: Put the real weight in there. Weight::zero() } @@ -1903,22 +1909,22 @@ impl ClaimAssets for Pallet { _context: &XcmContext, ) -> bool { let mut versioned = VersionedMultiAssets::from(assets.clone()); - match (ticket.parents, &ticket.interior) { - (0, X1(GeneralIndex(i))) => + match ticket.unpack() { + (0, [GeneralIndex(i)]) => versioned = match versioned.into_version(*i as u32) { Ok(v) => v, Err(()) => return false, }, - (0, Here) => (), + (0, []) => (), _ => return false, }; - let hash = BlakeTwo256::hash_of(&(origin, versioned.clone())); + let hash = BlakeTwo256::hash_of(&(origin.clone(), versioned.clone())); match AssetTraps::::get(hash) { 0 => return false, 1 => AssetTraps::::remove(hash), n => AssetTraps::::insert(hash, n - 1), } - Self::deposit_event(Event::AssetsClaimed(hash, *origin, versioned)); + Self::deposit_event(Event::AssetsClaimed(hash, origin.clone(), versioned)); return true } } @@ -1959,11 +1965,19 @@ impl OnResponse for Pallet { let origin: MultiLocation = match expected_origin.try_into() { Ok(o) if &o == origin => o, Ok(o) => { - Self::deposit_event(Event::InvalidResponder(*origin, query_id, Some(o))); + Self::deposit_event(Event::InvalidResponder( + origin.clone(), + query_id, + Some(o), + )); return Weight::zero() }, _ => { - Self::deposit_event(Event::InvalidResponder(*origin, query_id, None)); + Self::deposit_event(Event::InvalidResponder( + origin.clone(), + query_id, + None, + )); // TODO #3735: Correct weight for this. return Weight::zero() }, @@ -1972,7 +1986,10 @@ impl OnResponse for Pallet { if !is_active { Queries::::insert( query_id, - QueryStatus::VersionNotifier { origin: origin.into(), is_active: true }, + QueryStatus::VersionNotifier { + origin: origin.clone().into(), + is_active: true, + }, ); } // We're being notified of a version change. @@ -1992,13 +2009,16 @@ impl OnResponse for Pallet { let match_querier = match MultiLocation::try_from(match_querier) { Ok(mq) => mq, Err(_) => { - Self::deposit_event(Event::InvalidQuerierVersion(*origin, query_id)); + Self::deposit_event(Event::InvalidQuerierVersion( + origin.clone(), + query_id, + )); return Weight::zero() }, }; if querier.map_or(true, |q| q != &match_querier) { Self::deposit_event(Event::InvalidQuerier( - *origin, + origin.clone(), query_id, match_querier, querier.cloned(), @@ -2009,13 +2029,16 @@ impl OnResponse for Pallet { let responder = match MultiLocation::try_from(responder) { Ok(r) => r, Err(_) => { - Self::deposit_event(Event::InvalidResponderVersion(*origin, query_id)); + Self::deposit_event(Event::InvalidResponderVersion( + origin.clone(), + query_id, + )); return Weight::zero() }, }; if origin != &responder { Self::deposit_event(Event::InvalidResponder( - *origin, + origin.clone(), query_id, Some(responder), )); @@ -2043,7 +2066,7 @@ impl OnResponse for Pallet { Self::deposit_event(e); return Weight::zero() } - let dispatch_origin = Origin::Response(*origin).into(); + let dispatch_origin = Origin::Response(origin.clone()).into(); match call.dispatch(dispatch_origin) { Ok(post_info) => { let e = Event::Notified(query_id, pallet_index, call_index); @@ -2080,7 +2103,7 @@ impl OnResponse for Pallet { } }, _ => { - Self::deposit_event(Event::UnexpectedResponse(*origin, query_id)); + Self::deposit_event(Event::UnexpectedResponse(origin.clone(), query_id)); Weight::zero() }, } diff --git a/xcm/procedural/src/v2.rs b/xcm/procedural/src/v2.rs index dc2694a666f0..655fae91f38f 100644 --- a/xcm/procedural/src/v2.rs +++ b/xcm/procedural/src/v2.rs @@ -41,32 +41,31 @@ pub mod multilocation { (0..=num_junctions).map(|_| format_ident!("Junction")).collect::>(); let idents = (0..=num_junctions).map(|i| format_ident!("j{}", i)).collect::>(); - let variant = &format_ident!("X{}", num_junctions + 1); let array_size = num_junctions + 1; let mut from_tuple = quote! { impl From<( #(#junctions,)* )> for MultiLocation { fn from( ( #(#idents,)* ): ( #(#junctions,)* ) ) -> Self { - MultiLocation { parents: 0, interior: Junctions::#variant( #(#idents),* ) } + MultiLocation { parents: 0, interior: [#(#idents),*].into() } } } impl From<(u8, #(#junctions),*)> for MultiLocation { fn from( ( parents, #(#idents),* ): (u8, #(#junctions),* ) ) -> Self { - MultiLocation { parents, interior: Junctions::#variant( #(#idents),* ) } + MultiLocation { parents, interior: [#(#idents),*].into() } } } impl From<(Ancestor, #(#junctions),*)> for MultiLocation { fn from( ( Ancestor(parents), #(#idents),* ): (Ancestor, #(#junctions),* ) ) -> Self { - MultiLocation { parents, interior: Junctions::#variant( #(#idents),* ) } + MultiLocation { parents, interior: [#(#idents),*].into() } } } impl From<[Junction; #array_size]> for MultiLocation { fn from(j: [Junction; #array_size]) -> Self { let [#(#idents),*] = j; - MultiLocation { parents: 0, interior: Junctions::#variant( #(#idents),* ) } + MultiLocation { parents: 0, interior: [#(#idents),*].into() } } } }; @@ -80,7 +79,7 @@ pub mod multilocation { quote! { impl From<( #(#parents,)* #(#junctions),* )> for MultiLocation { fn from( (#(#underscores,)* #(#idents),*): ( #(#parents,)* #(#junctions),* ) ) -> Self { - MultiLocation { parents: #cur_parents, interior: Junctions::#variant( #(#idents),* ) } + MultiLocation { parents: #cur_parents, interior: [#(#idents),*].into() } } } } @@ -139,7 +138,7 @@ pub mod multilocation { impl From for MultiLocation { fn from(x: Junction) -> Self { - MultiLocation { parents: 0, interior: Junctions::X1(x) } + MultiLocation { parents: 0, interior: [x].into() } } } @@ -159,10 +158,19 @@ pub mod multilocation { let num_ancestors = cur_num + 1; let variant = format_ident!("X{}", num_ancestors); let idents = (0..=cur_num).map(|i| format_ident!("j{}", i)).collect::>(); + let convert = idents + .iter() + .map(|ident| { + quote! { let #ident = core::convert::TryInto::try_into(#ident)?; } + }) + .collect::>(); quote! { - crate::v3::Junctions::#variant( #(#idents),* ) => - #variant( #( core::convert::TryInto::try_into(#idents)? ),* ), + crate::v3::Junctions::#variant( junctions ) => { + let [#(#idents),*] = *junctions; + #(#convert);* + [#(#idents),*].into() + }, } }) .collect::(); diff --git a/xcm/procedural/src/v3.rs b/xcm/procedural/src/v3.rs index 246f90a46a3e..df255a50d7af 100644 --- a/xcm/procedural/src/v3.rs +++ b/xcm/procedural/src/v3.rs @@ -45,9 +45,8 @@ pub mod multilocation { let interior = if num_junctions == 0 { quote!(Junctions::Here) } else { - let variant = format_ident!("X{}", num_junctions); quote! { - Junctions::#variant( #(#idents .into()),* ) + [#(#idents .into()),*].into() } }; @@ -110,7 +109,7 @@ pub mod multilocation { impl From for MultiLocation { fn from(x: Junction) -> Self { - MultiLocation { parents: 0, interior: Junctions::X1(x) } + MultiLocation { parents: 0, interior: [x].into() } } } @@ -143,12 +142,11 @@ pub mod junctions { let idents = (0..num_junctions).map(|i| format_ident!("j{}", i)).collect::>(); let types = (0..num_junctions).map(|i| format_ident!("J{}", i)).collect::>(); - let variant = &format_ident!("X{}", num_junctions); quote! { impl<#(#types : Into,)*> From<( #(#types,)* )> for Junctions { fn from( ( #(#idents,)* ): ( #(#types,)* ) ) -> Self { - Self::#variant( #(#idents .into()),* ) + [#(#idents .into()),*].into() } } } @@ -162,10 +160,19 @@ pub mod junctions { let num_ancestors = cur_num + 1; let variant = format_ident!("X{}", num_ancestors); let idents = (0..=cur_num).map(|i| format_ident!("j{}", i)).collect::>(); + let convert = idents + .iter() + .map(|ident| { + quote! { let #ident = core::convert::TryInto::try_into(#ident.clone())?; } + }) + .collect::>(); quote! { - crate::v2::Junctions::#variant( #(#idents),* ) => - #variant( #( core::convert::TryInto::try_into(#idents)? ),* ), + crate::v2::Junctions::#variant( junctions ) => { + let [#(#idents),*] = &*junctions; + #(#convert);* + [#(#idents),*].into() + }, } }) .collect::(); diff --git a/xcm/src/lib.rs b/xcm/src/lib.rs index 40ba1dc7dcb4..948fc6fbf058 100644 --- a/xcm/src/lib.rs +++ b/xcm/src/lib.rs @@ -433,3 +433,59 @@ fn conversion_works() { use latest::prelude::*; let _: VersionedMultiAssets = (Here, 1u128).into(); } + +#[test] +fn size_limits() { + extern crate std; + + let mut test_failed = false; + macro_rules! check_sizes { + ($(($kind:ty, $expected:expr),)+) => { + $({ + let s = core::mem::size_of::<$kind>(); + // Since the types often affect the size of other types in which they're included + // it is more convenient to check multiple types at the same time and only fail + // the test at the end. For debugging it's also useful to print out all of the sizes, + // even if they're within the expected range. + if s > $expected { + test_failed = true; + std::eprintln!( + "assertion failed: size of '{}' is {} (which is more than the expected {})", + stringify!($kind), + s, + $expected + ); + } else { + std::eprintln!( + "type '{}' is of size {} which is within the expected {}", + stringify!($kind), + s, + $expected + ); + } + })+ + } + } + + check_sizes! { + (crate::v2::Instruction<()>, 96), + (crate::v3::Instruction<()>, 112), + (crate::v2::MultiAsset, 72), + (crate::v3::MultiAsset, 80), + (crate::v2::MultiLocation, 24), + (crate::v3::MultiLocation, 24), + (crate::v2::AssetId, 32), + (crate::v3::AssetId, 40), + (crate::v2::Junctions, 16), + (crate::v3::Junctions, 16), + + (crate::v2::Junction, 72), + (crate::v2::Response, 40), + (crate::v2::AssetInstance, 40), + (crate::v2::NetworkId, 32), + (crate::v2::BodyId, 32), + (crate::v2::MultiAssets, 24), + (crate::v2::BodyPart, 12), + } + assert!(!test_failed); +} diff --git a/xcm/src/v2/junction.rs b/xcm/src/v2/junction.rs index be075a31fe32..8d787e527476 100644 --- a/xcm/src/v2/junction.rs +++ b/xcm/src/v2/junction.rs @@ -16,7 +16,7 @@ //! Support data structures for `MultiLocation`, primarily the `Junction` datatype. -use super::{BodyId, BodyPart, Junctions, MultiLocation, NetworkId}; +use super::{BodyId, BodyPart, MultiLocation, NetworkId}; use crate::v3::Junction as NewJunction; use bounded_collections::{ConstU32, WeakBoundedVec}; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; @@ -109,14 +109,14 @@ impl Junction { /// Convert `self` into a `MultiLocation` containing 0 parents. /// /// Similar to `Into::into`, except that this method can be used in a const evaluation context. - pub const fn into(self) -> MultiLocation { - MultiLocation { parents: 0, interior: Junctions::X1(self) } + pub fn into(self) -> MultiLocation { + MultiLocation { parents: 0, interior: [self].into() } } /// Convert `self` into a `MultiLocation` containing `n` parents. /// /// Similar to `Self::into`, with the added ability to specify the number of parent junctions. - pub const fn into_exterior(self, n: u8) -> MultiLocation { - MultiLocation { parents: n, interior: Junctions::X1(self) } + pub fn into_exterior(self, n: u8) -> MultiLocation { + MultiLocation { parents: n, interior: [self].into() } } } diff --git a/xcm/src/v2/multilocation.rs b/xcm/src/v2/multilocation.rs index 086a83277322..5dae29050578 100644 --- a/xcm/src/v2/multilocation.rs +++ b/xcm/src/v2/multilocation.rs @@ -18,7 +18,8 @@ use super::Junction; use crate::v3::MultiLocation as NewMultiLocation; -use core::{mem, result}; +use alloc::sync::Arc; +use core::{mem, ops::Range, result}; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; @@ -102,7 +103,7 @@ impl MultiLocation { } /// Whether the `MultiLocation` has no parents and has a `Here` interior. - pub const fn is_here(&self) -> bool { + pub fn is_here(&self) -> bool { self.parents == 0 && self.interior.len() == 0 } @@ -128,7 +129,7 @@ impl MultiLocation { } /// Returns the number of parents and junctions in `self`. - pub const fn len(&self) -> usize { + pub fn len(&self) -> usize { self.parent_count() as usize + self.interior.len() } @@ -240,9 +241,9 @@ impl MultiLocation { /// ```rust /// # use xcm::v2::{Junctions::*, Junction::*, MultiLocation}; /// # fn main() { - /// let mut m = MultiLocation::new(1, X2(PalletInstance(3), OnlyChild)); + /// let mut m = MultiLocation::new(1, [PalletInstance(3), OnlyChild].into()); /// assert_eq!( - /// m.match_and_split(&MultiLocation::new(1, X1(PalletInstance(3)))), + /// m.match_and_split(&MultiLocation::new(1, [PalletInstance(3)].into())), /// Some(&OnlyChild), /// ); /// assert_eq!(m.match_and_split(&MultiLocation::new(1, Here)), None); @@ -261,10 +262,10 @@ impl MultiLocation { /// # Example /// ```rust /// # use xcm::v2::{Junctions::*, Junction::*, MultiLocation}; - /// let m = MultiLocation::new(1, X3(PalletInstance(3), OnlyChild, OnlyChild)); - /// assert!(m.starts_with(&MultiLocation::new(1, X1(PalletInstance(3))))); - /// assert!(!m.starts_with(&MultiLocation::new(1, X1(GeneralIndex(99))))); - /// assert!(!m.starts_with(&MultiLocation::new(0, X1(PalletInstance(3))))); + /// let m = MultiLocation::new(1, [PalletInstance(3), OnlyChild, OnlyChild].into()); + /// assert!(m.starts_with(&MultiLocation::new(1, [PalletInstance(3)].into()))); + /// assert!(!m.starts_with(&MultiLocation::new(1, [GeneralIndex(99)].into()))); + /// assert!(!m.starts_with(&MultiLocation::new(0, [PalletInstance(3)].into()))); /// ``` pub fn starts_with(&self, prefix: &MultiLocation) -> bool { if self.parents != prefix.parents { @@ -279,11 +280,11 @@ impl MultiLocation { /// /// # Example /// ```rust - /// # use xcm::v2::{Junctions::*, Junction::*, MultiLocation}; + /// # use xcm::v2::{Junction::*, MultiLocation}; /// # fn main() { - /// let mut m = MultiLocation::new(1, X1(Parachain(21))); - /// assert_eq!(m.append_with(X1(PalletInstance(3))), Ok(())); - /// assert_eq!(m, MultiLocation::new(1, X2(Parachain(21), PalletInstance(3)))); + /// let mut m = MultiLocation::new(1, [Parachain(21)].into()); + /// assert_eq!(m.append_with([PalletInstance(3)].into()), Ok(())); + /// assert_eq!(m, MultiLocation::new(1, [Parachain(21), PalletInstance(3)].into())); /// # } /// ``` pub fn append_with(&mut self, suffix: Junctions) -> Result<(), Junctions> { @@ -302,11 +303,11 @@ impl MultiLocation { /// /// # Example /// ```rust - /// # use xcm::v2::{Junctions::*, Junction::*, MultiLocation}; + /// # use xcm::v2::{Junction::*, MultiLocation}; /// # fn main() { - /// let mut m = MultiLocation::new(2, X1(PalletInstance(3))); - /// assert_eq!(m.prepend_with(MultiLocation::new(1, X2(Parachain(21), OnlyChild))), Ok(())); - /// assert_eq!(m, MultiLocation::new(1, X1(PalletInstance(3)))); + /// let mut m = MultiLocation::new(2, [PalletInstance(3)].into()); + /// assert_eq!(m.prepend_with(MultiLocation::new(1, [Parachain(21), OnlyChild].into())), Ok(())); + /// assert_eq!(m, MultiLocation::new(1, [PalletInstance(3)].into())); /// # } /// ``` pub fn prepend_with(&mut self, mut prefix: MultiLocation) -> Result<(), MultiLocation> { @@ -467,73 +468,93 @@ const MAX_JUNCTIONS: usize = 8; /// /// Parent junctions cannot be constructed with this type. Refer to `MultiLocation` for /// instructions on constructing parent junctions. -#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo)] #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] pub enum Junctions { /// The interpreting consensus system. Here, /// A relative path comprising 1 junction. - X1(Junction), + X1(Arc<[Junction; 1]>), /// A relative path comprising 2 junctions. - X2(Junction, Junction), + X2(Arc<[Junction; 2]>), /// A relative path comprising 3 junctions. - X3(Junction, Junction, Junction), + X3(Arc<[Junction; 3]>), /// A relative path comprising 4 junctions. - X4(Junction, Junction, Junction, Junction), + X4(Arc<[Junction; 4]>), /// A relative path comprising 5 junctions. - X5(Junction, Junction, Junction, Junction, Junction), + X5(Arc<[Junction; 5]>), /// A relative path comprising 6 junctions. - X6(Junction, Junction, Junction, Junction, Junction, Junction), + X6(Arc<[Junction; 6]>), /// A relative path comprising 7 junctions. - X7(Junction, Junction, Junction, Junction, Junction, Junction, Junction), + X7(Arc<[Junction; 7]>), /// A relative path comprising 8 junctions. - X8(Junction, Junction, Junction, Junction, Junction, Junction, Junction, Junction), + X8(Arc<[Junction; 8]>), +} + +// TODO: Remove this once deriving `MaxEncodedLen` on `Arc`s works. +impl MaxEncodedLen for Junctions { + fn max_encoded_len() -> usize { + <[Junction; 8]>::max_encoded_len().saturating_add(1) + } +} + +macro_rules! impl_junction { + ($count:expr, $variant:ident) => { + impl From<[Junction; $count]> for Junctions { + fn from(junctions: [Junction; $count]) -> Self { + Self::$variant(Arc::new(junctions)) + } + } + impl PartialEq<[Junction; $count]> for Junctions { + fn eq(&self, rhs: &[Junction; $count]) -> bool { + self.as_slice() == rhs + } + } + }; +} + +impl_junction!(1, X1); +impl_junction!(2, X2); +impl_junction!(3, X3); +impl_junction!(4, X4); +impl_junction!(5, X5); +impl_junction!(6, X6); +impl_junction!(7, X7); +impl_junction!(8, X8); + +pub struct JunctionsIterator { + junctions: Junctions, + range: Range, } -pub struct JunctionsIterator(Junctions); impl Iterator for JunctionsIterator { type Item = Junction; fn next(&mut self) -> Option { - self.0.take_first() + self.junctions.at(self.range.next()?).cloned() } } impl DoubleEndedIterator for JunctionsIterator { fn next_back(&mut self) -> Option { - self.0.take_last() + self.junctions.at(self.range.next_back()?).cloned() } } pub struct JunctionsRefIterator<'a> { junctions: &'a Junctions, - next: usize, - back: usize, + range: Range, } impl<'a> Iterator for JunctionsRefIterator<'a> { type Item = &'a Junction; fn next(&mut self) -> Option<&'a Junction> { - if self.next.saturating_add(self.back) >= self.junctions.len() { - return None - } - - let result = self.junctions.at(self.next); - self.next += 1; - result + self.junctions.at(self.range.next()?) } } impl<'a> DoubleEndedIterator for JunctionsRefIterator<'a> { fn next_back(&mut self) -> Option<&'a Junction> { - let next_back = self.back.saturating_add(1); - // checked_sub here, because if the result is less than 0, we end iteration - let index = self.junctions.len().checked_sub(next_back)?; - if self.next > index { - return None - } - self.back = next_back; - - self.junctions.at(index) + self.junctions.at(self.range.next_back()?) } } @@ -541,7 +562,7 @@ impl<'a> IntoIterator for &'a Junctions { type Item = &'a Junction; type IntoIter = JunctionsRefIterator<'a>; fn into_iter(self) -> Self::IntoIter { - JunctionsRefIterator { junctions: self, next: 0, back: 0 } + JunctionsRefIterator { junctions: self, range: 0..self.len() } } } @@ -549,7 +570,7 @@ impl IntoIterator for Junctions { type Item = Junction; type IntoIter = JunctionsIterator; fn into_iter(self) -> Self::IntoIter { - JunctionsIterator(self) + JunctionsIterator { range: 0..self.len(), junctions: self } } } @@ -568,34 +589,44 @@ impl Junctions { MultiLocation { parents: n, interior: self } } + /// Casts `self` into a slice containing `Junction`s. + pub fn as_slice(&self) -> &[Junction] { + match self { + Junctions::Here => &[], + Junctions::X1(ref a) => &a[..], + Junctions::X2(ref a) => &a[..], + Junctions::X3(ref a) => &a[..], + Junctions::X4(ref a) => &a[..], + Junctions::X5(ref a) => &a[..], + Junctions::X6(ref a) => &a[..], + Junctions::X7(ref a) => &a[..], + Junctions::X8(ref a) => &a[..], + } + } + + /// Casts `self` into a slice containing `Junction`s. + pub fn as_slice_mut(&mut self) -> &mut [Junction] { + match self { + Junctions::Here => &mut [], + Junctions::X1(ref mut a) => &mut Arc::make_mut(a)[..], + Junctions::X2(ref mut a) => &mut Arc::make_mut(a)[..], + Junctions::X3(ref mut a) => &mut Arc::make_mut(a)[..], + Junctions::X4(ref mut a) => &mut Arc::make_mut(a)[..], + Junctions::X5(ref mut a) => &mut Arc::make_mut(a)[..], + Junctions::X6(ref mut a) => &mut Arc::make_mut(a)[..], + Junctions::X7(ref mut a) => &mut Arc::make_mut(a)[..], + Junctions::X8(ref mut a) => &mut Arc::make_mut(a)[..], + } + } + /// Returns first junction, or `None` if the location is empty. pub fn first(&self) -> Option<&Junction> { - match &self { - Junctions::Here => None, - Junctions::X1(ref a) => Some(a), - Junctions::X2(ref a, ..) => Some(a), - Junctions::X3(ref a, ..) => Some(a), - Junctions::X4(ref a, ..) => Some(a), - Junctions::X5(ref a, ..) => Some(a), - Junctions::X6(ref a, ..) => Some(a), - Junctions::X7(ref a, ..) => Some(a), - Junctions::X8(ref a, ..) => Some(a), - } + self.as_slice().first() } /// Returns last junction, or `None` if the location is empty. pub fn last(&self) -> Option<&Junction> { - match &self { - Junctions::Here => None, - Junctions::X1(ref a) => Some(a), - Junctions::X2(.., ref a) => Some(a), - Junctions::X3(.., ref a) => Some(a), - Junctions::X4(.., ref a) => Some(a), - Junctions::X5(.., ref a) => Some(a), - Junctions::X6(.., ref a) => Some(a), - Junctions::X7(.., ref a) => Some(a), - Junctions::X8(.., ref a) => Some(a), - } + self.as_slice().last() } /// Splits off the first junction, returning the remaining suffix (first item in tuple) and the first element @@ -603,14 +634,45 @@ impl Junctions { pub fn split_first(self) -> (Junctions, Option) { match self { Junctions::Here => (Junctions::Here, None), - Junctions::X1(a) => (Junctions::Here, Some(a)), - Junctions::X2(a, b) => (Junctions::X1(b), Some(a)), - Junctions::X3(a, b, c) => (Junctions::X2(b, c), Some(a)), - Junctions::X4(a, b, c, d) => (Junctions::X3(b, c, d), Some(a)), - Junctions::X5(a, b, c, d, e) => (Junctions::X4(b, c, d, e), Some(a)), - Junctions::X6(a, b, c, d, e, f) => (Junctions::X5(b, c, d, e, f), Some(a)), - Junctions::X7(a, b, c, d, e, f, g) => (Junctions::X6(b, c, d, e, f, g), Some(a)), - Junctions::X8(a, b, c, d, e, f, g, h) => (Junctions::X7(b, c, d, e, f, g, h), Some(a)), + Junctions::X1(xs) => { + let [a] = &*xs; + (Junctions::Here, Some(a.clone())) + }, + Junctions::X2(xs) => { + let [a, b] = &*xs; + ([b.clone()].into(), Some(a.clone())) + }, + Junctions::X3(xs) => { + let [a, b, c] = &*xs; + ([b.clone(), c.clone()].into(), Some(a.clone())) + }, + Junctions::X4(xs) => { + let [a, b, c, d] = &*xs; + ([b.clone(), c.clone(), d.clone()].into(), Some(a.clone())) + }, + Junctions::X5(xs) => { + let [a, b, c, d, e] = &*xs; + ([b.clone(), c.clone(), d.clone(), e.clone()].into(), Some(a.clone())) + }, + Junctions::X6(xs) => { + let [a, b, c, d, e, f] = &*xs; + ([b.clone(), c.clone(), d.clone(), e.clone(), f.clone()].into(), Some(a.clone())) + }, + Junctions::X7(xs) => { + let [a, b, c, d, e, f, g] = &*xs; + ( + [b.clone(), c.clone(), d.clone(), e.clone(), f.clone(), g.clone()].into(), + Some(a.clone()), + ) + }, + Junctions::X8(xs) => { + let [a, b, c, d, e, f, g, h] = &*xs; + ( + [b.clone(), c.clone(), d.clone(), e.clone(), f.clone(), g.clone(), h.clone()] + .into(), + Some(a.clone()), + ) + }, } } @@ -619,14 +681,45 @@ impl Junctions { pub fn split_last(self) -> (Junctions, Option) { match self { Junctions::Here => (Junctions::Here, None), - Junctions::X1(a) => (Junctions::Here, Some(a)), - Junctions::X2(a, b) => (Junctions::X1(a), Some(b)), - Junctions::X3(a, b, c) => (Junctions::X2(a, b), Some(c)), - Junctions::X4(a, b, c, d) => (Junctions::X3(a, b, c), Some(d)), - Junctions::X5(a, b, c, d, e) => (Junctions::X4(a, b, c, d), Some(e)), - Junctions::X6(a, b, c, d, e, f) => (Junctions::X5(a, b, c, d, e), Some(f)), - Junctions::X7(a, b, c, d, e, f, g) => (Junctions::X6(a, b, c, d, e, f), Some(g)), - Junctions::X8(a, b, c, d, e, f, g, h) => (Junctions::X7(a, b, c, d, e, f, g), Some(h)), + Junctions::X1(xs) => { + let [a] = &*xs; + (Junctions::Here, Some(a.clone())) + }, + Junctions::X2(xs) => { + let [a, b] = &*xs; + ([a.clone()].into(), Some(b.clone())) + }, + Junctions::X3(xs) => { + let [a, b, c] = &*xs; + ([a.clone(), b.clone()].into(), Some(c.clone())) + }, + Junctions::X4(xs) => { + let [a, b, c, d] = &*xs; + ([a.clone(), b.clone(), c.clone()].into(), Some(d.clone())) + }, + Junctions::X5(xs) => { + let [a, b, c, d, e] = &*xs; + ([a.clone(), b.clone(), c.clone(), d.clone()].into(), Some(e.clone())) + }, + Junctions::X6(xs) => { + let [a, b, c, d, e, f] = &*xs; + ([a.clone(), b.clone(), c.clone(), d.clone(), e.clone()].into(), Some(f.clone())) + }, + Junctions::X7(xs) => { + let [a, b, c, d, e, f, g] = &*xs; + ( + [a.clone(), b.clone(), c.clone(), d.clone(), e.clone(), f.clone()].into(), + Some(g.clone()), + ) + }, + Junctions::X8(xs) => { + let [a, b, c, d, e, f, g, h] = &*xs; + ( + [a.clone(), b.clone(), c.clone(), d.clone(), e.clone(), f.clone(), g.clone()] + .into(), + Some(h.clone()), + ) + }, } } @@ -684,14 +777,36 @@ impl Junctions { /// original value of `self` and `new` in case of overflow. pub fn pushed_with(self, new: Junction) -> result::Result { Ok(match self { - Junctions::Here => Junctions::X1(new), - Junctions::X1(a) => Junctions::X2(a, new), - Junctions::X2(a, b) => Junctions::X3(a, b, new), - Junctions::X3(a, b, c) => Junctions::X4(a, b, c, new), - Junctions::X4(a, b, c, d) => Junctions::X5(a, b, c, d, new), - Junctions::X5(a, b, c, d, e) => Junctions::X6(a, b, c, d, e, new), - Junctions::X6(a, b, c, d, e, f) => Junctions::X7(a, b, c, d, e, f, new), - Junctions::X7(a, b, c, d, e, f, g) => Junctions::X8(a, b, c, d, e, f, g, new), + Junctions::Here => [new].into(), + Junctions::X1(xs) => { + let [a] = &*xs; + [a.clone(), new].into() + }, + Junctions::X2(xs) => { + let [a, b] = &*xs; + [a.clone(), b.clone(), new].into() + }, + Junctions::X3(xs) => { + let [a, b, c] = &*xs; + [a.clone(), b.clone(), c.clone(), new].into() + }, + Junctions::X4(xs) => { + let [a, b, c, d] = &*xs; + [a.clone(), b.clone(), c.clone(), d.clone(), new].into() + }, + Junctions::X5(xs) => { + let [a, b, c, d, e] = &*xs; + [a.clone(), b.clone(), c.clone(), d.clone(), e.clone(), new].into() + }, + Junctions::X6(xs) => { + let [a, b, c, d, e, f] = &*xs; + [a.clone(), b.clone(), c.clone(), d.clone(), e.clone(), f.clone(), new].into() + }, + Junctions::X7(xs) => { + let [a, b, c, d, e, f, g] = &*xs; + [a.clone(), b.clone(), c.clone(), d.clone(), e.clone(), f.clone(), g.clone(), new] + .into() + }, s => Err((s, new))?, }) } @@ -700,123 +815,59 @@ impl Junctions { /// original value of `self` and `new` in case of overflow. pub fn pushed_front_with(self, new: Junction) -> result::Result { Ok(match self { - Junctions::Here => Junctions::X1(new), - Junctions::X1(a) => Junctions::X2(new, a), - Junctions::X2(a, b) => Junctions::X3(new, a, b), - Junctions::X3(a, b, c) => Junctions::X4(new, a, b, c), - Junctions::X4(a, b, c, d) => Junctions::X5(new, a, b, c, d), - Junctions::X5(a, b, c, d, e) => Junctions::X6(new, a, b, c, d, e), - Junctions::X6(a, b, c, d, e, f) => Junctions::X7(new, a, b, c, d, e, f), - Junctions::X7(a, b, c, d, e, f, g) => Junctions::X8(new, a, b, c, d, e, f, g), + Junctions::Here => [new].into(), + Junctions::X1(xs) => { + let [a] = &*xs; + [new, a.clone()].into() + }, + Junctions::X2(xs) => { + let [a, b] = &*xs; + [new, a.clone(), b.clone()].into() + }, + Junctions::X3(xs) => { + let [a, b, c] = &*xs; + [new, a.clone(), b.clone(), c.clone()].into() + }, + Junctions::X4(xs) => { + let [a, b, c, d] = &*xs; + [new, a.clone(), b.clone(), c.clone(), d.clone()].into() + }, + Junctions::X5(xs) => { + let [a, b, c, d, e] = &*xs; + [new, a.clone(), b.clone(), c.clone(), d.clone(), e.clone()].into() + }, + Junctions::X6(xs) => { + let [a, b, c, d, e, f] = &*xs; + [new, a.clone(), b.clone(), c.clone(), d.clone(), e.clone(), f.clone()].into() + }, + Junctions::X7(xs) => { + let [a, b, c, d, e, f, g] = &*xs; + [new, a.clone(), b.clone(), c.clone(), d.clone(), e.clone(), f.clone(), g.clone()] + .into() + }, s => Err((s, new))?, }) } /// Returns the number of junctions in `self`. - pub const fn len(&self) -> usize { - match &self { - Junctions::Here => 0, - Junctions::X1(..) => 1, - Junctions::X2(..) => 2, - Junctions::X3(..) => 3, - Junctions::X4(..) => 4, - Junctions::X5(..) => 5, - Junctions::X6(..) => 6, - Junctions::X7(..) => 7, - Junctions::X8(..) => 8, - } + pub fn len(&self) -> usize { + self.as_slice().len() } /// Returns the junction at index `i`, or `None` if the location doesn't contain that many elements. pub fn at(&self, i: usize) -> Option<&Junction> { - Some(match (i, self) { - (0, Junctions::X1(ref a)) => a, - (0, Junctions::X2(ref a, ..)) => a, - (0, Junctions::X3(ref a, ..)) => a, - (0, Junctions::X4(ref a, ..)) => a, - (0, Junctions::X5(ref a, ..)) => a, - (0, Junctions::X6(ref a, ..)) => a, - (0, Junctions::X7(ref a, ..)) => a, - (0, Junctions::X8(ref a, ..)) => a, - (1, Junctions::X2(_, ref a)) => a, - (1, Junctions::X3(_, ref a, ..)) => a, - (1, Junctions::X4(_, ref a, ..)) => a, - (1, Junctions::X5(_, ref a, ..)) => a, - (1, Junctions::X6(_, ref a, ..)) => a, - (1, Junctions::X7(_, ref a, ..)) => a, - (1, Junctions::X8(_, ref a, ..)) => a, - (2, Junctions::X3(_, _, ref a)) => a, - (2, Junctions::X4(_, _, ref a, ..)) => a, - (2, Junctions::X5(_, _, ref a, ..)) => a, - (2, Junctions::X6(_, _, ref a, ..)) => a, - (2, Junctions::X7(_, _, ref a, ..)) => a, - (2, Junctions::X8(_, _, ref a, ..)) => a, - (3, Junctions::X4(_, _, _, ref a)) => a, - (3, Junctions::X5(_, _, _, ref a, ..)) => a, - (3, Junctions::X6(_, _, _, ref a, ..)) => a, - (3, Junctions::X7(_, _, _, ref a, ..)) => a, - (3, Junctions::X8(_, _, _, ref a, ..)) => a, - (4, Junctions::X5(_, _, _, _, ref a)) => a, - (4, Junctions::X6(_, _, _, _, ref a, ..)) => a, - (4, Junctions::X7(_, _, _, _, ref a, ..)) => a, - (4, Junctions::X8(_, _, _, _, ref a, ..)) => a, - (5, Junctions::X6(_, _, _, _, _, ref a)) => a, - (5, Junctions::X7(_, _, _, _, _, ref a, ..)) => a, - (5, Junctions::X8(_, _, _, _, _, ref a, ..)) => a, - (6, Junctions::X7(_, _, _, _, _, _, ref a)) => a, - (6, Junctions::X8(_, _, _, _, _, _, ref a, ..)) => a, - (7, Junctions::X8(_, _, _, _, _, _, _, ref a)) => a, - _ => return None, - }) + self.as_slice().get(i) } /// Returns a mutable reference to the junction at index `i`, or `None` if the location doesn't contain that many /// elements. pub fn at_mut(&mut self, i: usize) -> Option<&mut Junction> { - Some(match (i, self) { - (0, Junctions::X1(ref mut a)) => a, - (0, Junctions::X2(ref mut a, ..)) => a, - (0, Junctions::X3(ref mut a, ..)) => a, - (0, Junctions::X4(ref mut a, ..)) => a, - (0, Junctions::X5(ref mut a, ..)) => a, - (0, Junctions::X6(ref mut a, ..)) => a, - (0, Junctions::X7(ref mut a, ..)) => a, - (0, Junctions::X8(ref mut a, ..)) => a, - (1, Junctions::X2(_, ref mut a)) => a, - (1, Junctions::X3(_, ref mut a, ..)) => a, - (1, Junctions::X4(_, ref mut a, ..)) => a, - (1, Junctions::X5(_, ref mut a, ..)) => a, - (1, Junctions::X6(_, ref mut a, ..)) => a, - (1, Junctions::X7(_, ref mut a, ..)) => a, - (1, Junctions::X8(_, ref mut a, ..)) => a, - (2, Junctions::X3(_, _, ref mut a)) => a, - (2, Junctions::X4(_, _, ref mut a, ..)) => a, - (2, Junctions::X5(_, _, ref mut a, ..)) => a, - (2, Junctions::X6(_, _, ref mut a, ..)) => a, - (2, Junctions::X7(_, _, ref mut a, ..)) => a, - (2, Junctions::X8(_, _, ref mut a, ..)) => a, - (3, Junctions::X4(_, _, _, ref mut a)) => a, - (3, Junctions::X5(_, _, _, ref mut a, ..)) => a, - (3, Junctions::X6(_, _, _, ref mut a, ..)) => a, - (3, Junctions::X7(_, _, _, ref mut a, ..)) => a, - (3, Junctions::X8(_, _, _, ref mut a, ..)) => a, - (4, Junctions::X5(_, _, _, _, ref mut a)) => a, - (4, Junctions::X6(_, _, _, _, ref mut a, ..)) => a, - (4, Junctions::X7(_, _, _, _, ref mut a, ..)) => a, - (4, Junctions::X8(_, _, _, _, ref mut a, ..)) => a, - (5, Junctions::X6(_, _, _, _, _, ref mut a)) => a, - (5, Junctions::X7(_, _, _, _, _, ref mut a, ..)) => a, - (5, Junctions::X8(_, _, _, _, _, ref mut a, ..)) => a, - (6, Junctions::X7(_, _, _, _, _, _, ref mut a)) => a, - (6, Junctions::X8(_, _, _, _, _, _, ref mut a, ..)) => a, - (7, Junctions::X8(_, _, _, _, _, _, _, ref mut a)) => a, - _ => return None, - }) + self.as_slice_mut().get_mut(i) } /// Returns a reference iterator over the junctions. pub fn iter(&self) -> JunctionsRefIterator { - JunctionsRefIterator { junctions: self, next: 0, back: 0 } + JunctionsRefIterator { junctions: self, range: 0..self.len() } } /// Returns a reference iterator over the junctions in reverse. @@ -836,11 +887,11 @@ impl Junctions { /// /// # Example /// ```rust - /// # use xcm::v2::{Junctions::*, Junction::*}; + /// # use xcm::v2::{Junctions, Junction::*}; /// # fn main() { - /// let mut m = X3(Parachain(2), PalletInstance(3), OnlyChild); - /// assert_eq!(m.match_and_split(&X2(Parachain(2), PalletInstance(3))), Some(&OnlyChild)); - /// assert_eq!(m.match_and_split(&X1(Parachain(2))), None); + /// let mut m = Junctions::from([Parachain(2), PalletInstance(3), OnlyChild]); + /// assert_eq!(m.match_and_split(&[Parachain(2), PalletInstance(3)].into()), Some(&OnlyChild)); + /// assert_eq!(m.match_and_split(&[Parachain(2)].into()), None); /// # } /// ``` pub fn match_and_split(&self, prefix: &Junctions) -> Option<&Junction> { @@ -854,13 +905,13 @@ impl Junctions { /// /// # Example /// ```rust - /// # use xcm::v2::{Junctions::*, Junction::*}; - /// let mut j = X3(Parachain(2), PalletInstance(3), OnlyChild); - /// assert!(j.starts_with(&X2(Parachain(2), PalletInstance(3)))); + /// # use xcm::v2::{Junctions, Junction::*}; + /// let mut j = Junctions::from([Parachain(2), PalletInstance(3), OnlyChild]); + /// assert!(j.starts_with(&[Parachain(2), PalletInstance(3)].into())); /// assert!(j.starts_with(&j)); - /// assert!(j.starts_with(&X1(Parachain(2)))); - /// assert!(!j.starts_with(&X1(Parachain(999)))); - /// assert!(!j.starts_with(&X4(Parachain(2), PalletInstance(3), OnlyChild, OnlyChild))); + /// assert!(j.starts_with(&[Parachain(2)].into())); + /// assert!(!j.starts_with(&[Parachain(999)].into())); + /// assert!(!j.starts_with(&[Parachain(2), PalletInstance(3), OnlyChild, OnlyChild].into())); /// ``` pub fn starts_with(&self, prefix: &Junctions) -> bool { if self.len() < prefix.len() { @@ -883,10 +934,12 @@ impl TryFrom for Junctions { #[cfg(test)] mod tests { - use super::{Ancestor, AncestorThen, Junctions::*, MultiLocation, Parent, ParentThen}; + use super::{Ancestor, AncestorThen, Junctions, MultiLocation, Parent, ParentThen}; use crate::opaque::v2::{Junction::*, NetworkId::*}; use parity_scale_codec::{Decode, Encode}; + use Junctions::Here; + #[test] fn inverted_works() { let ancestry: MultiLocation = (Parachain(1000), PalletInstance(42)).into(); @@ -906,26 +959,26 @@ mod tests { 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 context = [Parachain(1000), PalletInstance(42)].into(); 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 context = [PalletInstance(42)].into(); 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 context = [Parachain(1000), PalletInstance(42)].into(); 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 context = [OnlyChild, Parachain(1000), PalletInstance(42)].into(); let expected = GeneralIndex(69).into(); location.simplify(&context); assert_eq!(location, expected); @@ -935,7 +988,7 @@ mod tests { 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 context = [Parachain(1000), PalletInstance(42), GeneralIndex(42)].into(); let expected = (Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into(); location.simplify(&context); @@ -943,7 +996,7 @@ mod tests { let mut location: MultiLocation = (Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into(); - let context = X1(Parachain(1000)); + let context = [Parachain(1000)].into(); let expected = (Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into(); location.simplify(&context); @@ -964,7 +1017,7 @@ mod tests { fn encode_and_decode_works() { let m = MultiLocation { parents: 1, - interior: X2(Parachain(42), AccountIndex64 { network: Any, index: 23 }), + interior: [Parachain(42), AccountIndex64 { network: Any, index: 23 }].into(), }; let encoded = m.encode(); assert_eq!(encoded, [1, 2, 0, 168, 2, 0, 92].to_vec()); @@ -976,11 +1029,11 @@ mod tests { fn match_and_split_works() { let m = MultiLocation { parents: 1, - interior: X2(Parachain(42), AccountIndex64 { network: Any, index: 23 }), + interior: [Parachain(42), AccountIndex64 { network: Any, index: 23 }].into(), }; 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)) }), + m.match_and_split(&MultiLocation { parents: 1, interior: [Parachain(42)].into() }), Some(&AccountIndex64 { network: Any, index: 23 }) ); assert_eq!(m.match_and_split(&m), None); @@ -1009,13 +1062,13 @@ mod tests { #[test] fn append_with_works() { let acc = AccountIndex64 { network: Any, index: 23 }; - let mut m = MultiLocation { parents: 1, interior: X1(Parachain(42)) }; - assert_eq!(m.append_with(X2(PalletInstance(3), acc.clone())), Ok(())); + let mut m = MultiLocation { parents: 1, interior: [Parachain(42)].into() }; + assert_eq!(m.append_with([PalletInstance(3), acc.clone()].into()), Ok(())); assert_eq!( m, MultiLocation { parents: 1, - interior: X3(Parachain(42), PalletInstance(3), acc.clone()) + interior: [Parachain(42), PalletInstance(3), acc.clone()].into() } ); @@ -1023,9 +1076,9 @@ mod tests { let acc = AccountIndex64 { network: Any, index: 23 }; let m = MultiLocation { parents: 254, - interior: X5(Parachain(42), OnlyChild, OnlyChild, OnlyChild, OnlyChild), + interior: [Parachain(42), OnlyChild, OnlyChild, OnlyChild, OnlyChild].into(), }; - let suffix = X4(PalletInstance(3), acc.clone(), OnlyChild, OnlyChild); + let suffix: Junctions = [PalletInstance(3), acc.clone(), OnlyChild, OnlyChild].into(); assert_eq!(m.clone().append_with(suffix.clone()), Err(suffix)); } @@ -1033,30 +1086,33 @@ mod tests { fn prepend_with_works() { let mut m = MultiLocation { parents: 1, - interior: X2(Parachain(42), AccountIndex64 { network: Any, index: 23 }), + interior: [Parachain(42), AccountIndex64 { network: Any, index: 23 }].into(), }; - assert_eq!(m.prepend_with(MultiLocation { parents: 1, interior: X1(OnlyChild) }), Ok(())); + assert_eq!( + m.prepend_with(MultiLocation { parents: 1, interior: [OnlyChild].into() }), + Ok(()) + ); assert_eq!( m, MultiLocation { parents: 1, - interior: X2(Parachain(42), AccountIndex64 { network: Any, index: 23 }) + interior: [Parachain(42), AccountIndex64 { network: Any, index: 23 }].into() } ); // cannot prepend to create overly long multilocation - let mut m = MultiLocation { parents: 254, interior: X1(Parachain(42)) }; + let mut m = MultiLocation { parents: 254, interior: [Parachain(42)].into() }; 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)) }); + assert_eq!(m, MultiLocation { parents: 255, interior: [Parachain(42)].into() }); } #[test] fn double_ended_ref_iteration_works() { - let m = X3(Parachain(1000), Parachain(3), PalletInstance(5)); + let m: Junctions = [Parachain(1000), Parachain(3), PalletInstance(5)].into(); let mut iter = m.iter(); let first = iter.next().unwrap(); @@ -1091,17 +1147,17 @@ mod tests { takes_multilocation(Parent); takes_multilocation(Here); - takes_multilocation(X1(Parachain(42))); + takes_multilocation([Parachain(42)]); takes_multilocation((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: Any, index: 155 }), + Junctions::from([Parachain(43), AccountIndex64 { network: Any, index: 155 }]), )); takes_multilocation((Parent, AccountId32 { network: Any, id: [0; 32] })); takes_multilocation((Parent, Here)); - takes_multilocation(ParentThen(X1(Parachain(75)))); + takes_multilocation(ParentThen([Parachain(75)].into())); takes_multilocation([Parachain(100), PalletInstance(3)]); } } diff --git a/xcm/src/v2/traits.rs b/xcm/src/v2/traits.rs index 524b659d57e1..e4adc7aa2566 100644 --- a/xcm/src/v2/traits.rs +++ b/xcm/src/v2/traits.rs @@ -285,7 +285,8 @@ pub type SendResult = result::Result<(), SendError>; /// struct Sender2; /// impl SendXcm for Sender2 { /// fn send_xcm(destination: impl Into, message: Xcm<()>) -> SendResult { -/// if let MultiLocation { parents: 0, interior: X2(j1, j2) } = destination.into() { +/// let destination = destination.into(); +/// if destination.parents == 0 && destination.interior.len() == 2 { /// Ok(()) /// } else { /// Err(SendError::Unroutable) diff --git a/xcm/src/v3/junction.rs b/xcm/src/v3/junction.rs index 55454226c868..d0cacc46aa38 100644 --- a/xcm/src/v3/junction.rs +++ b/xcm/src/v3/junction.rs @@ -16,7 +16,7 @@ //! Support data structures for `MultiLocation`, primarily the `Junction` datatype. -use super::{Junctions, MultiLocation}; +use super::MultiLocation; use crate::{ v2::{ BodyId as OldBodyId, BodyPart as OldBodyPart, Junction as OldJunction, @@ -350,21 +350,21 @@ impl Junction { /// Convert `self` into a `MultiLocation` containing 0 parents. /// /// Similar to `Into::into`, except that this method can be used in a const evaluation context. - pub const fn into_location(self) -> MultiLocation { - MultiLocation { parents: 0, interior: Junctions::X1(self) } + pub fn into_location(self) -> MultiLocation { + MultiLocation { parents: 0, interior: [self].into() } } /// Convert `self` into a `MultiLocation` containing `n` parents. /// /// Similar to `Self::into_location`, with the added ability to specify the number of parent junctions. - pub const fn into_exterior(self, n: u8) -> MultiLocation { - MultiLocation { parents: n, interior: Junctions::X1(self) } + pub fn into_exterior(self, n: u8) -> MultiLocation { + MultiLocation { parents: n, interior: [self].into() } } /// Convert `self` into a `VersionedMultiLocation` containing 0 parents. /// /// Similar to `Into::into`, except that this method can be used in a const evaluation context. - pub const fn into_versioned(self) -> VersionedMultiLocation { + pub fn into_versioned(self) -> VersionedMultiLocation { self.into_location().into_versioned() } diff --git a/xcm/src/v3/junctions.rs b/xcm/src/v3/junctions.rs index a412275d0596..feef0776d37e 100644 --- a/xcm/src/v3/junctions.rs +++ b/xcm/src/v3/junctions.rs @@ -17,7 +17,8 @@ //! XCM `Junctions`/`InteriorMultiLocation` datatype. use super::{Junction, MultiLocation, NetworkId}; -use core::{convert::TryFrom, mem, result}; +use alloc::sync::Arc; +use core::{convert::TryFrom, mem, ops::Range, result}; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; @@ -29,82 +30,100 @@ pub(crate) const MAX_JUNCTIONS: usize = 8; /// /// Parent junctions cannot be constructed with this type. Refer to `MultiLocation` for /// instructions on constructing parent junctions. -#[derive( - Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo, MaxEncodedLen, -)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo)] #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] pub enum Junctions { /// The interpreting consensus system. Here, /// A relative path comprising 1 junction. - X1(Junction), + X1(Arc<[Junction; 1]>), /// A relative path comprising 2 junctions. - X2(Junction, Junction), + X2(Arc<[Junction; 2]>), /// A relative path comprising 3 junctions. - X3(Junction, Junction, Junction), + X3(Arc<[Junction; 3]>), /// A relative path comprising 4 junctions. - X4(Junction, Junction, Junction, Junction), + X4(Arc<[Junction; 4]>), /// A relative path comprising 5 junctions. - X5(Junction, Junction, Junction, Junction, Junction), + X5(Arc<[Junction; 5]>), /// A relative path comprising 6 junctions. - X6(Junction, Junction, Junction, Junction, Junction, Junction), + X6(Arc<[Junction; 6]>), /// A relative path comprising 7 junctions. - X7(Junction, Junction, Junction, Junction, Junction, Junction, Junction), + X7(Arc<[Junction; 7]>), /// A relative path comprising 8 junctions. - X8(Junction, Junction, Junction, Junction, Junction, Junction, Junction, Junction), + X8(Arc<[Junction; 8]>), +} + +// TODO: Remove this once deriving `MaxEncodedLen` on `Arc`s works. +impl MaxEncodedLen for Junctions { + fn max_encoded_len() -> usize { + <[Junction; 8]>::max_encoded_len().saturating_add(1) + } +} + +macro_rules! impl_junctions { + ($count:expr, $variant:ident) => { + impl From<[Junction; $count]> for Junctions { + fn from(junctions: [Junction; $count]) -> Self { + Self::$variant(Arc::new(junctions)) + } + } + impl PartialEq<[Junction; $count]> for Junctions { + fn eq(&self, rhs: &[Junction; $count]) -> bool { + self.as_slice() == rhs + } + } + }; +} + +impl_junctions!(1, X1); +impl_junctions!(2, X2); +impl_junctions!(3, X3); +impl_junctions!(4, X4); +impl_junctions!(5, X5); +impl_junctions!(6, X6); +impl_junctions!(7, X7); +impl_junctions!(8, X8); + +pub struct JunctionsIterator { + junctions: Junctions, + range: Range, } -pub struct JunctionsIterator(Junctions); impl Iterator for JunctionsIterator { type Item = Junction; fn next(&mut self) -> Option { - self.0.take_first() + self.junctions.at(self.range.next()?).cloned() } } impl DoubleEndedIterator for JunctionsIterator { fn next_back(&mut self) -> Option { - self.0.take_last() + self.junctions.at(self.range.next_back()?).cloned() } } pub struct JunctionsRefIterator<'a> { junctions: &'a Junctions, - next: usize, - back: usize, + range: Range, } impl<'a> Iterator for JunctionsRefIterator<'a> { type Item = &'a Junction; fn next(&mut self) -> Option<&'a Junction> { - if self.next.saturating_add(self.back) >= self.junctions.len() { - return None - } - - let result = self.junctions.at(self.next); - self.next += 1; - result + self.junctions.at(self.range.next()?) } } impl<'a> DoubleEndedIterator for JunctionsRefIterator<'a> { fn next_back(&mut self) -> Option<&'a Junction> { - let next_back = self.back.saturating_add(1); - // checked_sub here, because if the result is less than 0, we end iteration - let index = self.junctions.len().checked_sub(next_back)?; - if self.next > index { - return None - } - self.back = next_back; - - self.junctions.at(index) + self.junctions.at(self.range.next_back()?) } } impl<'a> IntoIterator for &'a Junctions { type Item = &'a Junction; type IntoIter = JunctionsRefIterator<'a>; fn into_iter(self) -> Self::IntoIter { - JunctionsRefIterator { junctions: self, next: 0, back: 0 } + JunctionsRefIterator { junctions: self, range: 0..self.len() } } } @@ -112,7 +131,7 @@ impl IntoIterator for Junctions { type Item = Junction; type IntoIter = JunctionsIterator; fn into_iter(self) -> Self::IntoIter { - JunctionsIterator(self) + JunctionsIterator { range: 0..self.len(), junctions: self } } } @@ -131,6 +150,36 @@ impl Junctions { MultiLocation { parents: n, interior: self } } + /// Casts `self` into a slice containing `Junction`s. + pub fn as_slice(&self) -> &[Junction] { + match self { + Junctions::Here => &[], + Junctions::X1(ref a) => &a[..], + Junctions::X2(ref a) => &a[..], + Junctions::X3(ref a) => &a[..], + Junctions::X4(ref a) => &a[..], + Junctions::X5(ref a) => &a[..], + Junctions::X6(ref a) => &a[..], + Junctions::X7(ref a) => &a[..], + Junctions::X8(ref a) => &a[..], + } + } + + /// Casts `self` into a mutable slice containing `Junction`s. + pub fn as_slice_mut(&mut self) -> &mut [Junction] { + match self { + Junctions::Here => &mut [], + Junctions::X1(ref mut a) => &mut Arc::make_mut(a)[..], + Junctions::X2(ref mut a) => &mut Arc::make_mut(a)[..], + Junctions::X3(ref mut a) => &mut Arc::make_mut(a)[..], + Junctions::X4(ref mut a) => &mut Arc::make_mut(a)[..], + Junctions::X5(ref mut a) => &mut Arc::make_mut(a)[..], + Junctions::X6(ref mut a) => &mut Arc::make_mut(a)[..], + Junctions::X7(ref mut a) => &mut Arc::make_mut(a)[..], + Junctions::X8(ref mut a) => &mut Arc::make_mut(a)[..], + } + } + /// Remove the `NetworkId` value in any `Junction`s. pub fn remove_network_id(&mut self) { self.for_each_mut(Junction::remove_network_id); @@ -138,11 +187,12 @@ impl Junctions { /// Treating `self` as the universal context, return the location of the local consensus system /// from the point of view of the given `target`. - pub fn invert_target(mut self, target: &MultiLocation) -> Result { + pub fn invert_target(&self, target: &MultiLocation) -> Result { + let mut itself = self.clone(); let mut junctions = Self::Here; for _ in 0..target.parent_count() { junctions = junctions - .pushed_front_with(self.take_last().unwrap_or(Junction::OnlyChild)) + .pushed_front_with(itself.take_last().unwrap_or(Junction::OnlyChild)) .map_err(|_| ())?; } let parents = target.interior().len() as u8; @@ -151,62 +201,8 @@ impl Junctions { /// Execute a function `f` on every junction. We use this since we cannot implement a mutable /// `Iterator` without unsafe code. - pub fn for_each_mut(&mut self, mut x: impl FnMut(&mut Junction)) { - match self { - Junctions::Here => {}, - Junctions::X1(a) => { - x(a); - }, - Junctions::X2(a, b) => { - x(a); - x(b); - }, - Junctions::X3(a, b, c) => { - x(a); - x(b); - x(c); - }, - Junctions::X4(a, b, c, d) => { - x(a); - x(b); - x(c); - x(d); - }, - Junctions::X5(a, b, c, d, e) => { - x(a); - x(b); - x(c); - x(d); - x(e); - }, - Junctions::X6(a, b, c, d, e, f) => { - x(a); - x(b); - x(c); - x(d); - x(e); - x(f); - }, - Junctions::X7(a, b, c, d, e, f, g) => { - x(a); - x(b); - x(c); - x(d); - x(e); - x(f); - x(g); - }, - Junctions::X8(a, b, c, d, e, f, g, h) => { - x(a); - x(b); - x(c); - x(d); - x(e); - x(f); - x(g); - x(h); - }, - } + pub fn for_each_mut(&mut self, x: impl FnMut(&mut Junction)) { + self.as_slice_mut().iter_mut().for_each(x) } /// Extract the network ID treating this value as a universal location. @@ -270,32 +266,12 @@ impl Junctions { /// Returns first junction, or `None` if the location is empty. pub fn first(&self) -> Option<&Junction> { - match &self { - Junctions::Here => None, - Junctions::X1(ref a) => Some(a), - Junctions::X2(ref a, ..) => Some(a), - Junctions::X3(ref a, ..) => Some(a), - Junctions::X4(ref a, ..) => Some(a), - Junctions::X5(ref a, ..) => Some(a), - Junctions::X6(ref a, ..) => Some(a), - Junctions::X7(ref a, ..) => Some(a), - Junctions::X8(ref a, ..) => Some(a), - } + self.as_slice().first() } /// Returns last junction, or `None` if the location is empty. pub fn last(&self) -> Option<&Junction> { - match &self { - Junctions::Here => None, - Junctions::X1(ref a) => Some(a), - Junctions::X2(.., ref a) => Some(a), - Junctions::X3(.., ref a) => Some(a), - Junctions::X4(.., ref a) => Some(a), - Junctions::X5(.., ref a) => Some(a), - Junctions::X6(.., ref a) => Some(a), - Junctions::X7(.., ref a) => Some(a), - Junctions::X8(.., ref a) => Some(a), - } + self.as_slice().last() } /// Splits off the first junction, returning the remaining suffix (first item in tuple) and the first element @@ -303,14 +279,38 @@ impl Junctions { pub fn split_first(self) -> (Junctions, Option) { match self { Junctions::Here => (Junctions::Here, None), - Junctions::X1(a) => (Junctions::Here, Some(a)), - Junctions::X2(a, b) => (Junctions::X1(b), Some(a)), - Junctions::X3(a, b, c) => (Junctions::X2(b, c), Some(a)), - Junctions::X4(a, b, c, d) => (Junctions::X3(b, c, d), Some(a)), - Junctions::X5(a, b, c, d, e) => (Junctions::X4(b, c, d, e), Some(a)), - Junctions::X6(a, b, c, d, e, f) => (Junctions::X5(b, c, d, e, f), Some(a)), - Junctions::X7(a, b, c, d, e, f, g) => (Junctions::X6(b, c, d, e, f, g), Some(a)), - Junctions::X8(a, b, c, d, e, f, g, h) => (Junctions::X7(b, c, d, e, f, g, h), Some(a)), + Junctions::X1(xs) => { + let [a] = *xs; + (Junctions::Here, Some(a)) + }, + Junctions::X2(xs) => { + let [a, b] = *xs; + ([b].into(), Some(a)) + }, + Junctions::X3(xs) => { + let [a, b, c] = *xs; + ([b, c].into(), Some(a)) + }, + Junctions::X4(xs) => { + let [a, b, c, d] = *xs; + ([b, c, d].into(), Some(a)) + }, + Junctions::X5(xs) => { + let [a, b, c, d, e] = *xs; + ([b, c, d, e].into(), Some(a)) + }, + Junctions::X6(xs) => { + let [a, b, c, d, e, f] = *xs; + ([b, c, d, e, f].into(), Some(a)) + }, + Junctions::X7(xs) => { + let [a, b, c, d, e, f, g] = *xs; + ([b, c, d, e, f, g].into(), Some(a)) + }, + Junctions::X8(xs) => { + let [a, b, c, d, e, f, g, h] = *xs; + ([b, c, d, e, f, g, h].into(), Some(a)) + }, } } @@ -319,14 +319,38 @@ impl Junctions { pub fn split_last(self) -> (Junctions, Option) { match self { Junctions::Here => (Junctions::Here, None), - Junctions::X1(a) => (Junctions::Here, Some(a)), - Junctions::X2(a, b) => (Junctions::X1(a), Some(b)), - Junctions::X3(a, b, c) => (Junctions::X2(a, b), Some(c)), - Junctions::X4(a, b, c, d) => (Junctions::X3(a, b, c), Some(d)), - Junctions::X5(a, b, c, d, e) => (Junctions::X4(a, b, c, d), Some(e)), - Junctions::X6(a, b, c, d, e, f) => (Junctions::X5(a, b, c, d, e), Some(f)), - Junctions::X7(a, b, c, d, e, f, g) => (Junctions::X6(a, b, c, d, e, f), Some(g)), - Junctions::X8(a, b, c, d, e, f, g, h) => (Junctions::X7(a, b, c, d, e, f, g), Some(h)), + Junctions::X1(xs) => { + let [a] = *xs; + (Junctions::Here, Some(a)) + }, + Junctions::X2(xs) => { + let [a, b] = *xs; + ([a].into(), Some(b)) + }, + Junctions::X3(xs) => { + let [a, b, c] = *xs; + ([a, b].into(), Some(c)) + }, + Junctions::X4(xs) => { + let [a, b, c, d] = *xs; + ([a, b, c].into(), Some(d)) + }, + Junctions::X5(xs) => { + let [a, b, c, d, e] = *xs; + ([a, b, c, d].into(), Some(e)) + }, + Junctions::X6(xs) => { + let [a, b, c, d, e, f] = *xs; + ([a, b, c, d, e].into(), Some(f)) + }, + Junctions::X7(xs) => { + let [a, b, c, d, e, f, g] = *xs; + ([a, b, c, d, e, f].into(), Some(g)) + }, + Junctions::X8(xs) => { + let [a, b, c, d, e, f, g, h] = *xs; + ([a, b, c, d, e, f, g].into(), Some(h)) + }, } } @@ -387,14 +411,35 @@ impl Junctions { pub fn pushed_with(self, new: impl Into) -> result::Result { let new = new.into(); Ok(match self { - Junctions::Here => Junctions::X1(new), - Junctions::X1(a) => Junctions::X2(a, new), - Junctions::X2(a, b) => Junctions::X3(a, b, new), - Junctions::X3(a, b, c) => Junctions::X4(a, b, c, new), - Junctions::X4(a, b, c, d) => Junctions::X5(a, b, c, d, new), - Junctions::X5(a, b, c, d, e) => Junctions::X6(a, b, c, d, e, new), - Junctions::X6(a, b, c, d, e, f) => Junctions::X7(a, b, c, d, e, f, new), - Junctions::X7(a, b, c, d, e, f, g) => Junctions::X8(a, b, c, d, e, f, g, new), + Junctions::Here => [new].into(), + Junctions::X1(xs) => { + let [a] = *xs; + [a, new].into() + }, + Junctions::X2(xs) => { + let [a, b] = *xs; + [a, b, new].into() + }, + Junctions::X3(xs) => { + let [a, b, c] = *xs; + [a, b, c, new].into() + }, + Junctions::X4(xs) => { + let [a, b, c, d] = *xs; + [a, b, c, d, new].into() + }, + Junctions::X5(xs) => { + let [a, b, c, d, e] = *xs; + [a, b, c, d, e, new].into() + }, + Junctions::X6(xs) => { + let [a, b, c, d, e, f] = *xs; + [a, b, c, d, e, f, new].into() + }, + Junctions::X7(xs) => { + let [a, b, c, d, e, f, g] = *xs; + [a, b, c, d, e, f, g, new].into() + }, s => Err((s, new))?, }) } @@ -407,14 +452,35 @@ impl Junctions { ) -> result::Result { let new = new.into(); Ok(match self { - Junctions::Here => Junctions::X1(new), - Junctions::X1(a) => Junctions::X2(new, a), - Junctions::X2(a, b) => Junctions::X3(new, a, b), - Junctions::X3(a, b, c) => Junctions::X4(new, a, b, c), - Junctions::X4(a, b, c, d) => Junctions::X5(new, a, b, c, d), - Junctions::X5(a, b, c, d, e) => Junctions::X6(new, a, b, c, d, e), - Junctions::X6(a, b, c, d, e, f) => Junctions::X7(new, a, b, c, d, e, f), - Junctions::X7(a, b, c, d, e, f, g) => Junctions::X8(new, a, b, c, d, e, f, g), + Junctions::Here => [new].into(), + Junctions::X1(xs) => { + let [a] = *xs; + [new, a].into() + }, + Junctions::X2(xs) => { + let [a, b] = *xs; + [new, a, b].into() + }, + Junctions::X3(xs) => { + let [a, b, c] = *xs; + [new, a, b, c].into() + }, + Junctions::X4(xs) => { + let [a, b, c, d] = *xs; + [new, a, b, c, d].into() + }, + Junctions::X5(xs) => { + let [a, b, c, d, e] = *xs; + [new, a, b, c, d, e].into() + }, + Junctions::X6(xs) => { + let [a, b, c, d, e, f] = *xs; + [new, a, b, c, d, e, f].into() + }, + Junctions::X7(xs) => { + let [a, b, c, d, e, f, g] = *xs; + [new, a, b, c, d, e, f, g].into() + }, s => Err((s, new))?, }) } @@ -425,11 +491,11 @@ impl Junctions { /// /// # Example /// ```rust - /// # use xcm::v3::{Junctions::*, Junction::*, MultiLocation}; + /// # use xcm::v3::{Junctions, Junction::*, MultiLocation}; /// # fn main() { - /// let mut m = X1(Parachain(21)); - /// assert_eq!(m.append_with(X1(PalletInstance(3))), Ok(())); - /// assert_eq!(m, X2(Parachain(21), PalletInstance(3))); + /// let mut m = Junctions::from([Parachain(21)]); + /// assert_eq!(m.append_with([PalletInstance(3)]), Ok(())); + /// assert_eq!(m, [Parachain(21), PalletInstance(3)]); /// # } /// ``` pub fn append_with(&mut self, suffix: impl Into) -> Result<(), Junctions> { @@ -444,110 +510,24 @@ impl Junctions { } /// Returns the number of junctions in `self`. - pub const fn len(&self) -> usize { - match &self { - Junctions::Here => 0, - Junctions::X1(..) => 1, - Junctions::X2(..) => 2, - Junctions::X3(..) => 3, - Junctions::X4(..) => 4, - Junctions::X5(..) => 5, - Junctions::X6(..) => 6, - Junctions::X7(..) => 7, - Junctions::X8(..) => 8, - } + pub fn len(&self) -> usize { + self.as_slice().len() } /// Returns the junction at index `i`, or `None` if the location doesn't contain that many elements. pub fn at(&self, i: usize) -> Option<&Junction> { - Some(match (i, self) { - (0, Junctions::X1(ref a)) => a, - (0, Junctions::X2(ref a, ..)) => a, - (0, Junctions::X3(ref a, ..)) => a, - (0, Junctions::X4(ref a, ..)) => a, - (0, Junctions::X5(ref a, ..)) => a, - (0, Junctions::X6(ref a, ..)) => a, - (0, Junctions::X7(ref a, ..)) => a, - (0, Junctions::X8(ref a, ..)) => a, - (1, Junctions::X2(_, ref a)) => a, - (1, Junctions::X3(_, ref a, ..)) => a, - (1, Junctions::X4(_, ref a, ..)) => a, - (1, Junctions::X5(_, ref a, ..)) => a, - (1, Junctions::X6(_, ref a, ..)) => a, - (1, Junctions::X7(_, ref a, ..)) => a, - (1, Junctions::X8(_, ref a, ..)) => a, - (2, Junctions::X3(_, _, ref a)) => a, - (2, Junctions::X4(_, _, ref a, ..)) => a, - (2, Junctions::X5(_, _, ref a, ..)) => a, - (2, Junctions::X6(_, _, ref a, ..)) => a, - (2, Junctions::X7(_, _, ref a, ..)) => a, - (2, Junctions::X8(_, _, ref a, ..)) => a, - (3, Junctions::X4(_, _, _, ref a)) => a, - (3, Junctions::X5(_, _, _, ref a, ..)) => a, - (3, Junctions::X6(_, _, _, ref a, ..)) => a, - (3, Junctions::X7(_, _, _, ref a, ..)) => a, - (3, Junctions::X8(_, _, _, ref a, ..)) => a, - (4, Junctions::X5(_, _, _, _, ref a)) => a, - (4, Junctions::X6(_, _, _, _, ref a, ..)) => a, - (4, Junctions::X7(_, _, _, _, ref a, ..)) => a, - (4, Junctions::X8(_, _, _, _, ref a, ..)) => a, - (5, Junctions::X6(_, _, _, _, _, ref a)) => a, - (5, Junctions::X7(_, _, _, _, _, ref a, ..)) => a, - (5, Junctions::X8(_, _, _, _, _, ref a, ..)) => a, - (6, Junctions::X7(_, _, _, _, _, _, ref a)) => a, - (6, Junctions::X8(_, _, _, _, _, _, ref a, ..)) => a, - (7, Junctions::X8(_, _, _, _, _, _, _, ref a)) => a, - _ => return None, - }) + self.as_slice().get(i) } /// Returns a mutable reference to the junction at index `i`, or `None` if the location doesn't contain that many /// elements. pub fn at_mut(&mut self, i: usize) -> Option<&mut Junction> { - Some(match (i, self) { - (0, Junctions::X1(ref mut a)) => a, - (0, Junctions::X2(ref mut a, ..)) => a, - (0, Junctions::X3(ref mut a, ..)) => a, - (0, Junctions::X4(ref mut a, ..)) => a, - (0, Junctions::X5(ref mut a, ..)) => a, - (0, Junctions::X6(ref mut a, ..)) => a, - (0, Junctions::X7(ref mut a, ..)) => a, - (0, Junctions::X8(ref mut a, ..)) => a, - (1, Junctions::X2(_, ref mut a)) => a, - (1, Junctions::X3(_, ref mut a, ..)) => a, - (1, Junctions::X4(_, ref mut a, ..)) => a, - (1, Junctions::X5(_, ref mut a, ..)) => a, - (1, Junctions::X6(_, ref mut a, ..)) => a, - (1, Junctions::X7(_, ref mut a, ..)) => a, - (1, Junctions::X8(_, ref mut a, ..)) => a, - (2, Junctions::X3(_, _, ref mut a)) => a, - (2, Junctions::X4(_, _, ref mut a, ..)) => a, - (2, Junctions::X5(_, _, ref mut a, ..)) => a, - (2, Junctions::X6(_, _, ref mut a, ..)) => a, - (2, Junctions::X7(_, _, ref mut a, ..)) => a, - (2, Junctions::X8(_, _, ref mut a, ..)) => a, - (3, Junctions::X4(_, _, _, ref mut a)) => a, - (3, Junctions::X5(_, _, _, ref mut a, ..)) => a, - (3, Junctions::X6(_, _, _, ref mut a, ..)) => a, - (3, Junctions::X7(_, _, _, ref mut a, ..)) => a, - (3, Junctions::X8(_, _, _, ref mut a, ..)) => a, - (4, Junctions::X5(_, _, _, _, ref mut a)) => a, - (4, Junctions::X6(_, _, _, _, ref mut a, ..)) => a, - (4, Junctions::X7(_, _, _, _, ref mut a, ..)) => a, - (4, Junctions::X8(_, _, _, _, ref mut a, ..)) => a, - (5, Junctions::X6(_, _, _, _, _, ref mut a)) => a, - (5, Junctions::X7(_, _, _, _, _, ref mut a, ..)) => a, - (5, Junctions::X8(_, _, _, _, _, ref mut a, ..)) => a, - (6, Junctions::X7(_, _, _, _, _, _, ref mut a)) => a, - (6, Junctions::X8(_, _, _, _, _, _, ref mut a, ..)) => a, - (7, Junctions::X8(_, _, _, _, _, _, _, ref mut a)) => a, - _ => return None, - }) + self.as_slice_mut().get_mut(i) } /// Returns a reference iterator over the junctions. pub fn iter(&self) -> JunctionsRefIterator { - JunctionsRefIterator { junctions: self, next: 0, back: 0 } + JunctionsRefIterator { junctions: self, range: 0..self.len() } } /// Ensures that self begins with `prefix` and that it has a single `Junction` item following. @@ -555,11 +535,11 @@ impl Junctions { /// /// # Example /// ```rust - /// # use xcm::v3::{Junctions::*, Junction::*}; + /// # use xcm::v3::{Junctions, Junction::*}; /// # fn main() { - /// let mut m = X3(Parachain(2), PalletInstance(3), OnlyChild); - /// assert_eq!(m.match_and_split(&X2(Parachain(2), PalletInstance(3))), Some(&OnlyChild)); - /// assert_eq!(m.match_and_split(&X1(Parachain(2))), None); + /// let mut m = Junctions::from([Parachain(2), PalletInstance(3), OnlyChild]); + /// assert_eq!(m.match_and_split(&[Parachain(2), PalletInstance(3)].into()), Some(&OnlyChild)); + /// assert_eq!(m.match_and_split(&[Parachain(2)].into()), None); /// # } /// ``` pub fn match_and_split(&self, prefix: &Junctions) -> Option<&Junction> { @@ -592,7 +572,7 @@ impl TryFrom for Junctions { impl> From for Junctions { fn from(x: T) -> Self { - Self::X1(x.into()) + [x.into()].into() } } @@ -632,77 +612,105 @@ mod tests { #[test] fn relative_to_works() { - use Junctions::*; use NetworkId::*; - assert_eq!(X1(Polkadot.into()).relative_to(&X1(Kusama.into())), (Parent, Polkadot).into()); - let base = X3(Kusama.into(), Parachain(1), PalletInstance(1)); + assert_eq!( + Junctions::from([Polkadot.into()]).relative_to(&Junctions::from([Kusama.into()])), + (Parent, Polkadot).into() + ); + let base = Junctions::from([Kusama.into(), Parachain(1), PalletInstance(1)]); // Ancestors. assert_eq!(Here.relative_to(&base), (Parent, Parent, Parent).into()); - assert_eq!(X1(Kusama.into()).relative_to(&base), (Parent, Parent).into()); - assert_eq!(X2(Kusama.into(), Parachain(1)).relative_to(&base), (Parent,).into()); + assert_eq!(Junctions::from([Kusama.into()]).relative_to(&base), (Parent, Parent).into()); + assert_eq!( + Junctions::from([Kusama.into(), Parachain(1)]).relative_to(&base), + (Parent,).into() + ); assert_eq!( - X3(Kusama.into(), Parachain(1), PalletInstance(1)).relative_to(&base), + Junctions::from([Kusama.into(), Parachain(1), PalletInstance(1)]).relative_to(&base), Here.into() ); // Ancestors with one child. assert_eq!( - X1(Polkadot.into()).relative_to(&base), + Junctions::from([Polkadot.into()]).relative_to(&base), (Parent, Parent, Parent, Polkadot).into() ); assert_eq!( - X2(Kusama.into(), Parachain(2)).relative_to(&base), + Junctions::from([Kusama.into(), Parachain(2)]).relative_to(&base), (Parent, Parent, Parachain(2)).into() ); assert_eq!( - X3(Kusama.into(), Parachain(1), PalletInstance(2)).relative_to(&base), + Junctions::from([Kusama.into(), Parachain(1), PalletInstance(2)]).relative_to(&base), (Parent, PalletInstance(2)).into() ); assert_eq!( - X4(Kusama.into(), Parachain(1), PalletInstance(1), [1u8; 32].into()).relative_to(&base), + Junctions::from([Kusama.into(), Parachain(1), PalletInstance(1), [1u8; 32].into()]) + .relative_to(&base), ([1u8; 32],).into() ); // Ancestors with grandchildren. assert_eq!( - X2(Polkadot.into(), Parachain(1)).relative_to(&base), + Junctions::from([Polkadot.into(), Parachain(1)]).relative_to(&base), (Parent, Parent, Parent, Polkadot, Parachain(1)).into() ); assert_eq!( - X3(Kusama.into(), Parachain(2), PalletInstance(1)).relative_to(&base), + Junctions::from([Kusama.into(), Parachain(2), PalletInstance(1)]).relative_to(&base), (Parent, Parent, Parachain(2), PalletInstance(1)).into() ); assert_eq!( - X4(Kusama.into(), Parachain(1), PalletInstance(2), [1u8; 32].into()).relative_to(&base), + Junctions::from([Kusama.into(), Parachain(1), PalletInstance(2), [1u8; 32].into()]) + .relative_to(&base), (Parent, PalletInstance(2), [1u8; 32]).into() ); assert_eq!( - X5(Kusama.into(), Parachain(1), PalletInstance(1), [1u8; 32].into(), 1u128.into()) - .relative_to(&base), + Junctions::from([ + Kusama.into(), + Parachain(1), + PalletInstance(1), + [1u8; 32].into(), + 1u128.into() + ]) + .relative_to(&base), ([1u8; 32], 1u128).into() ); } #[test] fn global_consensus_works() { - use Junctions::*; use NetworkId::*; - assert_eq!(X1(Polkadot.into()).global_consensus(), Ok(Polkadot)); - assert_eq!(X2(Kusama.into(), 1u64.into()).global_consensus(), Ok(Kusama)); + assert_eq!(Junctions::from([Polkadot.into()]).global_consensus(), Ok(Polkadot)); + assert_eq!(Junctions::from([Kusama.into(), 1u64.into()]).global_consensus(), Ok(Kusama)); assert_eq!(Here.global_consensus(), Err(())); - assert_eq!(X1(1u64.into()).global_consensus(), Err(())); - assert_eq!(X2(1u64.into(), Kusama.into()).global_consensus(), Err(())); + assert_eq!(Junctions::from([1u64.into()]).global_consensus(), Err(())); + assert_eq!(Junctions::from([1u64.into(), Kusama.into()]).global_consensus(), Err(())); } #[test] fn test_conversion() { - use super::{Junction::*, Junctions::*, NetworkId::*}; + use super::{Junction::*, NetworkId::*}; let x: Junctions = GlobalConsensus(Polkadot).into(); - assert_eq!(x, X1(GlobalConsensus(Polkadot))); + assert_eq!(x, Junctions::from([GlobalConsensus(Polkadot)])); let x: Junctions = Polkadot.into(); - assert_eq!(x, X1(GlobalConsensus(Polkadot))); + assert_eq!(x, Junctions::from([GlobalConsensus(Polkadot)])); let x: Junctions = (Polkadot, Kusama).into(); - assert_eq!(x, X2(GlobalConsensus(Polkadot), GlobalConsensus(Kusama))); + assert_eq!(x, Junctions::from([GlobalConsensus(Polkadot), GlobalConsensus(Kusama)])); + } + + #[test] + fn encode_decode_junctions_works() { + let original = Junctions::from([ + Polkadot.into(), + Kusama.into(), + 1u64.into(), + GlobalConsensus(Polkadot), + Parachain(123), + PalletInstance(45), + ]); + let encoded = original.encode(); + assert_eq!(encoded, &[6, 9, 2, 9, 3, 2, 0, 4, 9, 2, 0, 237, 1, 4, 45]); + let decoded = Junctions::decode(&mut &encoded[..]).unwrap(); + assert_eq!(decoded, original); } } diff --git a/xcm/src/v3/mod.rs b/xcm/src/v3/mod.rs index 435998255a9c..941d4d296c04 100644 --- a/xcm/src/v3/mod.rs +++ b/xcm/src/v3/mod.rs @@ -177,7 +177,7 @@ pub mod prelude { Instruction::*, InteriorMultiLocation, Junction::{self, *}, - Junctions::{self, *}, + Junctions::{self, Here}, MaybeErrorCode, MultiAsset, MultiAssetFilter::{self, *}, MultiAssets, MultiLocation, @@ -895,7 +895,7 @@ pub enum Instruction { /// /// As an example, to export a message for execution on Statemine (parachain #1000 in the /// Kusama network), you would call with `network: NetworkId::Kusama` and - /// `destination: X1(Parachain(1000))`. Alternatively, to export a message for execution on + /// `destination: [Parachain(1000)].into()`. Alternatively, to export a message for execution on /// Polkadot, you would call with `network: NetworkId:: Polkadot` and `destination: Here`. /// /// Kind: *Instruction* diff --git a/xcm/src/v3/multiasset.rs b/xcm/src/v3/multiasset.rs index 06cd2c8b5b82..e7fda776b432 100644 --- a/xcm/src/v3/multiasset.rs +++ b/xcm/src/v3/multiasset.rs @@ -325,9 +325,7 @@ impl TryFrom for WildFungibility { } /// Classification of an asset being concrete or abstract. -#[derive( - Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Encode, Decode, TypeInfo, MaxEncodedLen, -)] +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Encode, Decode, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] pub enum AssetId { /// A specific location identifying an asset. @@ -369,7 +367,7 @@ impl AssetId { /// Prepend a `MultiLocation` to a concrete asset, giving it a new root location. pub fn prepend_with(&mut self, prepend: &MultiLocation) -> Result<(), ()> { if let AssetId::Concrete(ref mut l) = self { - l.prepend_with(*prepend).map_err(|_| ())?; + l.prepend_with(prepend.clone()).map_err(|_| ())?; } Ok(()) } @@ -379,7 +377,7 @@ impl AssetId { pub fn reanchor( &mut self, target: &MultiLocation, - context: InteriorMultiLocation, + context: &InteriorMultiLocation, ) -> Result<(), ()> { if let AssetId::Concrete(ref mut l) = self { l.reanchor(target, context)?; @@ -453,7 +451,7 @@ impl MultiAsset { pub fn reanchor( &mut self, target: &MultiLocation, - context: InteriorMultiLocation, + context: &InteriorMultiLocation, ) -> Result<(), ()> { self.id.reanchor(target, context) } @@ -463,7 +461,7 @@ impl MultiAsset { pub fn reanchored( mut self, target: &MultiLocation, - context: InteriorMultiLocation, + context: &InteriorMultiLocation, ) -> Result { self.id.reanchor(target, context)?; Ok(self) @@ -675,7 +673,7 @@ impl MultiAssets { pub fn reanchor( &mut self, target: &MultiLocation, - context: InteriorMultiLocation, + context: &InteriorMultiLocation, ) -> Result<(), ()> { self.0.iter_mut().try_for_each(|i| i.reanchor(target, context)) } @@ -757,7 +755,7 @@ impl WildMultiAsset { pub fn reanchor( &mut self, target: &MultiLocation, - context: InteriorMultiLocation, + context: &InteriorMultiLocation, ) -> Result<(), ()> { use WildMultiAsset::*; match self { @@ -849,7 +847,7 @@ impl MultiAssetFilter { pub fn reanchor( &mut self, target: &MultiLocation, - context: InteriorMultiLocation, + context: &InteriorMultiLocation, ) -> Result<(), ()> { match self { MultiAssetFilter::Definite(ref mut assets) => assets.reanchor(target, context), diff --git a/xcm/src/v3/multilocation.rs b/xcm/src/v3/multilocation.rs index 7a2f3eb0ca33..f9f735e64873 100644 --- a/xcm/src/v3/multilocation.rs +++ b/xcm/src/v3/multilocation.rs @@ -51,9 +51,7 @@ use scale_info::TypeInfo; /// 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, -)] +#[derive(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`. @@ -107,7 +105,7 @@ impl MultiLocation { } /// Whether the `MultiLocation` has no parents and has a `Here` interior. - pub const fn is_here(&self) -> bool { + pub fn is_here(&self) -> bool { self.parents == 0 && self.interior.len() == 0 } @@ -131,6 +129,23 @@ impl MultiLocation { self.parents } + /// Returns the parent count and the interior `Junctions` as a tuple. + /// + /// To be used when pattern matching, for example: + /// + /// ```rust + /// # use xcm::v3::{Junctions::*, Junction::*, MultiLocation}; + /// fn get_parachain_id(loc: &MultiLocation) -> Option { + /// match loc.unpack() { + /// (0, [Parachain(id)]) => Some(*id), + /// _ => None + /// } + /// } + /// ``` + pub fn unpack(&self) -> (u8, &[Junction]) { + (self.parents, self.interior.as_slice()) + } + /// 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 { @@ -138,7 +153,7 @@ impl MultiLocation { } /// Returns the number of parents and junctions in `self`. - pub const fn len(&self) -> usize { + pub fn len(&self) -> usize { self.parent_count() as usize + self.interior.len() } @@ -256,9 +271,9 @@ impl MultiLocation { /// ```rust /// # use xcm::v3::{Junctions::*, Junction::*, MultiLocation}; /// # fn main() { - /// let mut m = MultiLocation::new(1, X2(PalletInstance(3), OnlyChild)); + /// let mut m = MultiLocation::new(1, [PalletInstance(3), OnlyChild]); /// assert_eq!( - /// m.match_and_split(&MultiLocation::new(1, X1(PalletInstance(3)))), + /// m.match_and_split(&MultiLocation::new(1, [PalletInstance(3)])), /// Some(&OnlyChild), /// ); /// assert_eq!(m.match_and_split(&MultiLocation::new(1, Here)), None); @@ -285,7 +300,7 @@ impl MultiLocation { /// # 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)))); + /// assert_eq!(m, MultiLocation::new(1, [Parachain(21), PalletInstance(3)])); /// # } /// ``` pub fn append_with(&mut self, suffix: impl Into) -> Result<(), Self> { @@ -306,7 +321,7 @@ impl MultiLocation { /// # 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)))); + /// assert_eq!(r, MultiLocation::new(1, [Parachain(21), PalletInstance(3)])); /// # } /// ``` pub fn appended_with(mut self, suffix: impl Into) -> Result { @@ -326,7 +341,7 @@ impl MultiLocation { /// # 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)))); + /// assert_eq!(m, MultiLocation::new(1, [PalletInstance(3)])); /// # } /// ``` pub fn prepend_with(&mut self, prefix: impl Into) -> Result<(), Self> { @@ -375,7 +390,7 @@ impl MultiLocation { /// # 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)))); + /// assert_eq!(r, MultiLocation::new(1, [PalletInstance(3)])); /// # } /// ``` pub fn prepended_with(mut self, prefix: impl Into) -> Result { @@ -392,7 +407,7 @@ impl MultiLocation { pub fn reanchor( &mut self, target: &MultiLocation, - context: InteriorMultiLocation, + context: &InteriorMultiLocation, ) -> Result<(), ()> { // TODO: https://github.com/paritytech/polkadot/issues/4489 Optimize this. @@ -417,7 +432,7 @@ impl MultiLocation { pub fn reanchored( mut self, target: &MultiLocation, - context: InteriorMultiLocation, + context: &InteriorMultiLocation, ) -> Result { match self.reanchor(target, context) { Ok(()) => Ok(self), @@ -515,26 +530,26 @@ mod tests { 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 context = [Parachain(1000), PalletInstance(42)].into(); 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 context = [PalletInstance(42)].into(); 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 context = [Parachain(1000), PalletInstance(42)].into(); 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 context = [OnlyChild, Parachain(1000), PalletInstance(42)].into(); let expected = GeneralIndex(69).into(); location.simplify(&context); assert_eq!(location, expected); @@ -544,7 +559,7 @@ mod tests { 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 context = [Parachain(1000), PalletInstance(42), GeneralIndex(42)].into(); let expected = (Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into(); location.simplify(&context); @@ -552,7 +567,7 @@ mod tests { let mut location: MultiLocation = (Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into(); - let context = X1(Parachain(1000)); + let context = [Parachain(1000)].into(); let expected = (Parent, Parent, Parachain(1000), PalletInstance(42), GeneralIndex(69)).into(); location.simplify(&context); @@ -565,7 +580,7 @@ mod tests { let context = Parachain(2000).into(); let target = (Parent, Parachain(1000)).into(); let expected = GeneralIndex(42).into(); - id.reanchor(&target, context).unwrap(); + id.reanchor(&target, &context).unwrap(); assert_eq!(id, expected); } @@ -573,7 +588,7 @@ mod tests { fn encode_and_decode_works() { let m = MultiLocation { parents: 1, - interior: X2(Parachain(42), AccountIndex64 { network: None, index: 23 }), + interior: [Parachain(42), AccountIndex64 { network: None, index: 23 }].into(), }; let encoded = m.encode(); assert_eq!(encoded, [1, 2, 0, 168, 2, 0, 92].to_vec()); @@ -585,11 +600,11 @@ mod tests { fn match_and_split_works() { let m = MultiLocation { parents: 1, - interior: X2(Parachain(42), AccountIndex64 { network: None, index: 23 }), + interior: [Parachain(42), AccountIndex64 { network: None, index: 23 }].into(), }; 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)) }), + m.match_and_split(&MultiLocation { parents: 1, interior: [Parachain(42)].into() }), Some(&AccountIndex64 { network: None, index: 23 }) ); assert_eq!(m.match_and_split(&m), None); @@ -598,51 +613,54 @@ mod tests { #[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)), Ok(())); + let mut m = MultiLocation { parents: 1, interior: [Parachain(42)].into() }; + assert_eq!(m.append_with([PalletInstance(3), acc]), Ok(())); assert_eq!( m, - MultiLocation { parents: 1, interior: X3(Parachain(42), PalletInstance(3), acc) } + MultiLocation { parents: 1, interior: [Parachain(42), PalletInstance(3), acc].into() } ); // 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), + interior: [Parachain(42), OnlyChild, OnlyChild, OnlyChild, OnlyChild].into(), }; let suffix: MultiLocation = (PalletInstance(3), acc, OnlyChild, OnlyChild).into(); - assert_eq!(m.clone().append_with(suffix), Err(suffix)); + 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 }), + interior: [Parachain(42), AccountIndex64 { network: None, index: 23 }].into(), }; - assert_eq!(m.prepend_with(MultiLocation { parents: 1, interior: X1(OnlyChild) }), Ok(())); + assert_eq!( + m.prepend_with(MultiLocation { parents: 1, interior: [OnlyChild].into() }), + Ok(()) + ); assert_eq!( m, MultiLocation { parents: 1, - interior: X2(Parachain(42), AccountIndex64 { network: None, index: 23 }) + interior: [Parachain(42), AccountIndex64 { network: None, index: 23 }].into() } ); // cannot prepend to create overly long multilocation - let mut m = MultiLocation { parents: 254, interior: X1(Parachain(42)) }; + let mut m = MultiLocation { parents: 254, interior: [Parachain(42)].into() }; let prefix = MultiLocation { parents: 2, interior: Here }; - assert_eq!(m.prepend_with(prefix), Err(prefix)); + 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)) }); + assert_eq!(m, MultiLocation { parents: 255, interior: [Parachain(42)].into() }); } #[test] fn double_ended_ref_iteration_works() { - let m = X3(Parachain(1000), Parachain(3), PalletInstance(5)); + let m: Junctions = [Parachain(1000), Parachain(3), PalletInstance(5)].into(); let mut iter = m.iter(); let first = iter.next().unwrap(); @@ -680,17 +698,17 @@ mod tests { takes_multilocation(Parent); takes_multilocation(Here); - takes_multilocation(X1(Parachain(42))); + takes_multilocation([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 }), + [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(ParentThen([Parachain(75)].into())); takes_multilocation([Parachain(100), PalletInstance(3)]); assert_eq!( @@ -701,7 +719,7 @@ mod tests { assert_eq!( v2::MultiLocation::from((v2::Parent, v2::Parent, v2::Junction::GeneralIndex(42u128),)) .try_into(), - Ok(MultiLocation { parents: 2, interior: X1(GeneralIndex(42u128)) }), + Ok(MultiLocation { parents: 2, interior: [GeneralIndex(42u128)].into() }), ); } } diff --git a/xcm/src/v3/traits.rs b/xcm/src/v3/traits.rs index b752647b0819..a184443d9504 100644 --- a/xcm/src/v3/traits.rs +++ b/xcm/src/v3/traits.rs @@ -412,8 +412,8 @@ impl Unwrappable for Option { /// impl SendXcm for Sender2 { /// type Ticket = (); /// fn validate(destination: &mut Option, message: &mut Option>) -> SendResult<()> { -/// match destination.as_ref().ok_or(SendError::MissingArgument)? { -/// MultiLocation { parents: 0, interior: X2(j1, j2) } => Ok(((), MultiAssets::new())), +/// match destination.as_ref().ok_or(SendError::MissingArgument)?.unpack() { +/// (0, [_, _]) => Ok(((), MultiAssets::new())), /// _ => Err(SendError::Unroutable), /// } /// } diff --git a/xcm/xcm-builder/src/asset_conversion.rs b/xcm/xcm-builder/src/asset_conversion.rs index 5db425a75b8b..35dd786df8d9 100644 --- a/xcm/xcm-builder/src/asset_conversion.rs +++ b/xcm/xcm-builder/src/asset_conversion.rs @@ -233,13 +233,13 @@ mod tests { >; assert_eq!( TrustBackedAssetsPalletLocation::get(), - MultiLocation { parents: 0, interior: X1(PalletInstance(50)) } + MultiLocation { parents: 0, interior: [PalletInstance(50)].into() } ); // err - does not match assert_eq!( Converter::matches_fungibles(&MultiAsset { - id: Concrete(MultiLocation::new(1, X2(PalletInstance(50), GeneralIndex(1)))), + id: Concrete(MultiLocation::new(1, [PalletInstance(50), GeneralIndex(1)])), fun: Fungible(12345), }), Err(MatchError::AssetNotHandled) @@ -250,7 +250,7 @@ mod tests { Converter::matches_fungibles(&MultiAsset { id: Concrete(MultiLocation::new( 0, - X2(PalletInstance(50), GeneralKey { length: 1, data: [1; 32] }) + [PalletInstance(50), GeneralKey { length: 1, data: [1; 32] }] )), fun: Fungible(12345), }), @@ -260,7 +260,7 @@ mod tests { // err - matches, but NonFungible assert_eq!( Converter::matches_fungibles(&MultiAsset { - id: Concrete(MultiLocation::new(0, X2(PalletInstance(50), GeneralIndex(1)))), + id: Concrete(MultiLocation::new(0, [PalletInstance(50), GeneralIndex(1)])), fun: NonFungible(Index(54321)), }), Err(MatchError::AssetNotHandled) @@ -269,7 +269,7 @@ mod tests { // ok assert_eq!( Converter::matches_fungibles(&MultiAsset { - id: Concrete(MultiLocation::new(0, X2(PalletInstance(50), GeneralIndex(1)))), + id: Concrete(MultiLocation::new(0, [PalletInstance(50), GeneralIndex(1)])), fun: Fungible(12345), }), Ok((1, 12345)) @@ -305,13 +305,13 @@ mod tests { >; assert_eq!( TrustBackedAssetsPalletLocation::get(), - MultiLocation { parents: 0, interior: X1(PalletInstance(50)) } + MultiLocation { parents: 0, interior: [PalletInstance(50)].into() } ); // err - does not match assert_eq!( Converter::matches_nonfungibles(&MultiAsset { - id: Concrete(MultiLocation::new(1, X2(PalletInstance(50), GeneralIndex(1)))), + id: Concrete(MultiLocation::new(1, [PalletInstance(50), GeneralIndex(1)])), fun: NonFungible(Index(54321)), }), Err(MatchError::AssetNotHandled) @@ -322,7 +322,7 @@ mod tests { Converter::matches_nonfungibles(&MultiAsset { id: Concrete(MultiLocation::new( 0, - X2(PalletInstance(50), GeneralKey { length: 1, data: [1; 32] }) + [PalletInstance(50), GeneralKey { length: 1, data: [1; 32] }] )), fun: NonFungible(Index(54321)), }), @@ -332,7 +332,7 @@ mod tests { // err - matches, but Fungible vs NonFungible assert_eq!( Converter::matches_nonfungibles(&MultiAsset { - id: Concrete(MultiLocation::new(0, X2(PalletInstance(50), GeneralIndex(1)))), + id: Concrete(MultiLocation::new(0, [PalletInstance(50), GeneralIndex(1)])), fun: Fungible(12345), }), Err(MatchError::AssetNotHandled) @@ -341,7 +341,7 @@ mod tests { // ok assert_eq!( Converter::matches_nonfungibles(&MultiAsset { - id: Concrete(MultiLocation::new(0, X2(PalletInstance(50), GeneralIndex(1)))), + id: Concrete(MultiLocation::new(0, [PalletInstance(50), GeneralIndex(1)])), fun: NonFungible(Index(54321)), }), Ok((1, 54321)) diff --git a/xcm/xcm-builder/src/barriers.rs b/xcm/xcm-builder/src/barriers.rs index 489f91d6b659..fe83234d3f32 100644 --- a/xcm/xcm-builder/src/barriers.rs +++ b/xcm/xcm-builder/src/barriers.rs @@ -25,9 +25,7 @@ use polkadot_parachain::primitives::IsSystem; use sp_std::{cell::Cell, marker::PhantomData, ops::ControlFlow, result::Result}; use xcm::latest::{ Instruction::{self, *}, - InteriorMultiLocation, Junction, Junctions, - Junctions::X1, - MultiLocation, Weight, + InteriorMultiLocation, Junction, Junctions, MultiLocation, Weight, WeightLimit::*, }; use xcm_executor::traits::{CheckSuspension, OnResponse, ShouldExecute}; @@ -173,7 +171,7 @@ impl< "WithComputedOrigin origin: {:?}, instructions: {:?}, max_weight: {:?}, weight_credit: {:?}", origin, instructions, max_weight, weight_credit, ); - let mut actual_origin = *origin; + let mut actual_origin = origin.clone(); let skipped = Cell::new(0usize); // NOTE: We do not check the validity of `UniversalOrigin` here, meaning that a malicious // origin could place a `UniversalOrigin` in order to spoof some location which gets free @@ -188,10 +186,11 @@ impl< // Note the origin is *relative to local consensus*! So we need to escape // local consensus with the `parents` before diving in into the // `universal_location`. - actual_origin = X1(*new_global).relative_to(&LocalUniversal::get()); + actual_origin = + Junctions::from(*new_global).relative_to(&LocalUniversal::get()); }, DescendOrigin(j) => { - let Ok(_) = actual_origin.append_with(*j) else { + let Ok(_) = actual_origin.append_with(j.clone()) else { return Err(ProcessMessageError::Unsupported) }; }, @@ -286,8 +285,8 @@ pub struct IsChildSystemParachain(PhantomData); impl> Contains for IsChildSystemParachain { fn contains(l: &MultiLocation) -> bool { matches!( - l.interior(), - Junctions::X1(Junction::Parachain(id)) + l.interior().as_slice(), + [Junction::Parachain(id)] if ParaId::from(*id).is_system() && l.parent_count() == 0, ) } diff --git a/xcm/xcm-builder/src/location_conversion.rs b/xcm/xcm-builder/src/location_conversion.rs index 4239dc17dbdc..7782e1f1e9b9 100644 --- a/xcm/xcm-builder/src/location_conversion.rs +++ b/xcm/xcm-builder/src/location_conversion.rs @@ -72,33 +72,25 @@ impl + Clone> Convert for ForeignChainAliasAccount { fn convert_ref(location: impl Borrow) -> Result { - let entropy = match location.borrow() { + let entropy = match location.borrow().unpack() { // Used on the relay chain for sending paras that use 32 byte accounts - MultiLocation { - parents: 0, - interior: X2(Parachain(para_id), AccountId32 { id, .. }), - } => ForeignChainAliasAccount::::from_para_32(para_id, id, 0), + (0, [Parachain(para_id), AccountId32 { id, .. }]) => + ForeignChainAliasAccount::::from_para_32(para_id, id, 0), // Used on the relay chain for sending paras that use 20 byte accounts - MultiLocation { - parents: 0, - interior: X2(Parachain(para_id), AccountKey20 { key, .. }), - } => ForeignChainAliasAccount::::from_para_20(para_id, key, 0), + (0, [Parachain(para_id), AccountKey20 { key, .. }]) => + ForeignChainAliasAccount::::from_para_20(para_id, key, 0), // Used on para-chain for sending paras that use 32 byte accounts - MultiLocation { - parents: 1, - interior: X2(Parachain(para_id), AccountId32 { id, .. }), - } => ForeignChainAliasAccount::::from_para_32(para_id, id, 1), + (1, [Parachain(para_id), AccountId32 { id, .. }]) => + ForeignChainAliasAccount::::from_para_32(para_id, id, 1), // Used on para-chain for sending paras that use 20 byte accounts - MultiLocation { - parents: 1, - interior: X2(Parachain(para_id), AccountKey20 { key, .. }), - } => ForeignChainAliasAccount::::from_para_20(para_id, key, 1), + (1, [Parachain(para_id), AccountKey20 { key, .. }]) => + ForeignChainAliasAccount::::from_para_20(para_id, key, 1), // Used on para-chain for sending from the relay chain - MultiLocation { parents: 1, interior: X1(AccountId32 { id, .. }) } => + (1, [AccountId32 { id, .. }]) => ForeignChainAliasAccount::::from_relay_32(id, 1), // No other conversions provided @@ -173,9 +165,8 @@ impl + Into + AccountIdConversion, AccountId: Convert for ChildParachainConvertsVia { fn convert_ref(location: impl Borrow) -> Result { - match location.borrow() { - MultiLocation { parents: 0, interior: X1(Parachain(id)) } => - Ok(ParaId::from(*id).into_account_truncating()), + match location.borrow().unpack() { + (0, [Parachain(id)]) => Ok(ParaId::from(*id).into_account_truncating()), _ => Err(()), } } @@ -194,16 +185,15 @@ impl + Into + AccountIdConversion, AccountId: Convert for SiblingParachainConvertsVia { fn convert_ref(location: impl Borrow) -> Result { - match location.borrow() { - MultiLocation { parents: 1, interior: X1(Parachain(id)) } => - Ok(ParaId::from(*id).into_account_truncating()), + match location.borrow().unpack() { + (1, [Parachain(id)]) => Ok(ParaId::from(*id).into_account_truncating()), _ => Err(()), } } fn reverse_ref(who: impl Borrow) -> Result { if let Some(id) = ParaId::try_from_account(who.borrow()) { - Ok(MultiLocation::new(1, X1(Parachain(id.into())))) + Ok(MultiLocation::new(1, [Parachain(id.into())])) } else { Err(()) } @@ -216,14 +206,12 @@ impl>, AccountId: From<[u8; 32]> + Into<[u8; 32]> Convert for AccountId32Aliases { fn convert(location: MultiLocation) -> Result { - let id = match location { - MultiLocation { parents: 0, interior: X1(AccountId32 { id, network: None }) } => id, - MultiLocation { parents: 0, interior: X1(AccountId32 { id, network }) } - if network == Network::get() => - id, + let id = match location.unpack() { + (0, [AccountId32 { id, network: None }]) => id, + (0, [AccountId32 { id, network }]) if *network == Network::get() => id, _ => return Err(location), }; - Ok(id.into()) + Ok((*id).into()) } fn reverse(who: AccountId) -> Result { @@ -236,14 +224,12 @@ impl>, AccountId: From<[u8; 20]> + Into<[u8; 20]> Convert for AccountKey20Aliases { fn convert(location: MultiLocation) -> Result { - let key = match location { - MultiLocation { parents: 0, interior: X1(AccountKey20 { key, network: None }) } => key, - MultiLocation { parents: 0, interior: X1(AccountKey20 { key, network }) } - if network == Network::get() => - key, + let key = match location.unpack() { + (0, [AccountKey20 { key, network: None }]) => key, + (0, [AccountKey20 { key, network }]) if *network == Network::get() => key, _ => return Err(location), }; - Ok(key.into()) + Ok((*key).into()) } fn reverse(who: AccountId) -> Result { @@ -282,12 +268,12 @@ mod tests { #[test] fn inverter_works_in_tree() { parameter_types! { - pub UniversalLocation: InteriorMultiLocation = X3(Parachain(1), account20(), account20()); + pub UniversalLocation: InteriorMultiLocation = [Parachain(1), account20(), account20()].into(); } - let input = MultiLocation::new(3, X2(Parachain(2), account32())); + let input = MultiLocation::new(3, [Parachain(2), account32()]); let inverted = UniversalLocation::get().invert_target(&input).unwrap(); - assert_eq!(inverted, MultiLocation::new(2, X3(Parachain(1), account20(), account20()))); + assert_eq!(inverted, MultiLocation::new(2, [Parachain(1), account20(), account20()])); } // Network Topology @@ -297,12 +283,12 @@ mod tests { #[test] fn inverter_uses_context_as_inverted_location() { parameter_types! { - pub UniversalLocation: InteriorMultiLocation = X2(account20(), account20()); + pub UniversalLocation: InteriorMultiLocation = [account20(), account20()].into(); } let input = MultiLocation::grandparent(); let inverted = UniversalLocation::get().invert_target(&input).unwrap(); - assert_eq!(inverted, X2(account20(), account20()).into()); + assert_eq!(inverted, [account20(), account20()].into()); } // Network Topology @@ -326,7 +312,7 @@ mod tests { pub UniversalLocation: InteriorMultiLocation = Here; } - let input = MultiLocation { parents: 99, interior: X1(Parachain(88)) }; + let input = MultiLocation { parents: 99, interior: [Parachain(88)].into() }; let inverted = UniversalLocation::get().invert_target(&input); assert_eq!(inverted, Err(())); } @@ -335,7 +321,7 @@ mod tests { fn remote_account_convert_on_para_sending_para_32() { let mul = MultiLocation { parents: 1, - interior: X2(Parachain(1), AccountId32 { network: None, id: [0u8; 32] }), + interior: [Parachain(1), AccountId32 { network: None, id: [0u8; 32] }].into(), }; let rem_1 = ForeignChainAliasAccount::<[u8; 32]>::convert(mul).unwrap(); @@ -349,17 +335,18 @@ mod tests { let mul = MultiLocation { parents: 1, - interior: X2( + interior: [ Parachain(1), AccountId32 { network: Some(NetworkId::Polkadot), id: [0u8; 32] }, - ), + ] + .into(), }; assert_eq!(ForeignChainAliasAccount::<[u8; 32]>::convert(mul).unwrap(), rem_1); let mul = MultiLocation { parents: 1, - interior: X2(Parachain(2), AccountId32 { network: None, id: [0u8; 32] }), + interior: [Parachain(2), AccountId32 { network: None, id: [0u8; 32] }].into(), }; let rem_2 = ForeignChainAliasAccount::<[u8; 32]>::convert(mul).unwrap(); @@ -378,7 +365,7 @@ mod tests { fn remote_account_convert_on_para_sending_para_20() { let mul = MultiLocation { parents: 1, - interior: X2(Parachain(1), AccountKey20 { network: None, key: [0u8; 20] }), + interior: [Parachain(1), AccountKey20 { network: None, key: [0u8; 20] }].into(), }; let rem_1 = ForeignChainAliasAccount::<[u8; 32]>::convert(mul).unwrap(); @@ -392,17 +379,18 @@ mod tests { let mul = MultiLocation { parents: 1, - interior: X2( + interior: [ Parachain(1), AccountKey20 { network: Some(NetworkId::Polkadot), key: [0u8; 20] }, - ), + ] + .into(), }; assert_eq!(ForeignChainAliasAccount::<[u8; 32]>::convert(mul).unwrap(), rem_1); let mul = MultiLocation { parents: 1, - interior: X2(Parachain(2), AccountKey20 { network: None, key: [0u8; 20] }), + interior: [Parachain(2), AccountKey20 { network: None, key: [0u8; 20] }].into(), }; let rem_2 = ForeignChainAliasAccount::<[u8; 32]>::convert(mul).unwrap(); @@ -421,7 +409,7 @@ mod tests { fn remote_account_convert_on_para_sending_relay() { let mul = MultiLocation { parents: 1, - interior: X1(AccountId32 { network: None, id: [0u8; 32] }), + interior: [AccountId32 { network: None, id: [0u8; 32] }].into(), }; let rem_1 = ForeignChainAliasAccount::<[u8; 32]>::convert(mul).unwrap(); @@ -435,14 +423,14 @@ mod tests { let mul = MultiLocation { parents: 1, - interior: X1(AccountId32 { network: Some(NetworkId::Polkadot), id: [0u8; 32] }), + interior: [AccountId32 { network: Some(NetworkId::Polkadot), id: [0u8; 32] }].into(), }; assert_eq!(ForeignChainAliasAccount::<[u8; 32]>::convert(mul).unwrap(), rem_1); let mul = MultiLocation { parents: 1, - interior: X1(AccountId32 { network: None, id: [1u8; 32] }), + interior: [AccountId32 { network: None, id: [1u8; 32] }].into(), }; let rem_2 = ForeignChainAliasAccount::<[u8; 32]>::convert(mul).unwrap(); @@ -461,7 +449,7 @@ mod tests { fn remote_account_convert_on_relay_sending_para_20() { let mul = MultiLocation { parents: 0, - interior: X2(Parachain(1), AccountKey20 { network: None, key: [0u8; 20] }), + interior: [Parachain(1), AccountKey20 { network: None, key: [0u8; 20] }].into(), }; let rem_1 = ForeignChainAliasAccount::<[u8; 32]>::convert(mul).unwrap(); @@ -475,7 +463,7 @@ mod tests { let mul = MultiLocation { parents: 0, - interior: X2(Parachain(2), AccountKey20 { network: None, key: [0u8; 20] }), + interior: [Parachain(2), AccountKey20 { network: None, key: [0u8; 20] }].into(), }; let rem_2 = ForeignChainAliasAccount::<[u8; 32]>::convert(mul).unwrap(); @@ -494,7 +482,7 @@ mod tests { fn remote_account_convert_on_relay_sending_para_32() { let mul = MultiLocation { parents: 0, - interior: X2(Parachain(1), AccountId32 { network: None, id: [0u8; 32] }), + interior: [Parachain(1), AccountId32 { network: None, id: [0u8; 32] }].into(), }; let rem_1 = ForeignChainAliasAccount::<[u8; 32]>::convert(mul).unwrap(); @@ -508,17 +496,18 @@ mod tests { let mul = MultiLocation { parents: 0, - interior: X2( + interior: [ Parachain(1), AccountId32 { network: Some(NetworkId::Polkadot), id: [0u8; 32] }, - ), + ] + .into(), }; assert_eq!(ForeignChainAliasAccount::<[u8; 32]>::convert(mul).unwrap(), rem_1); let mul = MultiLocation { parents: 0, - interior: X2(Parachain(2), AccountId32 { network: None, id: [0u8; 32] }), + interior: [Parachain(2), AccountId32 { network: None, id: [0u8; 32] }].into(), }; let rem_2 = ForeignChainAliasAccount::<[u8; 32]>::convert(mul).unwrap(); @@ -537,7 +526,7 @@ mod tests { fn remote_account_fails_with_bad_multilocation() { let mul = MultiLocation { parents: 1, - interior: X1(AccountKey20 { network: None, key: [0u8; 20] }), + interior: [AccountKey20 { network: None, key: [0u8; 20] }].into(), }; assert!(ForeignChainAliasAccount::<[u8; 32]>::convert(mul).is_err()); } diff --git a/xcm/xcm-builder/src/origin_conversion.rs b/xcm/xcm-builder/src/origin_conversion.rs index 22a79d0f8028..f89e6c4c8a5d 100644 --- a/xcm/xcm-builder/src/origin_conversion.rs +++ b/xcm/xcm-builder/src/origin_conversion.rs @@ -81,12 +81,11 @@ impl, RuntimeOrigin: OriginTrait> ConvertOrigin Result { let origin = origin.into(); log::trace!(target: "xcm::origin_conversion", "ChildSystemParachainAsSuperuser origin: {:?}, kind: {:?}", origin, kind); - match (kind, origin) { - ( - OriginKind::Superuser, - MultiLocation { parents: 0, interior: X1(Junction::Parachain(id)) }, - ) if ParaId::from(id).is_system() => Ok(RuntimeOrigin::root()), - (_, origin) => Err(origin), + match (kind, origin.unpack()) { + (OriginKind::Superuser, (0, [Junction::Parachain(id)])) + if ParaId::from(*id).is_system() => + Ok(RuntimeOrigin::root()), + _ => Err(origin), } } } @@ -107,12 +106,11 @@ impl, RuntimeOrigin: OriginTrait> ConvertOrigin Ok(RuntimeOrigin::root()), - (_, origin) => Err(origin), + match (kind, origin.unpack()) { + (OriginKind::Superuser, (1, [Junction::Parachain(id)])) + if ParaId::from(*id).is_system() => + Ok(RuntimeOrigin::root()), + _ => Err(origin), } } } @@ -129,12 +127,10 @@ impl, RuntimeOrigin: From> ConvertOr ) -> Result { let origin = origin.into(); log::trace!(target: "xcm::origin_conversion", "ChildParachainAsNative origin: {:?}, kind: {:?}", origin, kind); - match (kind, origin) { - ( - OriginKind::Native, - MultiLocation { parents: 0, interior: X1(Junction::Parachain(id)) }, - ) => Ok(RuntimeOrigin::from(ParachainOrigin::from(id))), - (_, origin) => Err(origin), + match (kind, origin.unpack()) { + (OriginKind::Native, (0, [Junction::Parachain(id)])) => + Ok(RuntimeOrigin::from(ParachainOrigin::from(*id))), + _ => Err(origin), } } } @@ -155,12 +151,10 @@ impl, RuntimeOrigin: From> ConvertOr "SiblingParachainAsNative origin: {:?}, kind: {:?}", origin, kind, ); - match (kind, origin) { - ( - OriginKind::Native, - MultiLocation { parents: 1, interior: X1(Junction::Parachain(id)) }, - ) => Ok(RuntimeOrigin::from(ParachainOrigin::from(id))), - (_, origin) => Err(origin), + match (kind, origin.unpack()) { + (OriginKind::Native, (1, [Junction::Parachain(id)])) => + Ok(RuntimeOrigin::from(ParachainOrigin::from(*id))), + _ => Err(origin), } } } @@ -202,13 +196,11 @@ where "SignedAccountId32AsNative origin: {:?}, kind: {:?}", origin, kind, ); - match (kind, origin) { - ( - OriginKind::Native, - MultiLocation { parents: 0, interior: X1(Junction::AccountId32 { id, network }) }, - ) if matches!(network, None) || network == Network::get() => - Ok(RuntimeOrigin::signed(id.into())), - (_, origin) => Err(origin), + match (kind, origin.unpack()) { + (OriginKind::Native, (0, [Junction::AccountId32 { id, network }])) + if matches!(network, None) || *network == Network::get() => + Ok(RuntimeOrigin::signed((*id).into())), + _ => Err(origin), } } } @@ -231,13 +223,11 @@ where "SignedAccountKey20AsNative origin: {:?}, kind: {:?}", origin, kind, ); - match (kind, origin) { - ( - OriginKind::Native, - MultiLocation { parents: 0, interior: X1(Junction::AccountKey20 { key, network }) }, - ) if (matches!(network, None) || network == Network::get()) => - Ok(RuntimeOrigin::signed(key.into())), - (_, origin) => Err(origin), + match (kind, origin.unpack()) { + (OriginKind::Native, (0, [Junction::AccountKey20 { key, network }])) + if (matches!(network, None) || *network == Network::get()) => + Ok(RuntimeOrigin::signed((*key).into())), + _ => Err(origin), } } } diff --git a/xcm/xcm-builder/src/test_utils.rs b/xcm/xcm-builder/src/test_utils.rs index d0f867ba62d6..b286351e0792 100644 --- a/xcm/xcm-builder/src/test_utils.rs +++ b/xcm/xcm-builder/src/test_utils.rs @@ -45,14 +45,14 @@ impl VersionChangeNotifier for TestSubscriptionService { _context: &XcmContext, ) -> XcmResult { let mut r = SubscriptionRequests::get(); - r.push((*location, Some((query_id, max_weight)))); + r.push((location.clone(), Some((query_id, max_weight)))); SubscriptionRequests::set(r); Ok(()) } fn stop(location: &MultiLocation, _context: &XcmContext) -> XcmResult { let mut r = SubscriptionRequests::get(); r.retain(|(l, _q)| l != location); - r.push((*location, None)); + r.push((location.clone(), None)); SubscriptionRequests::set(r); Ok(()) } @@ -71,7 +71,7 @@ pub struct TestAssetTrap; impl DropAssets for TestAssetTrap { fn drop_assets(origin: &MultiLocation, assets: Assets, _context: &XcmContext) -> Weight { let mut t: Vec<(MultiLocation, MultiAssets)> = TrappedAssets::get(); - t.push((*origin, assets.into())); + t.push((origin.clone(), assets.into())); TrappedAssets::set(t); Weight::from_parts(5, 5) } @@ -85,7 +85,7 @@ impl ClaimAssets for TestAssetTrap { _context: &XcmContext, ) -> bool { let mut t: Vec<(MultiLocation, MultiAssets)> = TrappedAssets::get(); - if let (0, X1(GeneralIndex(i))) = (ticket.parents, &ticket.interior) { + if let (0, [GeneralIndex(i)]) = ticket.unpack() { if let Some((l, a)) = t.get(*i as usize) { if l == origin && a == what { t.swap_remove(*i as usize); diff --git a/xcm/xcm-builder/src/tests/assets.rs b/xcm/xcm-builder/src/tests/assets.rs index 9b8ba0e459de..b416ccd4718e 100644 --- a/xcm/xcm-builder/src/tests/assets.rs +++ b/xcm/xcm-builder/src/tests/assets.rs @@ -110,13 +110,13 @@ fn paying_reserve_deposit_should_work() { #[test] fn transfer_should_work() { // we'll let them have message execution for free. - AllowUnpaidFrom::set(vec![X1(Parachain(1)).into()]); + AllowUnpaidFrom::set(vec![[Parachain(1)].into()]); // Child parachain #1 owns 1000 tokens held by us in reserve. add_asset(Parachain(1), (Here, 1000)); // They want to transfer 100 of them to their sibling parachain #2 let message = Xcm(vec![TransferAsset { assets: (Here, 100u128).into(), - beneficiary: X1(AccountIndex64 { index: 3, network: None }).into(), + beneficiary: [AccountIndex64 { index: 3, network: None }].into(), }]); let hash = fake_message_hash(&message); let r = XcmExecutor::::execute_xcm( @@ -136,11 +136,11 @@ fn transfer_should_work() { #[test] fn reserve_transfer_should_work() { - AllowUnpaidFrom::set(vec![X1(Parachain(1)).into()]); + AllowUnpaidFrom::set(vec![[Parachain(1)].into()]); // Child parachain #1 owns 1000 tokens held by us in reserve. add_asset(Parachain(1), (Here, 1000)); // The remote account owned by gav. - let three: MultiLocation = X1(AccountIndex64 { index: 3, network: None }).into(); + let three: MultiLocation = [AccountIndex64 { index: 3, network: None }].into(); // They want to transfer 100 of our native asset from sovereign account of parachain #1 into #2 // and let them know to hand it to account #3. @@ -174,7 +174,7 @@ fn reserve_transfer_should_work() { #[test] fn burn_should_work() { // we'll let them have message execution for free. - AllowUnpaidFrom::set(vec![X1(Parachain(1)).into()]); + AllowUnpaidFrom::set(vec![[Parachain(1)].into()]); // Child parachain #1 owns 1000 tokens held by us in reserve. add_asset(Parachain(1), (Here, 1000)); // They want to burn 100 of them @@ -215,7 +215,7 @@ fn burn_should_work() { #[test] fn basic_asset_trap_should_work() { // we'll let them have message execution for free. - AllowUnpaidFrom::set(vec![X1(Parachain(1)).into(), X1(Parachain(2)).into()]); + AllowUnpaidFrom::set(vec![[Parachain(1)].into(), [Parachain(2)].into()]); // Child parachain #1 owns 1000 tokens held by us in reserve. add_asset(Parachain(1), (Here, 1000)); @@ -343,7 +343,7 @@ fn basic_asset_trap_should_work() { #[test] fn max_assets_limit_should_work() { // we'll let them have message execution for free. - AllowUnpaidFrom::set(vec![X1(Parachain(1)).into()]); + AllowUnpaidFrom::set(vec![[Parachain(1)].into()]); // Child parachain #1 owns 1000 tokens held by us in reserve. add_asset(Parachain(1), ([1u8; 32], 1000u128)); add_asset(Parachain(1), ([2u8; 32], 1000u128)); diff --git a/xcm/xcm-builder/src/tests/basic.rs b/xcm/xcm-builder/src/tests/basic.rs index 02fcd8962dbf..63278337fec2 100644 --- a/xcm/xcm-builder/src/tests/basic.rs +++ b/xcm/xcm-builder/src/tests/basic.rs @@ -28,11 +28,11 @@ fn basic_setup_works() { assert_eq!(to_account((Parent, Parachain(1))), Ok(2001)); assert_eq!(to_account((Parent, Parachain(50))), Ok(2050)); assert_eq!( - to_account(MultiLocation::new(0, X1(AccountIndex64 { index: 1, network: None }))), + to_account(MultiLocation::new(0, [AccountIndex64 { index: 1, network: None }])), Ok(1), ); assert_eq!( - to_account(MultiLocation::new(0, X1(AccountIndex64 { index: 42, network: None }))), + to_account(MultiLocation::new(0, [AccountIndex64 { index: 42, network: None }])), Ok(42), ); assert_eq!(to_account(Here), Ok(3000)); @@ -65,7 +65,7 @@ fn code_registers_should_work() { SetErrorHandler(Xcm(vec![ TransferAsset { assets: (Here, 2u128).into(), - beneficiary: X1(AccountIndex64 { index: 3, network: None }).into(), + beneficiary: [(AccountIndex64 { index: 3, network: None })].into(), }, // It was handled fine. ClearError, @@ -73,17 +73,17 @@ fn code_registers_should_work() { // Set the appendix - this will always fire. SetAppendix(Xcm(vec![TransferAsset { assets: (Here, 4u128).into(), - beneficiary: X1(AccountIndex64 { index: 3, network: None }).into(), + beneficiary: [(AccountIndex64 { index: 3, network: None })].into(), }])), // First xfer always works ok TransferAsset { assets: (Here, 1u128).into(), - beneficiary: X1(AccountIndex64 { index: 3, network: None }).into(), + beneficiary: [(AccountIndex64 { index: 3, network: None })].into(), }, // Second xfer results in error on the second message - our error handler will fire. TransferAsset { assets: (Here, 8u128).into(), - beneficiary: X1(AccountIndex64 { index: 3, network: None }).into(), + beneficiary: [(AccountIndex64 { index: 3, network: None })].into(), }, ]); // Weight limit of 70 is needed. diff --git a/xcm/xcm-builder/src/tests/bridging/local_para_para.rs b/xcm/xcm-builder/src/tests/bridging/local_para_para.rs index 117909725b76..c5a3d5b1010f 100644 --- a/xcm/xcm-builder/src/tests/bridging/local_para_para.rs +++ b/xcm/xcm-builder/src/tests/bridging/local_para_para.rs @@ -21,8 +21,8 @@ use super::*; parameter_types! { - pub UniversalLocation: Junctions = X2(GlobalConsensus(Local::get()), Parachain(1)); - pub RemoteUniversalLocation: Junctions = X2(GlobalConsensus(Remote::get()), Parachain(1)); + pub UniversalLocation: Junctions = [GlobalConsensus(Local::get()), Parachain(1)].into(); + pub RemoteUniversalLocation: Junctions = [GlobalConsensus(Remote::get()), Parachain(1)].into(); } type TheBridge = TestBridge>; diff --git a/xcm/xcm-builder/src/tests/bridging/local_relay_relay.rs b/xcm/xcm-builder/src/tests/bridging/local_relay_relay.rs index 66099bb823d4..8621979c1167 100644 --- a/xcm/xcm-builder/src/tests/bridging/local_relay_relay.rs +++ b/xcm/xcm-builder/src/tests/bridging/local_relay_relay.rs @@ -21,8 +21,8 @@ use super::*; parameter_types! { - pub UniversalLocation: Junctions = X1(GlobalConsensus(Local::get())); - pub RemoteUniversalLocation: Junctions = X1(GlobalConsensus(Remote::get())); + pub UniversalLocation: Junctions = [GlobalConsensus(Local::get())].into(); + pub RemoteUniversalLocation: Junctions = [GlobalConsensus(Remote::get())].into(); } type TheBridge = TestBridge>; diff --git a/xcm/xcm-builder/src/tests/bridging/paid_remote_relay_relay.rs b/xcm/xcm-builder/src/tests/bridging/paid_remote_relay_relay.rs index a618193d6e30..afee28a411e1 100644 --- a/xcm/xcm-builder/src/tests/bridging/paid_remote_relay_relay.rs +++ b/xcm/xcm-builder/src/tests/bridging/paid_remote_relay_relay.rs @@ -24,9 +24,9 @@ use super::*; parameter_types! { - pub UniversalLocation: Junctions = X2(GlobalConsensus(Local::get()), Parachain(100)); - pub RelayUniversalLocation: Junctions = X1(GlobalConsensus(Local::get())); - pub RemoteUniversalLocation: Junctions = X1(GlobalConsensus(Remote::get())); + pub UniversalLocation: Junctions = [GlobalConsensus(Local::get()), Parachain(100)].into(); + pub RelayUniversalLocation: Junctions = [GlobalConsensus(Local::get())].into(); + pub RemoteUniversalLocation: Junctions = [GlobalConsensus(Remote::get())].into(); pub static BridgeTable: Vec<(NetworkId, MultiLocation, Option)> = vec![(Remote::get(), MultiLocation::parent(), Some((Parent, 200u128).into()))]; // ^^^ 100 to use the bridge (export) and 100 for the remote execution weight (5 instructions diff --git a/xcm/xcm-builder/src/tests/bridging/remote_para_para.rs b/xcm/xcm-builder/src/tests/bridging/remote_para_para.rs index 06df4cae2a79..37714cc3c928 100644 --- a/xcm/xcm-builder/src/tests/bridging/remote_para_para.rs +++ b/xcm/xcm-builder/src/tests/bridging/remote_para_para.rs @@ -21,9 +21,9 @@ use super::*; parameter_types! { - pub UniversalLocation: Junctions = X2(GlobalConsensus(Local::get()), Parachain(1000)); - pub ParaBridgeUniversalLocation: Junctions = X2(GlobalConsensus(Local::get()), Parachain(1)); - pub RemoteParaBridgeUniversalLocation: Junctions = X2(GlobalConsensus(Remote::get()), Parachain(1)); + pub UniversalLocation: Junctions = [GlobalConsensus(Local::get()), Parachain(1000)].into(); + pub ParaBridgeUniversalLocation: Junctions = [GlobalConsensus(Local::get()), Parachain(1)].into(); + pub RemoteParaBridgeUniversalLocation: Junctions = [GlobalConsensus(Remote::get()), Parachain(1)].into(); pub BridgeTable: Vec<(NetworkId, MultiLocation, Option)> = vec![(Remote::get(), (Parent, Parachain(1)).into(), None)]; } diff --git a/xcm/xcm-builder/src/tests/bridging/remote_para_para_via_relay.rs b/xcm/xcm-builder/src/tests/bridging/remote_para_para_via_relay.rs index 56579643861d..cadb39ce7e3d 100644 --- a/xcm/xcm-builder/src/tests/bridging/remote_para_para_via_relay.rs +++ b/xcm/xcm-builder/src/tests/bridging/remote_para_para_via_relay.rs @@ -21,9 +21,9 @@ use super::*; parameter_types! { - pub UniversalLocation: Junctions = X1(GlobalConsensus(Local::get())); - pub ParaBridgeUniversalLocation: Junctions = X2(GlobalConsensus(Local::get()), Parachain(1)); - pub RemoteParaBridgeUniversalLocation: Junctions = X2(GlobalConsensus(Remote::get()), Parachain(1)); + pub UniversalLocation: Junctions = [GlobalConsensus(Local::get())].into(); + pub ParaBridgeUniversalLocation: Junctions = [GlobalConsensus(Local::get()), Parachain(1)].into(); + pub RemoteParaBridgeUniversalLocation: Junctions = [GlobalConsensus(Remote::get()), Parachain(1)].into(); pub BridgeTable: Vec<(NetworkId, MultiLocation, Option)> = vec![(Remote::get(), Parachain(1).into(), None)]; } diff --git a/xcm/xcm-builder/src/tests/bridging/remote_relay_relay.rs b/xcm/xcm-builder/src/tests/bridging/remote_relay_relay.rs index 4230ea27b715..d2ef85fc5c37 100644 --- a/xcm/xcm-builder/src/tests/bridging/remote_relay_relay.rs +++ b/xcm/xcm-builder/src/tests/bridging/remote_relay_relay.rs @@ -21,9 +21,9 @@ use super::*; parameter_types! { - pub UniversalLocation: Junctions = X2(GlobalConsensus(Local::get()), Parachain(1000)); - pub RelayUniversalLocation: Junctions = X1(GlobalConsensus(Local::get())); - pub RemoteUniversalLocation: Junctions = X1(GlobalConsensus(Remote::get())); + pub UniversalLocation: Junctions = [GlobalConsensus(Local::get()), Parachain(1000)].into(); + pub RelayUniversalLocation: Junctions = [GlobalConsensus(Local::get())].into(); + pub RemoteUniversalLocation: Junctions = [GlobalConsensus(Remote::get())].into(); pub BridgeTable: Vec<(NetworkId, MultiLocation, Option)> = vec![(Remote::get(), MultiLocation::parent(), None)]; } diff --git a/xcm/xcm-builder/src/tests/expecting.rs b/xcm/xcm-builder/src/tests/expecting.rs index 6d5e0ff47b51..7fec4ae47ba6 100644 --- a/xcm/xcm-builder/src/tests/expecting.rs +++ b/xcm/xcm-builder/src/tests/expecting.rs @@ -18,7 +18,7 @@ use super::*; #[test] fn expect_pallet_should_work() { - AllowUnpaidFrom::set(vec![X1(Parachain(1)).into()]); + AllowUnpaidFrom::set(vec![[(Parachain(1))].into()]); // They want to transfer 100 of our native asset from sovereign account of parachain #1 into #2 // and let them know to hand it to account #3. let message = Xcm(vec![ExpectPallet { @@ -56,7 +56,7 @@ fn expect_pallet_should_work() { #[test] fn expect_pallet_should_fail_correctly() { - AllowUnpaidFrom::set(vec![X1(Parachain(1)).into()]); + AllowUnpaidFrom::set(vec![[(Parachain(1))].into()]); let message = Xcm(vec![ExpectPallet { index: 1, name: b"Balances".as_ref().into(), diff --git a/xcm/xcm-builder/src/tests/mock.rs b/xcm/xcm-builder/src/tests/mock.rs index dad4e8854448..eea0ad8eb9a0 100644 --- a/xcm/xcm-builder/src/tests/mock.rs +++ b/xcm/xcm-builder/src/tests/mock.rs @@ -269,18 +269,19 @@ impl TransactAsset for TestAssetTransactor { } pub fn to_account(l: impl Into) -> Result { - Ok(match l.into() { + let l = l.into(); + Ok(match l.unpack() { // Siblings at 2000+id - MultiLocation { parents: 1, interior: X1(Parachain(id)) } => 2000 + id as u64, + (1, [Parachain(id)]) => 2000 + *id as u64, // Accounts are their number - MultiLocation { parents: 0, interior: X1(AccountIndex64 { index, .. }) } => index, + (0, [AccountIndex64 { index, .. }]) => *index, // Children at 1000+id - MultiLocation { parents: 0, interior: X1(Parachain(id)) } => 1000 + id as u64, + (0, [Parachain(id)]) => 1000 + *id as u64, // Self at 3000 - MultiLocation { parents: 0, interior: Here } => 3000, + (0, []) => 3000, // Parent at 3001 - MultiLocation { parents: 1, interior: Here } => 3001, - l => { + (1, []) => 3001, + _ => { // Is it a foreign-consensus? let uni = ExecutorUniversalLocation::get(); if l.parents as usize != uni.len() { @@ -302,15 +303,14 @@ impl ConvertOrigin for TestOriginConverter { kind: OriginKind, ) -> Result { use OriginKind::*; - match (kind, origin.into()) { + let origin = origin.into(); + match (kind, origin.unpack()) { (Superuser, _) => Ok(TestOrigin::Root), - (SovereignAccount, l) => Ok(TestOrigin::Signed(to_account(l)?)), - (Native, MultiLocation { parents: 0, interior: X1(Parachain(id)) }) => - Ok(TestOrigin::Parachain(id)), - (Native, MultiLocation { parents: 1, interior: Here }) => Ok(TestOrigin::Relay), - (Native, MultiLocation { parents: 0, interior: X1(AccountIndex64 { index, .. }) }) => - Ok(TestOrigin::Signed(index)), - (_, origin) => Err(origin), + (SovereignAccount, _) => Ok(TestOrigin::Signed(to_account(origin)?)), + (Native, (0, [Parachain(id)])) => Ok(TestOrigin::Parachain(*id)), + (Native, (1, [])) => Ok(TestOrigin::Relay), + (Native, (0, [AccountIndex64 { index, .. }])) => Ok(TestOrigin::Signed(*index)), + _ => Err(origin), } } } diff --git a/xcm/xcm-builder/src/tests/origins.rs b/xcm/xcm-builder/src/tests/origins.rs index d3d6278eff8e..e6ef640bb93a 100644 --- a/xcm/xcm-builder/src/tests/origins.rs +++ b/xcm/xcm-builder/src/tests/origins.rs @@ -18,7 +18,7 @@ use super::*; #[test] fn universal_origin_should_work() { - AllowUnpaidFrom::set(vec![X1(Parachain(1)).into(), X1(Parachain(2)).into()]); + AllowUnpaidFrom::set(vec![[(Parachain(1))].into(), [(Parachain(2))].into()]); clear_universal_aliases(); // Parachain 1 may represent Kusama to us add_universal_alias(Parachain(1), Kusama); @@ -70,7 +70,7 @@ fn universal_origin_should_work() { #[test] fn export_message_should_work() { // Bridge chain (assumed to be Relay) lets Parachain #1 have message execution for free. - AllowUnpaidFrom::set(vec![X1(Parachain(1)).into()]); + AllowUnpaidFrom::set(vec![[(Parachain(1))].into()]); // Local parachain #1 issues a transfer asset on Polkadot Relay-chain, transfering 100 Planck to // Polkadot parachain #2. let expected_message = Xcm(vec![TransferAsset { @@ -101,10 +101,10 @@ fn export_message_should_work() { #[test] fn unpaid_execution_should_work() { // Bridge chain (assumed to be Relay) lets Parachain #1 have message execution for free. - AllowUnpaidFrom::set(vec![X1(Parachain(1)).into()]); + AllowUnpaidFrom::set(vec![[(Parachain(1))].into()]); // Bridge chain (assumed to be Relay) lets Parachain #2 have message execution for free if it // asks. - AllowExplicitUnpaidFrom::set(vec![X1(Parachain(2)).into()]); + AllowExplicitUnpaidFrom::set(vec![[(Parachain(2))].into()]); // Asking for unpaid execution of up to 9 weight on the assumption it is origin of #2. let message = Xcm(vec![UnpaidExecution { weight_limit: Limited(Weight::from_parts(9, 9)), diff --git a/xcm/xcm-builder/src/tests/querying.rs b/xcm/xcm-builder/src/tests/querying.rs index be8edfe87b8d..8505f91057c2 100644 --- a/xcm/xcm-builder/src/tests/querying.rs +++ b/xcm/xcm-builder/src/tests/querying.rs @@ -18,7 +18,7 @@ use super::*; #[test] fn pallet_query_should_work() { - AllowUnpaidFrom::set(vec![X1(Parachain(1)).into()]); + AllowUnpaidFrom::set(vec![[(Parachain(1))].into()]); // They want to transfer 100 of our native asset from sovereign account of parachain #1 into #2 // and let them know to hand it to account #3. let message = Xcm(vec![QueryPallet { @@ -50,7 +50,7 @@ fn pallet_query_should_work() { #[test] fn pallet_query_with_results_should_work() { - AllowUnpaidFrom::set(vec![X1(Parachain(1)).into()]); + AllowUnpaidFrom::set(vec![[(Parachain(1))].into()]); // They want to transfer 100 of our native asset from sovereign account of parachain #1 into #2 // and let them know to hand it to account #3. let message = Xcm(vec![QueryPallet { diff --git a/xcm/xcm-builder/src/tests/version_subscriptions.rs b/xcm/xcm-builder/src/tests/version_subscriptions.rs index 434c92202c83..c893c8b2587d 100644 --- a/xcm/xcm-builder/src/tests/version_subscriptions.rs +++ b/xcm/xcm-builder/src/tests/version_subscriptions.rs @@ -53,7 +53,7 @@ fn simple_version_subscriptions_should_work() { fn version_subscription_instruction_should_work() { let origin = Parachain(1000); let message = Xcm::(vec![ - DescendOrigin(X1(AccountIndex64 { index: 1, network: None })), + DescendOrigin([AccountIndex64 { index: 1, network: None }].into()), SubscribeVersion { query_id: 42, max_response_weight: Weight::from_parts(5000, 5000) }, ]); let hash = fake_message_hash(&message); @@ -118,7 +118,7 @@ fn version_unsubscription_instruction_should_work() { // Not allowed to do it when origin has been changed. let message = Xcm::(vec![ - DescendOrigin(X1(AccountIndex64 { index: 1, network: None })), + DescendOrigin([AccountIndex64 { index: 1, network: None }].into()), UnsubscribeVersion, ]); let hash = fake_message_hash(&message); diff --git a/xcm/xcm-builder/src/tests/weight.rs b/xcm/xcm-builder/src/tests/weight.rs index 99ef029196ff..ac37a227e3d3 100644 --- a/xcm/xcm-builder/src/tests/weight.rs +++ b/xcm/xcm-builder/src/tests/weight.rs @@ -57,17 +57,17 @@ fn errors_should_return_unused_weight() { // First xfer results in an error on the last message only TransferAsset { assets: (Here, 1u128).into(), - beneficiary: X1(AccountIndex64 { index: 3, network: None }).into(), + beneficiary: [AccountIndex64 { index: 3, network: None }].into(), }, // Second xfer results in error third message and after TransferAsset { assets: (Here, 2u128).into(), - beneficiary: X1(AccountIndex64 { index: 3, network: None }).into(), + beneficiary: [AccountIndex64 { index: 3, network: None }].into(), }, // Third xfer results in error second message and after TransferAsset { assets: (Here, 4u128).into(), - beneficiary: X1(AccountIndex64 { index: 3, network: None }).into(), + beneficiary: [(AccountIndex64 { index: 3, network: None })].into(), }, ]); // Weight limit of 70 is needed. @@ -163,7 +163,8 @@ fn weight_trader_tuple_should_work() { let mut traders = Traders::new(); // trader one failed; trader two buys weight assert_eq!( - traders.buy_weight(Weight::from_parts(5, 5), fungible_multi_asset(para_1, 10).into()), + traders + .buy_weight(Weight::from_parts(5, 5), fungible_multi_asset(para_1.clone(), 10).into()), Ok(vec![].into()), ); // trader two refunds diff --git a/xcm/xcm-builder/src/universal_exports.rs b/xcm/xcm-builder/src/universal_exports.rs index a9868021c011..25458c4e6654 100644 --- a/xcm/xcm-builder/src/universal_exports.rs +++ b/xcm/xcm-builder/src/universal_exports.rs @@ -35,7 +35,7 @@ fn ensure_is_remote( }; let universal_destination: InteriorMultiLocation = universal_local .into_location() - .appended_with(dest) + .appended_with(dest.clone()) .map_err(|x| x.1)? .try_into()?; let (remote_dest, remote_net) = match universal_destination.split_first() { @@ -66,7 +66,7 @@ impl> SendXcm ) -> SendResult { let d = dest.take().ok_or(MissingArgument)?; let universal_source = UniversalLocation::get(); - let devolved = match ensure_is_remote(universal_source, d) { + let devolved = match ensure_is_remote(universal_source.clone(), d) { Ok(x) => x, Err(d) => { *dest = Some(d); @@ -147,7 +147,7 @@ impl, xcm: &mut Option>, ) -> SendResult { - let d = dest.ok_or(MissingArgument)?; + let d = dest.clone().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)?; @@ -187,7 +187,7 @@ impl, xcm: &mut Option>, ) -> SendResult { - let d = *dest.as_ref().ok_or(MissingArgument)?; + let d = dest.as_ref().ok_or(MissingArgument)?.clone(); let devolved = ensure_is_remote(UniversalLocation::get(), d).map_err(|_| NotApplicable)?; let (remote_network, remote_location) = devolved; @@ -203,7 +203,7 @@ impl impl Iterator + '_ { self.fungible .iter() - .map(|(id, &amount)| MultiAsset { fun: Fungible(amount), id: *id }) + .map(|(id, &amount)| MultiAsset { fun: Fungible(amount), id: id.clone() }) } /// A borrowing iterator over the non-fungible assets. pub fn non_fungible_assets_iter(&self) -> impl Iterator + '_ { self.non_fungible .iter() - .map(|(id, instance)| MultiAsset { fun: NonFungible(*instance), id: *id }) + .map(|(id, instance)| MultiAsset { fun: NonFungible(*instance), id: id.clone() }) } /// A consuming iterator over all assets. @@ -216,7 +216,7 @@ impl Assets { pub fn reanchor( &mut self, target: &MultiLocation, - context: InteriorMultiLocation, + context: &InteriorMultiLocation, mut maybe_failed_bin: Option<&mut Self>, ) { let mut fungible = Default::default(); @@ -251,7 +251,7 @@ impl Assets { MultiAsset { fun: Fungible(amount), id } => self.fungible.get(id).map_or(false, |a| a >= amount), MultiAsset { fun: NonFungible(instance), id } => - self.non_fungible.contains(&(*id, *instance)), + self.non_fungible.contains(&(id.clone(), *instance)), } } @@ -276,11 +276,11 @@ impl Assets { match asset { MultiAsset { fun: Fungible(amount), id } => { if self.fungible.get(id).map_or(true, |a| a < amount) { - return Err(TakeError::AssetUnderflow((*id, *amount).into())) + return Err(TakeError::AssetUnderflow((id.clone(), *amount).into())) } }, MultiAsset { fun: NonFungible(instance), id } => { - let id_instance = (*id, *instance); + let id_instance = (id.clone(), *instance); if !self.non_fungible.contains(&id_instance) { return Err(TakeError::AssetUnderflow(id_instance.into())) } @@ -460,14 +460,14 @@ impl Assets { if maybe_limit.map_or(true, |l| self.len() <= l) { return self.clone() } else { - for (&c, &amount) in self.fungible.iter() { - masked.fungible.insert(c, amount); + for (c, &amount) in self.fungible.iter() { + masked.fungible.insert(c.clone(), amount); if maybe_limit.map_or(false, |l| masked.len() >= l) { return masked } } for (c, instance) in self.non_fungible.iter() { - masked.non_fungible.insert((*c, *instance)); + masked.non_fungible.insert((c.clone(), *instance)); if maybe_limit.map_or(false, |l| masked.len() >= l) { return masked } @@ -477,13 +477,13 @@ impl Assets { MultiAssetFilter::Wild(AllOfCounted { fun: WildFungible, id, .. }) | MultiAssetFilter::Wild(AllOf { fun: WildFungible, id }) => if let Some(&amount) = self.fungible.get(&id) { - masked.fungible.insert(*id, amount); + masked.fungible.insert(id.clone(), amount); }, MultiAssetFilter::Wild(AllOfCounted { fun: WildNonFungible, id, .. }) | MultiAssetFilter::Wild(AllOf { fun: WildNonFungible, id }) => for (c, instance) in self.non_fungible.iter() { if c == id { - masked.non_fungible.insert((*c, *instance)); + masked.non_fungible.insert((c.clone(), *instance)); if maybe_limit.map_or(false, |l| masked.len() >= l) { return masked } @@ -494,11 +494,11 @@ impl Assets { match asset { MultiAsset { fun: Fungible(amount), id } => { if let Some(m) = self.fungible.get(id) { - masked.subsume((*id, Fungible(*amount.min(m))).into()); + masked.subsume((id.clone(), Fungible(*amount.min(m))).into()); } }, MultiAsset { fun: NonFungible(instance), id } => { - let id_instance = (*id, *instance); + let id_instance = (id.clone(), *instance); if self.non_fungible.contains(&id_instance) { masked.subsume(id_instance.into()); } diff --git a/xcm/xcm-executor/src/lib.rs b/xcm/xcm-executor/src/lib.rs index 749a63114d95..774e0f17ebea 100644 --- a/xcm/xcm-executor/src/lib.rs +++ b/xcm/xcm-executor/src/lib.rs @@ -277,7 +277,7 @@ impl XcmExecutor { Self { holding: Assets::new(), holding_limit: Config::MaxAssetsIntoHolding::get() as usize, - context: XcmContext { origin: Some(origin), message_hash, topic: None }, + context: XcmContext { origin: Some(origin.clone()), message_hash, topic: None }, original_origin: origin, trader: Config::Trader::new(), error: None, @@ -390,7 +390,7 @@ impl XcmExecutor { } fn cloned_origin(&self) -> Option { - self.context.origin + self.context.origin.clone() } /// Send an XCM, charging fees from Holding as needed. @@ -474,17 +474,17 @@ impl XcmExecutor { match instr { WithdrawAsset(assets) => { // Take `assets` from the origin account (on-chain) and place in holding. - let origin = *self.origin_ref().ok_or(XcmError::BadOrigin)?; for asset in assets.into_inner().into_iter() { - Config::AssetTransactor::withdraw_asset(&asset, &origin, Some(&self.context))?; + let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?; + Config::AssetTransactor::withdraw_asset(&asset, origin, Some(&self.context))?; self.subsume_asset(asset)?; } Ok(()) }, ReserveAssetDeposited(assets) => { // check whether we trust origin to be our reserve location for this asset. - let origin = *self.origin_ref().ok_or(XcmError::BadOrigin)?; for asset in assets.into_inner().into_iter() { + let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?; // Must ensure that we recognise the asset as being managed by the origin. ensure!( Config::IsReserve::contains(&asset, &origin), @@ -514,20 +514,20 @@ impl XcmExecutor { Config::AssetTransactor::transfer_asset(asset, origin, &dest, &self.context)?; } let reanchor_context = Config::UniversalLocation::get(); - assets.reanchor(&dest, reanchor_context).map_err(|()| XcmError::LocationFull)?; + assets.reanchor(&dest, &reanchor_context).map_err(|()| XcmError::LocationFull)?; let mut message = vec![ReserveAssetDeposited(assets), ClearOrigin]; message.extend(xcm.0.into_iter()); self.send(dest, Xcm(message), FeeReason::TransferReserveAsset)?; Ok(()) }, ReceiveTeleportedAsset(assets) => { - let origin = *self.origin_ref().ok_or(XcmError::BadOrigin)?; // check whether we trust origin to teleport this asset to us via config trait. for asset in assets.inner() { + let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?; // We only trust the origin to send us assets that they identify as their // sovereign assets. ensure!( - Config::IsTeleporter::contains(asset, &origin), + Config::IsTeleporter::contains(asset, origin), XcmError::UntrustedTeleportLocation ); // We should check that the asset can actually be teleported in (for this to be in error, there @@ -536,6 +536,7 @@ impl XcmExecutor { Config::AssetTransactor::can_check_in(&origin, asset, &self.context)?; } for asset in assets.into_inner().into_iter() { + let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?; Config::AssetTransactor::check_in(&origin, &asset, &self.context); self.subsume_asset(asset)?; } @@ -543,7 +544,7 @@ impl XcmExecutor { }, Transact { origin_kind, require_weight_at_most, mut call } => { // We assume that the Relay-chain is allowed to use transact on this parachain. - let origin = *self.origin_ref().ok_or(XcmError::BadOrigin)?; + let origin = self.cloned_origin().ok_or(XcmError::BadOrigin)?; // TODO: #2841 #TRANSACTFILTER allow the trait to issue filters for the relay-chain let message_call = call.take_decoded().map_err(|_| XcmError::FailedToDecode)?; @@ -810,12 +811,12 @@ impl XcmExecutor { UniversalOrigin(new_global) => { let universal_location = Config::UniversalLocation::get(); ensure!(universal_location.first() != Some(&new_global), XcmError::InvalidLocation); - let origin = *self.origin_ref().ok_or(XcmError::BadOrigin)?; + let origin = self.cloned_origin().ok_or(XcmError::BadOrigin)?; let origin_xform = (origin, new_global); let ok = Config::UniversalAliases::contains(&origin_xform); ensure!(ok, XcmError::InvalidLocation); let (_, new_global) = origin_xform; - let new_origin = X1(new_global).relative_to(&universal_location); + let new_origin = Junctions::from([new_global]).relative_to(&universal_location); self.context.origin = Some(new_origin); Ok(()) }, @@ -827,7 +828,7 @@ impl XcmExecutor { // // This only works because the remote chain empowers the bridge // to speak for the local network. - let origin = self.context.origin.ok_or(XcmError::BadOrigin)?; + let origin = self.context.origin.as_ref().ok_or(XcmError::BadOrigin)?.clone(); let universal_source = Config::UniversalLocation::get() .within_global(origin) .map_err(|()| XcmError::Unanchored)?; @@ -848,11 +849,12 @@ impl XcmExecutor { Ok(()) }, LockAsset { asset, unlocker } => { - let origin = *self.origin_ref().ok_or(XcmError::BadOrigin)?; + let origin = self.cloned_origin().ok_or(XcmError::BadOrigin)?; let (remote_asset, context) = Self::try_reanchor(asset.clone(), &unlocker)?; - let lock_ticket = Config::AssetLocker::prepare_lock(unlocker, asset, origin)?; + let lock_ticket = + Config::AssetLocker::prepare_lock(unlocker.clone(), asset, origin.clone())?; let owner = - origin.reanchored(&unlocker, context).map_err(|_| XcmError::ReanchorFailed)?; + origin.reanchored(&unlocker, &context).map_err(|_| XcmError::ReanchorFailed)?; let msg = Xcm::<()>(vec![NoteUnlockable { asset: remote_asset, owner }]); let (ticket, price) = validate_send::(unlocker, msg)?; self.take_fee(price, FeeReason::LockAsset)?; @@ -861,20 +863,23 @@ impl XcmExecutor { Ok(()) }, UnlockAsset { asset, target } => { - let origin = *self.origin_ref().ok_or(XcmError::BadOrigin)?; + let origin = self.cloned_origin().ok_or(XcmError::BadOrigin)?; Config::AssetLocker::prepare_unlock(origin, asset, target)?.enact()?; Ok(()) }, NoteUnlockable { asset, owner } => { - let origin = *self.origin_ref().ok_or(XcmError::BadOrigin)?; + let origin = self.cloned_origin().ok_or(XcmError::BadOrigin)?; Config::AssetLocker::note_unlockable(origin, asset, owner)?; Ok(()) }, RequestUnlock { asset, locker } => { - let origin = *self.origin_ref().ok_or(XcmError::BadOrigin)?; + let origin = self.cloned_origin().ok_or(XcmError::BadOrigin)?; let remote_asset = Self::try_reanchor(asset.clone(), &locker)?.0; - let reduce_ticket = - Config::AssetLocker::prepare_reduce_unlockable(locker, asset, origin)?; + let reduce_ticket = Config::AssetLocker::prepare_reduce_unlockable( + locker.clone(), + asset, + origin.clone(), + )?; let msg = Xcm::<()>(vec![UnlockAsset { asset: remote_asset, target: origin }]); let (ticket, price) = validate_send::(locker, msg)?; self.take_fee(price, FeeReason::RequestUnlock)?; @@ -948,7 +953,7 @@ impl XcmExecutor { Ok(match local_querier { None => None, Some(q) => Some( - q.reanchored(&destination, Config::UniversalLocation::get()) + q.reanchored(&destination, &Config::UniversalLocation::get()) .map_err(|_| XcmError::ReanchorFailed)?, ), }) @@ -982,7 +987,7 @@ impl XcmExecutor { ) -> Result<(MultiAsset, InteriorMultiLocation), XcmError> { let reanchor_context = Config::UniversalLocation::get(); let asset = asset - .reanchored(&destination, reanchor_context) + .reanchored(&destination, &reanchor_context) .map_err(|()| XcmError::ReanchorFailed)?; Ok((asset, reanchor_context)) } @@ -994,7 +999,7 @@ impl XcmExecutor { maybe_failed_bin: Option<&mut Assets>, ) -> MultiAssets { let reanchor_context = Config::UniversalLocation::get(); - assets.reanchor(dest, reanchor_context, maybe_failed_bin); + assets.reanchor(dest, &reanchor_context, maybe_failed_bin); assets.into_assets_iter().collect::>().into() } } diff --git a/xcm/xcm-executor/src/traits/conversion.rs b/xcm/xcm-executor/src/traits/conversion.rs index c33269a6566f..537ecfd7d625 100644 --- a/xcm/xcm-executor/src/traits/conversion.rs +++ b/xcm/xcm-executor/src/traits/conversion.rs @@ -147,9 +147,9 @@ impl Convert, T> for Decoded { /// struct BumpParaId; /// impl ConvertOrigin for BumpParaId { /// fn convert_origin(origin: impl Into, _: OriginKind) -> Result { -/// match origin.into() { -/// MultiLocation { parents: 0, interior: Junctions::X1(Junction::Parachain(id)) } => { -/// Err(Junctions::X1(Junction::Parachain(id + 1)).into()) +/// match origin.into().unpack() { +/// (0, [Junction::Parachain(id)]) => { +/// Err([Junction::Parachain(id + 1)].into()) /// } /// _ => unreachable!() /// } @@ -159,16 +159,17 @@ impl Convert, T> for Decoded { /// struct AcceptPara7; /// impl ConvertOrigin for AcceptPara7 { /// fn convert_origin(origin: impl Into, _: OriginKind) -> Result { -/// match origin.into() { -/// MultiLocation { parents: 0, interior: Junctions::X1(Junction::Parachain(id)) } if id == 7 => { +/// let origin = origin.into(); +/// match origin.unpack() { +/// (0, [Junction::Parachain(id)]) if *id == 7 => { /// Ok(7) /// } -/// o => Err(o) +/// _ => Err(origin) /// } /// } /// } /// # fn main() { -/// let origin: MultiLocation = Junctions::X1(Junction::Parachain(6)).into(); +/// let origin: MultiLocation = [Junction::Parachain(6)].into(); /// assert!( /// <(BumpParaId, AcceptPara7) as ConvertOrigin>::convert_origin(origin, OriginKind::Native) /// .is_ok() diff --git a/xcm/xcm-executor/src/traits/transact_asset.rs b/xcm/xcm-executor/src/traits/transact_asset.rs index 0770228ed827..8ca8462bae97 100644 --- a/xcm/xcm-executor/src/traits/transact_asset.rs +++ b/xcm/xcm-executor/src/traits/transact_asset.rs @@ -21,7 +21,7 @@ use xcm::latest::{Error as XcmError, MultiAsset, MultiLocation, Result as XcmRes /// Facility for asset transacting. /// /// This should work with as many asset/location combinations as possible. Locations to support may include non-account -/// locations such as a `MultiLocation::X1(Junction::Parachain)`. Different chains may handle them in different ways. +/// locations such as a `[Junction::Parachain]`. Different chains may handle them in different ways. /// /// Can be amalgamated as a tuple of items that implement this trait. In such executions, if any of the transactors /// returns `Ok(())`, then it will short circuit. Else, execution is passed to the next transactor. diff --git a/xcm/xcm-simulator/fuzzer/src/parachain.rs b/xcm/xcm-simulator/fuzzer/src/parachain.rs index aace3b379c6a..3b3f51184c28 100644 --- a/xcm/xcm-simulator/fuzzer/src/parachain.rs +++ b/xcm/xcm-simulator/fuzzer/src/parachain.rs @@ -237,7 +237,7 @@ pub mod mock_msg_queue { let message_hash = xcm.using_encoded(sp_io::hashing::blake2_256); let (result, event) = match Xcm::::try_from(xcm) { Ok(xcm) => { - let location = MultiLocation::new(1, X1(Parachain(sender.into()))); + let location = MultiLocation::new(1, [Parachain(sender.into())]); match T::XcmExecutor::execute_xcm(location, xcm, message_hash, max_weight) { Outcome::Error(e) => (Err(e.clone()), Event::Fail(Some(hash), e)), Outcome::Complete(w) => (Ok(w), Event::Success(Some(hash))), diff --git a/xcm/xcm-simulator/src/lib.rs b/xcm/xcm-simulator/src/lib.rs index 6a5b1b49e0ca..f0f70246cb84 100644 --- a/xcm/xcm-simulator/src/lib.rs +++ b/xcm/xcm-simulator/src/lib.rs @@ -290,8 +290,8 @@ macro_rules! decl_test_network { while let Some((para_id, destination, message)) = $crate::PARA_MESSAGE_BUS.with( |b| b.borrow_mut().pop_front()) { - match destination.interior() { - $crate::Junctions::Here if destination.parent_count() == 1 => { + match destination.unpack() { + (1, []) => { let encoded = $crate::encode_xcm(message, $crate::MessageKind::Ump); let r = <$relay_chain>::process_upward_message( para_id, &encoded[..], @@ -302,7 +302,7 @@ macro_rules! decl_test_network { } }, $( - $crate::X1($crate::Parachain(id)) if *id == $para_id && destination.parent_count() == 1 => { + (1, [$crate::Parachain(id)]) if *id == $para_id => { let encoded = $crate::encode_xcm(message, $crate::MessageKind::Xcmp); let messages = vec![(para_id, 1, &encoded[..])]; let _weight = <$parachain>::handle_xcmp_messages( @@ -326,9 +326,9 @@ macro_rules! decl_test_network { while let Some((destination, message)) = $crate::RELAY_MESSAGE_BUS.with( |b| b.borrow_mut().pop_front()) { - match destination.interior() { + match destination.unpack() { $( - $crate::X1($crate::Parachain(id)) if *id == $para_id && destination.parent_count() == 0 => { + (0, [$crate::Parachain(id)]) if *id == $para_id => { let encoded = $crate::encode_xcm(message, $crate::MessageKind::Dmp); // NOTE: RelayChainBlockNumber is hard-coded to 1 let messages = vec![(1, encoded)]; @@ -356,10 +356,10 @@ macro_rules! decl_test_network { use $crate::{UmpSink, XcmpMessageHandlerT}; let d = destination.take().ok_or($crate::SendError::MissingArgument)?; - match (d.interior(), d.parent_count()) { - ($crate::Junctions::Here, 1) => {}, + match d.unpack() { + (1, []) => {}, $( - ($crate::X1($crate::Parachain(id)), 1) if id == &$para_id => {} + (1, [$crate::Parachain(id)]) if id == &$para_id => {} )* _ => { *destination = Some(d); @@ -389,9 +389,9 @@ macro_rules! decl_test_network { use $crate::DmpMessageHandlerT; let d = destination.take().ok_or($crate::SendError::MissingArgument)?; - match (d.interior(), d.parent_count()) { + match d.unpack() { $( - ($crate::X1($crate::Parachain(id)), 0) if id == &$para_id => {}, + (0, [$crate::Parachain(id)]) if id == &$para_id => {}, )* _ => { *destination = Some(d);