diff --git a/Cargo.lock b/Cargo.lock index fab596ab2dd9..ea7d46e1b8c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3233,6 +3233,7 @@ dependencies = [ "pallet-treasury", "pallet-utility", "pallet-vesting", + "pallet-xcm", "parity-scale-codec", "polkadot-primitives", "polkadot-runtime-common", @@ -11309,6 +11310,7 @@ dependencies = [ "pallet-treasury", "pallet-utility", "pallet-vesting", + "pallet-xcm", "parity-scale-codec", "polkadot-parachain", "polkadot-primitives", diff --git a/runtime/kusama/Cargo.toml b/runtime/kusama/Cargo.toml index 8166e998eada..0116a5d6a970 100644 --- a/runtime/kusama/Cargo.toml +++ b/runtime/kusama/Cargo.toml @@ -69,6 +69,7 @@ pallet-tips = { git = "https://github.com/paritytech/substrate", branch = "maste pallet-treasury = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-utility = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-vesting = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-xcm = { path = "../../xcm/pallet-xcm", default-features = false } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } frame-try-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } @@ -148,6 +149,7 @@ std = [ "pallet-vesting/std", "pallet-babe/std", "pallet-randomness-collective-flip/std", + "pallet-xcm/std", "sp-runtime/std", "sp-staking/std", "frame-system/std", @@ -198,6 +200,7 @@ runtime-benchmarks = [ "pallet-vesting/runtime-benchmarks", "pallet-offences-benchmarking", "pallet-session-benchmarking", + "pallet-xcm/runtime-benchmarks", "frame-system-benchmarking", "hex-literal", "xcm-builder/runtime-benchmarks", diff --git a/runtime/kusama/src/lib.rs b/runtime/kusama/src/lib.rs index 614a563aefe8..5d80bbd6bbbb 100644 --- a/runtime/kusama/src/lib.rs +++ b/runtime/kusama/src/lib.rs @@ -52,12 +52,12 @@ use runtime_parachains::scheduler as parachains_scheduler; use runtime_parachains::reward_points as parachains_reward_points; use runtime_parachains::runtime_api_impl::v1 as parachains_runtime_api_impl; -use xcm::v0::{MultiLocation, NetworkId}; +use xcm::v0::{MultiLocation, NetworkId, BodyId, Xcm}; use xcm_builder::{ AccountId32Aliases, ChildParachainConvertsVia, SovereignSignedViaLocation, CurrencyAdapter as XcmCurrencyAdapter, - ChildParachainAsNative, SignedAccountId32AsNative, ChildSystemParachainAsSuperuser, LocationInverter, IsConcrete, - FixedWeightBounds, TakeWeightCredit, AllowTopLevelPaidExecutionFrom, - AllowUnpaidExecutionFrom, IsChildSystemParachain, UsingComponents, + ChildParachainAsNative, SignedAccountId32AsNative, ChildSystemParachainAsSuperuser, LocationInverter, + IsConcrete, FixedWeightBounds, TakeWeightCredit, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, + IsChildSystemParachain, UsingComponents, BackingToPlurality, SignedToAccountId32 }; use xcm_executor::XcmExecutor; use sp_runtime::{ @@ -115,7 +115,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("kusama"), impl_name: create_runtime_str!("parity-kusama"), authoring_version: 2, - spec_version: 900, + spec_version: 9000, impl_version: 0, #[cfg(not(feature = "disable-runtime-api"))] apis: RUNTIME_API_VERSIONS, @@ -1146,6 +1146,79 @@ impl xcm_executor::Config for XcmConfig { type ResponseHandler = (); } +parameter_types! { + pub const CouncilBodyId: BodyId = BodyId::Executive; +} + +/// Type to convert an `Origin` type value into a `MultiLocation` value which represents an interior location +/// of this chain. +pub type LocalOriginToLocation = ( + // We allow an origin from the Collective pallet to be used in XCM as a corresponding Plurality of the + // `Unit` body. + BackingToPlurality, CouncilBodyId>, + // And a usual Signed origin to be used in XCM as a corresponding AccountId32 + SignedToAccountId32, +); + +pub struct OnlyWithdrawTeleportForAccounts; +impl frame_support::traits::Contains<(MultiLocation, Xcm)> for OnlyWithdrawTeleportForAccounts { + fn contains((ref origin, ref msg): &(MultiLocation, Xcm)) -> bool { + use xcm::v0::{ + Xcm::WithdrawAsset, Order::{BuyExecution, InitiateTeleport, DepositAsset}, + MultiAsset::{All, ConcreteFungible}, Junction::{AccountId32, Plurality, Parachain}, + MultiLocation::{Null, X1}, + }; + match origin { + // Root and council are are allowed to execute anything. + Null | X1(Plurality { .. }) => true, + X1(AccountId32 { .. }) => { + // An account ID trying to send a message. We ensure that it's sensible. + // This checks that it's of the form: + // WithdrawAsset { + // assets: [ ConcreteFungible { id: Null } ], + // effects: [ BuyExecution, InitiateTeleport { + // assets: All, + // dest: Parachain, + // effects: [ BuyExecution, DepositAssets { + // assets: All, + // dest: AccountId32, + // } ] + // } ] + // } + matches!(msg, WithdrawAsset { ref assets, ref effects } + if assets.len() == 1 + && matches!(assets[0], ConcreteFungible { id: Null, .. }) + && effects.len() == 2 + && matches!(effects[0], BuyExecution { .. }) + && matches!(effects[1], InitiateTeleport { ref assets, dest: X1(Parachain(..)), ref effects } + if assets.len() == 1 + && matches!(assets[0], All) + && effects.len() == 2 + && matches!(effects[0], BuyExecution { .. }) + && matches!(effects[1], DepositAsset { ref assets, dest: X1(AccountId32{..}) } + if assets.len() == 1 + && matches!(assets[0], All) + ) + ) + ) + } + // Nobody else is allowed to execute anything. + _ => false, + } + } +} + +impl pallet_xcm::Config for Runtime { + type Event = Event; + type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; + type XcmRouter = XcmRouter; + // Anyone can execute XCM messages locally... + type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; + // ...but they must match our filter, which requires them to be a simple withdraw + teleport. + type XcmExecuteFilter = OnlyWithdrawTeleportForAccounts; + type XcmExecutor = XcmExecutor; +} + construct_runtime! { pub enum Runtime where Block = Block, @@ -1235,6 +1308,9 @@ construct_runtime! { // Parachain Onboarding Pallets. Start indices at 70 to leave room. Registrar: paras_registrar::{Pallet, Call, Storage, Event} = 70, Slots: slots::{Pallet, Call, Storage, Event} = 71, + + // Pallet for sending XCM. + XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event} = 99, } } diff --git a/runtime/polkadot/src/lib.rs b/runtime/polkadot/src/lib.rs index a9ab23a43b27..af636a2def70 100644 --- a/runtime/polkadot/src/lib.rs +++ b/runtime/polkadot/src/lib.rs @@ -95,7 +95,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("polkadot"), impl_name: create_runtime_str!("parity-polkadot"), authoring_version: 0, - spec_version: 900, + spec_version: 9000, impl_version: 0, #[cfg(not(feature = "disable-runtime-api"))] apis: RUNTIME_API_VERSIONS, diff --git a/runtime/rococo/src/lib.rs b/runtime/rococo/src/lib.rs index bc8aefada2e5..ddcdc4bd198d 100644 --- a/runtime/rococo/src/lib.rs +++ b/runtime/rococo/src/lib.rs @@ -110,7 +110,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("rococo"), impl_name: create_runtime_str!("parity-rococo-v1.5"), authoring_version: 0, - spec_version: 232, + spec_version: 9000, impl_version: 0, #[cfg(not(feature = "disable-runtime-api"))] apis: RUNTIME_API_VERSIONS, @@ -664,11 +664,11 @@ impl frame_support::traits::Contains<(MultiLocation, Xcm)> for OnlyWithdra fn contains((ref origin, ref msg): &(MultiLocation, Xcm)) -> bool { use xcm::v0::{ Xcm::WithdrawAsset, Order::{BuyExecution, InitiateTeleport, DepositAsset}, - MultiAsset::{All, ConcreteFungible}, Junction::AccountId32, + MultiAsset::{All, ConcreteFungible}, Junction::{AccountId32, Plurality}, }; match origin { - // Root is allowed to execute anything. - Null => true, + // Root and collective are allowed to execute anything. + Null | X1(Plurality { .. }) => true, X1(AccountId32 { .. }) => { // An account ID trying to send a message. We ensure that it's sensible. // This checks that it's of the form: diff --git a/runtime/westend/Cargo.toml b/runtime/westend/Cargo.toml index 54c089977b0d..d2cd1576e0c0 100644 --- a/runtime/westend/Cargo.toml +++ b/runtime/westend/Cargo.toml @@ -68,6 +68,7 @@ pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/parityt pallet-treasury = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-utility = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-vesting = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-xcm = { path = "../../xcm/pallet-xcm", default-features = false } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } frame-try-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } @@ -146,6 +147,7 @@ std = [ "pallet-treasury/std", "pallet-utility/std", "pallet-vesting/std", + "pallet-xcm/std", "pallet-babe/std", "pallet-randomness-collective-flip/std", "frame-executive/std", @@ -194,6 +196,7 @@ runtime-benchmarks = [ "pallet-vesting/runtime-benchmarks", "pallet-offences-benchmarking", "pallet-session-benchmarking", + "pallet-xcm/runtime-benchmarks", "frame-system-benchmarking", "hex-literal", "xcm-builder/runtime-benchmarks", diff --git a/runtime/westend/src/lib.rs b/runtime/westend/src/lib.rs index 6c59a0d2ad28..390399832dca 100644 --- a/runtime/westend/src/lib.rs +++ b/runtime/westend/src/lib.rs @@ -54,13 +54,13 @@ use runtime_parachains::scheduler as parachains_scheduler; use runtime_parachains::reward_points as parachains_reward_points; use runtime_parachains::runtime_api_impl::v1 as parachains_runtime_api_impl; -use xcm::v0::{MultiLocation, NetworkId}; +use xcm::v0::{MultiLocation, NetworkId, Xcm}; use xcm_executor::XcmExecutor; use xcm_builder::{ AccountId32Aliases, ChildParachainConvertsVia, SovereignSignedViaLocation, CurrencyAdapter as XcmCurrencyAdapter, ChildParachainAsNative, SignedAccountId32AsNative, ChildSystemParachainAsSuperuser, LocationInverter, IsConcrete, - FixedWeightBounds, TakeWeightCredit, AllowTopLevelPaidExecutionFrom, - AllowUnpaidExecutionFrom, IsChildSystemParachain, UsingComponents, + FixedWeightBounds, TakeWeightCredit, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, + IsChildSystemParachain, UsingComponents, SignedToAccountId32, }; use sp_runtime::{ @@ -116,7 +116,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("westend"), impl_name: create_runtime_str!("parity-westend"), authoring_version: 2, - spec_version: 900, + spec_version: 9000, impl_version: 0, #[cfg(not(feature = "disable-runtime-api"))] apis: RUNTIME_API_VERSIONS, @@ -859,6 +859,72 @@ impl xcm_executor::Config for XcmConfig { type ResponseHandler = (); } +/// Type to convert an `Origin` type value into a `MultiLocation` value which represents an interior location +/// of this chain. +pub type LocalOriginToLocation = ( + // And a usual Signed origin to be used in XCM as a corresponding AccountId32 + SignedToAccountId32, +); + +pub struct OnlyWithdrawTeleportForAccounts; +impl frame_support::traits::Contains<(MultiLocation, Xcm)> for OnlyWithdrawTeleportForAccounts { + fn contains((ref origin, ref msg): &(MultiLocation, Xcm)) -> bool { + use xcm::v0::{ + Xcm::WithdrawAsset, Order::{BuyExecution, InitiateTeleport, DepositAsset}, + MultiAsset::{All, ConcreteFungible}, Junction::{AccountId32, Parachain}, + MultiLocation::{Null, X1}, + }; + match origin { + // Root is allowed to execute anything. + Null => true, + X1(AccountId32 { .. }) => { + // An account ID trying to send a message. We ensure that it's sensible. + // This checks that it's of the form: + // WithdrawAsset { + // assets: [ ConcreteFungible { id: Null } ], + // effects: [ BuyExecution, InitiateTeleport { + // assets: All, + // dest: Parachain, + // effects: [ BuyExecution, DepositAssets { + // assets: All, + // dest: AccountId32, + // } ] + // } ] + // } + matches!(msg, WithdrawAsset { ref assets, ref effects } + if assets.len() == 1 + && matches!(assets[0], ConcreteFungible { id: Null, .. }) + && effects.len() == 2 + && matches!(effects[0], BuyExecution { .. }) + && matches!(effects[1], InitiateTeleport { ref assets, dest: X1(Parachain(..)), ref effects } + if assets.len() == 1 + && matches!(assets[0], All) + && effects.len() == 2 + && matches!(effects[0], BuyExecution { .. }) + && matches!(effects[1], DepositAsset { ref assets, dest: X1(AccountId32{..}) } + if assets.len() == 1 + && matches!(assets[0], All) + ) + ) + ) + } + // Nobody else is allowed to execute anything. + _ => false, + } + } +} + +impl pallet_xcm::Config for Runtime { + type Event = Event; + type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; + type XcmRouter = XcmRouter; + // Anyone can execute XCM messages locally... + type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; + // ...but they must match our filter, which requires them to be a simple withdraw + teleport. + type XcmExecuteFilter = OnlyWithdrawTeleportForAccounts; + type XcmExecutor = XcmExecutor; +} + construct_runtime! { pub enum Runtime where Block = Block, @@ -932,6 +998,9 @@ construct_runtime! { Registrar: paras_registrar::{Pallet, Call, Storage, Event} = 60, Slots: slots::{Pallet, Call, Storage, Event} = 61, ParasSudoWrapper: paras_sudo_wrapper::{Pallet, Call} = 62, + + // Pallet for sending XCM. + XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event} = 99, } }