From f81257199df1888587b1ba67acffa0d447951dc8 Mon Sep 17 00:00:00 2001 From: kylezs Date: Mon, 25 Sep 2023 11:54:25 +0200 Subject: [PATCH] chore: ingress-egress pallet migrations --- Cargo.lock | 1 + state-chain/pallets/cf-broadcast/src/lib.rs | 7 ++ .../pallets/cf-ingress-egress/Cargo.toml | 7 +- .../pallets/cf-ingress-egress/src/lib.rs | 1 + .../cf-ingress-egress/src/migrations.rs | 7 ++ .../src/migrations/ingress_expiry.rs | 119 ++++++++++++++++++ 6 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 state-chain/pallets/cf-ingress-egress/src/migrations.rs create mode 100644 state-chain/pallets/cf-ingress-egress/src/migrations/ingress_expiry.rs diff --git a/Cargo.lock b/Cargo.lock index 68ea096442..a0bc4e04c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7184,6 +7184,7 @@ version = "0.1.0" dependencies = [ "cf-chains", "cf-primitives", + "cf-runtime-upgrade-utilities", "cf-runtime-utilities", "cf-test-utilities", "cf-traits", diff --git a/state-chain/pallets/cf-broadcast/src/lib.rs b/state-chain/pallets/cf-broadcast/src/lib.rs index fd3c0c0923..9330c7b5b3 100644 --- a/state-chain/pallets/cf-broadcast/src/lib.rs +++ b/state-chain/pallets/cf-broadcast/src/lib.rs @@ -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, I: 'static = ()> = StorageMap<_, Twox64Concat, TransactionOutIdFor, BroadcastId, OptionQuery>; @@ -452,6 +454,7 @@ pub mod pallet { threshold_signature_payload: PayloadFor, api_call: Box<>::ApiCall>, broadcast_id: BroadcastId, + // insert chain tracking block number here? ) -> DispatchResultWithPostInfo { let _ = T::EnsureThresholdSigned::ensure_origin(origin)?; @@ -616,6 +619,9 @@ impl, I: 'static> Pallet { if let Some(callback) = maybe_callback { RequestCallbacks::::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(), @@ -648,6 +654,7 @@ impl, I: 'static> Pallet { T::BroadcastReadyProvider::on_broadcast_ready(&api_call); + // Here is the out id. TransactionOutIdToBroadcastId::::insert(&transaction_out_id, broadcast_id); ThresholdSignatureData::::insert(broadcast_id, (api_call, signature)); diff --git a/state-chain/pallets/cf-ingress-egress/Cargo.toml b/state-chain/pallets/cf-ingress-egress/Cargo.toml index 1ab44ee32d..933bbcde12 100644 --- a/state-chain/pallets/cf-ingress-egress/Cargo.toml +++ b/state-chain/pallets/cf-ingress-egress/Cargo.toml @@ -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 } @@ -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', @@ -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', +] diff --git a/state-chain/pallets/cf-ingress-egress/src/lib.rs b/state-chain/pallets/cf-ingress-egress/src/lib.rs index 772942567a..e00b403242 100644 --- a/state-chain/pallets/cf-ingress-egress/src/lib.rs +++ b/state-chain/pallets/cf-ingress-egress/src/lib.rs @@ -5,6 +5,7 @@ mod benchmarking; +pub mod migrations; #[cfg(test)] mod mock; #[cfg(test)] diff --git a/state-chain/pallets/cf-ingress-egress/src/migrations.rs b/state-chain/pallets/cf-ingress-egress/src/migrations.rs new file mode 100644 index 0000000000..5d482ba4a7 --- /dev/null +++ b/state-chain/pallets/cf-ingress-egress/src/migrations.rs @@ -0,0 +1,7 @@ +pub mod ingress_expiry; + +use cf_runtime_upgrade_utilities::VersionedMigration; + +// TODO: Check version +pub type PalletMigration = + (VersionedMigration, ingress_expiry::Migration, 0, 1>,); diff --git a/state-chain/pallets/cf-ingress-egress/src/migrations/ingress_expiry.rs b/state-chain/pallets/cf-ingress-egress/src/migrations/ingress_expiry.rs new file mode 100644 index 0000000000..3c5c33943b --- /dev/null +++ b/state-chain/pallets/cf-ingress-egress/src/migrations/ingress_expiry.rs @@ -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, 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, I: 'static> { + pub deposit_channel: DepositChannel, + /// The block number at which the deposit channel was opened, expressed as a block number + /// on the external Chain. + pub opened_at: ::ChainBlockNumber, + // *State Chain block number* + pub expires_at: BlockNumberFor, + } + + #[frame_support::storage_alias] + pub type ChannelActions, I: 'static> = StorageMap< + Pallet, + Twox64Concat, + TargetChainAccount, + ChannelAction<::AccountId>, + OptionQuery, + >; + + #[frame_support::storage_alias] + pub type DepositChannelLookup, I: 'static> = StorageMap< + Pallet, + Twox64Concat, + TargetChainAccount, + DepositChannelDetails, + OptionQuery, + >; +} + +impl, I: 'static> OnRuntimeUpgrade for Migration { + fn on_runtime_upgrade() -> frame_support::weights::Weight { + let lifetime: TargetChainBlockNumber = match T::TargetChain::NAME { + "Bitcoin" => BITCOIN_EXPIRY_BLOCKS.into(), + "Ethereum" => ETHEREUM_EXPIRY_BLOCKS.into(), + "Polkadot" => POLKADOT_EXPIRY_BLOCKS.into(), + _ => unreachable!("Unsupported chain"), + }; + + DepositChannelLifetime::::put(lifetime); + + let channel_lifetime = DepositChannelLifetime::::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::::drain().collect::>(); + + for (address, old_channel) in old_channel_lookup { + if let Some(action) = old::ChannelActions::::take(&address) { + DepositChannelLookup::::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::::append((recycle_block, address)); + + // Remove any we missed above. + let _ = old::ChannelActions::::drain().collect::>(); + } + + Weight::zero() + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, DispatchError> { + let number_of_channels_in_lookup = + old::DepositChannelLookup::::iter_keys().count() as u32; + + Ok(number_of_channels_in_lookup.encode()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(state: Vec) -> Result<(), DispatchError> { + let number_of_channels_in_lookup_pre_migration = ::decode(&mut &state[..]).unwrap(); + ensure!( + DepositChannelLookup::::iter_keys().count() as u32 == + number_of_channels_in_lookup_pre_migration, + "DepositChannelLookup migration failed." + ); + ensure!( + DepositChannelRecycleBlocks::::decode_len().unwrap_or_default() as u32 == + number_of_channels_in_lookup_pre_migration, + "DepositChannelRecycleBlocks migration failed." + ); + Ok(()) + } +}