pallet_contracts/migration/
v11.rs1use crate::{
22 migration::{IsFinished, MigrationStep},
23 weights::WeightInfo,
24 Config, Pallet, TrieId, Weight, LOG_TARGET,
25};
26use alloc::vec::Vec;
27use codec::{Decode, Encode};
28use core::marker::PhantomData;
29use frame_support::{pallet_prelude::*, storage_alias, weights::WeightMeter, DefaultNoBound};
30#[cfg(feature = "try-runtime")]
31use sp_runtime::TryRuntimeError;
32
33mod v10 {
34 use super::*;
35
36 #[derive(Encode, Decode, TypeInfo, MaxEncodedLen)]
37 pub struct DeletedContract {
38 pub(crate) trie_id: TrieId,
39 }
40
41 #[storage_alias]
42 pub type DeletionQueue<T: Config> = StorageValue<Pallet<T>, Vec<DeletedContract>>;
43}
44
45#[derive(Encode, Decode, TypeInfo, MaxEncodedLen, DefaultNoBound, Clone)]
46#[scale_info(skip_type_params(T))]
47pub struct DeletionQueueManager<T: Config> {
48 insert_counter: u32,
49 delete_counter: u32,
50 _phantom: PhantomData<T>,
51}
52
53#[cfg(any(feature = "runtime-benchmarks", feature = "try-runtime"))]
54pub fn fill_old_queue<T: Config>(len: usize) {
55 let queue: Vec<v10::DeletedContract> =
56 core::iter::repeat_with(|| v10::DeletedContract { trie_id: Default::default() })
57 .take(len)
58 .collect();
59 v10::DeletionQueue::<T>::set(Some(queue));
60}
61
62#[storage_alias]
63type DeletionQueue<T: Config> = StorageMap<Pallet<T>, Twox64Concat, u32, TrieId>;
64
65#[storage_alias]
66type DeletionQueueCounter<T: Config> = StorageValue<Pallet<T>, DeletionQueueManager<T>, ValueQuery>;
67
68#[derive(Encode, Decode, MaxEncodedLen, DefaultNoBound)]
69pub struct Migration<T: Config> {
70 _phantom: PhantomData<T>,
71}
72
73impl<T: Config> MigrationStep for Migration<T> {
74 const VERSION: u16 = 11;
75
76 fn max_step_weight() -> Weight {
80 T::WeightInfo::v11_migration_step(128)
81 }
82
83 fn step(&mut self, meter: &mut WeightMeter) -> IsFinished {
84 let Some(old_queue) = v10::DeletionQueue::<T>::take() else {
85 meter.consume(T::WeightInfo::v11_migration_step(0));
86 return IsFinished::Yes
87 };
88 let len = old_queue.len();
89
90 log::debug!(
91 target: LOG_TARGET,
92 "Migrating deletion queue with {} deleted contracts",
93 old_queue.len()
94 );
95
96 if !old_queue.is_empty() {
97 let mut queue = DeletionQueueManager::<T>::default();
98 for contract in old_queue {
99 <DeletionQueue<T>>::insert(queue.insert_counter, contract.trie_id);
100 queue.insert_counter += 1;
101 }
102
103 <DeletionQueueCounter<T>>::set(queue);
104 }
105
106 meter.consume(T::WeightInfo::v11_migration_step(len as u32));
107 IsFinished::Yes
108 }
109
110 #[cfg(feature = "try-runtime")]
111 fn pre_upgrade_step() -> Result<Vec<u8>, TryRuntimeError> {
112 let old_queue = v10::DeletionQueue::<T>::take().unwrap_or_default();
113
114 if old_queue.is_empty() {
115 let len = 10u32;
116 log::debug!(
117 target: LOG_TARGET,
118 "Injecting {len} entries to deletion queue to test migration"
119 );
120 fill_old_queue::<T>(len as usize);
121 return Ok(len.encode())
122 }
123
124 Ok((old_queue.len() as u32).encode())
125 }
126
127 #[cfg(feature = "try-runtime")]
128 fn post_upgrade_step(state: Vec<u8>) -> Result<(), TryRuntimeError> {
129 let len = <u32 as Decode>::decode(&mut &state[..])
130 .expect("pre_upgrade_step provides a valid state; qed");
131 let counter = <DeletionQueueCounter<T>>::get();
132 ensure!(counter.insert_counter == len, "invalid insert counter");
133 ensure!(counter.delete_counter == 0, "invalid delete counter");
134 Ok(())
135 }
136}