From e9b03537525f960a68e33c5bdba6ed79bd2e8f48 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Thu, 15 Aug 2024 13:12:54 +0200 Subject: [PATCH] add RemoveMarkets migration --- runtime/battery-station/src/lib.rs | 4 + runtime/common/src/lib.rs | 5 +- runtime/zeitgeist/src/lib.rs | 4 + zrml/market-commons/src/lib.rs | 2 +- zrml/market-commons/src/migrations.rs | 175 ++++++++++++++++++++------ 5 files changed, 147 insertions(+), 43 deletions(-) diff --git a/runtime/battery-station/src/lib.rs b/runtime/battery-station/src/lib.rs index 6f2069d77..10b98a779 100644 --- a/runtime/battery-station/src/lib.rs +++ b/runtime/battery-station/src/lib.rs @@ -174,6 +174,10 @@ impl Contains for IsCallable { } } +parameter_types! { + pub RemovableMarketIds: Vec = vec![879u32, 877u32, 878u32, 880u32, 882u32]; +} + decl_common_types!(); create_runtime_with_additional_pallets!( diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index d64d0c01b..ac016306c 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -86,13 +86,14 @@ macro_rules! decl_common_types { generic, DispatchError, DispatchResult, RuntimeDebug, SaturatedConversion, }; use zeitgeist_primitives::traits::{DeployPoolApi, DistributeFees, MarketCommonsPalletApi}; - use zrml_market_commons::migrations::MigrateDisputeMechanism; + use zrml_market_commons::migrations::{MigrateDisputeMechanism, RemoveMarkets}; pub type Block = generic::Block; type Address = sp_runtime::MultiAddress; - type Migrations = (MigrateDisputeMechanism); + type Migrations = + (RemoveMarkets, MigrateDisputeMechanism); pub type Executive = frame_executive::Executive< Runtime, diff --git a/runtime/zeitgeist/src/lib.rs b/runtime/zeitgeist/src/lib.rs index a29bb28f1..083ba343e 100644 --- a/runtime/zeitgeist/src/lib.rs +++ b/runtime/zeitgeist/src/lib.rs @@ -191,6 +191,10 @@ impl Contains for IsCallable { } } +parameter_types! { + pub RemovableMarketIds: Vec = vec![]; +} + decl_common_types!(); create_runtime_with_additional_pallets!(); diff --git a/zrml/market-commons/src/lib.rs b/zrml/market-commons/src/lib.rs index 8a3deb0f9..2189acbbc 100644 --- a/zrml/market-commons/src/lib.rs +++ b/zrml/market-commons/src/lib.rs @@ -57,7 +57,7 @@ mod pallet { }; /// The current storage version. - const STORAGE_VERSION: StorageVersion = StorageVersion::new(12); + const STORAGE_VERSION: StorageVersion = StorageVersion::new(13); pub(crate) type AccountIdOf = ::AccountId; pub(crate) type AssetOf = Asset>; diff --git a/zrml/market-commons/src/migrations.rs b/zrml/market-commons/src/migrations.rs index d21f20c54..84e0bdba1 100644 --- a/zrml/market-commons/src/migrations.rs +++ b/zrml/market-commons/src/migrations.rs @@ -17,7 +17,7 @@ // along with Zeitgeist. If not, see . use crate::{AccountIdOf, BalanceOf, Config, MarketIdOf, MomentOf, Pallet as MarketCommons}; -use alloc::vec::Vec; +use alloc::{vec, vec::Vec}; use core::marker::PhantomData; use frame_support::{ pallet_prelude::Weight, @@ -47,6 +47,78 @@ const MARKET_COMMONS: &[u8] = b"MarketCommons"; #[cfg(any(feature = "try-runtime", test))] const MARKETS: &[u8] = b"Markets"; +const MARKET_COMMONS_REQUIRED_STORAGE_VERSION_0: u16 = 11; +const MARKET_COMMONS_NEXT_STORAGE_VERSION_0: u16 = 12; + +#[cfg(feature = "try-runtime")] +#[frame_support::storage_alias] +pub(crate) type Markets = + StorageMap, Blake2_128Concat, MarketIdOf, OldMarketOf>; + +pub struct RemoveMarkets(PhantomData, MarketIds); + +impl OnRuntimeUpgrade for RemoveMarkets +where + T: Config, + MarketIds: Get>, +{ + fn on_runtime_upgrade() -> Weight { + let mut total_weight = T::DbWeight::get().reads(1); + let market_commons_version = StorageVersion::get::>(); + if market_commons_version != MARKET_COMMONS_REQUIRED_STORAGE_VERSION_0 { + log::info!( + "RemoveMarkets: market-commons version is {:?}, but {:?} is required", + market_commons_version, + MARKET_COMMONS_REQUIRED_STORAGE_VERSION_0, + ); + return total_weight; + } + log::info!("RemoveMarkets: Starting..."); + + let mut corrupted_markets = vec![]; + + for &market_id in MarketIds::get().iter() { + let market_id = market_id.saturated_into::>(); + if crate::Markets::::contains_key(market_id) + // this produces a decoding error for the corrupted markets + && crate::Markets::::try_get(market_id).is_err() + { + crate::Markets::::remove(market_id); + corrupted_markets.push(market_id); + } + } + + log::info!("RemoveMarkets: Removed markets {:?}.", corrupted_markets); + let count = corrupted_markets.len() as u64; + total_weight = total_weight.saturating_add(T::DbWeight::get().reads_writes(count, count)); + + StorageVersion::new(MARKET_COMMONS_NEXT_STORAGE_VERSION_0).put::>(); + total_weight = total_weight.saturating_add(T::DbWeight::get().writes(1)); + log::info!("RemoveMarkets: Done!"); + total_weight + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, DispatchError> { + Ok(vec![]) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(_previous_state: Vec) -> Result<(), DispatchError> { + for &market_id in MarketIds::get().iter() { + let market_id = market_id.saturated_into::>(); + assert!(!crate::Markets::::contains_key(market_id)); + assert!(crate::Markets::::try_get(market_id).is_err()); + } + + log::info!("RemoveMarkets: Post-upgrade done!"); + Ok(()) + } +} + +const MARKET_COMMONS_REQUIRED_STORAGE_VERSION_1: u16 = 12; +const MARKET_COMMONS_NEXT_STORAGE_VERSION_1: u16 = 13; + #[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug, TypeInfo)] pub struct OldMarket { pub market_id: MarketId, @@ -95,16 +167,6 @@ pub enum OldMarketDisputeMechanism { SimpleDisputes, } -const MARKET_COMMONS_REQUIRED_STORAGE_VERSION: u16 = 11; -const MARKET_COMMONS_NEXT_STORAGE_VERSION: u16 = 12; - -const CORRUPTED_MARKET_IDS_BATTERY_STATION: [u32; 5] = [879u32, 877u32, 878u32, 880u32, 882u32]; - -#[cfg(feature = "try-runtime")] -#[frame_support::storage_alias] -pub(crate) type Markets = - StorageMap, Blake2_128Concat, MarketIdOf, OldMarketOf>; - pub struct MigrateDisputeMechanism(PhantomData); /// Removes the `SimpleDisputes` MDM by switching markets that use `SimpleDisputes` to `Authorized`. @@ -117,28 +179,16 @@ where fn on_runtime_upgrade() -> Weight { let mut total_weight = T::DbWeight::get().reads(1); let market_commons_version = StorageVersion::get::>(); - if market_commons_version != MARKET_COMMONS_REQUIRED_STORAGE_VERSION { + if market_commons_version != MARKET_COMMONS_REQUIRED_STORAGE_VERSION_1 { log::info!( "MigrateDisputeMechanism: market-commons version is {:?}, but {:?} is required", market_commons_version, - MARKET_COMMONS_REQUIRED_STORAGE_VERSION, + MARKET_COMMONS_REQUIRED_STORAGE_VERSION_1, ); return total_weight; } log::info!("MigrateDisputeMechanism: Starting..."); - // 879, 877, 878, 880, 882 markets on Battery Station - // each have a campaign asset as the base asset, which is invalid - for market_id in CORRUPTED_MARKET_IDS_BATTERY_STATION { - let market_id = market_id.saturated_into::>(); - if crate::Markets::::contains_key(market_id) - // this produces a decoding error for the corrupted markets - && crate::Markets::::try_get(market_id).is_err() - { - crate::Markets::::remove(market_id); - } - } - let mut translated = 0u64; crate::Markets::::translate::, _>(|_, old_market| { translated.saturating_inc(); @@ -172,7 +222,7 @@ where total_weight = total_weight.saturating_add(T::DbWeight::get().reads_writes(translated, translated)); - StorageVersion::new(MARKET_COMMONS_NEXT_STORAGE_VERSION).put::>(); + StorageVersion::new(MARKET_COMMONS_NEXT_STORAGE_VERSION_1).put::>(); total_weight = total_weight.saturating_add(T::DbWeight::get().writes(1)); log::info!("MigrateDisputeMechanism: Done!"); total_weight @@ -228,12 +278,6 @@ where assert_eq!(old_market.early_close, new_market.early_close); } - for market_id in CORRUPTED_MARKET_IDS_BATTERY_STATION { - let market_id = market_id.saturated_into::>(); - assert!(!crate::Markets::::contains_key(market_id)); - assert!(crate::Markets::::try_get(market_id).is_err()); - } - log::info!("MigrateDisputeMechanism: Post-upgrade market count is {}!", new_market_count); Ok(()) } @@ -247,22 +291,68 @@ mod tests { MarketOf, }; use alloc::fmt::Debug; - use frame_support::{migration::put_storage_value, Blake2_128Concat, StorageHasher}; + use frame_support::{ + migration::put_storage_value, parameter_types, Blake2_128Concat, StorageHasher, + }; use parity_scale_codec::Encode; use sp_io::storage::root as storage_root; use sp_runtime::{Perbill, StateVersion}; use test_case::test_case; use zeitgeist_primitives::types::{Bond, EarlyCloseState, MarketId}; + parameter_types! { + pub RemovableMarketIds: Vec = vec![879u32, 877u32, 878u32, 880u32, 882u32]; + pub NoRemovableMarketIds: Vec = vec![]; + } + #[test] fn on_runtime_upgrade_increments_the_storage_version() { ExtBuilder::default().build().execute_with(|| { - set_up_version(); + set_up_version_remove_markets(); + RemoveMarkets::::on_runtime_upgrade(); + assert_eq!( + StorageVersion::get::>(), + MARKET_COMMONS_NEXT_STORAGE_VERSION_0 + ); MigrateDisputeMechanism::::on_runtime_upgrade(); assert_eq!( StorageVersion::get::>(), - MARKET_COMMONS_NEXT_STORAGE_VERSION + MARKET_COMMONS_NEXT_STORAGE_VERSION_1 + ); + }); + } + + #[test] + fn on_runtime_upgrade_remove_corrupted_markets_works_as_expected() { + ExtBuilder::default().build().execute_with(|| { + set_up_version_remove_markets(); + let pallet = MARKET_COMMONS; + let prefix = MARKETS; + let (old_market, _) = construct_old_new_tuple( + Some(OldMarketDisputeMechanism::SimpleDisputes), + Some(MarketDisputeMechanism::Authorized), ); + for market_id in RemovableMarketIds::get().iter() { + let storage_hash = MarketId::from(*market_id).using_encoded(Blake2_128Concat::hash); + put_storage_value::>( + pallet, + prefix, + &storage_hash, + old_market.clone(), + ); + } + + for market_id in RemovableMarketIds::get().iter() { + let market_id = MarketId::from(*market_id); + assert!(crate::Markets::::contains_key(market_id)); + } + + RemoveMarkets::::on_runtime_upgrade(); + + for market_id in RemovableMarketIds::get().iter() { + let market_id = MarketId::from(*market_id); + assert!(!crate::Markets::::contains_key(market_id)); + } }); } @@ -276,12 +366,12 @@ mod tests { Some(OldMarketDisputeMechanism::SimpleDisputes), Some(MarketDisputeMechanism::Authorized) )] - fn on_runtime_upgrade_works_as_expected( + fn on_runtime_upgrade_mdm_works_as_expected( old_scoring_rule: Option, new_scoring_rule: Option, ) { ExtBuilder::default().build().execute_with(|| { - set_up_version(); + set_up_version_mdm(); let (old_market, new_market) = construct_old_new_tuple(old_scoring_rule, new_scoring_rule); populate_test_data::>( @@ -297,7 +387,7 @@ mod tests { #[test] fn on_runtime_upgrade_is_noop_if_versions_are_not_correct() { ExtBuilder::default().build().execute_with(|| { - StorageVersion::new(MARKET_COMMONS_NEXT_STORAGE_VERSION) + StorageVersion::new(MARKET_COMMONS_NEXT_STORAGE_VERSION_1) .put::>(); let market = Market { market_id: 7, @@ -332,8 +422,13 @@ mod tests { }); } - fn set_up_version() { - StorageVersion::new(MARKET_COMMONS_REQUIRED_STORAGE_VERSION) + fn set_up_version_remove_markets() { + StorageVersion::new(MARKET_COMMONS_REQUIRED_STORAGE_VERSION_0) + .put::>(); + } + + fn set_up_version_mdm() { + StorageVersion::new(MARKET_COMMONS_REQUIRED_STORAGE_VERSION_1) .put::>(); }