Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

RemovePallet migration tool #6977

Closed
wants to merge 40 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
eb49fda
try_kill_gov_v1_storage test poc
liamaharon Mar 28, 2023
5ab6c31
log key counts and clear keys
liamaharon Mar 28, 2023
f95ab4b
move count_keys into remote_tests
liamaharon Mar 28, 2023
a1702ee
remove code duplication
liamaharon Mar 28, 2023
cefdab5
improve comment
liamaharon Mar 28, 2023
a812fa6
cleanup syntax
liamaharon Mar 28, 2023
b6ef384
typo
liamaharon Mar 28, 2023
10654e2
migrate removal functionality from test to onruntimeupgrade
liamaharon Mar 29, 2023
359d8eb
fix formatting
liamaharon Mar 29, 2023
cb0dbc9
Merge branch 'master' of github.com:paritytech/polkadot into liam-rem…
liamaharon Mar 29, 2023
b1864d6
formatting
liamaharon Mar 29, 2023
53a0316
improve error log
liamaharon Mar 29, 2023
212e6a1
use struct const syntax
liamaharon Mar 29, 2023
69feee0
refactor to generic RemovePallet
liamaharon Mar 29, 2023
49865f8
count initial prefix read in weight
liamaharon Mar 29, 2023
28b499c
improve comment
liamaharon Mar 29, 2023
abc6c93
add licence and docs
liamaharon Mar 29, 2023
cd46283
revert redundant change
liamaharon Mar 29, 2023
4069109
typo
liamaharon Mar 29, 2023
b2044f1
Merge branch 'master' of github.com:paritytech/polkadot into liam-rem…
liamaharon Mar 30, 2023
e5934b2
use helper storage methods
liamaharon Mar 30, 2023
ba87f37
remove tips storage
liamaharon Mar 30, 2023
a3f3b31
Merge branch 'master' of github.com:paritytech/polkadot into liam-rem…
liamaharon Mar 31, 2023
c0081eb
usage docs
liamaharon Mar 31, 2023
f181f1c
make parameter types consts
liamaharon Mar 31, 2023
9d0ce58
move docs to struct
liamaharon Mar 31, 2023
afa82e9
Update runtime/common/src/remove_pallet.rs
liamaharon Mar 31, 2023
e477c92
add error log if clear_prefix returns unexpected result
liamaharon Mar 31, 2023
0bf4140
Merge branch 'liam-remove-kusama-gov-v1-storage' of github.com:parity…
liamaharon Mar 31, 2023
fc37d00
return error from post_upgrade in case of failure
liamaharon Mar 31, 2023
a0fbaa7
typo
liamaharon Mar 31, 2023
dd6cab9
improve outer comment
liamaharon Mar 31, 2023
7766cb1
Update runtime/common/src/remove_pallet.rs
liamaharon Mar 31, 2023
39ce205
Merge branch 'liam-remove-kusama-gov-v1-storage' of github.com:parity…
liamaharon Apr 1, 2023
f935984
Update runtime/common/src/remove_pallet.rs
liamaharon Apr 5, 2023
e0632be
Update runtime/common/src/remove_pallet.rs
liamaharon Apr 5, 2023
fb39cbe
Merge branch 'master' of github.com:paritytech/polkadot into liam-rem…
liamaharon Apr 5, 2023
299ce74
remove kusama gov v1 storage deletion
liamaharon Apr 5, 2023
21baa56
fix universal alias function signature
liamaharon Apr 5, 2023
29848c7
generic DbWeight
liamaharon Apr 5, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions runtime/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub mod impls;
pub mod paras_registrar;
pub mod paras_sudo_wrapper;
pub mod purchase;
pub mod remove_pallet;
pub mod slot_range;
pub mod slots;
pub mod traits;
Expand Down
136 changes: 136 additions & 0 deletions runtime/common/src/remove_pallet.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// Copyright 2017-2023 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 <http://www.gnu.org/licenses/>.

//! Contains `RemovePallet`, a tool for deleting all storage items of a given pallet.
//!
//! This can be useful for cleaning up the storage of a pallet which has been removed from the
//! runtime.
#[cfg(feature = "try-runtime")]
use frame_support::storage::unhashed::contains_prefixed_key;
use frame_support::weights::RuntimeDbWeight;
use sp_core::Get;
use sp_io::{hashing::twox_128, storage::clear_prefix, KillStorageResult};
use sp_std::marker::PhantomData;
#[cfg(feature = "try-runtime")]
use sp_std::vec::Vec;

