diff --git a/CHANGELOG.md b/CHANGELOG.md index 7910e3a829..8bf3a95a96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - PAH: filter `staking.reap_stash` from both `BaseCallFilter` and the XCM `SafeCallFilter` while the validator self-stake transition to higher bond. See Ref: [#1890](https://polkadot.subsquare.io/referenda/1890) ([#1159](https://github.com/polkadot-fellows/runtimes/pull/1159)) - Collectives Polkadot: Increase the Secretary Collective salary budget ([#1172](https://github.com/polkadot-fellows/runtimes/pull/1172)) - Align all runtimes to use the same values for e.g. `TransactionByteFee` and some other clean ups. ([#1175](https://github.com/polkadot-fellows/runtimes/pull/1175)) +- Flexible minimum validator set size on rc ([#PR1193](https://github.com/polkadot-fellows/runtimes/pull/1193)) + ## [2.2.2] 23.04.2026 diff --git a/Cargo.lock b/Cargo.lock index 94a1a03864..15cbaaf382 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12446,6 +12446,7 @@ dependencies = [ "pallet-nomination-pools-runtime-api", "pallet-offences", "pallet-offences-benchmarking", + "pallet-parameters", "pallet-preimage", "pallet-proxy", "pallet-rc-migrator", diff --git a/relay/kusama/src/lib.rs b/relay/kusama/src/lib.rs index 12f97f473d..dcf5f884b1 100644 --- a/relay/kusama/src/lib.rs +++ b/relay/kusama/src/lib.rs @@ -795,6 +795,15 @@ pub mod dynamic_params { #[codec(index = 1)] pub static BurnDestination: BurnDestinationAccount = Default::default(); } + + /// Parameters used by `pallet-staking-async-ah-client`. + #[dynamic_pallet_params] + #[codec(index = 2)] + pub mod ah_client { + /// Minimum size of the validator set that the relay chain will accept from Asset Hub. + #[codec(index = 0)] + pub static MinimumValidatorSetSize: u32 = 100; + } } #[cfg(feature = "runtime-benchmarks")] @@ -822,6 +831,12 @@ impl EnsureOriginWithArg for DynamicParamet Inflation(_) => frame_system::ensure_root(origin.clone()), Treasury(_) => EitherOf::, GeneralAdmin>::ensure_origin(origin.clone()), + AhClient(_) => EitherOfDiverse::< + // either local root or StakingAdmin, or same from OpenGov on AH + EitherOf, StakingAdmin>, + EnsureXcm>, + >::ensure_origin(origin.clone()) + .map(|_success| ()), } .map_err(|_| origin) } @@ -1760,8 +1775,6 @@ impl pallet_nomination_pools::Config for Runtime { parameter_types! { pub const DelegatedStakingPalletId: PalletId = PalletId(*b"py/dlstk"); pub const SlashRewardFraction: Perbill = Perbill::from_percent(1); - // Kusama always wants 1000 validators, we reject anything smaller than that. - pub storage MinimumValidatorSetSize: u32 = 1000; } impl pallet_delegated_staking::Config for Runtime { @@ -1782,7 +1795,7 @@ impl pallet_staking_async_ah_client::Config for Runtime { type AdminOrigin = EnsureRoot; type SessionInterface = Session; type SendToAssetHub = StakingXcmToAssetHub; - type MinimumValidatorSetSize = MinimumValidatorSetSize; + type MinimumValidatorSetSize = dynamic_params::ah_client::MinimumValidatorSetSize; type UnixTime = Timestamp; type PointsPerBlock = ConstU32<20>; type MaxOffenceBatchSize = ConstU32<32>; diff --git a/relay/polkadot/Cargo.toml b/relay/polkadot/Cargo.toml index 6b9ad60d81..4a9738aaa2 100644 --- a/relay/polkadot/Cargo.toml +++ b/relay/polkadot/Cargo.toml @@ -68,6 +68,7 @@ pallet-multisig = { workspace = true } pallet-nomination-pools = { workspace = true } pallet-nomination-pools-runtime-api = { workspace = true } pallet-offences = { workspace = true } +pallet-parameters = { workspace = true } pallet-preimage = { workspace = true } pallet-proxy = { workspace = true } pallet-referenda = { workspace = true } @@ -180,6 +181,7 @@ std = [ "pallet-nomination-pools/std", "pallet-offences-benchmarking?/std", "pallet-offences/std", + "pallet-parameters/std", "pallet-preimage/std", "pallet-proxy/std", "pallet-referenda/std", @@ -264,6 +266,7 @@ runtime-benchmarks = [ "pallet-nomination-pools/runtime-benchmarks", "pallet-offences-benchmarking/runtime-benchmarks", "pallet-offences/runtime-benchmarks", + "pallet-parameters/runtime-benchmarks", "pallet-preimage/runtime-benchmarks", "pallet-proxy/runtime-benchmarks", "pallet-referenda/runtime-benchmarks", @@ -326,6 +329,7 @@ try-runtime = [ "pallet-multisig/try-runtime", "pallet-nomination-pools/try-runtime", "pallet-offences/try-runtime", + "pallet-parameters/try-runtime", "pallet-preimage/try-runtime", "pallet-proxy/try-runtime", "pallet-referenda/try-runtime", diff --git a/relay/polkadot/src/lib.rs b/relay/polkadot/src/lib.rs index d72db9ceb7..4f96235bd3 100644 --- a/relay/polkadot/src/lib.rs +++ b/relay/polkadot/src/lib.rs @@ -40,14 +40,15 @@ use frame_election_provider_support::{ }; use frame_support::{ construct_runtime, + dynamic_params::{dynamic_pallet_params, dynamic_params}, genesis_builder_helper::{build_state, get_preset}, parameter_types, traits::{ fungible::HoldConsideration, tokens::{imbalance::ResolveTo, UnityOrOuterConversion}, - ConstU32, ConstU8, ConstUint, Contains, EitherOf, EitherOfDiverse, FromContains, Get, - InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, PrivilegeCmp, ProcessMessage, - ProcessMessageError, WithdrawReasons, + ConstU32, ConstU8, ConstUint, Contains, EitherOf, EitherOfDiverse, EnsureOrigin, + EnsureOriginWithArg, FromContains, Get, InstanceFilter, KeyOwnerProofSystem, + LinearStoragePrice, PrivilegeCmp, ProcessMessage, ProcessMessageError, WithdrawReasons, }, weights::{ constants::{WEIGHT_PROOF_SIZE_PER_KB, WEIGHT_REF_TIME_PER_MICROS}, @@ -1601,6 +1602,67 @@ impl pallet_delegated_staking::Config for Runtime { type CoreStaking = Staking; } +/// Dynamic params that can be adjusted at runtime. +#[dynamic_params(RuntimeParameters, pallet_parameters::Parameters::)] +pub mod dynamic_params { + use super::*; + + /// Parameters used by `pallet-staking-async-ah-client`. + #[dynamic_pallet_params] + #[codec(index = 0)] + pub mod ah_client { + /// Minimum size of the validator set that the relay chain will accept from Asset Hub. + #[codec(index = 0)] + pub static MinimumValidatorSetSize: u32 = 250; + } +} + +#[cfg(feature = "runtime-benchmarks")] +impl Default for RuntimeParameters { + fn default() -> Self { + RuntimeParameters::AhClient(dynamic_params::ah_client::Parameters::MinimumValidatorSetSize( + dynamic_params::ah_client::MinimumValidatorSetSize, + Some(250), + )) + } +} + +/// Defines what origin can modify which dynamic parameters. +pub struct DynamicParameterOrigin; +impl EnsureOriginWithArg for DynamicParameterOrigin { + type Success = (); + + fn try_origin( + origin: RuntimeOrigin, + key: &RuntimeParametersKey, + ) -> Result { + use crate::RuntimeParametersKey::*; + + match key { + AhClient(_) => EitherOfDiverse::< + // either local root or StakingAdmin, or same from OpenGov on AH + EitherOf, StakingAdmin>, + EnsureXcm>, + >::ensure_origin(origin.clone()) + .map(|_success| ()), + } + .map_err(|_| origin) + } + + #[cfg(feature = "runtime-benchmarks")] + fn try_successful_origin(_key: &RuntimeParametersKey) -> Result { + // Provide the origin for the parameter returned by `Default`: + Ok(RuntimeOrigin::root()) + } +} + +impl pallet_parameters::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeParameters = RuntimeParameters; + type AdminOrigin = DynamicParameterOrigin; + type WeightInfo = weights::pallet_parameters::WeightInfo; +} + impl ah_client::Config for Runtime { type CurrencyBalance = Balance; type AssetHubOrigin = @@ -1608,9 +1670,7 @@ impl ah_client::Config for Runtime { type AdminOrigin = EnsureRoot; type SessionInterface = Session; type SendToAssetHub = StakingXcmToAssetHub; - // Polkadot RC currently has 600 validators. Note: this has to be updated with AH validator - // count increasing. - type MinimumValidatorSetSize = ConstU32<600>; + type MinimumValidatorSetSize = dynamic_params::ah_client::MinimumValidatorSetSize; type UnixTime = Timestamp; type PointsPerBlock = ConstU32<20>; type MaxOffenceBatchSize = ConstU32<32>; @@ -1844,6 +1904,9 @@ construct_runtime! { DelegatedStaking: pallet_delegated_staking = 41, StakingAhClient: pallet_staking_async_ah_client = 42, + // Dynamic, configurable parameters. + Parameters: pallet_parameters = 46, + // Parachains pallets. Start indices at 50 to leave room. ParachainsOrigin: parachains_origin = 50, Configuration: parachains_configuration = 51, @@ -1999,6 +2062,7 @@ mod benches { [pallet_multisig, Multisig] [pallet_nomination_pools, NominationPoolsBench::] [pallet_offences, OffencesBench::] + [pallet_parameters, Parameters] [pallet_preimage, Preimage] [pallet_proxy, Proxy] [pallet_scheduler, Scheduler] diff --git a/relay/polkadot/src/weights/mod.rs b/relay/polkadot/src/weights/mod.rs index f9b9c932bb..ed01de078b 100644 --- a/relay/polkadot/src/weights/mod.rs +++ b/relay/polkadot/src/weights/mod.rs @@ -31,6 +31,7 @@ pub mod pallet_indices; pub mod pallet_message_queue; pub mod pallet_multisig; pub mod pallet_nomination_pools; +pub mod pallet_parameters; pub mod pallet_preimage; pub mod pallet_proxy; pub mod pallet_referenda; diff --git a/relay/polkadot/src/weights/pallet_parameters.rs b/relay/polkadot/src/weights/pallet_parameters.rs new file mode 100644 index 0000000000..156b32a7c2 --- /dev/null +++ b/relay/polkadot/src/weights/pallet_parameters.rs @@ -0,0 +1,66 @@ +// Copyright (C) Parity Technologies and the various Polkadot contributors, see Contributions.md +// for a list of specific contributors. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Autogenerated weights for `pallet_parameters` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 54.0.0 +//! DATE: 2026-04-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `bm1-3`, CPU: `Intel(R) Xeon(R) E-2388G CPU @ 3.20GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --extrinsic=* +// --runtime=target/production/wbuild/polkadot-runtime/polkadot_runtime.wasm +// --pallet=pallet_parameters +// --header=/opt/actions-runner/_work/runtimes/runtimes/.github/scripts/cmd/file_header.txt +// --output=./relay/polkadot/src/weights +// --wasm-execution=compiled +// --steps=50 +// --repeat=20 +// --heap-pages=4096 +// --min-duration +// 1 +// --quiet + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_parameters`. +pub struct WeightInfo(PhantomData); +impl pallet_parameters::WeightInfo for WeightInfo { + /// Storage: `Parameters::Parameters` (r:1 w:1) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(53), added: 2528, mode: `MaxEncodedLen`) + fn set_parameter() -> Weight { + // Proof Size summary in bytes: + // Measured: `4` + // Estimated: `3518` + // Minimum execution time: 6_496_000 picoseconds. + Weight::from_parts(7_005_000, 0) + .saturating_add(Weight::from_parts(0, 3518)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +}