Skip to content

Commit

Permalink
chore: ingress-egress pallet migrations
Browse files Browse the repository at this point in the history
  • Loading branch information
kylezs committed Sep 25, 2023
1 parent cdc5e0d commit 26b60b0
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 1 deletion.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions state-chain/pallets/cf-broadcast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ pub mod pallet {
>;

/// Lookup table between TransactionOutId -> Broadcast.
/// This storage item is used by the CFE to track which broadcasts/egresses it needs to
/// witness.
#[pallet::storage]
pub type TransactionOutIdToBroadcastId<T: Config<I>, I: 'static = ()> =
StorageMap<_, Twox64Concat, TransactionOutIdFor<T, I>, BroadcastId, OptionQuery>;
Expand Down Expand Up @@ -452,6 +454,7 @@ pub mod pallet {
threshold_signature_payload: PayloadFor<T, I>,
api_call: Box<<T as Config<I>>::ApiCall>,
broadcast_id: BroadcastId,
// insert chain tracking block number here?
) -> DispatchResultWithPostInfo {
let _ = T::EnsureThresholdSigned::ensure_origin(origin)?;

Expand Down Expand Up @@ -616,6 +619,9 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
if let Some(callback) = maybe_callback {
RequestCallbacks::<T, I>::insert(broadcast_id, callback);
}

// Get and insert some chain tracking block number here?

let threshold_signature_payload = api_call.threshold_signature_payload();
let signature_request_id = T::ThresholdSigner::request_signature_with_callback(
threshold_signature_payload.clone(),
Expand Down Expand Up @@ -648,6 +654,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {

T::BroadcastReadyProvider::on_broadcast_ready(&api_call);

// Here is the out id.
TransactionOutIdToBroadcastId::<T, I>::insert(&transaction_out_id, broadcast_id);

ThresholdSignatureData::<T, I>::insert(broadcast_id, (api_call, signature));
Expand Down
7 changes: 6 additions & 1 deletion state-chain/pallets/cf-ingress-egress/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ cf-traits = { path = '../../traits', default-features = false }
cf-runtime-utilities = { path = '../../runtime-utilities', default-features = false, features = [
'derive',
] }
cf-runtime-upgrade-utilities = { path = '../../runtime-upgrade-utilities', default-features = false }

log = { version = '0.4.16', default-features = false }

Expand Down Expand Up @@ -47,6 +48,7 @@ std = [
'cf-chains/std',
'cf-primitives/std',
'cf-traits/std',
'cf-runtime-upgrade-utilities/std',
'codec/std',
'frame-benchmarking?/std',
'frame-support/std',
Expand All @@ -64,4 +66,7 @@ runtime-benchmarks = [
'frame-system/runtime-benchmarks',
'pallet-cf-governance/runtime-benchmarks',
]
try-runtime = ['frame-support/try-runtime']
try-runtime = [
'frame-support/try-runtime',
'cf-runtime-upgrade-utilities/try-runtime',
]
4 changes: 4 additions & 0 deletions state-chain/pallets/cf-ingress-egress/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

mod benchmarking;

pub mod migrations;
#[cfg(test)]
mod mock;
#[cfg(test)]
Expand Down Expand Up @@ -90,6 +91,8 @@ pub struct VaultTransfer<C: Chain> {
destination_address: C::ChainAccount,
}

pub const PALLET_VERSION: StorageVersion = StorageVersion::new(1);

#[frame_support::pallet]
pub mod pallet {
use super::*;
Expand Down Expand Up @@ -222,6 +225,7 @@ pub mod pallet {
}

#[pallet::pallet]
#[pallet::storage_version(PALLET_VERSION)]
#[pallet::without_storage_info]
pub struct Pallet<T, I = ()>(PhantomData<(T, I)>);

Expand Down
6 changes: 6 additions & 0 deletions state-chain/pallets/cf-ingress-egress/src/migrations.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pub mod ingress_expiry;

use cf_runtime_upgrade_utilities::VersionedMigration;

pub type PalletMigration<T, I> =
(VersionedMigration<crate::Pallet<T, I>, ingress_expiry::Migration<T, I>, 0, 1>,);
119 changes: 119 additions & 0 deletions state-chain/pallets/cf-ingress-egress/src/migrations/ingress_expiry.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
use crate::*;
use frame_support::traits::OnRuntimeUpgrade;
use sp_std::marker::PhantomData;

#[cfg(feature = "try-runtime")]
use codec::{Decode, Encode};
#[cfg(feature = "try-runtime")]
use frame_support::dispatch::DispatchError;

// Copied from state-chain/node/src/chain_spec/testnet.rs:
// These represent approximately 2 hours on testnet block times
pub const BITCOIN_EXPIRY_BLOCKS: u32 = 2 * 60 * 60 / (10 * 60);
pub const ETHEREUM_EXPIRY_BLOCKS: u32 = 2 * 60 * 60 / 14;
pub const POLKADOT_EXPIRY_BLOCKS: u32 = 2 * 60 * 60 / 6;

pub struct Migration<T: Config<I>, I: 'static>(PhantomData<(T, I)>);

// These were removed in 0.9.4
mod old {

use super::*;

#[derive(
CloneNoBound, RuntimeDebug, PartialEq, Eq, Encode, Decode, TypeInfo, MaxEncodedLen,
)]
#[scale_info(skip_type_params(T, I))]
pub struct DepositChannelDetails<T: Config<I>, I: 'static> {
pub deposit_channel: DepositChannel<T::TargetChain>,
/// The block number at which the deposit channel was opened, expressed as a block number
/// on the external Chain.
pub opened_at: <T::TargetChain as Chain>::ChainBlockNumber,
// *State Chain block number*
pub expires_at: BlockNumberFor<T>,
}

#[frame_support::storage_alias]
pub type ChannelActions<T: Config<I>, I: 'static> = StorageMap<
Pallet<T, I>,
Twox64Concat,
TargetChainAccount<T, I>,
ChannelAction<<T as frame_system::Config>::AccountId>,
OptionQuery,
>;

#[frame_support::storage_alias]
pub type DepositChannelLookup<T: Config<I>, I: 'static> = StorageMap<
Pallet<T, I>,
Twox64Concat,
TargetChainAccount<T, I>,
DepositChannelDetails<T, I>,
OptionQuery,
>;
}

impl<T: Config<I>, I: 'static> OnRuntimeUpgrade for Migration<T, I> {
fn on_runtime_upgrade() -> frame_support::weights::Weight {
let lifetime: TargetChainBlockNumber<T, I> = match T::TargetChain::NAME {
"Bitcoin" => BITCOIN_EXPIRY_BLOCKS.into(),
"Ethereum" => ETHEREUM_EXPIRY_BLOCKS.into(),
"Polkadot" => POLKADOT_EXPIRY_BLOCKS.into(),
_ => unreachable!("Unsupported chain"),
};

DepositChannelLifetime::<T, I>::put(lifetime);

let channel_lifetime = DepositChannelLifetime::<T, I>::get();
let current_external_block_height = T::ChainTracking::get_block_height();
let expiry_block = current_external_block_height.saturating_add(channel_lifetime);
let recycle_block = expiry_block.saturating_add(channel_lifetime);

let old_channel_lookup = old::DepositChannelLookup::<T, I>::drain().collect::<Vec<_>>();

for (address, old_channel) in old_channel_lookup {
if let Some(action) = old::ChannelActions::<T, I>::take(&address) {
DepositChannelLookup::<T, I>::insert(
address.clone(),
DepositChannelDetails {
deposit_channel: old_channel.deposit_channel,
opened_at: old_channel.opened_at,
expires_at: expiry_block,
action,
},
);
}

// We're just going to recycle them 2 hours from when we did the migration.
DepositChannelRecycleBlocks::<T, I>::append((recycle_block, address));

// Remove any we missed above.
let _ = old::ChannelActions::<T, I>::drain().collect::<Vec<_>>();
}

Weight::zero()
}

#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, DispatchError> {
let number_of_channels_in_lookup =
old::DepositChannelLookup::<T, I>::iter_keys().count() as u32;

Ok(number_of_channels_in_lookup.encode())
}

#[cfg(feature = "try-runtime")]
fn post_upgrade(state: Vec<u8>) -> Result<(), DispatchError> {
let number_of_channels_in_lookup_pre_migration = <u32>::decode(&mut &state[..]).unwrap();
ensure!(
DepositChannelLookup::<T, I>::iter_keys().count() as u32 ==
number_of_channels_in_lookup_pre_migration,
"DepositChannelLookup migration failed."
);
ensure!(
DepositChannelRecycleBlocks::<T, I>::decode_len().unwrap_or_default() as u32 ==
number_of_channels_in_lookup_pre_migration,
"DepositChannelRecycleBlocks migration failed."
);
Ok(())
}
}

0 comments on commit 26b60b0

Please sign in to comment.