/// `RemovePallet` is a utility struct used to remove all storage items associated with a specific
/// pallet.
///
/// This struct is generic over two parameters:
/// - `P` is a type that implements the `Get` trait for a static string, representing the pallet's name.
/// - `DbWeight` is a type that implements the `Get` trait for `RuntimeDbWeight`, providing the weight
/// for database operations.
///
/// On runtime upgrade, the `on_runtime_upgrade` function will clear all storage items associated with
/// the specified pallet, logging the number of keys removed. If the `try-runtime` feature is enabled,
/// the `pre_upgrade` and `post_upgrade` functions can be used to verify the storage removal before and
/// after the upgrade.
///
/// # Examples:
/// ```ignore
/// construct_runtime! {
/// pub enum Runtime where
/// Block = Block,
/// NodeBlock = primitives::Block,
/// UncheckedExtrinsic = UncheckedExtrinsic
/// {
/// System: frame_system::{Pallet, Call, Storage, Config, Event<T>} = 0,
///
/// SomePalletToRemove: pallet_something::{Pallet, Call, Storage, Event<T>} = 1,
/// AnotherPalletToRemove: pallet_something_else::{Pallet, Call, Storage, Event<T>} = 2,
///
/// YourOtherPallets...
/// }
/// };
///
/// parameter_types! {
/// pub const SomePalletToRemoveStr: &'static str = "SomePalletToRemove";
/// pub const AnotherPalletToRemoveStr: &'static str = "AnotherPalletToRemove";
/// }
///
/// pub type Migrations = (
/// RemovePallet<SomePalletToRemoveStr, RocksDbWeight>,
/// RemovePallet<AnotherPalletToRemoveStr, RocksDbWeight>,
/// AnyOtherMigrations...
/// );
///
/// pub type Executive = frame_executive::Executive<
/// Runtime,
/// Block,
/// frame_system::ChainContext<Runtime>,
/// Runtime,
/// Migrations
/// >;
/// ```
///
/// WARNING: `RemovePallet` has no guard rails preventing it from bricking the chain if the
/// operation of removing storage for the given pallet would exceed the block weight limit.
///
/// If your pallet has too many keys to be removed in a single block, it is advised to wait for
/// a multi-block scheduler currently under development which will allow for removal of storage
/// items (and performing other heavy migrations) over multiple blocks.
/// (https://github.com/paritytech/substrate/issues/13690)
pub struct RemovePallet<P: Get<&'static str>, DbWeight: Get<RuntimeDbWeight>>(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also move it to Substrate… 🤷‍♂️
Not sure if it is worth it right now though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ggwpez good point, I think we may as well do it now if it would need to happen later anyway.

Is there an existing package in substrate you think this would fit well into?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably frame-support.

PhantomData<(P, DbWeight)>,
);
impl<P: Get<&'static str>, DbWeight: Get<RuntimeDbWeight>> frame_support::traits::OnRuntimeUpgrade
for RemovePallet<P, DbWeight>
{
fn on_runtime_upgrade() -> frame_support::weights::Weight {
let hashed_prefix = twox_128(P::get().as_bytes());
let keys_removed = match clear_prefix(&hashed_prefix, None) {
KillStorageResult::AllRemoved(value) => value,
KillStorageResult::SomeRemaining(value) => {
log::error!(
"`clear_prefix` failed to remove all keys for {}. THIS SHOULD NEVER HAPPEN! 🚨",
P::get()
);
value
},
} as u64;

log::info!("Removed {} {} keys 🧹", keys_removed, P::get());

DbWeight::get().reads_writes(keys_removed + 1, keys_removed)
}

#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
let hashed_prefix = twox_128(P::get().as_bytes());
match contains_prefixed_key(&hashed_prefix) {
true => log::info!("Found {} keys pre-removal 👀", P::get()),
false => log::warn!(
"Migration RemovePallet<{}> can be removed (no keys found pre-removal).",
P::get()
),
};
Ok(Vec::new())
}

#[cfg(feature = "try-runtime")]
fn post_upgrade(_state: Vec<u8>) -> Result<(), &'static str> {
let hashed_prefix = twox_128(P::get().as_bytes());
match contains_prefixed_key(&hashed_prefix) {
true => {
log::error!("{} has keys remaining post-removal ❗", P::get());
return Err("Keys remaining post-removal, this should never happen 🚨")
},
false => log::info!("No {} keys found post-removal 🎉", P::get()),
};
Ok(())
}
}