pallet_revive/migrations/
v1.rs1extern crate alloc;
23
24use super::PALLET_MIGRATIONS_ID;
25use crate::{weights::WeightInfo, AccountInfo, AccountInfoOf, Config, H160};
26use frame_support::{
27 migrations::{MigrationId, SteppedMigration, SteppedMigrationError},
28 pallet_prelude::PhantomData,
29 weights::WeightMeter,
30};
31
32#[cfg(feature = "try-runtime")]
33use alloc::collections::btree_map::BTreeMap;
34
35#[cfg(feature = "try-runtime")]
36use alloc::vec::Vec;
37
38pub mod old {
40 use super::Config;
41 use crate::{pallet::Pallet, ContractInfo, H160};
42 use frame_support::{storage_alias, Identity};
43
44 #[storage_alias]
45 pub type ContractInfoOf<T: Config> = StorageMap<Pallet<T>, Identity, H160, ContractInfo<T>>;
47}
48
49pub struct Migration<T: Config>(PhantomData<T>);
51
52impl<T: Config> SteppedMigration for Migration<T> {
53 type Cursor = H160;
54 type Identifier = MigrationId<17>;
55
56 fn id() -> Self::Identifier {
57 MigrationId { pallet_id: *PALLET_MIGRATIONS_ID, version_from: 0, version_to: 1 }
58 }
59
60 fn step(
61 mut cursor: Option<Self::Cursor>,
62 meter: &mut WeightMeter,
63 ) -> Result<Option<Self::Cursor>, SteppedMigrationError> {
64 let required = <T as Config>::WeightInfo::v1_migration_step();
65 if meter.remaining().any_lt(required) {
66 return Err(SteppedMigrationError::InsufficientWeight { required });
67 }
68
69 loop {
70 if meter.try_consume(required).is_err() {
71 break;
72 }
73
74 let iter = if let Some(last_key) = cursor {
75 old::ContractInfoOf::<T>::iter_from(old::ContractInfoOf::<T>::hashed_key_for(
76 last_key,
77 ))
78 } else {
79 old::ContractInfoOf::<T>::iter()
80 };
81
82 if let Some((last_key, value)) = iter.drain().next() {
83 AccountInfoOf::<T>::insert(
84 last_key,
85 AccountInfo { account_type: value.into(), ..Default::default() },
86 );
87 cursor = Some(last_key)
88 } else {
89 cursor = None;
90 break
91 }
92 }
93 Ok(cursor)
94 }
95
96 #[cfg(feature = "try-runtime")]
97 fn pre_upgrade() -> Result<Vec<u8>, frame_support::sp_runtime::TryRuntimeError> {
98 use codec::Encode;
99
100 Ok(old::ContractInfoOf::<T>::iter().collect::<BTreeMap<_, _>>().encode())
102 }
103
104 #[cfg(feature = "try-runtime")]
105 fn post_upgrade(prev: Vec<u8>) -> Result<(), frame_support::sp_runtime::TryRuntimeError> {
106 use codec::Decode;
107
108 let prev_map = BTreeMap::<H160, crate::ContractInfo<T>>::decode(&mut &prev[..])
110 .expect("Failed to decode the previous storage state");
111
112 assert_eq!(
114 AccountInfoOf::<T>::iter().count(),
115 prev_map.len(),
116 "Migration failed: the number of items in the storage after the migration is not the same as before"
117 );
118
119 for (key, value) in prev_map {
120 let new_value = AccountInfo::<T>::load_contract(&key);
121 assert_eq!(
122 Some(value),
123 new_value,
124 "Migration failed: the value after the migration is not the same as before"
125 );
126 }
127
128 Ok(())
129 }
130}
131
132#[test]
133fn migrate_to_v1() {
134 use crate::{
135 tests::{ExtBuilder, Test},
136 ContractInfo,
137 };
138 ExtBuilder::default().build().execute_with(|| {
139 for i in 0..10u8 {
140 let addr = H160::from([i; 20]);
141 old::ContractInfoOf::<Test>::insert(
142 addr,
143 ContractInfo::new(&addr, 1u32.into(), Default::default()).unwrap(),
144 );
145 }
146
147 let mut cursor = None;
148 let mut weight_meter = WeightMeter::new();
149 while let Some(new_cursor) = Migration::<Test>::step(cursor, &mut weight_meter).unwrap() {
150 cursor = Some(new_cursor);
151 }
152
153 assert_eq!(old::ContractInfoOf::<Test>::iter().count(), 0);
154 assert_eq!(AccountInfoOf::<Test>::iter().count(), 10);
155 })
156}