referrerpolicy=no-referrer-when-downgrade

pallet_assets/
migration.rs

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
18use super::*;
19use frame_support::traits::OnRuntimeUpgrade;
20use log;
21
22#[cfg(feature = "try-runtime")]
23use sp_runtime::TryRuntimeError;
24
25pub mod next_asset_id {
26	use super::*;
27	use sp_core::Get;
28
29	/// Set [`NextAssetId`] to the value of `ID` if [`NextAssetId`] does not exist yet.
30	pub struct SetNextAssetId<ID, T: Config<I>, I: 'static = ()>(
31		core::marker::PhantomData<(ID, T, I)>,
32	);
33	impl<ID, T: Config<I>, I: 'static> OnRuntimeUpgrade for SetNextAssetId<ID, T, I>
34	where
35		T::AssetId: Incrementable,
36		ID: Get<T::AssetId>,
37	{
38		fn on_runtime_upgrade() -> frame_support::weights::Weight {
39			if !NextAssetId::<T, I>::exists() {
40				NextAssetId::<T, I>::put(ID::get());
41				T::DbWeight::get().reads_writes(1, 1)
42			} else {
43				T::DbWeight::get().reads(1)
44			}
45		}
46	}
47}
48
49pub mod v1 {
50	use frame_support::{pallet_prelude::*, weights::Weight};
51
52	use super::*;
53
54	#[derive(Decode)]
55	pub struct OldAssetDetails<Balance, AccountId, DepositBalance> {
56		pub owner: AccountId,
57		pub issuer: AccountId,
58		pub admin: AccountId,
59		pub freezer: AccountId,
60		pub supply: Balance,
61		pub deposit: DepositBalance,
62		pub min_balance: Balance,
63		pub is_sufficient: bool,
64		pub accounts: u32,
65		pub sufficients: u32,
66		pub approvals: u32,
67		pub is_frozen: bool,
68	}
69
70	impl<Balance, AccountId, DepositBalance> OldAssetDetails<Balance, AccountId, DepositBalance> {
71		fn migrate_to_v1(self) -> AssetDetails<Balance, AccountId, DepositBalance> {
72			let status = if self.is_frozen { AssetStatus::Frozen } else { AssetStatus::Live };
73
74			AssetDetails {
75				owner: self.owner,
76				issuer: self.issuer,
77				admin: self.admin,
78				freezer: self.freezer,
79				supply: self.supply,
80				deposit: self.deposit,
81				min_balance: self.min_balance,
82				is_sufficient: self.is_sufficient,
83				accounts: self.accounts,
84				sufficients: self.sufficients,
85				approvals: self.approvals,
86				status,
87			}
88		}
89	}
90
91	pub struct MigrateToV1<T>(core::marker::PhantomData<T>);
92	impl<T: Config> OnRuntimeUpgrade for MigrateToV1<T> {
93		fn on_runtime_upgrade() -> Weight {
94			let in_code_version = Pallet::<T>::in_code_storage_version();
95			let on_chain_version = Pallet::<T>::on_chain_storage_version();
96			if on_chain_version == 0 && in_code_version == 1 {
97				let mut translated = 0u64;
98				Asset::<T>::translate::<
99					OldAssetDetails<T::Balance, T::AccountId, DepositBalanceOf<T>>,
100					_,
101				>(|_key, old_value| {
102					translated.saturating_inc();
103					Some(old_value.migrate_to_v1())
104				});
105				in_code_version.put::<Pallet<T>>();
106				log::info!(
107					target: LOG_TARGET,
108					"Upgraded {} pools, storage to version {:?}",
109					translated,
110					in_code_version
111				);
112				T::DbWeight::get().reads_writes(translated + 1, translated + 1)
113			} else {
114				log::info!(
115					target: LOG_TARGET,
116					"Migration did not execute. This probably should be removed"
117				);
118				T::DbWeight::get().reads(1)
119			}
120		}
121
122		#[cfg(feature = "try-runtime")]
123		fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
124			frame_support::ensure!(
125				Pallet::<T>::on_chain_storage_version() == 0,
126				"must upgrade linearly"
127			);
128			let prev_count = Asset::<T>::iter().count();
129			Ok((prev_count as u32).encode())
130		}
131
132		#[cfg(feature = "try-runtime")]
133		fn post_upgrade(prev_count: Vec<u8>) -> Result<(), TryRuntimeError> {
134			let prev_count: u32 = Decode::decode(&mut prev_count.as_slice()).expect(
135				"the state parameter should be something that was generated by pre_upgrade",
136			);
137			let post_count = Asset::<T>::iter().count() as u32;
138			ensure!(
139				prev_count == post_count,
140				"the asset count before and after the migration should be the same"
141			);
142
143			let in_code_version = Pallet::<T>::in_code_storage_version();
144			let on_chain_version = Pallet::<T>::on_chain_storage_version();
145
146			frame_support::ensure!(in_code_version == 1, "must_upgrade");
147			ensure!(
148				in_code_version == on_chain_version,
149				"after migration, the in_code_version and on_chain_version should be the same"
150			);
151
152			Asset::<T>::iter().try_for_each(|(_id, asset)| -> Result<(), TryRuntimeError> {
153				ensure!(
154					asset.status == AssetStatus::Live || asset.status == AssetStatus::Frozen,
155					 "assets should only be live or frozen. None should be in destroying status, or undefined state"
156				);
157				Ok(())
158			})?;
159			Ok(())
160		}
161	}
162}