diff --git a/Cargo.lock b/Cargo.lock index 32d80f6403..91859f4f7e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1982,6 +1982,7 @@ dependencies = [ "pallet-xcm", "pallet-xcm-benchmarks", "pallet-xcm-bridge-hub", + "pallets-common", "parachains-common", "parachains-runtimes-test-utils", "parity-scale-codec", @@ -2502,6 +2503,7 @@ dependencies = [ "pallet-utility", "pallet-xcm", "pallet-xcm-benchmarks", + "pallets-common", "parachains-common", "parachains-runtimes-test-utils", "parity-scale-codec", @@ -2856,6 +2858,7 @@ dependencies = [ "pallet-utility", "pallet-xcm", "pallet-xcm-benchmarks", + "pallets-common", "parachains-common", "parachains-runtimes-test-utils", "parity-scale-codec", @@ -9346,6 +9349,19 @@ dependencies = [ "staging-xcm-builder", ] +[[package]] +name = "pallets-common" +version = "1.0.0" +dependencies = [ + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "staging-xcm", + "staging-xcm-executor", +] + [[package]] name = "parachains-common" version = "18.0.0" @@ -9863,6 +9879,7 @@ dependencies = [ "pallet-utility", "pallet-xcm", "pallet-xcm-benchmarks", + "pallets-common", "parachains-common", "parachains-runtimes-test-utils", "parity-scale-codec", @@ -10215,6 +10232,7 @@ dependencies = [ "pallet-whitelist", "pallet-xcm", "pallet-xcm-benchmarks", + "pallets-common", "parity-scale-codec", "polkadot-parachain-primitives", "polkadot-primitives", diff --git a/Cargo.toml b/Cargo.toml index 68143b7b64..bb7f6a62c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -261,6 +261,7 @@ zombienet-sdk = { version = "0.2.4" } tuplex = { version = "0.1.0", default-features = false } relay-common = { path = "relay/common", default-features = false } ss58-registry = { version = "1.47.0" } +pallets-common = { path = "pallets/common", default-features = false } [workspace] resolver = "2" @@ -297,6 +298,7 @@ members = [ "integration-tests/zombienet", "pallets/ah-migrator", "pallets/ah-ops", + "pallets/common", "pallets/rc-migrator", "pallets/remote-proxy", "relay/common", diff --git a/pallets/common/Cargo.toml b/pallets/common/Cargo.toml new file mode 100644 index 0000000000..37879280b4 --- /dev/null +++ b/pallets/common/Cargo.toml @@ -0,0 +1,29 @@ +[package] +authors.workspace = true +description = "Shared utilities" +edition.workspace = true +license.workspace = true +name = "pallets-common" +repository.workspace = true +version.workspace = true + +[dependencies] +codec = { features = ["derive", "max-encoded-len"], workspace = true } +scale-info = { features = ["derive"], workspace = true } +xcm = { workspace = true } +xcm-executor = { workspace = true } +frame-support = { workspace = true } +frame-system = { workspace = true } +log = { workspace = true } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-support/std", + "frame-system/std", + "log/std", + "scale-info/std", + "xcm-executor/std", + "xcm/std", +] diff --git a/pallets/common/src/lib.rs b/pallets/common/src/lib.rs new file mode 100644 index 0000000000..8f1757c8c2 --- /dev/null +++ b/pallets/common/src/lib.rs @@ -0,0 +1,140 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Code shared between all runtimes +#![cfg_attr(not(feature = "std"), no_std)] + +use core::marker::PhantomData; +use frame_support::traits::{Contains, OriginTrait}; +use xcm::latest::{Location, OriginKind}; +use xcm_executor::traits::ConvertOrigin; + +/// TODO: `LocationAsSuperuser` is temporary placed here, the final solution will be imported from +/// `xcm_builder` (depends on backports) instead. +/// +/// A converter that allows a specific `Location` to act as a superuser (`RuntimeOrigin::root()`) +/// if it matches the predefined `SuperuserLocation` filter and `OriginKind::Superuser`. +pub struct LocationAsSuperuser( + PhantomData<(SuperuserLocation, RuntimeOrigin)>, +); +impl, RuntimeOrigin: OriginTrait> ConvertOrigin + for LocationAsSuperuser +{ + fn convert_origin( + origin: impl Into, + kind: OriginKind, + ) -> Result { + let origin = origin.into(); + log::trace!(target: "xcm::origin_conversion", "LocationAsSuperuser origin: {:?}, kind: {:?}", origin, kind); + match (kind, &origin) { + (OriginKind::Superuser, loc) if SuperuserLocation::contains(loc) => + Ok(RuntimeOrigin::root()), + _ => Err(origin), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use frame_support::{construct_runtime, derive_impl, parameter_types, traits::Equals}; + use xcm::latest::{Junction::*, Junctions::*, OriginKind}; + + type Block = frame_system::mocking::MockBlock; + + construct_runtime!( + pub enum Test + { + System: frame_system, + } + ); + + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] + impl frame_system::Config for Test { + type Block = Block; + } + + parameter_types! { + pub SuperuserLocation: Location = Location::new(0, Parachain(1)); + } + + #[test] + fn superuser_location_works() { + let test_conversion = |loc, kind| { + LocationAsSuperuser::, RuntimeOrigin>::convert_origin( + loc, kind, + ) + }; + + // Location that was set as SuperUserLocation should result in success conversion to Root + assert!(matches!(test_conversion(SuperuserLocation::get(), OriginKind::Superuser), Ok(..))); + // Same Location as SuperUserLocation::get() + assert!(matches!( + test_conversion(Location::new(0, Parachain(1)), OriginKind::Superuser), + Ok(..) + )); + + // Same Location but different origin kind + assert!(matches!(test_conversion(SuperuserLocation::get(), OriginKind::Native), Err(..))); + assert!(matches!( + test_conversion(SuperuserLocation::get(), OriginKind::SovereignAccount), + Err(..) + )); + assert!(matches!(test_conversion(SuperuserLocation::get(), OriginKind::Xcm), Err(..))); + + // No other location should result in successful conversion to Root + // thus expecting Err in all cases below + // + // Non-matching parachain number + assert!(matches!( + test_conversion(Location::new(0, Parachain(2)), OriginKind::Superuser), + Err(..) + )); + // Non-matching parents count + assert!(matches!( + test_conversion(Location::new(1, Parachain(1)), OriginKind::Superuser), + Err(..) + )); + // Child location of SuperUserLocation + assert!(matches!( + test_conversion( + Location::new(1, [Parachain(1), GeneralIndex(0)]), + OriginKind::Superuser + ), + Err(..) + )); + // Here + assert!(matches!(test_conversion(Location::new(0, Here), OriginKind::Superuser), Err(..))); + // Parent + assert!(matches!(test_conversion(Location::new(1, Here), OriginKind::Superuser), Err(..))); + // Some random account + assert!(matches!( + test_conversion( + Location::new(0, AccountId32 { network: None, id: [0u8; 32] }), + OriginKind::Superuser + ), + Err(..) + )); + // Child location of SuperUserLocation + assert!(matches!( + test_conversion( + Location::new(0, [Parachain(1), AccountId32 { network: None, id: [1u8; 32] }]), + OriginKind::Superuser + ), + Err(..) + )); + } +} diff --git a/relay/common/Cargo.toml b/relay/common/Cargo.toml index 0b735c6645..038757b28c 100644 --- a/relay/common/Cargo.toml +++ b/relay/common/Cargo.toml @@ -16,7 +16,6 @@ sp-runtime = { workspace = true } polkadot-primitives = { workspace = true } pallet-staking-reward-fn = { workspace = true } - [features] default = ["std"] std = [ diff --git a/relay/kusama/src/lib.rs b/relay/kusama/src/lib.rs index 4e570938dd..1f4c26de48 100644 --- a/relay/kusama/src/lib.rs +++ b/relay/kusama/src/lib.rs @@ -726,7 +726,7 @@ impl EnsureOriginWithArg for DynamicParamet match key { Inflation(_) => frame_system::ensure_root(origin.clone()), Treasury(_) => - // TODO: review - GeneralAdmin propagation from AssetHub? + // TODO: review - GeneralAdmin propagation from AssetHub? EitherOf::, GeneralAdmin>::ensure_origin(origin.clone()), } .map_err(|_| origin) diff --git a/relay/polkadot/Cargo.toml b/relay/polkadot/Cargo.toml index c3cf82fee2..1f316d9bf5 100644 --- a/relay/polkadot/Cargo.toml +++ b/relay/polkadot/Cargo.toml @@ -104,6 +104,7 @@ polkadot-runtime-common = { workspace = true } runtime-parachains = { workspace = true } polkadot-primitives = { workspace = true } relay-common = { workspace = true } +pallets-common = { workspace = true } xcm = { workspace = true } xcm-executor = { workspace = true } @@ -197,6 +198,7 @@ std = [ "pallet-whitelist/std", "pallet-xcm-benchmarks?/std", "pallet-xcm/std", + "pallets-common/std", "polkadot-parachain-primitives/std", "polkadot-primitives/std", "polkadot-runtime-common/std", diff --git a/relay/polkadot/src/lib.rs b/relay/polkadot/src/lib.rs index 489db03fee..cc2ff192e4 100644 --- a/relay/polkadot/src/lib.rs +++ b/relay/polkadot/src/lib.rs @@ -68,9 +68,9 @@ use frame_support::{ traits::{ fungible::HoldConsideration, tokens::{imbalance::ResolveTo, UnityOrOuterConversion}, - ConstU32, ConstU8, Contains, EitherOf, EitherOfDiverse, FromContains, Get, InstanceFilter, - KeyOwnerProofSystem, LinearStoragePrice, OnRuntimeUpgrade, PrivilegeCmp, ProcessMessage, - ProcessMessageError, WithdrawReasons, + ConstU32, ConstU8, Contains, EitherOf, EitherOfDiverse, Equals, FromContains, Get, + InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, OnRuntimeUpgrade, PrivilegeCmp, + ProcessMessage, ProcessMessageError, WithdrawReasons, }, weights::{ constants::{WEIGHT_PROOF_SIZE_PER_KB, WEIGHT_REF_TIME_PER_MICROS}, @@ -1524,20 +1524,13 @@ parameter_types! { pub AhExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT / 100; } -pub struct ContainsAssetHub; -impl Contains for ContainsAssetHub { - fn contains(loc: &Location) -> bool { - *loc == AssetHubLocation::get() - } -} - impl pallet_rc_migrator::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ManagerOrigin = EitherOfDiverse< EnsureRoot, EitherOfDiverse< EnsureXcm>, - EnsureXcm, + EnsureXcm, Location>, >, >; type Currency = Balances; diff --git a/relay/polkadot/src/xcm_config.rs b/relay/polkadot/src/xcm_config.rs index 53719e3a34..149e58ea89 100644 --- a/relay/polkadot/src/xcm_config.rs +++ b/relay/polkadot/src/xcm_config.rs @@ -46,6 +46,8 @@ use xcm_builder::{ WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents, }; +use pallets_common::LocationAsSuperuser; + pub use pallet_rc_migrator::xcm_config::*; parameter_types! { @@ -113,6 +115,8 @@ type LocalOriginConverter = ( SignedAccountId32AsNative, // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. XcmPassthrough, + // AssetHub can execute as root + LocationAsSuperuser, RuntimeOrigin>, ); parameter_types! { diff --git a/system-parachains/asset-hubs/asset-hub-polkadot/src/governance/mod.rs b/system-parachains/asset-hubs/asset-hub-polkadot/src/governance/mod.rs index 316e9fd938..25bb07f4d2 100644 --- a/system-parachains/asset-hubs/asset-hub-polkadot/src/governance/mod.rs +++ b/system-parachains/asset-hubs/asset-hub-polkadot/src/governance/mod.rs @@ -40,7 +40,7 @@ impl pallet_conviction_voting::Config for Runtime { type Currency = Balances; type VoteLockingPeriod = VoteLockingPeriod; type MaxVotes = ConstU32<512>; // TODO check with weight - // TODO: review - after/before migration check? + // TODO: review - after/before migration check? type MaxTurnout = frame_support::traits::tokens::currency::ActiveIssuanceOf; type Polls = Referenda; diff --git a/system-parachains/bridge-hubs/bridge-hub-polkadot/Cargo.toml b/system-parachains/bridge-hubs/bridge-hub-polkadot/Cargo.toml index babee6733f..773582d276 100644 --- a/system-parachains/bridge-hubs/bridge-hub-polkadot/Cargo.toml +++ b/system-parachains/bridge-hubs/bridge-hub-polkadot/Cargo.toml @@ -85,6 +85,7 @@ cumulus-primitives-utility = { workspace = true } pallet-collator-selection = { workspace = true } parachain-info = { workspace = true } parachains-common = { workspace = true } +pallets-common = { workspace = true } system-parachains-constants = { workspace = true } # Bridges @@ -186,6 +187,7 @@ std = [ "pallet-xcm-benchmarks?/std", "pallet-xcm-bridge-hub/std", "pallet-xcm/std", + "pallets-common/std", "parachain-info/std", "parachains-common/std", "polkadot-core-primitives/std", diff --git a/system-parachains/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs b/system-parachains/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs index 5aba9d14d5..a1d62b4e20 100644 --- a/system-parachains/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs +++ b/system-parachains/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs @@ -28,6 +28,7 @@ use frame_support::{ use frame_system::EnsureRoot; use pallet_collator_selection::StakingPotAccountId; use pallet_xcm::XcmPassthrough; +use pallets_common::LocationAsSuperuser; use parachains_common::xcm_config::{ AllSiblingSystemParachains, ConcreteAssetFromSystem, ParentRelayOrSiblingParachains, RelayOrOtherSystemParachains, @@ -73,6 +74,7 @@ parameter_types! { LocationToAccountId::convert_location(&RelayTreasuryLocation::get()) .unwrap_or(TreasuryAccount::get()); pub StakingPot: AccountId = CollatorSelection::account_id(); + pub AssetHubLocation: Location = (Parent, Parachain(system_parachain::ASSET_HUB_ID)).into(); } /// Type for specifying how a `Location` can be converted into an `AccountId`. @@ -127,6 +129,8 @@ pub type XcmOriginToTransactDispatchOrigin = ( SignedAccountId32AsNative, // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. XcmPassthrough, + // AssetHub can execute as root + LocationAsSuperuser, RuntimeOrigin>, ); pub struct ParentOrParentsPlurality; @@ -171,6 +175,7 @@ pub type Barrier = TrailingSetTopicAsId< ParentOrParentsPlurality, FellowsPlurality, Equals, + Equals, )>, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, diff --git a/system-parachains/collectives/collectives-polkadot/Cargo.toml b/system-parachains/collectives/collectives-polkadot/Cargo.toml index 9ecc69471e..70529c5d9c 100644 --- a/system-parachains/collectives/collectives-polkadot/Cargo.toml +++ b/system-parachains/collectives/collectives-polkadot/Cargo.toml @@ -84,6 +84,7 @@ cumulus-primitives-utility = { workspace = true } pallet-collator-selection = { workspace = true } parachain-info = { workspace = true } parachains-common = { workspace = true } +pallets-common = { workspace = true } system-parachains-constants = { workspace = true } [dev-dependencies] @@ -213,6 +214,7 @@ std = [ "pallet-utility/std", "pallet-xcm-benchmarks?/std", "pallet-xcm/std", + "pallets-common/std", "parachain-info/std", "parachains-common/std", "polkadot-core-primitives/std", diff --git a/system-parachains/collectives/collectives-polkadot/src/xcm_config.rs b/system-parachains/collectives/collectives-polkadot/src/xcm_config.rs index 8a8d67f29f..5dcfc76ce4 100644 --- a/system-parachains/collectives/collectives-polkadot/src/xcm_config.rs +++ b/system-parachains/collectives/collectives-polkadot/src/xcm_config.rs @@ -25,6 +25,7 @@ use frame_support::{ }; use frame_system::EnsureRoot; use pallet_xcm::XcmPassthrough; +use pallets_common::LocationAsSuperuser; use parachains_common::xcm_config::{ AllSiblingSystemParachains, ConcreteAssetFromSystem, ParentRelayOrSiblingParachains, RelayOrOtherSystemParachains, @@ -68,9 +69,9 @@ parameter_types! { LocationToAccountId::convert_location(&RelayTreasuryLocation::get()) .unwrap_or(TreasuryAccount::get()); pub const FellowshipAdminBodyId: BodyId = BodyId::Index(FELLOWSHIP_ADMIN_INDEX); - pub AssetHub: Location = (Parent, Parachain(ASSET_HUB_ID)).into(); + pub AssetHubLocation: Location = (Parent, Parachain(ASSET_HUB_ID)).into(); pub AssetHubUsdt: LocatableAssetId = LocatableAssetId { - location: AssetHub::get(), + location: AssetHubLocation::get(), asset_id: (PalletInstance(50), GeneralIndex(1984)).into(), }; pub StakingPot: AccountId = CollatorSelection::account_id(); @@ -131,6 +132,8 @@ pub type XcmOriginToTransactDispatchOrigin = ( SignedAccountId32AsNative, // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. XcmPassthrough, + // AssetHub can execute as root + LocationAsSuperuser, RuntimeOrigin>, ); parameter_types! { @@ -173,6 +176,7 @@ pub type Barrier = TrailingSetTopicAsId< AllowExplicitUnpaidExecutionFrom<( ParentOrParentsPlurality, Equals, + Equals, )>, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, diff --git a/system-parachains/coretime/coretime-polkadot/Cargo.toml b/system-parachains/coretime/coretime-polkadot/Cargo.toml index ed605b911e..4b40a9eb15 100644 --- a/system-parachains/coretime/coretime-polkadot/Cargo.toml +++ b/system-parachains/coretime/coretime-polkadot/Cargo.toml @@ -79,6 +79,7 @@ cumulus-primitives-utility = { workspace = true } pallet-collator-selection = { workspace = true } parachain-info = { workspace = true } parachains-common = { workspace = true } +pallets-common = { workspace = true } [dev-dependencies] parachains-runtimes-test-utils = { workspace = true } @@ -122,6 +123,7 @@ std = [ "pallet-utility/std", "pallet-xcm-benchmarks?/std", "pallet-xcm/std", + "pallets-common/std", "parachain-info/std", "parachains-common/std", "polkadot-core-primitives/std", diff --git a/system-parachains/coretime/coretime-polkadot/src/xcm_config.rs b/system-parachains/coretime/coretime-polkadot/src/xcm_config.rs index 5d4fe22f6d..34a613f2f2 100644 --- a/system-parachains/coretime/coretime-polkadot/src/xcm_config.rs +++ b/system-parachains/coretime/coretime-polkadot/src/xcm_config.rs @@ -26,6 +26,7 @@ use frame_support::{ }; use frame_system::EnsureRoot; use pallet_xcm::XcmPassthrough; +use pallets_common::LocationAsSuperuser; use parachains_common::xcm_config::{ AllSiblingSystemParachains, ConcreteAssetFromSystem, ParentRelayOrSiblingParachains, RelayOrOtherSystemParachains, @@ -62,6 +63,7 @@ parameter_types! { pub const GovernanceLocation: Location = Location::parent(); pub FellowshipLocation: Location = Location::new(1, Parachain(system_parachain::COLLECTIVES_ID)); pub StakingPot: AccountId = CollatorSelection::account_id(); + pub AssetHubLocation: Location = (Parent, Parachain(system_parachain::ASSET_HUB_ID)).into(); } /// Type for specifying how a `Location` can be converted into an `AccountId`. @@ -136,6 +138,8 @@ pub type XcmOriginToTransactDispatchOrigin = ( SignedAccountId32AsNative, // XCM origins can be represented natively under the XCM pallet's `Xcm` origin. XcmPassthrough, + // AssetHub can execute as root + LocationAsSuperuser, RuntimeOrigin>, ); pub struct ParentOrParentsPlurality; @@ -180,6 +184,7 @@ pub type Barrier = TrailingSetTopicAsId< ParentOrParentsPlurality, FellowsPlurality, Equals, + Equals, )>, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, diff --git a/system-parachains/people/people-polkadot/Cargo.toml b/system-parachains/people/people-polkadot/Cargo.toml index 362ce2a1e1..7c9112b4d9 100644 --- a/system-parachains/people/people-polkadot/Cargo.toml +++ b/system-parachains/people/people-polkadot/Cargo.toml @@ -75,6 +75,7 @@ cumulus-primitives-utility = { workspace = true } pallet-collator-selection = { workspace = true } parachain-info = { workspace = true } parachains-common = { workspace = true } +pallets-common = { workspace = true } system-parachains-constants = { workspace = true } [dev-dependencies] @@ -120,6 +121,7 @@ std = [ "pallet-utility/std", "pallet-xcm-benchmarks?/std", "pallet-xcm/std", + "pallets-common/std", "parachain-info/std", "parachains-common/std", "polkadot-parachain-primitives/std", diff --git a/system-parachains/people/people-polkadot/src/xcm_config.rs b/system-parachains/people/people-polkadot/src/xcm_config.rs index 28163ab207..f58faadd33 100644 --- a/system-parachains/people/people-polkadot/src/xcm_config.rs +++ b/system-parachains/people/people-polkadot/src/xcm_config.rs @@ -24,6 +24,7 @@ use frame_support::{ }; use frame_system::EnsureRoot; use pallet_xcm::XcmPassthrough; +use pallets_common::LocationAsSuperuser; use parachains_common::{ xcm_config::{ AllSiblingSystemParachains, ConcreteAssetFromSystem, ParentRelayOrSiblingParachains, @@ -70,6 +71,7 @@ parameter_types! { LocationToAccountId::convert_location(&RelayTreasuryLocation::get()) .unwrap_or(TreasuryAccount::get()); pub StakingPot: AccountId = CollatorSelection::account_id(); + pub AssetHubLocation: Location = (Parent, Parachain(system_parachain::ASSET_HUB_ID)).into(); } pub type PriceForParentDelivery = polkadot_runtime_common::xcm_sender::ExponentialPrice< @@ -140,6 +142,8 @@ pub type XcmOriginToTransactDispatchOrigin = ( SignedAccountId32AsNative, // XCM origins can be represented natively under the XCM pallet's `Xcm` origin. XcmPassthrough, + // AssetHub can execute as root + LocationAsSuperuser, RuntimeOrigin>, ); pub struct LocalPlurality; @@ -191,6 +195,7 @@ pub type Barrier = TrailingSetTopicAsId< ParentOrParentsPlurality, FellowsPlurality, Equals, + Equals, )>, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom,