diff --git a/runtime/parachains/src/configuration.rs b/runtime/parachains/src/configuration.rs index 69ff43615678..b5c38aad56a3 100644 --- a/runtime/parachains/src/configuration.rs +++ b/runtime/parachains/src/configuration.rs @@ -34,6 +34,7 @@ pub use pallet::*; pub mod migration; +#[allow(dead_code)] const LOG_TARGET: &str = "runtime::configuration"; /// All configuration of the runtime with respect to parachains and parathreads. diff --git a/runtime/parachains/src/configuration/migration.rs b/runtime/parachains/src/configuration/migration.rs index 6909eecc15a9..ce7959053d1b 100644 --- a/runtime/parachains/src/configuration/migration.rs +++ b/runtime/parachains/src/configuration/migration.rs @@ -16,299 +16,13 @@ //! A module that is responsible for migration of storage. -use crate::configuration::{self, Config, Pallet, Store}; -use frame_support::{pallet_prelude::*, traits::StorageVersion, weights::Weight}; -use frame_system::pallet_prelude::BlockNumberFor; +use crate::configuration::Config; +use frame_support::{traits::StorageVersion, weights::Weight}; /// The current storage version. pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); /// Migrates the pallet storage to the most recent version, checking and setting the `StorageVersion`. pub fn migrate_to_latest() -> Weight { - let mut weight = 0; - - if StorageVersion::get::>() == 0 { - weight += migrate_to_v1::(); - StorageVersion::new(1).put::>(); - } - - weight -} - -mod v0 { - use super::*; - use primitives::v1::{Balance, SessionIndex}; - - #[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug)] - pub struct HostConfiguration { - pub max_code_size: u32, - pub max_head_data_size: u32, - pub max_upward_queue_count: u32, - pub max_upward_queue_size: u32, - pub max_upward_message_size: u32, - pub max_upward_message_num_per_candidate: u32, - pub hrmp_max_message_num_per_candidate: u32, - pub validation_upgrade_frequency: BlockNumber, - pub validation_upgrade_delay: BlockNumber, - pub max_pov_size: u32, - pub max_downward_message_size: u32, - pub ump_service_total_weight: Weight, - pub hrmp_max_parachain_outbound_channels: u32, - pub hrmp_max_parathread_outbound_channels: u32, - pub _hrmp_open_request_ttl: u32, - pub hrmp_sender_deposit: Balance, - pub hrmp_recipient_deposit: Balance, - pub hrmp_channel_max_capacity: u32, - pub hrmp_channel_max_total_size: u32, - pub hrmp_max_parachain_inbound_channels: u32, - pub hrmp_max_parathread_inbound_channels: u32, - pub hrmp_channel_max_message_size: u32, - pub code_retention_period: BlockNumber, - pub parathread_cores: u32, - pub parathread_retries: u32, - pub group_rotation_frequency: BlockNumber, - pub chain_availability_period: BlockNumber, - pub thread_availability_period: BlockNumber, - pub scheduling_lookahead: u32, - pub max_validators_per_core: Option, - pub max_validators: Option, - pub dispute_period: SessionIndex, - pub dispute_post_conclusion_acceptance_period: BlockNumber, - pub dispute_max_spam_slots: u32, - pub dispute_conclusion_by_time_out_period: BlockNumber, - pub no_show_slots: u32, - pub n_delay_tranches: u32, - pub zeroth_delay_tranche_width: u32, - pub needed_approvals: u32, - pub relay_vrf_modulo_samples: u32, - } - - impl> Default for HostConfiguration { - fn default() -> Self { - HostConfiguration { - group_rotation_frequency: 1u32.into(), - chain_availability_period: 1u32.into(), - thread_availability_period: 1u32.into(), - no_show_slots: 1u32.into(), - validation_upgrade_frequency: Default::default(), - validation_upgrade_delay: Default::default(), - code_retention_period: Default::default(), - max_code_size: Default::default(), - max_pov_size: Default::default(), - max_head_data_size: Default::default(), - parathread_cores: Default::default(), - parathread_retries: Default::default(), - scheduling_lookahead: Default::default(), - max_validators_per_core: Default::default(), - max_validators: None, - dispute_period: 6, - dispute_post_conclusion_acceptance_period: 100.into(), - dispute_max_spam_slots: 2, - dispute_conclusion_by_time_out_period: 200.into(), - n_delay_tranches: Default::default(), - zeroth_delay_tranche_width: Default::default(), - needed_approvals: Default::default(), - relay_vrf_modulo_samples: Default::default(), - max_upward_queue_count: Default::default(), - max_upward_queue_size: Default::default(), - max_downward_message_size: Default::default(), - ump_service_total_weight: Default::default(), - max_upward_message_size: Default::default(), - max_upward_message_num_per_candidate: Default::default(), - _hrmp_open_request_ttl: Default::default(), - hrmp_sender_deposit: Default::default(), - hrmp_recipient_deposit: Default::default(), - hrmp_channel_max_capacity: Default::default(), - hrmp_channel_max_total_size: Default::default(), - hrmp_max_parachain_inbound_channels: Default::default(), - hrmp_max_parathread_inbound_channels: Default::default(), - hrmp_channel_max_message_size: Default::default(), - hrmp_max_parachain_outbound_channels: Default::default(), - hrmp_max_parathread_outbound_channels: Default::default(), - hrmp_max_message_num_per_candidate: Default::default(), - } - } - } -} - -/// Migrates the `HostConfiguration` from v0 (with deprecated `hrmp_open_request_ttl` and without -/// `ump_max_individual_weight`) to v1 (without HRMP TTL and with max individual weight). -/// Uses the `Default` implementation of `HostConfiguration` to choose a value for `ump_max_individual_weight`. -/// -/// NOTE: Only use this function if you know what you are doing. Default to using `migrate_to_latest`. -pub fn migrate_to_v1() -> Weight { - // Unusual formatting is justified: - // - make it easier to verify that fields assign what they supposed to assign. - // - this code is transient and will be removed after all migrations are done. - // - this code is important enough to optimize for legibility sacrificing consistency. - #[rustfmt::skip] - let translate = - |pre: v0::HostConfiguration>| -> configuration::HostConfiguration> - { - super::HostConfiguration { - -max_code_size : pre.max_code_size, -max_head_data_size : pre.max_head_data_size, -max_upward_queue_count : pre.max_upward_queue_count, -max_upward_queue_size : pre.max_upward_queue_size, -max_upward_message_size : pre.max_upward_message_size, -max_upward_message_num_per_candidate : pre.max_upward_message_num_per_candidate, -hrmp_max_message_num_per_candidate : pre.hrmp_max_message_num_per_candidate, -validation_upgrade_frequency : pre.validation_upgrade_frequency, -validation_upgrade_delay : pre.validation_upgrade_delay, -max_pov_size : pre.max_pov_size, -max_downward_message_size : pre.max_downward_message_size, -ump_service_total_weight : pre.ump_service_total_weight, -hrmp_max_parachain_outbound_channels : pre.hrmp_max_parachain_outbound_channels, -hrmp_max_parathread_outbound_channels : pre.hrmp_max_parathread_outbound_channels, -hrmp_sender_deposit : pre.hrmp_sender_deposit, -hrmp_recipient_deposit : pre.hrmp_recipient_deposit, -hrmp_channel_max_capacity : pre.hrmp_channel_max_capacity, -hrmp_channel_max_total_size : pre.hrmp_channel_max_total_size, -hrmp_max_parachain_inbound_channels : pre.hrmp_max_parachain_inbound_channels, -hrmp_max_parathread_inbound_channels : pre.hrmp_max_parathread_inbound_channels, -hrmp_channel_max_message_size : pre.hrmp_channel_max_message_size, -code_retention_period : pre.code_retention_period, -parathread_cores : pre.parathread_cores, -parathread_retries : pre.parathread_retries, -group_rotation_frequency : pre.group_rotation_frequency, -chain_availability_period : pre.chain_availability_period, -thread_availability_period : pre.thread_availability_period, -scheduling_lookahead : pre.scheduling_lookahead, -max_validators_per_core : pre.max_validators_per_core, -max_validators : pre.max_validators, -dispute_period : pre.dispute_period, -dispute_post_conclusion_acceptance_period: pre.dispute_post_conclusion_acceptance_period, -dispute_max_spam_slots : pre.dispute_max_spam_slots, -dispute_conclusion_by_time_out_period : pre.dispute_conclusion_by_time_out_period, -no_show_slots : pre.no_show_slots, -n_delay_tranches : pre.n_delay_tranches, -zeroth_delay_tranche_width : pre.zeroth_delay_tranche_width, -needed_approvals : pre.needed_approvals, -relay_vrf_modulo_samples : pre.relay_vrf_modulo_samples, - -ump_max_individual_weight: >>::default().ump_max_individual_weight, - } - }; - - if let Err(_) = as Store>::ActiveConfig::translate(|pre| pre.map(translate)) { - // `Err` is returned when the pre-migration type cannot be deserialized. This - // cannot happen if the migration runs correctly, i.e. against the expected version. - // - // This happening almost surely will lead to a panic somewhere else. Corruption seems - // to be unlikely to be caused by this. So we just log. Maybe it'll work out still? - log::error!( - target: configuration::LOG_TARGET, - "unexpected error when performing translation of the configuration type during storage upgrade to v1." - ); - } - - T::DbWeight::get().reads_writes(1, 1) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::mock::{new_test_ext, Test}; - - #[test] - fn v0_deserialized_from_actual_data() { - // Fetched at Kusama 9,207,703 (0xbfe5227324c08b3ab67e0473a360acbce43efbd7b42041d0033adaf9ff2c5330) - // - // This exceeds the maximal line width length, but that's fine, since this is not code and - // doesn't need to be read and also leaving it as one line allows to easily copy it. - let raw_config = hex_literal::hex!["0000a000005000000a00000000c8000000c800000a0000000a00000040380000580200000000500000c8000000e87648170000000a0000000000000048000000c09e5d9a2f3d00000000000000000000c09e5d9a2f3d00000000000000000000e8030000009001000a00000000000000009001008070000000000000000000000a0000000a0000000a00000001000000010500000001c8000000060000005802000002000000580200000200000059000000000000001e00000028000000"]; - - let v0 = v0::HostConfiguration::::decode(&mut &raw_config[..]) - .unwrap(); - - // We check only a sample of the values here. If we missed any fields or messed up data types - // that would skew all the fields coming after. - assert_eq!(v0.max_code_size, 10_485_760); - assert_eq!(v0.validation_upgrade_frequency, 14_400); - assert_eq!(v0.max_pov_size, 5_242_880); - assert_eq!(v0._hrmp_open_request_ttl, 72); - assert_eq!(v0.hrmp_channel_max_message_size, 102_400); - assert_eq!(v0.dispute_max_spam_slots, 2); - assert_eq!(v0.n_delay_tranches, 89); - assert_eq!(v0.relay_vrf_modulo_samples, 40); - } - - #[test] - fn test_migrate_to_v1() { - // Host configuration has lots of fields. However, in this migration we add one and remove one - // field. The most important part to check are a couple of the last fields. We also pick - // extra fields to check arbitrarily, e.g. depending on their position (i.e. the middle) and - // also their type. - // - // We specify only the picked fields and the rest should be provided by the `Default` - // implementation. That implementation is copied over between the two types and should work - // fine. - let v0 = v0::HostConfiguration:: { - relay_vrf_modulo_samples: 0xFEEDBEEFu32, - needed_approvals: 69, - thread_availability_period: 55, - hrmp_recipient_deposit: 1337, - max_pov_size: 1111, - ..Default::default() - }; - - new_test_ext(Default::default()).execute_with(|| { - // Implant the v0 version in the state. - frame_support::storage::unhashed::put_raw( - &configuration::ActiveConfig::::hashed_key(), - &v0.encode(), - ); - - migrate_to_v1::(); - - let v1 = configuration::ActiveConfig::::get(); - - // The same motivation as for the migration code. See `migrate_to_v1`. - #[rustfmt::skip] - { - assert_eq!(v0.max_code_size , v1.max_code_size); - assert_eq!(v0.max_head_data_size , v1.max_head_data_size); - assert_eq!(v0.max_upward_queue_count , v1.max_upward_queue_count); - assert_eq!(v0.max_upward_queue_size , v1.max_upward_queue_size); - assert_eq!(v0.max_upward_message_size , v1.max_upward_message_size); - assert_eq!(v0.max_upward_message_num_per_candidate , v1.max_upward_message_num_per_candidate); - assert_eq!(v0.hrmp_max_message_num_per_candidate , v1.hrmp_max_message_num_per_candidate); - assert_eq!(v0.validation_upgrade_frequency , v1.validation_upgrade_frequency); - assert_eq!(v0.validation_upgrade_delay , v1.validation_upgrade_delay); - assert_eq!(v0.max_pov_size , v1.max_pov_size); - assert_eq!(v0.max_downward_message_size , v1.max_downward_message_size); - assert_eq!(v0.ump_service_total_weight , v1.ump_service_total_weight); - assert_eq!(v0.hrmp_max_parachain_outbound_channels , v1.hrmp_max_parachain_outbound_channels); - assert_eq!(v0.hrmp_max_parathread_outbound_channels , v1.hrmp_max_parathread_outbound_channels); - assert_eq!(v0.hrmp_sender_deposit , v1.hrmp_sender_deposit); - assert_eq!(v0.hrmp_recipient_deposit , v1.hrmp_recipient_deposit); - assert_eq!(v0.hrmp_channel_max_capacity , v1.hrmp_channel_max_capacity); - assert_eq!(v0.hrmp_channel_max_total_size , v1.hrmp_channel_max_total_size); - assert_eq!(v0.hrmp_max_parachain_inbound_channels , v1.hrmp_max_parachain_inbound_channels); - assert_eq!(v0.hrmp_max_parathread_inbound_channels , v1.hrmp_max_parathread_inbound_channels); - assert_eq!(v0.hrmp_channel_max_message_size , v1.hrmp_channel_max_message_size); - assert_eq!(v0.code_retention_period , v1.code_retention_period); - assert_eq!(v0.parathread_cores , v1.parathread_cores); - assert_eq!(v0.parathread_retries , v1.parathread_retries); - assert_eq!(v0.group_rotation_frequency , v1.group_rotation_frequency); - assert_eq!(v0.chain_availability_period , v1.chain_availability_period); - assert_eq!(v0.thread_availability_period , v1.thread_availability_period); - assert_eq!(v0.scheduling_lookahead , v1.scheduling_lookahead); - assert_eq!(v0.max_validators_per_core , v1.max_validators_per_core); - assert_eq!(v0.max_validators , v1.max_validators); - assert_eq!(v0.dispute_period , v1.dispute_period); - assert_eq!(v0.dispute_post_conclusion_acceptance_period, v1.dispute_post_conclusion_acceptance_period); - assert_eq!(v0.dispute_max_spam_slots , v1.dispute_max_spam_slots); - assert_eq!(v0.dispute_conclusion_by_time_out_period , v1.dispute_conclusion_by_time_out_period); - assert_eq!(v0.no_show_slots , v1.no_show_slots); - assert_eq!(v0.n_delay_tranches , v1.n_delay_tranches); - assert_eq!(v0.zeroth_delay_tranche_width , v1.zeroth_delay_tranche_width); - assert_eq!(v0.needed_approvals , v1.needed_approvals); - assert_eq!(v0.relay_vrf_modulo_samples , v1.relay_vrf_modulo_samples); - - assert_eq!(v1.ump_max_individual_weight, 20_000_000_000); - }; // ; makes this a statement. `rustfmt::skip` cannot be put on an expression. - }); - } + 0 } diff --git a/runtime/polkadot/src/lib.rs b/runtime/polkadot/src/lib.rs index e57f4564e7a2..ec783693708e 100644 --- a/runtime/polkadot/src/lib.rs +++ b/runtime/polkadot/src/lib.rs @@ -1546,6 +1546,26 @@ impl OnRuntimeUpgrade for SetInitialHostConfiguration { Configuration::force_set_active_config(active_config); } + { + // At the moment, the `parachains_configuration` crate has already had one runtime + // storage migration (performed as part of [#3575]). As the result a call to + // `StorageVersion::get::` will return `Some(1)` + // + // However, Polkadot is just about to have its first version of parachains runtime + // pallets and thus there is no existing storage which needs to be migrated. Above + // we just have set the active configuration of the actual version, i.e. the same as the + // version 1 on Kusama. + // + // The caveat here is when we deploy a module for the first time, it's runtime version + // will be empty and thus it will be considered as version 0. Since we want to avoid + // the situation where the same storage structure has version 0 on Polkadot and + // version 1 on Kusama we need to set the storage version explicitly. + // + // [#3575]: https://github.com/paritytech/polkadot/pull/3575 + use frame_support::traits::StorageVersion; + StorageVersion::new(1).put::(); + } + RocksDbWeight::get().reads(1) + RocksDbWeight::get().writes(1) } }