referrerpolicy=no-referrer-when-downgrade

pallet_bridge_messages/
migration.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Parity Bridges Common.
3
4// Parity Bridges Common is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Parity Bridges Common is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
16
17//! A module that is responsible for migration of storage.
18
19use crate::{Config, Pallet};
20use frame_support::{
21	traits::{Get, StorageVersion},
22	weights::Weight,
23};
24
25/// The in-code storage version.
26pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
27
28/// This module contains data structures that are valid for the initial state of `0`.
29/// (used with v1 migration).
30pub mod v0 {
31	use super::Config;
32	use crate::BridgedChainOf;
33	use bp_messages::{MessageNonce, UnrewardedRelayer};
34	use bp_runtime::AccountIdOf;
35	use codec::{Decode, Encode};
36	use sp_std::collections::vec_deque::VecDeque;
37
38	#[derive(Encode, Decode, Clone, PartialEq, Eq)]
39	pub(crate) struct StoredInboundLaneData<T: Config<I>, I: 'static>(
40		pub(crate) InboundLaneData<AccountIdOf<BridgedChainOf<T, I>>>,
41	);
42	#[derive(Encode, Decode, Clone, PartialEq, Eq)]
43	pub(crate) struct InboundLaneData<RelayerId> {
44		pub(crate) relayers: VecDeque<UnrewardedRelayer<RelayerId>>,
45		pub(crate) last_confirmed_nonce: MessageNonce,
46	}
47	#[derive(Encode, Decode, Clone, PartialEq, Eq)]
48	pub(crate) struct OutboundLaneData {
49		pub(crate) oldest_unpruned_nonce: MessageNonce,
50		pub(crate) latest_received_nonce: MessageNonce,
51		pub(crate) latest_generated_nonce: MessageNonce,
52	}
53}
54
55/// This migration to `1` updates the metadata of `InboundLanes` and `OutboundLanes` to the new
56/// structures.
57pub mod v1 {
58	use super::*;
59	use crate::{
60		InboundLaneData, InboundLanes, OutboundLaneData, OutboundLanes, StoredInboundLaneData,
61	};
62	use bp_messages::LaneState;
63	use frame_support::traits::UncheckedOnRuntimeUpgrade;
64	use sp_std::marker::PhantomData;
65
66	/// Migrates the pallet storage to v1.
67	pub struct UncheckedMigrationV0ToV1<T, I>(PhantomData<(T, I)>);
68
69	impl<T: Config<I>, I: 'static> UncheckedOnRuntimeUpgrade for UncheckedMigrationV0ToV1<T, I> {
70		fn on_runtime_upgrade() -> Weight {
71			let mut weight = T::DbWeight::get().reads(1);
72
73			// `InboundLanes` - add state to the old structs
74			let translate_inbound =
75				|pre: v0::StoredInboundLaneData<T, I>| -> Option<v1::StoredInboundLaneData<T, I>> {
76					weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
77					Some(v1::StoredInboundLaneData(v1::InboundLaneData {
78						state: LaneState::Opened,
79						relayers: pre.0.relayers,
80						last_confirmed_nonce: pre.0.last_confirmed_nonce,
81					}))
82				};
83			InboundLanes::<T, I>::translate_values(translate_inbound);
84
85			// `OutboundLanes` - add state to the old structs
86			let translate_outbound = |pre: v0::OutboundLaneData| -> Option<v1::OutboundLaneData> {
87				weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
88				Some(v1::OutboundLaneData {
89					state: LaneState::Opened,
90					oldest_unpruned_nonce: pre.oldest_unpruned_nonce,
91					latest_received_nonce: pre.latest_received_nonce,
92					latest_generated_nonce: pre.latest_generated_nonce,
93				})
94			};
95			OutboundLanes::<T, I>::translate_values(translate_outbound);
96
97			weight
98		}
99
100		#[cfg(feature = "try-runtime")]
101		fn pre_upgrade() -> Result<sp_std::vec::Vec<u8>, sp_runtime::DispatchError> {
102			use codec::Encode;
103
104			let number_of_inbound_to_migrate = InboundLanes::<T, I>::iter_keys().count();
105			let number_of_outbound_to_migrate = OutboundLanes::<T, I>::iter_keys().count();
106			Ok((number_of_inbound_to_migrate as u32, number_of_outbound_to_migrate as u32).encode())
107		}
108
109		#[cfg(feature = "try-runtime")]
110		fn post_upgrade(state: sp_std::vec::Vec<u8>) -> Result<(), sp_runtime::DispatchError> {
111			use codec::Decode;
112			const LOG_TARGET: &str = "runtime::bridge-messages-migration";
113
114			let (number_of_inbound_to_migrate, number_of_outbound_to_migrate): (u32, u32) =
115				Decode::decode(&mut &state[..]).unwrap();
116			let number_of_inbound = InboundLanes::<T, I>::iter_keys().count();
117			let number_of_outbound = OutboundLanes::<T, I>::iter_keys().count();
118
119			tracing::info!(target: LOG_TARGET, %number_of_inbound_to_migrate, "post-upgrade expects inbound lanes to have been migrated.");
120			tracing::info!(target: LOG_TARGET, %number_of_outbound_to_migrate, "post-upgrade expects outbound lanes to have been migrated.");
121
122			frame_support::ensure!(
123				number_of_inbound_to_migrate as usize == number_of_inbound,
124				"must migrate all `InboundLanes`."
125			);
126			frame_support::ensure!(
127				number_of_outbound_to_migrate as usize == number_of_outbound,
128				"must migrate all `OutboundLanes`."
129			);
130
131			tracing::info!(target: LOG_TARGET, "migrated all.");
132			Ok(())
133		}
134	}
135
136	/// [`UncheckedMigrationV0ToV1`] wrapped in a
137	/// [`VersionedMigration`](frame_support::migrations::VersionedMigration), ensuring the
138	/// migration is only performed when on-chain version is 0.
139	pub type MigrationToV1<T, I> = frame_support::migrations::VersionedMigration<
140		0,
141		1,
142		UncheckedMigrationV0ToV1<T, I>,
143		Pallet<T, I>,
144		<T as frame_system::Config>::DbWeight,
145	>;
146}