1use super::*;
21use frame_support::{
22 pallet_prelude::*,
23 storage_alias,
24 traits::{DefensiveTruncateFrom, UncheckedOnRuntimeUpgrade},
25 BoundedVec,
26};
27
28#[cfg(feature = "try-runtime")]
29use alloc::vec::Vec;
30#[cfg(feature = "try-runtime")]
31use sp_runtime::TryRuntimeError;
32
33mod v0 {
34 use frame_system::pallet_prelude::BlockNumberFor;
35
36 use super::*;
37
38 #[derive(Encode, Decode, Eq, PartialEq, Clone, TypeInfo, MaxEncodedLen, Debug)]
39 pub struct ParamsType<Balance, BlockNumber, const RANKS: usize> {
40 pub active_salary: [Balance; RANKS],
41 pub passive_salary: [Balance; RANKS],
42 pub demotion_period: [BlockNumber; RANKS],
43 pub min_promotion_period: [BlockNumber; RANKS],
44 pub offboard_timeout: BlockNumber,
45 }
46
47 impl<Balance: Default + Copy, BlockNumber: Default + Copy, const RANKS: usize> Default
48 for ParamsType<Balance, BlockNumber, RANKS>
49 {
50 fn default() -> Self {
51 Self {
52 active_salary: [Balance::default(); RANKS],
53 passive_salary: [Balance::default(); RANKS],
54 demotion_period: [BlockNumber::default(); RANKS],
55 min_promotion_period: [BlockNumber::default(); RANKS],
56 offboard_timeout: BlockNumber::default(),
57 }
58 }
59 }
60
61 pub(crate) const RANK_COUNT: usize = 9;
63
64 pub type ParamsOf<T, I> = ParamsType<<T as Config<I>>::Balance, BlockNumberFor<T>, RANK_COUNT>;
65
66 #[storage_alias]
68 pub type Params<T: Config<I>, I: 'static> =
69 StorageValue<Pallet<T, I>, ParamsOf<T, I>, ValueQuery>;
70}
71
72pub mod v1 {
73 use super::*;
74 use frame_system::pallet_prelude::BlockNumberFor as LocalBlockNumberFor;
75
76 pub type MemberStatusOf<T> = MemberStatus<LocalBlockNumberFor<T>>;
77 #[storage_alias]
79 pub type Member<T: Config<I>, I: 'static> = StorageMap<
80 Pallet<T, I>,
81 Twox64Concat,
82 <T as frame_system::Config>::AccountId,
83 MemberStatusOf<T>,
84 OptionQuery,
85 >;
86
87 pub type ParamsOf<T, I> = ParamsType<
88 <T as Config<I>>::Balance,
89 LocalBlockNumberFor<T>,
90 ConvertU16ToU32<<T as Config<I>>::MaxRank>,
91 >;
92 #[storage_alias]
94 pub type Params<T: Config<I>, I: 'static> =
95 StorageValue<Pallet<T, I>, ParamsOf<T, I>, ValueQuery>;
96
97 pub struct MigrateToV1<T, I = ()>(PhantomData<(T, I)>);
98 impl<T: Config<I>, I: 'static> UncheckedOnRuntimeUpgrade for MigrateToV1<T, I> {
99 #[cfg(feature = "try-runtime")]
100 fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
101 ensure!(
102 T::MaxRank::get() as usize >= v0::RANK_COUNT,
103 "pallet-core-fellowship: new bound should not truncate"
104 );
105 Ok(Default::default())
106 }
107
108 fn on_runtime_upgrade() -> frame_support::weights::Weight {
109 let old_value = v0::Params::<T, I>::take();
111 let new = ParamsOf::<T, I> {
113 active_salary: BoundedVec::defensive_truncate_from(
114 old_value.active_salary.to_vec(),
115 ),
116 passive_salary: BoundedVec::defensive_truncate_from(
117 old_value.passive_salary.to_vec(),
118 ),
119 demotion_period: BoundedVec::defensive_truncate_from(
120 old_value.demotion_period.to_vec(),
121 ),
122 min_promotion_period: BoundedVec::defensive_truncate_from(
123 old_value.min_promotion_period.to_vec(),
124 ),
125 offboard_timeout: old_value.offboard_timeout,
126 };
127 Params::<T, I>::put(new);
128 T::DbWeight::get().reads_writes(1, 1)
129 }
130 }
131}
132
133pub mod v2 {
134 use super::*;
135 use crate::BlockNumberFor as NewBlockNumberFor;
136 use frame_system::pallet_prelude::BlockNumberFor as LocalBlockNumberFor;
137
138 pub trait ConvertBlockNumber<L, N> {
141 fn equivalent_moment_in_time(local_moment: L) -> N;
168
169 fn equivalent_block_duration(local_duration: L) -> N;
197 }
198
199 pub struct MigrateToV2<T, BlockNumberConverter, I = ()>(
200 PhantomData<(T, BlockNumberConverter, I)>,
201 );
202
203 impl<T: Config<I>, BlockNumberConverter, I: 'static> UncheckedOnRuntimeUpgrade
204 for MigrateToV2<T, BlockNumberConverter, I>
205 where
206 BlockNumberConverter: ConvertBlockNumber<LocalBlockNumberFor<T>, NewBlockNumberFor<T, I>>,
207 {
208 #[cfg(feature = "try-runtime")]
209 fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
210 let params_exists = v1::Params::<T, I>::exists();
211 let member_count = v1::Member::<T, I>::iter().count() as u32;
212 Ok((params_exists, member_count).encode())
213 }
214
215 fn on_runtime_upgrade() -> frame_support::weights::Weight {
216 let mut translation_count = 0;
217
218 let old_params = v1::Params::<T, I>::take();
220 let new_params = crate::ParamsOf::<T, I> {
221 active_salary: old_params.active_salary,
222 passive_salary: old_params.passive_salary,
223 demotion_period: BoundedVec::defensive_truncate_from(
224 old_params
225 .demotion_period
226 .into_iter()
227 .map(|original| BlockNumberConverter::equivalent_block_duration(original))
228 .collect(),
229 ),
230 min_promotion_period: BoundedVec::defensive_truncate_from(
231 old_params
232 .min_promotion_period
233 .into_iter()
234 .map(|original| BlockNumberConverter::equivalent_block_duration(original))
235 .collect(),
236 ),
237 offboard_timeout: BlockNumberConverter::equivalent_block_duration(
238 old_params.offboard_timeout,
239 ),
240 };
241 crate::Params::<T, I>::put(new_params);
242 translation_count.saturating_inc();
243
244 crate::Member::<T, I>::translate::<v1::MemberStatusOf<T>, _>(|_, member_data| {
246 translation_count.saturating_inc();
247 Some(crate::MemberStatus {
248 is_active: member_data.is_active,
249 last_promotion: BlockNumberConverter::equivalent_moment_in_time(
250 member_data.last_promotion,
251 ),
252 last_proof: BlockNumberConverter::equivalent_moment_in_time(
253 member_data.last_proof,
254 ),
255 })
256 });
257
258 T::DbWeight::get().reads_writes(translation_count, translation_count)
259 }
260
261 #[cfg(feature = "try-runtime")]
262 fn post_upgrade(state: Vec<u8>) -> Result<(), TryRuntimeError> {
263 let (params_existed, pre_member_count): (bool, u32) =
264 Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed");
265
266 ensure!(crate::Params::<T, I>::exists() == params_existed, "The Params storage's existence should remain the same before and after the upgrade.");
267 let post_member_count = crate::Member::<T, I>::iter().count() as u32;
268 ensure!(
269 post_member_count == pre_member_count,
270 "The member count should remain the same before and after the upgrade."
271 );
272 Ok(())
273 }
274 }
275}
276
277pub type MigrateV0ToV1<T, I> = frame_support::migrations::VersionedMigration<
283 0, 1, v1::MigrateToV1<T, I>,
286 crate::pallet::Pallet<T, I>,
287 <T as frame_system::Config>::DbWeight,
288>;
289
290pub type MigrateV1ToV2<T, BC, I> = frame_support::migrations::VersionedMigration<
296 1, 2, v2::MigrateToV2<T, BC, I>,
299 crate::pallet::Pallet<T, I>,
300 <T as frame_system::Config>::DbWeight,
301>;