use crate::{Config, Pallet};
use frame_support::{
traits::{Get, StorageVersion},
weights::Weight,
};
pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
pub mod v0 {
use super::Config;
use crate::BridgedChainOf;
use bp_messages::{MessageNonce, UnrewardedRelayer};
use bp_runtime::AccountIdOf;
use codec::{Decode, Encode};
use sp_std::collections::vec_deque::VecDeque;
#[derive(Encode, Decode, Clone, PartialEq, Eq)]
pub(crate) struct StoredInboundLaneData<T: Config<I>, I: 'static>(
pub(crate) InboundLaneData<AccountIdOf<BridgedChainOf<T, I>>>,
);
#[derive(Encode, Decode, Clone, PartialEq, Eq)]
pub(crate) struct InboundLaneData<RelayerId> {
pub(crate) relayers: VecDeque<UnrewardedRelayer<RelayerId>>,
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,
}
}
pub mod v1 {
use super::*;
use crate::{
InboundLaneData, InboundLanes, OutboundLaneData, OutboundLanes, StoredInboundLaneData,
};
use bp_messages::LaneState;
use frame_support::traits::UncheckedOnRuntimeUpgrade;
use sp_std::marker::PhantomData;
pub struct UncheckedMigrationV0ToV1<T, I>(PhantomData<(T, I)>);
impl<T: Config<I>, I: 'static> UncheckedOnRuntimeUpgrade for UncheckedMigrationV0ToV1<T, I> {
fn on_runtime_upgrade() -> Weight {
let mut weight = T::DbWeight::get().reads(1);
let translate_inbound =
|pre: v0::StoredInboundLaneData<T, I>| -> Option<v1::StoredInboundLaneData<T, I>> {
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::<T, I>::translate_values(translate_inbound);
let translate_outbound = |pre: v0::OutboundLaneData| -> Option<v1::OutboundLaneData> {
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::<T, I>::translate_values(translate_outbound);
weight
}
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<sp_std::vec::Vec<u8>, sp_runtime::DispatchError> {
use codec::Encode;
let number_of_inbound_to_migrate = InboundLanes::<T, I>::iter_keys().count();
let number_of_outbound_to_migrate = OutboundLanes::<T, I>::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: sp_std::vec::Vec<u8>) -> Result<(), sp_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::<T, I>::iter_keys().count();
let number_of_outbound = OutboundLanes::<T, I>::iter_keys().count();
log::info!(target: LOG_TARGET, "post-upgrade expects '{number_of_inbound_to_migrate}' inbound lanes to have been migrated.");
log::info!(target: LOG_TARGET, "post-upgrade expects '{number_of_outbound_to_migrate}' outbound lanes to have been migrated.");
frame_support::ensure!(
number_of_inbound_to_migrate as usize == number_of_inbound,
"must migrate all `InboundLanes`."
);
frame_support::ensure!(
number_of_outbound_to_migrate as usize == number_of_outbound,
"must migrate all `OutboundLanes`."
);
log::info!(target: LOG_TARGET, "migrated all.");
Ok(())
}
}
pub type MigrationToV1<T, I> = frame_support::migrations::VersionedMigration<
0,
1,
UncheckedMigrationV0ToV1<T, I>,
Pallet<T, I>,
<T as frame_system::Config>::DbWeight,
>;
}