diff --git a/polkadot/runtime/kusama/src/lib.rs b/polkadot/runtime/kusama/src/lib.rs index a67e2d4673511bb7537094bb2804c9258c62b51d..125ce049b1955c7f243544560828ad465e7e1910 100644 --- a/polkadot/runtime/kusama/src/lib.rs +++ b/polkadot/runtime/kusama/src/lib.rs @@ -106,7 +106,7 @@ pub mod xcm_config; // Governance configurations. pub mod governance; use governance::{ - old::CouncilCollective, pallet_custom_origins, AuctionAdmin, GeneralAdmin, LeaseAdmin, + old::CouncilCollective, pallet_custom_origins, AuctionAdmin, Fellows, GeneralAdmin, LeaseAdmin, StakingAdmin, Treasurer, TreasurySpender, }; use xcm_config::CheckAccount; diff --git a/polkadot/runtime/kusama/src/xcm_config.rs b/polkadot/runtime/kusama/src/xcm_config.rs index 17310dd5ead194e663e565128728ea9afed69d4c..55a474e239f6fcdfb2e10bdf2aa2d49b94a7f1fe 100644 --- a/polkadot/runtime/kusama/src/xcm_config.rs +++ b/polkadot/runtime/kusama/src/xcm_config.rs @@ -17,8 +17,8 @@ //! XCM configurations for the Kusama runtime. use super::{ - parachains_origin, AccountId, Balances, CouncilCollective, ParaId, Runtime, RuntimeCall, - RuntimeEvent, RuntimeOrigin, WeightToFee, XcmPallet, + parachains_origin, AccountId, Balances, CouncilCollective, Fellows, ParaId, Runtime, + RuntimeCall, RuntimeEvent, RuntimeOrigin, StakingAdmin, WeightToFee, XcmPallet, }; use frame_support::{match_types, parameter_types, traits::Everything}; use runtime_common::{xcm_sender, ToAuthor}; @@ -28,8 +28,8 @@ use xcm_builder::{ AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, BackingToPlurality, ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser, CurrencyAdapter as XcmCurrencyAdapter, FixedWeightBounds, IsChildSystemParachain, IsConcrete, - LocationInverter, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, - TakeWeightCredit, UsingComponents, WeightInfoBounds, + LocationInverter, OriginToPluralityVoice, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, WeightInfoBounds, }; parameter_types! { @@ -154,6 +154,10 @@ impl xcm_executor::Config for XcmConfig { parameter_types! { pub const CouncilBodyId: BodyId = BodyId::Executive; + // StakingAdmin pluralistic body. + pub const StakingAdminBodyId: BodyId = BodyId::Defense; + // Fellows pluralistic body. + pub const FellowsBodyId: BodyId = BodyId::Technical; } /// Type to convert the council origin to a Plurality `MultiLocation` value. @@ -172,13 +176,33 @@ pub type LocalOriginToLocation = ( // And a usual Signed origin to be used in XCM as a corresponding AccountId32 SignedToAccountId32<RuntimeOrigin, AccountId, KusamaNetwork>, ); + +/// Type to convert the `StakingAdmin` origin to a Plurality `MultiLocation` value. +pub type StakingAdminToPlurality = + OriginToPluralityVoice<RuntimeOrigin, StakingAdmin, StakingAdminBodyId>; + +/// Type to convert the Fellows origin to a Plurality `MultiLocation` value. +pub type FellowsToPlurality = OriginToPluralityVoice<RuntimeOrigin, Fellows, FellowsBodyId>; + +/// Type to convert a pallet `Origin` type value into a `MultiLocation` value which represents an interior location +/// of this chain for a destination chain. +pub type LocalPalletOriginToLocation = ( + // We allow an origin from the Collective pallet to be used in XCM as a corresponding Plurality of the + // `Unit` body. + CouncilToPlurality, + // StakingAdmin origin to be used in XCM as a corresponding Plurality `MultiLocation` value. + StakingAdminToPlurality, + // Fellows origin to be used in XCM as a corresponding Plurality `MultiLocation` value. + FellowsToPlurality, +); + impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; - // We only allow the council to send messages. This is basically safe to enable for everyone - // (safe the possibility of someone spamming the parachain if they're willing to pay the KSM to - // send from the Relay-chain), but it's useless until we bring in XCM v3 which will make - // `DescendOrigin` a bit more useful. - type SendXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, CouncilToPlurality>; + // We only allow the root, the council, fellows and the staking admin to send messages. + // This is basically safe to enable for everyone (safe the possibility of someone spamming the parachain + // if they're willing to pay the KSM to send from the Relay-chain), but it's useless until we bring in XCM v3 + // which will make `DescendOrigin` a bit more useful. + type SendXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalPalletOriginToLocation>; type XcmRouter = XcmRouter; // Anyone can execute XCM messages locally. type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>; diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index f645e3cfc86f5f57c61c341ecab902e87b1a30e3..3502c79b5d253531a53259398218f6d872b331d0 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -1527,6 +1527,19 @@ impl<Prefix: Get<MultiLocation>, Body: Get<BodyId>> Contains<MultiLocation> } } +/// Filter for `MultiLocation` to find those which represent a voice of an identified plurality. +/// +/// May reasonably be used with `EnsureXcm`. +pub struct IsVoiceOfBody<Prefix, Body>(PhantomData<(Prefix, Body)>); +impl<Prefix: Get<MultiLocation>, Body: Get<BodyId>> Contains<MultiLocation> + for IsVoiceOfBody<Prefix, Body> +{ + fn contains(l: &MultiLocation) -> bool { + let maybe_suffix = l.match_and_split(&Prefix::get()); + matches!(maybe_suffix, Some(Plurality { id, part }) if id == &Body::get() && part == &BodyPart::Voice) + } +} + /// `EnsureOrigin` implementation succeeding with a `MultiLocation` value to recognize and filter the /// `Origin::Xcm` item. pub struct EnsureXcm<F>(PhantomData<F>); diff --git a/polkadot/xcm/src/v0/junction.rs b/polkadot/xcm/src/v0/junction.rs index 67f17f464a37a811493ffefc6bf8d05e1b7e3b2b..450e882ac3e86b3990c419170270d61bf6398f0c 100644 --- a/polkadot/xcm/src/v0/junction.rs +++ b/polkadot/xcm/src/v0/junction.rs @@ -52,6 +52,15 @@ pub enum BodyId { /// The unambiguous judicial body (this doesn't exist on Polkadot, but if it were to get a "grand oracle", it /// may be considered as that). Judicial, + /// The unambiguous defense body (for Polkadot, an opinion on the topic given via a public referendum + /// on the `staking_admin` track). + Defense, + /// The unambiguous administration body (for Polkadot, an opinion on the topic given via a public referendum + /// on the `general_admin` track). + Administration, + /// The unambiguous treasury body (for Polkadot, an opinion on the topic given via a public referendum + /// on the `treasurer` track). + Treasury, } /// A part of a pluralistic body. diff --git a/polkadot/xcm/xcm-builder/src/lib.rs b/polkadot/xcm/xcm-builder/src/lib.rs index e3473d55d5ebe346162d887db5a4284935001afc..aa55c56d2cd76f6170f21722fcfabb96e73e2cdb 100644 --- a/polkadot/xcm/xcm-builder/src/lib.rs +++ b/polkadot/xcm/xcm-builder/src/lib.rs @@ -37,7 +37,7 @@ pub use location_conversion::{ mod origin_conversion; pub use origin_conversion::{ BackingToPlurality, ChildParachainAsNative, ChildSystemParachainAsSuperuser, EnsureXcmOrigin, - ParentAsSuperuser, RelayChainAsNative, SiblingParachainAsNative, + OriginToPluralityVoice, ParentAsSuperuser, RelayChainAsNative, SiblingParachainAsNative, SiblingSystemParachainAsSuperuser, SignedAccountId32AsNative, SignedAccountKey20AsNative, SignedToAccountId32, SovereignSignedViaLocation, }; diff --git a/polkadot/xcm/xcm-builder/src/origin_conversion.rs b/polkadot/xcm/xcm-builder/src/origin_conversion.rs index 9fe50eaf9c3f40a9e0cee1c62b601f2b37ec8c2e..4d024a9d12c293c52dfa90089e5861c473e6ef45 100644 --- a/polkadot/xcm/xcm-builder/src/origin_conversion.rs +++ b/polkadot/xcm/xcm-builder/src/origin_conversion.rs @@ -321,3 +321,20 @@ where }) } } + +/// `Convert` implementation to convert from an origin which passes the check of an `EnsureOrigin` +/// into a voice of a given pluralistic `Body`. +pub struct OriginToPluralityVoice<RuntimeOrigin, EnsureBodyOrigin, Body>( + PhantomData<(RuntimeOrigin, EnsureBodyOrigin, Body)>, +); +impl<RuntimeOrigin: Clone, EnsureBodyOrigin: EnsureOrigin<RuntimeOrigin>, Body: Get<BodyId>> + Convert<RuntimeOrigin, MultiLocation> + for OriginToPluralityVoice<RuntimeOrigin, EnsureBodyOrigin, Body> +{ + fn convert(o: RuntimeOrigin) -> Result<MultiLocation, RuntimeOrigin> { + match EnsureBodyOrigin::try_origin(o) { + Ok(_) => Ok(Junction::Plurality { id: Body::get(), part: BodyPart::Voice }.into()), + Err(o) => Err(o), + } + } +}