From f1fb358193fb9e261ee08dc60a9b606b30479865 Mon Sep 17 00:00:00 2001 From: s0me0ne-unkn0wn <48632512+s0me0ne-unkn0wn@users.noreply.github.com> Date: Fri, 1 Mar 2024 00:15:35 +0100 Subject: [PATCH] Remove `im-online` pallet from Kusama and Polkadot runtimes (#178) # Summary This PR aims to remove `im-online` pallet, its session keys, and its on-chain storage from both Kusama and Polkadot relay chain runtimes, thus giving up liveness slashing. # Motivation * Missing out on rewards because of being offline is enough disincentive for validators. Slashing them for being offline is redundant. * Disabling liveness slashing is a prerequisite for validator disabling. # See also paritytech/polkadot-sdk#1964 paritytech/polkadot-sdk#784 --- CHANGELOG.md | 1 + Cargo.lock | 3 - chain-spec-generator/Cargo.toml | 1 - chain-spec-generator/src/relay_chain_specs.rs | 24 +-- .../emulated/chains/relays/kusama/Cargo.toml | 1 - .../chains/relays/kusama/src/genesis.rs | 6 - .../chains/relays/polkadot/Cargo.toml | 1 - .../chains/relays/polkadot/src/genesis.rs | 6 - relay/kusama/src/lib.rs | 174 +++++++++++++++--- relay/kusama/src/weights/mod.rs | 1 - relay/kusama/src/weights/pallet_im_online.rs | 78 -------- relay/polkadot/src/lib.rs | 166 ++++++++++++++--- relay/polkadot/src/weights/mod.rs | 1 - .../polkadot/src/weights/pallet_im_online.rs | 78 -------- 14 files changed, 294 insertions(+), 247 deletions(-) delete mode 100644 relay/kusama/src/weights/pallet_im_online.rs delete mode 100644 relay/polkadot/src/weights/pallet_im_online.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index ec51af649a..b85931cf27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Removed - Removed the `SafeCallFilter` from the Relay Chain XCM config ([polkadot-fellows/runtimes#172](https://github.com/polkadot-fellows/runtimes/pull/172)). +- Removed the `ImOnline` pallet ([polkadot-fellows/runtimes#178](https://github.com/polkadot-fellows/runtimes/pull/178)) ### Based on Polkadot-SDK diff --git a/Cargo.lock b/Cargo.lock index 4d0a464a0f..adda6b521d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1861,7 +1861,6 @@ dependencies = [ "encointer-kusama-runtime", "glutton-kusama-runtime", "kusama-runtime-constants", - "pallet-im-online", "pallet-staking", "parachains-common", "polkadot-primitives", @@ -5044,7 +5043,6 @@ version = "1.0.0" dependencies = [ "emulated-integration-tests-common", "kusama-runtime-constants", - "pallet-im-online", "parachains-common", "polkadot-primitives", "sc-consensus-grandpa", @@ -8735,7 +8733,6 @@ name = "polkadot-emulated-chain" version = "1.0.0" dependencies = [ "emulated-integration-tests-common", - "pallet-im-online", "pallet-staking", "parachains-common", "polkadot-primitives", diff --git a/chain-spec-generator/Cargo.toml b/chain-spec-generator/Cargo.toml index bfb49761fa..c77b78670a 100644 --- a/chain-spec-generator/Cargo.toml +++ b/chain-spec-generator/Cargo.toml @@ -24,7 +24,6 @@ sp-authority-discovery = "26.0.0" sp-core = "28.0.0" pallet-staking = "28.0.0" sc-consensus-grandpa = "0.19.0" -pallet-im-online = "27.0.0" sp-runtime = "31.0.1" sp-consensus-beefy = "13.0.0" xcm = { package = "staging-xcm", version = "7.0.0" } diff --git a/chain-spec-generator/src/relay_chain_specs.rs b/chain-spec-generator/src/relay_chain_specs.rs index 075c965762..3fb70efdd0 100644 --- a/chain-spec-generator/src/relay_chain_specs.rs +++ b/chain-spec-generator/src/relay_chain_specs.rs @@ -16,7 +16,6 @@ // along with Polkadot. If not, see . use kusama_runtime_constants::currency::UNITS as KSM; -use pallet_im_online::sr25519::AuthorityId as ImOnlineId; use pallet_staking::Forcing; use polkadot_primitives::{AccountId, AccountPublic, AssignmentId, ValidatorId}; use polkadot_runtime_constants::currency::UNITS as DOT; @@ -84,7 +83,6 @@ fn default_parachains_host_configuration() -> HostConfiguration(seed)) + (keys.0, keys.1, keys.2, keys.3, keys.4, keys.5, keys.6, get_from_seed::(seed)) } /// Helper function to generate stash, controller and session key from seed pub fn get_authority_keys_from_seed_no_beefy( seed: &str, -) -> ( - AccountId, - AccountId, - BabeId, - GrandpaId, - ImOnlineId, - ValidatorId, - AssignmentId, - AuthorityDiscoveryId, -) { +) -> (AccountId, AccountId, BabeId, GrandpaId, ValidatorId, AssignmentId, AuthorityDiscoveryId) { ( get_account_id_from_seed::(&format!("{}//stash", seed)), get_account_id_from_seed::(seed), get_from_seed::(seed), get_from_seed::(seed), - get_from_seed::(seed), get_from_seed::(seed), get_from_seed::(seed), get_from_seed::(seed), @@ -202,7 +186,6 @@ pub fn polkadot_testnet_genesis( AccountId, BabeId, GrandpaId, - ImOnlineId, ValidatorId, AssignmentId, AuthorityDiscoveryId, @@ -234,7 +217,6 @@ pub fn polkadot_testnet_genesis( x.5.clone(), x.6.clone(), x.7.clone(), - x.8.clone(), ), ) }) @@ -266,7 +248,6 @@ pub fn kusama_testnet_genesis( AccountId, BabeId, GrandpaId, - ImOnlineId, ValidatorId, AssignmentId, AuthorityDiscoveryId, @@ -298,7 +279,6 @@ pub fn kusama_testnet_genesis( x.5.clone(), x.6.clone(), x.7.clone(), - x.8.clone(), ), ) }) diff --git a/integration-tests/emulated/chains/relays/kusama/Cargo.toml b/integration-tests/emulated/chains/relays/kusama/Cargo.toml index 79040a6c8a..d3933eef4e 100644 --- a/integration-tests/emulated/chains/relays/kusama/Cargo.toml +++ b/integration-tests/emulated/chains/relays/kusama/Cargo.toml @@ -17,7 +17,6 @@ authority-discovery-primitives = { package = "sp-authority-discovery", version = babe-primitives = { package = "sp-consensus-babe", version = "0.32.0" } beefy-primitives = { package = "sp-consensus-beefy", version = "13.0.0" } grandpa = { package = "sc-consensus-grandpa", version = "0.19.0" } -pallet-im-online = { version = "27.0.0" } # Polkadot polkadot-primitives = { version = "7.0.0" } diff --git a/integration-tests/emulated/chains/relays/kusama/src/genesis.rs b/integration-tests/emulated/chains/relays/kusama/src/genesis.rs index ca1b016511..df7b002dde 100644 --- a/integration-tests/emulated/chains/relays/kusama/src/genesis.rs +++ b/integration-tests/emulated/chains/relays/kusama/src/genesis.rs @@ -18,7 +18,6 @@ use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId; use babe_primitives::AuthorityId as BabeId; use beefy_primitives::ecdsa_crypto::AuthorityId as BeefyId; use grandpa::AuthorityId as GrandpaId; -use pallet_im_online::sr25519::AuthorityId as ImOnlineId; use sp_core::{sr25519, storage::Storage}; // Polkadot @@ -43,7 +42,6 @@ mod validators { AccountId, BabeId, GrandpaId, - ImOnlineId, ValidatorId, AssignmentId, AuthorityDiscoveryId, @@ -55,7 +53,6 @@ mod validators { get_account_id_from_seed::(seed), get_from_seed::(seed), get_from_seed::(seed), - get_from_seed::(seed), get_from_seed::(seed), get_from_seed::(seed), get_from_seed::(seed), @@ -67,7 +64,6 @@ mod validators { fn session_keys( babe: BabeId, grandpa: GrandpaId, - im_online: ImOnlineId, para_validator: ValidatorId, para_assignment: AssignmentId, authority_discovery: AuthorityDiscoveryId, @@ -76,7 +72,6 @@ fn session_keys( kusama_runtime::SessionKeys { grandpa, babe, - im_online, para_validator, para_assignment, authority_discovery, @@ -104,7 +99,6 @@ pub fn genesis() -> Storage { x.5.clone(), x.6.clone(), x.7.clone(), - x.8.clone(), ), ) }) diff --git a/integration-tests/emulated/chains/relays/polkadot/Cargo.toml b/integration-tests/emulated/chains/relays/polkadot/Cargo.toml index a161064a15..3780db0b32 100644 --- a/integration-tests/emulated/chains/relays/polkadot/Cargo.toml +++ b/integration-tests/emulated/chains/relays/polkadot/Cargo.toml @@ -17,7 +17,6 @@ authority-discovery-primitives = { package = "sp-authority-discovery", version = babe-primitives = { package = "sp-consensus-babe", version = "0.32.0" } beefy-primitives = { package = "sp-consensus-beefy", version = "13.0.0" } grandpa = { package = "sc-consensus-grandpa", version = "0.19.0" } -pallet-im-online = { version = "27.0.0" } pallet-staking = { version = "28.0.0" } # Polkadot diff --git a/integration-tests/emulated/chains/relays/polkadot/src/genesis.rs b/integration-tests/emulated/chains/relays/polkadot/src/genesis.rs index 6697aa2bad..cb054a5033 100644 --- a/integration-tests/emulated/chains/relays/polkadot/src/genesis.rs +++ b/integration-tests/emulated/chains/relays/polkadot/src/genesis.rs @@ -18,7 +18,6 @@ use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId; use babe_primitives::AuthorityId as BabeId; use beefy_primitives::ecdsa_crypto::AuthorityId as BeefyId; use grandpa::AuthorityId as GrandpaId; -use pallet_im_online::sr25519::AuthorityId as ImOnlineId; use sp_core::{sr25519, storage::Storage}; use sp_runtime::Perbill; @@ -45,7 +44,6 @@ mod validators { AccountId, BabeId, GrandpaId, - ImOnlineId, ValidatorId, AssignmentId, AuthorityDiscoveryId, @@ -57,7 +55,6 @@ mod validators { get_account_id_from_seed::(seed), get_from_seed::(seed), get_from_seed::(seed), - get_from_seed::(seed), get_from_seed::(seed), get_from_seed::(seed), get_from_seed::(seed), @@ -69,7 +66,6 @@ mod validators { fn session_keys( babe: BabeId, grandpa: GrandpaId, - im_online: ImOnlineId, para_validator: ValidatorId, para_assignment: AssignmentId, authority_discovery: AuthorityDiscoveryId, @@ -78,7 +74,6 @@ fn session_keys( polkadot_runtime::SessionKeys { babe, grandpa, - im_online, para_validator, para_assignment, authority_discovery, @@ -106,7 +101,6 @@ pub fn genesis() -> Storage { x.5.clone(), x.6.clone(), x.7.clone(), - x.8.clone(), ), ) }) diff --git a/relay/kusama/src/lib.rs b/relay/kusama/src/lib.rs index d76e764dc7..1a5e6ced2f 100644 --- a/relay/kusama/src/lib.rs +++ b/relay/kusama/src/lib.rs @@ -86,7 +86,6 @@ use frame_support::{ use frame_system::EnsureRoot; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId}; use pallet_identity::legacy::IdentityInfo; -use pallet_im_online::sr25519::AuthorityId as ImOnlineId; use pallet_session::historical as session_historical; use pallet_transaction_payment::{CurrencyAdapter, FeeDetails, RuntimeDispatchInfo}; use sp_core::{ConstU128, OpaqueMetadata, H256}; @@ -97,7 +96,8 @@ use sp_runtime::{ IdentityLookup, Keccak256, OpaqueKeys, SaturatedConversion, Verify, }, transaction_validity::{TransactionPriority, TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, FixedU128, KeyTypeId, Perbill, Percent, Permill, RuntimeDebug, + ApplyExtrinsicResult, BoundToRuntimeAppPublic, FixedU128, KeyTypeId, Perbill, Percent, Permill, + RuntimeAppPublic, RuntimeDebug, }; use sp_staking::SessionIndex; #[cfg(any(feature = "std", test))] @@ -158,7 +158,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("kusama"), impl_name: create_runtime_str!("parity-kusama"), authoring_version: 2, - spec_version: 1_001_000, + spec_version: 1_002_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 25, @@ -440,14 +440,53 @@ impl pallet_timestamp::Config for Runtime { impl pallet_authorship::Config for Runtime { type FindAuthor = pallet_session::FindAccountFromAuthorIndex; - type EventHandler = (Staking, ImOnline); + type EventHandler = Staking; +} + +#[derive(Clone, Debug, PartialEq, Eq, Encode, Decode)] +pub struct OldSessionKeys { + pub grandpa: ::Public, + pub babe: ::Public, + pub im_online: pallet_im_online::sr25519::AuthorityId, + pub para_validator: ::Public, + pub para_assignment: ::Public, + pub authority_discovery: ::Public, + pub beefy: ::Public, +} + +impl OpaqueKeys for OldSessionKeys { + type KeyTypeIdProviders = (); + fn key_ids() -> &'static [KeyTypeId] { + &[ + <::Public>::ID, + <::Public>::ID, + sp_core::crypto::key_types::IM_ONLINE, + <::Public>::ID, + <::Public>::ID, + <::Public>::ID, + <::Public>::ID, + ] + } + fn get_raw(&self, i: KeyTypeId) -> &[u8] { + match i { + <::Public>::ID => self.grandpa.as_ref(), + <::Public>::ID => self.babe.as_ref(), + sp_core::crypto::key_types::IM_ONLINE => self.im_online.as_ref(), + <::Public>::ID => self.para_validator.as_ref(), + <::Public>::ID => + self.para_assignment.as_ref(), + <::Public>::ID => + self.authority_discovery.as_ref(), + <::Public>::ID => self.beefy.as_ref(), + _ => &[], + } + } } impl_opaque_keys! { pub struct SessionKeys { pub grandpa: Grandpa, pub babe: Babe, - pub im_online: ImOnline, pub para_validator: Initializer, pub para_assignment: ParaSessionInfo, pub authority_discovery: AuthorityDiscovery, @@ -455,6 +494,18 @@ impl_opaque_keys! { } } +// remove this when removing `OldSessionKeys` +fn transform_session_keys(_val: AccountId, old: OldSessionKeys) -> SessionKeys { + SessionKeys { + grandpa: old.grandpa, + babe: old.babe, + para_validator: old.para_validator, + para_assignment: old.para_assignment, + authority_discovery: old.authority_discovery, + beefy: old.beefy, + } +} + impl pallet_session::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ValidatorId = AccountId; @@ -813,22 +864,6 @@ impl pallet_authority_discovery::Config for Runtime { type MaxAuthorities = MaxAuthorities; } -parameter_types! { - pub const ImOnlineUnsignedPriority: TransactionPriority = TransactionPriority::max_value(); -} - -impl pallet_im_online::Config for Runtime { - type AuthorityId = ImOnlineId; - type RuntimeEvent = RuntimeEvent; - type ValidatorSet = Historical; - type NextSessionRotation = Babe; - type ReportUnresponsiveness = Offences; - type UnsignedPriority = ImOnlineUnsignedPriority; - type WeightInfo = weights::pallet_im_online::WeightInfo; - type MaxKeys = MaxKeys; - type MaxPeerInHeartbeats = MaxPeerInHeartbeats; -} - parameter_types! { pub MaxSetIdSessionEntries: u32 = BondingDuration::get() * SessionsPerEra::get(); } @@ -1092,7 +1127,6 @@ impl InstanceFilter for ProxyType { RuntimeCall::Staking(..) | RuntimeCall::Session(..) | RuntimeCall::Grandpa(..) | - RuntimeCall::ImOnline(..) | RuntimeCall::Treasury(..) | RuntimeCall::Bounties(..) | RuntimeCall::ChildBounties(..) | @@ -1564,7 +1598,6 @@ construct_runtime! { Session: pallet_session = 8, Grandpa: pallet_grandpa = 10, - ImOnline: pallet_im_online = 11, AuthorityDiscovery: pallet_authority_discovery = 12, // Governance stuff. @@ -1711,10 +1744,9 @@ pub type Migrations = migrations::Unreleased; /// The runtime migrations per release. #[allow(deprecated, missing_docs)] pub mod migrations { - use super::{ - coretime, parachains_configuration, parachains_scheduler, slots, BlockNumber, LeasePeriod, - Leaser, ParaId, Runtime, - }; + use super::*; + #[cfg(feature = "try-runtime")] + use sp_core::crypto::ByteArray; // We don't have a limit in the Relay Chain. const IDENTITY_MIGRATION_KEY_LIMIT: u64 = u64::MAX; @@ -1737,6 +1769,86 @@ pub mod migrations { } } + parameter_types! { + pub const ImOnlinePalletName: &'static str = "ImOnline"; + } + + /// Upgrade Session keys to exclude `ImOnline` key. + /// When this is removed, should also remove `OldSessionKeys`. + pub struct UpgradeSessionKeys; + const UPGRADE_SESSION_KEYS_FROM_SPEC: u32 = 1001002; + + impl frame_support::traits::OnRuntimeUpgrade for UpgradeSessionKeys { + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, sp_runtime::TryRuntimeError> { + if System::last_runtime_upgrade_spec_version() > UPGRADE_SESSION_KEYS_FROM_SPEC { + log::warn!(target: "runtime::session_keys", "Skipping session keys migration pre-upgrade check due to spec version (already applied?)"); + return Ok(Vec::new()) + } + + log::info!(target: "runtime::session_keys", "Collecting pre-upgrade session keys state"); + let key_ids = SessionKeys::key_ids(); + frame_support::ensure!( + key_ids + .into_iter() + .find(|&k| *k == sp_core::crypto::key_types::IM_ONLINE) + .is_none(), + "New session keys contain the ImOnline key that should have been removed", + ); + let storage_key = pallet_session::QueuedKeys::::hashed_key(); + let mut state: Vec = Vec::new(); + frame_support::storage::unhashed::get::>( + &storage_key, + ) + .ok_or::("Queued keys are not available".into())? + .into_iter() + .for_each(|(id, keys)| { + state.extend_from_slice(id.as_slice()); + for key_id in key_ids { + state.extend_from_slice(keys.get_raw(*key_id)); + } + }); + frame_support::ensure!(state.len() > 0, "Queued keys are not empty before upgrade"); + Ok(state) + } + + fn on_runtime_upgrade() -> Weight { + if System::last_runtime_upgrade_spec_version() > UPGRADE_SESSION_KEYS_FROM_SPEC { + log::info!("Skipping session keys upgrade: already applied"); + return ::DbWeight::get().reads(1) + } + log::trace!("Upgrading session keys"); + Session::upgrade_keys::(transform_session_keys); + Perbill::from_percent(50) * BlockWeights::get().max_block + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade( + old_state: sp_std::vec::Vec, + ) -> Result<(), sp_runtime::TryRuntimeError> { + if System::last_runtime_upgrade_spec_version() > UPGRADE_SESSION_KEYS_FROM_SPEC { + log::warn!(target: "runtime::session_keys", "Skipping session keys migration post-upgrade check due to spec version (already applied?)"); + return Ok(()) + } + + let key_ids = SessionKeys::key_ids(); + let mut new_state: Vec = Vec::new(); + pallet_session::QueuedKeys::::get().into_iter().for_each(|(id, keys)| { + new_state.extend_from_slice(id.as_slice()); + for key_id in key_ids { + new_state.extend_from_slice(keys.get_raw(*key_id)); + } + }); + frame_support::ensure!(new_state.len() > 0, "Queued keys are not empty after upgrade"); + frame_support::ensure!( + old_state == new_state, + "Pre-upgrade and post-upgrade keys do not match!" + ); + log::info!(target: "runtime::session_keys", "Session keys migrated successfully"); + Ok(()) + } + } + /// Unreleased migrations. Add new ones here: pub type Unreleased = ( pallet_nomination_pools::migration::versioned::V7ToV8, @@ -1753,6 +1865,13 @@ pub mod migrations { crate::xcm_config::XcmRouter, GetLegacyLeaseImpl, >, + // Upgrade `SessionKeys` to exclude `ImOnline` + UpgradeSessionKeys, + // Remove `im-online` pallet on-chain storage + frame_support::migrations::RemovePallet< + ImOnlinePalletName, + ::DbWeight, + >, ); } @@ -1805,7 +1924,6 @@ mod benches { [pallet_fast_unstake, FastUnstake] [pallet_nis, Nis] [pallet_identity, Identity] - [pallet_im_online, ImOnline] [pallet_indices, Indices] [pallet_message_queue, MessageQueue] [pallet_multisig, Multisig] diff --git a/relay/kusama/src/weights/mod.rs b/relay/kusama/src/weights/mod.rs index 94f14c40da..8e68ad27da 100644 --- a/relay/kusama/src/weights/mod.rs +++ b/relay/kusama/src/weights/mod.rs @@ -27,7 +27,6 @@ pub mod pallet_conviction_voting; pub mod pallet_election_provider_multi_phase; pub mod pallet_fast_unstake; pub mod pallet_identity; -pub mod pallet_im_online; pub mod pallet_indices; pub mod pallet_message_queue; pub mod pallet_multisig; diff --git a/relay/kusama/src/weights/pallet_im_online.rs b/relay/kusama/src/weights/pallet_im_online.rs deleted file mode 100644 index 5db95d66f6..0000000000 --- a/relay/kusama/src/weights/pallet_im_online.rs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Polkadot is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see . - -//! Autogenerated weights for `pallet_im_online` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `ggwpez-ref-hw`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("../kusama-chain-spec.json")`, DB CACHE: 1024 - -// Executed Command: -// ./target/production/polkadot -// benchmark -// pallet -// --chain=../kusama-chain-spec.json -// --steps -// 50 -// --repeat -// 20 -// --pallet=pallet_im_online -// --extrinsic=* -// --wasm-execution=compiled -// --heap-pages=4096 -// --output -// ./kusama-weights/ -// --header -// ./file_header.txt - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] - -use frame_support::{traits::Get, weights::Weight}; -use core::marker::PhantomData; - -/// Weight functions for `pallet_im_online`. -pub struct WeightInfo(PhantomData); -impl pallet_im_online::WeightInfo for WeightInfo { - /// Storage: `Session::Validators` (r:1 w:0) - /// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Session::CurrentIndex` (r:1 w:0) - /// Proof: `Session::CurrentIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ImOnline::Keys` (r:1 w:0) - /// Proof: `ImOnline::Keys` (`max_values`: Some(1), `max_size`: Some(320002), added: 320497, mode: `MaxEncodedLen`) - /// Storage: `ImOnline::ReceivedHeartbeats` (r:1 w:1) - /// Proof: `ImOnline::ReceivedHeartbeats` (`max_values`: None, `max_size`: Some(25), added: 2500, mode: `MaxEncodedLen`) - /// Storage: `ImOnline::AuthoredBlocks` (r:1 w:0) - /// Proof: `ImOnline::AuthoredBlocks` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) - /// The range of component `k` is `[1, 1000]`. - fn validate_unsigned_and_then_heartbeat(k: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `559 + k * (32 ±0)` - // Estimated: `321487 + k * (1761 ±0)` - // Minimum execution time: 79_478_000 picoseconds. - Weight::from_parts(98_448_476, 0) - .saturating_add(Weight::from_parts(0, 321487)) - // Standard Error: 667 - .saturating_add(Weight::from_parts(37_721, 0).saturating_mul(k.into())) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(1)) - .saturating_add(Weight::from_parts(0, 1761).saturating_mul(k.into())) - } -} diff --git a/relay/polkadot/src/lib.rs b/relay/polkadot/src/lib.rs index 6ff280ba8e..41ef405a89 100644 --- a/relay/polkadot/src/lib.rs +++ b/relay/polkadot/src/lib.rs @@ -67,7 +67,6 @@ use frame_support::{ use frame_system::EnsureRoot; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId}; use pallet_identity::legacy::IdentityInfo; -use pallet_im_online::sr25519::AuthorityId as ImOnlineId; use pallet_session::historical as session_historical; use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo}; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; @@ -89,7 +88,8 @@ use sp_runtime::{ IdentityLookup, Keccak256, OpaqueKeys, SaturatedConversion, Verify, }, transaction_validity::{TransactionPriority, TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, FixedU128, KeyTypeId, Perbill, Percent, Permill, RuntimeDebug, + ApplyExtrinsicResult, BoundToRuntimeAppPublic, FixedU128, KeyTypeId, Perbill, Percent, Permill, + RuntimeAppPublic, RuntimeDebug, }; use sp_staking::SessionIndex; use sp_std::{cmp::Ordering, collections::btree_map::BTreeMap, prelude::*}; @@ -144,7 +144,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("polkadot"), impl_name: create_runtime_str!("parity-polkadot"), authoring_version: 0, - spec_version: 1_001_000, + spec_version: 1_002_000, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 25, @@ -427,14 +427,53 @@ impl pallet_timestamp::Config for Runtime { impl pallet_authorship::Config for Runtime { type FindAuthor = pallet_session::FindAccountFromAuthorIndex; - type EventHandler = (Staking, ImOnline); + type EventHandler = Staking; +} + +#[derive(Clone, Debug, PartialEq, Eq, Encode, Decode)] +pub struct OldSessionKeys { + pub grandpa: ::Public, + pub babe: ::Public, + pub im_online: pallet_im_online::sr25519::AuthorityId, + pub para_validator: ::Public, + pub para_assignment: ::Public, + pub authority_discovery: ::Public, + pub beefy: ::Public, +} + +impl OpaqueKeys for OldSessionKeys { + type KeyTypeIdProviders = (); + fn key_ids() -> &'static [KeyTypeId] { + &[ + <::Public>::ID, + <::Public>::ID, + sp_core::crypto::key_types::IM_ONLINE, + <::Public>::ID, + <::Public>::ID, + <::Public>::ID, + <::Public>::ID, + ] + } + fn get_raw(&self, i: KeyTypeId) -> &[u8] { + match i { + <::Public>::ID => self.grandpa.as_ref(), + <::Public>::ID => self.babe.as_ref(), + sp_core::crypto::key_types::IM_ONLINE => self.im_online.as_ref(), + <::Public>::ID => self.para_validator.as_ref(), + <::Public>::ID => + self.para_assignment.as_ref(), + <::Public>::ID => + self.authority_discovery.as_ref(), + <::Public>::ID => self.beefy.as_ref(), + _ => &[], + } + } } impl_opaque_keys! { pub struct SessionKeys { pub grandpa: Grandpa, pub babe: Babe, - pub im_online: ImOnline, pub para_validator: Initializer, pub para_assignment: ParaSessionInfo, pub authority_discovery: AuthorityDiscovery, @@ -442,6 +481,18 @@ impl_opaque_keys! { } } +// remove this when removing `OldSessionKeys` +fn transform_session_keys(_v: AccountId, old: OldSessionKeys) -> SessionKeys { + SessionKeys { + grandpa: old.grandpa, + babe: old.babe, + para_validator: old.para_validator, + para_assignment: old.para_assignment, + authority_discovery: old.authority_discovery, + beefy: old.beefy, + } +} + impl pallet_session::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ValidatorId = AccountId; @@ -899,19 +950,6 @@ impl pallet_authority_discovery::Config for Runtime { parameter_types! { pub NposSolutionPriority: TransactionPriority = Perbill::from_percent(90) * TransactionPriority::max_value(); - pub const ImOnlineUnsignedPriority: TransactionPriority = TransactionPriority::max_value(); -} - -impl pallet_im_online::Config for Runtime { - type AuthorityId = ImOnlineId; - type RuntimeEvent = RuntimeEvent; - type ValidatorSet = Historical; - type NextSessionRotation = Babe; - type ReportUnresponsiveness = Offences; - type UnsignedPriority = ImOnlineUnsignedPriority; - type WeightInfo = weights::pallet_im_online::WeightInfo; - type MaxKeys = MaxKeys; - type MaxPeerInHeartbeats = MaxPeerInHeartbeats; } parameter_types! { @@ -1146,7 +1184,6 @@ impl InstanceFilter for ProxyType { RuntimeCall::Staking(..) | RuntimeCall::Session(..) | RuntimeCall::Grandpa(..) | - RuntimeCall::ImOnline(..) | RuntimeCall::Treasury(..) | RuntimeCall::Bounties(..) | RuntimeCall::ChildBounties(..) | @@ -1538,7 +1575,6 @@ construct_runtime! { Session: pallet_session = 9, Grandpa: pallet_grandpa = 11, - ImOnline: pallet_im_online = 12, AuthorityDiscovery: pallet_authority_discovery = 13, // OpenGov stuff. @@ -1661,12 +1697,96 @@ pub type Migrations = migrations::Unreleased; #[allow(deprecated, missing_docs)] pub mod migrations { use super::*; + #[cfg(feature = "try-runtime")] + use sp_core::crypto::ByteArray; + + parameter_types! { + pub const ImOnlinePalletName: &'static str = "ImOnline"; + } + + /// Upgrade Session keys to exclude `ImOnline` key. + /// When this is removed, should also remove `OldSessionKeys`. + pub struct UpgradeSessionKeys; + const UPGRADE_SESSION_KEYS_FROM_SPEC: u32 = 1001002; + + impl frame_support::traits::OnRuntimeUpgrade for UpgradeSessionKeys { + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, sp_runtime::TryRuntimeError> { + if System::last_runtime_upgrade_spec_version() > UPGRADE_SESSION_KEYS_FROM_SPEC { + log::warn!(target: "runtime::session_keys", "Skipping session keys migration pre-upgrade check due to spec version (already applied?)"); + return Ok(Vec::new()) + } + + log::info!(target: "runtime::session_keys", "Collecting pre-upgrade session keys state"); + let key_ids = SessionKeys::key_ids(); + frame_support::ensure!( + key_ids + .into_iter() + .find(|&k| *k == sp_core::crypto::key_types::IM_ONLINE) + .is_none(), + "New session keys contain the ImOnline key that should have been removed", + ); + let storage_key = pallet_session::QueuedKeys::::hashed_key(); + let mut state: Vec = Vec::new(); + frame_support::storage::unhashed::get::>( + &storage_key, + ) + .ok_or::("Queued keys are not available".into())? + .into_iter() + .for_each(|(id, keys)| { + state.extend_from_slice(id.as_slice()); + for key_id in key_ids { + state.extend_from_slice(keys.get_raw(*key_id)); + } + }); + frame_support::ensure!(state.len() > 0, "Queued keys are not empty before upgrade"); + Ok(state) + } + + fn on_runtime_upgrade() -> Weight { + if System::last_runtime_upgrade_spec_version() > UPGRADE_SESSION_KEYS_FROM_SPEC { + log::info!("Skipping session keys upgrade: already applied"); + return ::DbWeight::get().reads(1) + } + log::trace!("Upgrading session keys"); + Session::upgrade_keys::(transform_session_keys); + Perbill::from_percent(50) * BlockWeights::get().max_block + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade( + old_state: sp_std::vec::Vec, + ) -> Result<(), sp_runtime::TryRuntimeError> { + if System::last_runtime_upgrade_spec_version() > UPGRADE_SESSION_KEYS_FROM_SPEC { + log::warn!(target: "runtime::session_keys", "Skipping session keys migration post-upgrade check due to spec version (already applied?)"); + return Ok(()) + } + + let key_ids = SessionKeys::key_ids(); + let mut new_state: Vec = Vec::new(); + pallet_session::QueuedKeys::::get().into_iter().for_each(|(id, keys)| { + new_state.extend_from_slice(id.as_slice()); + for key_id in key_ids { + new_state.extend_from_slice(keys.get_raw(*key_id)); + } + }); + frame_support::ensure!(new_state.len() > 0, "Queued keys are not empty after upgrade"); + frame_support::ensure!( + old_state == new_state, + "Pre-upgrade and post-upgrade keys do not match!" + ); + log::info!(target: "runtime::session_keys", "Session keys migrated successfully"); + Ok(()) + } + } // We don't have a limit in the Relay Chain. const IDENTITY_MIGRATION_KEY_LIMIT: u64 = u64::MAX; /// Unreleased migrations. Add new ones here: pub type Unreleased = ( + // Upgrade SessionKeys to exclude ImOnline key + UpgradeSessionKeys, pallet_nomination_pools::migration::versioned::V7ToV8, pallet_staking::migrations::v14::MigrateToV14, parachains_configuration::migration::v10::MigrateToV10, @@ -1675,6 +1795,11 @@ pub mod migrations { // Migrate Identity pallet for Usernames pallet_identity::migration::versioned::V0ToV1, parachains_scheduler::migration::MigrateV1ToV2, + // Remove `im-online` pallet on-chain storage + frame_support::migrations::RemovePallet< + ImOnlinePalletName, + ::DbWeight, + >, ); } @@ -1723,7 +1848,6 @@ mod benches { [frame_election_provider_support, ElectionProviderBench::] [pallet_fast_unstake, FastUnstake] [pallet_identity, Identity] - [pallet_im_online, ImOnline] [pallet_indices, Indices] [pallet_message_queue, MessageQueue] [pallet_multisig, Multisig] diff --git a/relay/polkadot/src/weights/mod.rs b/relay/polkadot/src/weights/mod.rs index 2e5c22c55c..2b5daffde6 100644 --- a/relay/polkadot/src/weights/mod.rs +++ b/relay/polkadot/src/weights/mod.rs @@ -26,7 +26,6 @@ pub mod pallet_conviction_voting; pub mod pallet_election_provider_multi_phase; pub mod pallet_fast_unstake; pub mod pallet_identity; -pub mod pallet_im_online; pub mod pallet_indices; pub mod pallet_message_queue; pub mod pallet_multisig; diff --git a/relay/polkadot/src/weights/pallet_im_online.rs b/relay/polkadot/src/weights/pallet_im_online.rs deleted file mode 100644 index 3e20819f97..0000000000 --- a/relay/polkadot/src/weights/pallet_im_online.rs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Polkadot is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see . - -//! Autogenerated weights for `pallet_im_online` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-18, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `ggwpez-ref-hw`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("../polkadot-chain-spec.json")`, DB CACHE: 1024 - -// Executed Command: -// ../polkadot-sdk/target/production/polkadot -// benchmark -// pallet -// --chain=../polkadot-chain-spec.json -// --steps -// 50 -// --repeat -// 20 -// --pallet=pallet_im_online -// --extrinsic=* -// --wasm-execution=compiled -// --heap-pages=4096 -// --output -// ./polkadot-weights/ -// --header -// ./file_header.txt - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] - -use frame_support::{traits::Get, weights::Weight}; -use core::marker::PhantomData; - -/// Weight functions for `pallet_im_online`. -pub struct WeightInfo(PhantomData); -impl pallet_im_online::WeightInfo for WeightInfo { - /// Storage: `Session::Validators` (r:1 w:0) - /// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `Session::CurrentIndex` (r:1 w:0) - /// Proof: `Session::CurrentIndex` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ImOnline::Keys` (r:1 w:0) - /// Proof: `ImOnline::Keys` (`max_values`: Some(1), `max_size`: Some(320002), added: 320497, mode: `MaxEncodedLen`) - /// Storage: `ImOnline::ReceivedHeartbeats` (r:1 w:1) - /// Proof: `ImOnline::ReceivedHeartbeats` (`max_values`: None, `max_size`: Some(25), added: 2500, mode: `MaxEncodedLen`) - /// Storage: `ImOnline::AuthoredBlocks` (r:1 w:0) - /// Proof: `ImOnline::AuthoredBlocks` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) - /// The range of component `k` is `[1, 1000]`. - fn validate_unsigned_and_then_heartbeat(k: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `559 + k * (32 ±0)` - // Estimated: `321487 + k * (1761 ±0)` - // Minimum execution time: 76_514_000 picoseconds. - Weight::from_parts(93_114_641, 0) - .saturating_add(Weight::from_parts(0, 321487)) - // Standard Error: 522 - .saturating_add(Weight::from_parts(31_583, 0).saturating_mul(k.into())) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(1)) - .saturating_add(Weight::from_parts(0, 1761).saturating_mul(k.into())) - } -}