Skip to content

Commit d5fe478

Browse files
jessechejiehdoordashconbkchr
authored
Adds MaxRank Config in pallet-core-fellowship (#3393)
resolves #3315 --------- Co-authored-by: doordashcon <jessechejieh@doordashcon.local> Co-authored-by: command-bot <> Co-authored-by: Bastian Köcher <git@kchr.de>
1 parent 943eb46 commit d5fe478

11 files changed

Lines changed: 280 additions & 111 deletions

File tree

cumulus/parachains/runtimes/collectives/collectives-westend/src/ambassador/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ impl pallet_core_fellowship::Config<AmbassadorCoreInstance> for Runtime {
220220
type ApproveOrigin = PromoteOrigin;
221221
type PromoteOrigin = PromoteOrigin;
222222
type EvidenceSize = ConstU32<65536>;
223+
type MaxRank = ConstU32<9>;
223224
}
224225

225226
pub type AmbassadorSalaryInstance = pallet_salary::Instance2;

cumulus/parachains/runtimes/collectives/collectives-westend/src/fellowship/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ impl pallet_core_fellowship::Config<FellowshipCoreInstance> for Runtime {
210210
EnsureCanPromoteTo,
211211
>;
212212
type EvidenceSize = ConstU32<65536>;
213+
type MaxRank = ConstU32<9>;
213214
}
214215

215216
pub type FellowshipSalaryInstance = pallet_salary::Instance1;

cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ pub mod xcm_config;
4444
pub mod fellowship;
4545
pub use ambassador::pallet_ambassador_origins;
4646

47+
use ambassador::AmbassadorCoreInstance;
4748
use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases;
48-
use fellowship::{pallet_fellowship_origins, Fellows};
49+
use fellowship::{pallet_fellowship_origins, Fellows, FellowshipCoreInstance};
4950
use impls::{AllianceProposalProvider, EqualOrGreatestRootCmp};
5051
use sp_api::impl_runtime_apis;
5152
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
@@ -739,6 +740,10 @@ type Migrations = (
739740
cumulus_pallet_xcmp_queue::migration::v5::MigrateV4ToV5<Runtime>,
740741
// permanent
741742
pallet_xcm::migration::MigrateToLatestXcmVersion<Runtime>,
743+
// unreleased
744+
pallet_core_fellowship::migration::MigrateV0ToV1<Runtime, FellowshipCoreInstance>,
745+
// unreleased
746+
pallet_core_fellowship::migration::MigrateV0ToV1<Runtime, AmbassadorCoreInstance>,
742747
);
743748

744749
/// Executive: handles dispatch to the various modules.

prdoc/pr_3393.prdoc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
2+
# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json
3+
4+
title: Add `MaxRank` Config to `pallet-core-fellowship`
5+
6+
doc:
7+
- audience: Runtime User
8+
description: |
9+
This PR adds a new Config `MaxRank` to the core fellowship pallet. Initially, the maximum rank was set to IX (Grand Master) on the core-fellowship pallet, corresponding to the establishment of the Technical Fellowship and setting the default member count to nine. However, with the introduction of new collectives, this maximum rank is expected to evolve.
10+
11+
crates:
12+
- name: pallet-core-fellowship

substrate/bin/node/runtime/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1869,6 +1869,7 @@ impl pallet_core_fellowship::Config for Runtime {
18691869
type ApproveOrigin = EnsureRootWithSuccess<AccountId, ConstU16<9>>;
18701870
type PromoteOrigin = EnsureRootWithSuccess<AccountId, ConstU16<9>>;
18711871
type EvidenceSize = ConstU32<16_384>;
1872+
type MaxRank = ConstU32<9>;
18721873
}
18731874

18741875
parameter_types! {

substrate/frame/core-fellowship/src/benchmarking.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,12 @@ mod benchmarks {
5454
}
5555

5656
fn set_benchmark_params<T: Config<I>, I: 'static>() -> Result<(), BenchmarkError> {
57+
let max_rank = T::MaxRank::get().try_into().unwrap();
5758
let params = ParamsType {
58-
active_salary: [100u32.into(); 9],
59-
passive_salary: [10u32.into(); 9],
60-
demotion_period: [100u32.into(); 9],
61-
min_promotion_period: [100u32.into(); 9],
59+
active_salary: BoundedVec::try_from(vec![100u32.into(); max_rank]).unwrap(),
60+
passive_salary: BoundedVec::try_from(vec![10u32.into(); max_rank]).unwrap(),
61+
demotion_period: BoundedVec::try_from(vec![100u32.into(); max_rank]).unwrap(),
62+
min_promotion_period: BoundedVec::try_from(vec![100u32.into(); max_rank]).unwrap(),
6263
offboard_timeout: 1u32.into(),
6364
};
6465

@@ -68,11 +69,12 @@ mod benchmarks {
6869

6970
#[benchmark]
7071
fn set_params() -> Result<(), BenchmarkError> {
72+
let max_rank = T::MaxRank::get().try_into().unwrap();
7173
let params = ParamsType {
72-
active_salary: [100u32.into(); 9],
73-
passive_salary: [10u32.into(); 9],
74-
demotion_period: [100u32.into(); 9],
75-
min_promotion_period: [100u32.into(); 9],
74+
active_salary: BoundedVec::try_from(vec![100u32.into(); max_rank]).unwrap(),
75+
passive_salary: BoundedVec::try_from(vec![10u32.into(); max_rank]).unwrap(),
76+
demotion_period: BoundedVec::try_from(vec![100u32.into(); max_rank]).unwrap(),
77+
min_promotion_period: BoundedVec::try_from(vec![100u32.into(); max_rank]).unwrap(),
7678
offboard_timeout: 1u32.into(),
7779
};
7880

@@ -151,10 +153,14 @@ mod benchmarks {
151153
fn promote() -> Result<(), BenchmarkError> {
152154
// Ensure that the `min_promotion_period` wont get in our way.
153155
let mut params = Params::<T, I>::get();
154-
params.min_promotion_period = [Zero::zero(); RANK_COUNT];
156+
let max_rank = T::MaxRank::get().try_into().unwrap();
157+
params.min_promotion_period = BoundedVec::try_from(vec![Zero::zero(); max_rank]).unwrap();
155158
Params::<T, I>::put(&params);
156159

157160
let member = make_member::<T, I>(1)?;
161+
162+
// Set it to the max value to ensure that any possible auto-demotion period has passed.
163+
frame_system::Pallet::<T>::set_block_number(BlockNumberFor::<T>::max_value());
158164
ensure_evidence::<T, I>(&member)?;
159165

160166
#[extrinsic_call]

substrate/frame/core-fellowship/src/lib.rs

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ use codec::{Decode, Encode, MaxEncodedLen};
6161
use scale_info::TypeInfo;
6262
use sp_arithmetic::traits::{Saturating, Zero};
6363
use sp_runtime::RuntimeDebug;
64-
use sp_std::{marker::PhantomData, prelude::*};
64+
use sp_std::{fmt::Debug, marker::PhantomData, prelude::*};
6565

6666
use frame_support::{
6767
defensive,
@@ -71,18 +71,19 @@ use frame_support::{
7171
tokens::Balance as BalanceTrait, EnsureOrigin, EnsureOriginWithArg, Get, RankedMembers,
7272
RankedMembersSwapHandler,
7373
},
74-
BoundedVec,
74+
BoundedVec, CloneNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound,
7575
};
7676

7777
#[cfg(test)]
7878
mod tests;
7979

8080
#[cfg(feature = "runtime-benchmarks")]
8181
mod benchmarking;
82+
pub mod migration;
8283
pub mod weights;
8384

8485
pub use pallet::*;
85-
pub use weights::WeightInfo;
86+
pub use weights::*;
8687

8788
/// The desired outcome for which evidence is presented.
8889
#[derive(Encode, Decode, Eq, PartialEq, Copy, Clone, TypeInfo, MaxEncodedLen, RuntimeDebug)]
@@ -100,29 +101,46 @@ pub enum Wish {
100101
pub type Evidence<T, I> = BoundedVec<u8, <T as Config<I>>::EvidenceSize>;
101102

102103
/// The status of the pallet instance.
103-
#[derive(Encode, Decode, Eq, PartialEq, Clone, TypeInfo, MaxEncodedLen, RuntimeDebug)]
104-
pub struct ParamsType<Balance, BlockNumber, const RANKS: usize> {
104+
#[derive(
105+
Encode,
106+
Decode,
107+
CloneNoBound,
108+
EqNoBound,
109+
PartialEqNoBound,
110+
RuntimeDebugNoBound,
111+
TypeInfo,
112+
MaxEncodedLen,
113+
)]
114+
#[scale_info(skip_type_params(Ranks))]
115+
pub struct ParamsType<
116+
Balance: Clone + Eq + PartialEq + Debug,
117+
BlockNumber: Clone + Eq + PartialEq + Debug,
118+
Ranks: Get<u32>,
119+
> {
105120
/// The amounts to be paid when a member of a given rank (-1) is active.
106-
active_salary: [Balance; RANKS],
121+
pub active_salary: BoundedVec<Balance, Ranks>,
107122
/// The amounts to be paid when a member of a given rank (-1) is passive.
108-
passive_salary: [Balance; RANKS],
123+
pub passive_salary: BoundedVec<Balance, Ranks>,
109124
/// The period between which unproven members become demoted.
110-
demotion_period: [BlockNumber; RANKS],
125+
pub demotion_period: BoundedVec<BlockNumber, Ranks>,
111126
/// The period between which members must wait before they may proceed to this rank.
112-
min_promotion_period: [BlockNumber; RANKS],
127+
pub min_promotion_period: BoundedVec<BlockNumber, Ranks>,
113128
/// Amount by which an account can remain at rank 0 (candidate before being offboard entirely).
114-
offboard_timeout: BlockNumber,
129+
pub offboard_timeout: BlockNumber,
115130
}
116131

117-
impl<Balance: Default + Copy, BlockNumber: Default + Copy, const RANKS: usize> Default
118-
for ParamsType<Balance, BlockNumber, RANKS>
132+
impl<
133+
Balance: Default + Copy + Eq + Debug,
134+
BlockNumber: Default + Copy + Eq + Debug,
135+
Ranks: Get<u32>,
136+
> Default for ParamsType<Balance, BlockNumber, Ranks>
119137
{
120138
fn default() -> Self {
121139
Self {
122-
active_salary: [Balance::default(); RANKS],
123-
passive_salary: [Balance::default(); RANKS],
124-
demotion_period: [BlockNumber::default(); RANKS],
125-
min_promotion_period: [BlockNumber::default(); RANKS],
140+
active_salary: Default::default(),
141+
passive_salary: Default::default(),
142+
demotion_period: Default::default(),
143+
min_promotion_period: Default::default(),
126144
offboard_timeout: BlockNumber::default(),
127145
}
128146
}
@@ -148,11 +166,11 @@ pub mod pallet {
148166
traits::{tokens::GetSalary, EnsureOrigin},
149167
};
150168
use frame_system::{ensure_root, pallet_prelude::*};
151-
152-
/// Number of available ranks.
153-
pub(crate) const RANK_COUNT: usize = 9;
169+
/// The in-code storage version.
170+
const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
154171

155172
#[pallet::pallet]
173+
#[pallet::storage_version(STORAGE_VERSION)]
156174
pub struct Pallet<T, I = ()>(PhantomData<(T, I)>);
157175

158176
#[pallet::config]
@@ -194,9 +212,16 @@ pub mod pallet {
194212
/// The maximum size in bytes submitted evidence is allowed to be.
195213
#[pallet::constant]
196214
type EvidenceSize: Get<u32>;
215+
216+
/// Represents the highest possible rank in this pallet.
217+
///
218+
/// Increasing this value is supported, but decreasing it may lead to a broken state.
219+
#[pallet::constant]
220+
type MaxRank: Get<u32>;
197221
}
198222

199-
pub type ParamsOf<T, I> = ParamsType<<T as Config<I>>::Balance, BlockNumberFor<T>, RANK_COUNT>;
223+
pub type ParamsOf<T, I> =
224+
ParamsType<<T as Config<I>>::Balance, BlockNumberFor<T>, <T as Config<I>>::MaxRank>;
200225
pub type MemberStatusOf<T> = MemberStatus<BlockNumberFor<T>>;
201226
pub type RankOf<T, I> = <<T as Config<I>>::Members as RankedMembers>::Rank;
202227

@@ -338,8 +363,10 @@ pub mod pallet {
338363
#[pallet::call_index(1)]
339364
pub fn set_params(origin: OriginFor<T>, params: Box<ParamsOf<T, I>>) -> DispatchResult {
340365
T::ParamsOrigin::ensure_origin_or_root(origin)?;
366+
341367
Params::<T, I>::put(params.as_ref());
342368
Self::deposit_event(Event::<T, I>::ParamsChanged { params: *params });
369+
343370
Ok(())
344371
}
345372

@@ -540,7 +567,7 @@ pub mod pallet {
540567
/// in the range `1..=RANK_COUNT` is `None`.
541568
pub(crate) fn rank_to_index(rank: RankOf<T, I>) -> Option<usize> {
542569
match TryInto::<usize>::try_into(rank) {
543-
Ok(r) if r <= RANK_COUNT && r > 0 => Some(r - 1),
570+
Ok(r) if r as u32 <= <T as Config<I>>::MaxRank::get() && r > 0 => Some(r - 1),
544571
_ => return None,
545572
}
546573
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// This file is part of Substrate.
2+
3+
// Copyright (C) Parity Technologies (UK) Ltd.
4+
// SPDX-License-Identifier: Apache-2.0
5+
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
18+
//! Storage migrations for the core-fellowship pallet.
19+
use super::*;
20+
use frame_support::{
21+
pallet_prelude::*,
22+
storage_alias,
23+
traits::{DefensiveTruncateFrom, UncheckedOnRuntimeUpgrade},
24+
BoundedVec,
25+
};
26+
27+
#[cfg(feature = "try-runtime")]
28+
use sp_runtime::TryRuntimeError;
29+
30+
mod v0 {
31+
use frame_system::pallet_prelude::BlockNumberFor;
32+
33+
use super::*;
34+
35+
#[derive(Encode, Decode, Eq, PartialEq, Clone, TypeInfo, MaxEncodedLen, RuntimeDebug)]
36+
pub struct ParamsType<Balance, BlockNumber, const RANKS: usize> {
37+
pub active_salary: [Balance; RANKS],
38+
pub passive_salary: [Balance; RANKS],
39+
pub demotion_period: [BlockNumber; RANKS],
40+
pub min_promotion_period: [BlockNumber; RANKS],
41+
pub offboard_timeout: BlockNumber,
42+
}
43+
44+
impl<Balance: Default + Copy, BlockNumber: Default + Copy, const RANKS: usize> Default
45+
for ParamsType<Balance, BlockNumber, RANKS>
46+
{
47+
fn default() -> Self {
48+
Self {
49+
active_salary: [Balance::default(); RANKS],
50+
passive_salary: [Balance::default(); RANKS],
51+
demotion_period: [BlockNumber::default(); RANKS],
52+
min_promotion_period: [BlockNumber::default(); RANKS],
53+
offboard_timeout: BlockNumber::default(),
54+
}
55+
}
56+
}
57+
58+
/// Number of available ranks from old version.
59+
pub(crate) const RANK_COUNT: usize = 9;
60+
61+
pub type ParamsOf<T, I> = ParamsType<<T as Config<I>>::Balance, BlockNumberFor<T>, RANK_COUNT>;
62+
63+
/// V0 type for [`crate::Params`].
64+
#[storage_alias]
65+
pub type Params<T: Config<I>, I: 'static> =
66+
StorageValue<Pallet<T, I>, ParamsOf<T, I>, ValueQuery>;
67+
}
68+
69+
pub struct MigrateToV1<T, I = ()>(PhantomData<(T, I)>);
70+
impl<T: Config<I>, I: 'static> UncheckedOnRuntimeUpgrade for MigrateToV1<T, I> {
71+
#[cfg(feature = "try-runtime")]
72+
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
73+
ensure!(
74+
T::MaxRank::get() >= v0::RANK_COUNT as u32,
75+
"pallet-core-fellowship: new bound should not truncate"
76+
);
77+
Ok(Default::default())
78+
}
79+
80+
fn on_runtime_upgrade() -> frame_support::weights::Weight {
81+
// Read the old value from storage
82+
let old_value = v0::Params::<T, I>::take();
83+
// Write the new value to storage
84+
let new = crate::ParamsType {
85+
active_salary: BoundedVec::defensive_truncate_from(old_value.active_salary.to_vec()),
86+
passive_salary: BoundedVec::defensive_truncate_from(old_value.passive_salary.to_vec()),
87+
demotion_period: BoundedVec::defensive_truncate_from(
88+
old_value.demotion_period.to_vec(),
89+
),
90+
min_promotion_period: BoundedVec::defensive_truncate_from(
91+
old_value.min_promotion_period.to_vec(),
92+
),
93+
offboard_timeout: old_value.offboard_timeout,
94+
};
95+
crate::Params::<T, I>::put(new);
96+
T::DbWeight::get().reads_writes(1, 1)
97+
}
98+
}
99+
100+
/// [`UncheckedOnRuntimeUpgrade`] implementation [`MigrateToV1`] wrapped in a
101+
/// [`VersionedMigration`](frame_support::migrations::VersionedMigration), which ensures that:
102+
/// - The migration only runs once when the on-chain storage version is 0
103+
/// - The on-chain storage version is updated to `1` after the migration executes
104+
/// - Reads/Writes from checking/settings the on-chain storage version are accounted for
105+
pub type MigrateV0ToV1<T, I> = frame_support::migrations::VersionedMigration<
106+
0, // The migration will only execute when the on-chain storage version is 0
107+
1, // The on-chain storage version will be set to 1 after the migration is complete
108+
MigrateToV1<T, I>,
109+
crate::pallet::Pallet<T, I>,
110+
<T as frame_system::Config>::DbWeight,
111+
>;

0 commit comments

Comments
 (0)