// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Bridges Common is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see .
//! A module that is responsible for migration of storage.
use crate::{Config, Pallet};
use pezframe_support::{
traits::{Get, StorageVersion},
weights::Weight,
};
/// The in-code storage version.
pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
/// This module contains data structures that are valid for the initial state of `0`.
/// (used with v1 migration).
pub mod v0 {
use super::Config;
use crate::BridgedChainOf;
use bp_messages::{MessageNonce, UnrewardedRelayer};
use bp_runtime::AccountIdOf;
use codec::{Decode, Encode};
use pezsp_std::collections::vec_deque::VecDeque;
#[derive(Encode, Decode, Clone, PartialEq, Eq)]
pub(crate) struct StoredInboundLaneData, I: 'static>(
pub(crate) InboundLaneData>>,
);
#[derive(Encode, Decode, Clone, PartialEq, Eq)]
pub(crate) struct InboundLaneData {
pub(crate) relayers: VecDeque>,
pub(crate) last_confirmed_nonce: MessageNonce,
}
#[derive(Encode, Decode, Clone, PartialEq, Eq)]
pub(crate) struct OutboundLaneData {
pub(crate) oldest_unpruned_nonce: MessageNonce,
pub(crate) latest_received_nonce: MessageNonce,
pub(crate) latest_generated_nonce: MessageNonce,
}
}
/// This migration to `1` updates the metadata of `InboundLanes` and `OutboundLanes` to the new
/// structures.
pub mod v1 {
use super::*;
use crate::{
InboundLaneData, InboundLanes, OutboundLaneData, OutboundLanes, StoredInboundLaneData,
};
use bp_messages::LaneState;
use pezframe_support::traits::UncheckedOnRuntimeUpgrade;
use pezsp_std::marker::PhantomData;
/// Migrates the pallet storage to v1.
pub struct UncheckedMigrationV0ToV1(PhantomData<(T, I)>);
impl, I: 'static> UncheckedOnRuntimeUpgrade for UncheckedMigrationV0ToV1 {
fn on_runtime_upgrade() -> Weight {
let mut weight = T::DbWeight::get().reads(1);
// `InboundLanes` - add state to the old structs
let translate_inbound =
|pre: v0::StoredInboundLaneData| -> Option> {
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
Some(v1::StoredInboundLaneData(v1::InboundLaneData {
state: LaneState::Opened,
relayers: pre.0.relayers,
last_confirmed_nonce: pre.0.last_confirmed_nonce,
}))
};
InboundLanes::::translate_values(translate_inbound);
// `OutboundLanes` - add state to the old structs
let translate_outbound = |pre: v0::OutboundLaneData| -> Option {
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
Some(v1::OutboundLaneData {
state: LaneState::Opened,
oldest_unpruned_nonce: pre.oldest_unpruned_nonce,
latest_received_nonce: pre.latest_received_nonce,
latest_generated_nonce: pre.latest_generated_nonce,
})
};
OutboundLanes::::translate_values(translate_outbound);
weight
}
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result, pezsp_runtime::DispatchError> {
use codec::Encode;
let number_of_inbound_to_migrate = InboundLanes::::iter_keys().count();
let number_of_outbound_to_migrate = OutboundLanes::::iter_keys().count();
Ok((number_of_inbound_to_migrate as u32, number_of_outbound_to_migrate as u32).encode())
}
#[cfg(feature = "try-runtime")]
fn post_upgrade(state: pezsp_std::vec::Vec) -> Result<(), pezsp_runtime::DispatchError> {
use codec::Decode;
const LOG_TARGET: &str = "runtime::bridge-messages-migration";
let (number_of_inbound_to_migrate, number_of_outbound_to_migrate): (u32, u32) =
Decode::decode(&mut &state[..]).unwrap();
let number_of_inbound = InboundLanes::::iter_keys().count();
let number_of_outbound = OutboundLanes::::iter_keys().count();
tracing::info!(target: LOG_TARGET, %number_of_inbound_to_migrate, "post-upgrade expects inbound lanes to have been migrated.");
tracing::info!(target: LOG_TARGET, %number_of_outbound_to_migrate, "post-upgrade expects outbound lanes to have been migrated.");
pezframe_support::ensure!(
number_of_inbound_to_migrate as usize == number_of_inbound,
"must migrate all `InboundLanes`."
);
pezframe_support::ensure!(
number_of_outbound_to_migrate as usize == number_of_outbound,
"must migrate all `OutboundLanes`."
);
tracing::info!(target: LOG_TARGET, "migrated all.");
Ok(())
}
}
/// [`UncheckedMigrationV0ToV1`] wrapped in a
/// [`VersionedMigration`](pezframe_support::migrations::VersionedMigration), ensuring the
/// migration is only performed when on-chain version is 0.
pub type MigrationToV1 = pezframe_support::migrations::VersionedMigration<
0,
1,
UncheckedMigrationV0ToV1,
Pallet,
::DbWeight,
>;
}