pallet_child_bounties/
migration.rs1use super::*;
19use core::marker::PhantomData;
20use frame_support::{
21 storage_alias,
22 traits::{Get, UncheckedOnRuntimeUpgrade},
23};
24
25use alloc::collections::BTreeSet;
26#[cfg(feature = "try-runtime")]
27use alloc::vec::Vec;
28#[cfg(feature = "try-runtime")]
29use frame_support::ensure;
30
31pub mod v1 {
32 use super::*;
33
34 pub struct MigrateToV1Impl<T, TransferWeight>(PhantomData<(T, TransferWeight)>);
42
43 #[storage_alias]
44 type ChildBountyDescriptions<T: Config + pallet_bounties::Config> = StorageMap<
45 Pallet<T>,
46 Twox64Concat,
47 BountyIndex,
48 BoundedVec<u8, <T as pallet_bounties::Config>::MaximumReasonLength>,
49 >;
50
51 impl<T: Config, TransferWeight: Get<Weight>> UncheckedOnRuntimeUpgrade
52 for MigrateToV1Impl<T, TransferWeight>
53 {
54 fn on_runtime_upgrade() -> frame_support::weights::Weight {
55 let mut reads = 0u64;
57 let mut writes = 0u64;
58 let mut transfer_weights: Weight = Weight::zero();
59
60 let mut old_bounty_ids = BTreeSet::new();
62 for (parent_bounty_id, old_child_bounty_id) in ChildBounties::<T>::iter_keys() {
64 reads += 1;
65 old_bounty_ids.insert((parent_bounty_id, old_child_bounty_id));
66 }
67
68 log::info!(
69 target: LOG_TARGET,
70 "Migrating {} child bounties",
71 old_bounty_ids.len(),
72 );
73
74 for (parent_bounty_id, old_child_bounty_id) in old_bounty_ids {
75 let new_child_bounty_id = ParentTotalChildBounties::<T>::get(parent_bounty_id);
77 reads += 1;
78 ParentTotalChildBounties::<T>::insert(
79 parent_bounty_id,
80 new_child_bounty_id.saturating_add(1),
81 );
82 writes += 1;
83
84 V0ToV1ChildBountyIds::<T>::insert(
85 old_child_bounty_id,
86 (parent_bounty_id, new_child_bounty_id),
87 );
88 writes += 1;
89
90 let old_child_bounty_account =
91 Self::old_child_bounty_account_id(old_child_bounty_id);
92 let new_child_bounty_account =
93 Pallet::<T>::child_bounty_account_id(parent_bounty_id, new_child_bounty_id);
94 let old_balance = T::Currency::free_balance(&old_child_bounty_account);
95 log::info!(
96 "Transferring {:?} funds from old child bounty account {:?} to new child bounty account {:?}",
97 old_balance, old_child_bounty_account, new_child_bounty_account
98 );
99 if let Err(err) = T::Currency::transfer(
100 &old_child_bounty_account,
101 &new_child_bounty_account,
102 old_balance,
103 AllowDeath,
104 ) {
105 log::error!(
106 target: LOG_TARGET,
107 "Error transferring funds: {:?}",
108 err
109 );
110 }
111 transfer_weights += TransferWeight::get();
112
113 log::info!(
114 target: LOG_TARGET,
115 "Remapped parent bounty {} child bounty id {}->{}",
116 parent_bounty_id,
117 old_child_bounty_id,
118 new_child_bounty_id,
119 );
120
121 let bounty_description = ChildBountyDescriptions::<T>::take(old_child_bounty_id);
122 writes += 1;
123 let child_bounty = ChildBounties::<T>::take(parent_bounty_id, old_child_bounty_id);
124 writes += 1;
125
126 if let Some(taken) = child_bounty {
128 ChildBounties::<T>::insert(parent_bounty_id, new_child_bounty_id, taken);
129 writes += 1;
130 } else {
131 log::error!(
132 "child bounty with old id {} not found, should be impossible",
133 old_child_bounty_id
134 );
135 }
136 if let Some(bounty_description) = bounty_description {
137 super::super::ChildBountyDescriptionsV1::<T>::insert(
138 parent_bounty_id,
139 new_child_bounty_id,
140 bounty_description,
141 );
142 writes += 1;
143 } else {
144 log::error!(
145 "child bounty description with old id {} not found, should be impossible",
146 old_child_bounty_id
147 );
148 }
149 }
150
151 log::info!(
152 target: LOG_TARGET,
153 "Migration done, reads: {}, writes: {}, transfer weights: {}",
154 reads, writes, transfer_weights
155 );
156
157 T::DbWeight::get().reads_writes(reads, writes) + transfer_weights
158 }
159
160 #[cfg(feature = "try-runtime")]
161 fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
162 let old_child_bounty_count = ChildBounties::<T>::iter_keys().count() as u32;
163 let old_child_bounty_descriptions =
164 v1::ChildBountyDescriptions::<T>::iter_keys().count() as u32;
165 let old_child_bounty_ids = ChildBounties::<T>::iter_keys().collect::<Vec<_>>();
166 Ok((old_child_bounty_count, old_child_bounty_descriptions, old_child_bounty_ids)
167 .encode())
168 }
169
170 #[cfg(feature = "try-runtime")]
171 fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
172 type StateType = (u32, u32, Vec<(u32, u32)>);
173 let (old_child_bounty_count, old_child_bounty_descriptions, old_child_bounty_ids) =
174 StateType::decode(&mut &state[..]).expect("Can't decode previous state");
175 let new_child_bounty_count = ChildBounties::<T>::iter_keys().count() as u32;
176 let new_child_bounty_descriptions =
177 super::super::ChildBountyDescriptionsV1::<T>::iter_keys().count() as u32;
178
179 ensure!(
180 old_child_bounty_count == new_child_bounty_count,
181 "child bounty count doesn't match"
182 );
183 ensure!(
184 old_child_bounty_descriptions == new_child_bounty_descriptions,
185 "child bounty descriptions count doesn't match"
186 );
187
188 let old_child_bounty_descriptions_storage =
189 v1::ChildBountyDescriptions::<T>::iter_keys().count();
190 log::info!("old child bounty descriptions: {}", old_child_bounty_descriptions_storage);
191 ensure!(
192 old_child_bounty_descriptions_storage == 0,
193 "Old bounty descriptions should have been drained."
194 );
195
196 for (_, old_child_bounty_id) in old_child_bounty_ids {
197 let old_account_id = Self::old_child_bounty_account_id(old_child_bounty_id);
198 let balance = T::Currency::total_balance(&old_account_id);
199 if !balance.is_zero() {
200 log::error!(
201 "Old child bounty id {} still has balance {:?}",
202 old_child_bounty_id,
203 balance
204 );
205 }
206 }
207
208 Ok(())
209 }
210 }
211
212 impl<T: Config, TransferWeight: Get<Weight>> MigrateToV1Impl<T, TransferWeight> {
213 fn old_child_bounty_account_id(id: BountyIndex) -> T::AccountId {
214 T::PalletId::get().into_sub_account_truncating(("cb", id))
218 }
219 }
220}
221
222pub type MigrateV0ToV1<T, TransferWeight> = frame_support::migrations::VersionedMigration<
224 0,
225 1,
226 v1::MigrateToV1Impl<T, TransferWeight>,
227 Pallet<T>,
228 <T as frame_system::Config>::DbWeight,
229>;