From 4374b5d598d39ef0938c396f635c27785de53440 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Wed, 24 Jan 2024 14:18:54 +0100 Subject: [PATCH] Refactor `pallet-state-trie-migration` to `fungible::*` traits (#1801) ## Summary This PR consolidates `pallet-state-trie-migration` as a part of https://github.com/paritytech/polkadot-sdk/issues/226 / https://github.com/paritytech/polkadot-sdk/issues/171: `pallet-state-trie-migration`: - [x] replace `Currency` with `fungible` traits - [x] run benchmarks - [x] refactor to `DefaultConfig` `pallet_nicks`: - [x] remove others: - [x] remove `as Fn*` or `asFun*` stuff based on discussion [here](https://github.com/paritytech/polkadot-sdk/issues/226#issuecomment-1822861445) --------- Co-authored-by: Richard Melkonian <35300528+0xmovses@users.noreply.github.com> Co-authored-by: command-bot <> --- Cargo.lock | 15 - Cargo.toml | 1 - .../assets/asset-hub-rococo/src/lib.rs | 4 +- polkadot/runtime/rococo/src/lib.rs | 5 +- substrate/bin/node/runtime/src/lib.rs | 3 +- substrate/frame/alliance/src/mock.rs | 2 +- substrate/frame/nicks/Cargo.toml | 49 -- substrate/frame/nicks/README.md | 25 -- substrate/frame/nicks/src/lib.rs | 424 ------------------ substrate/frame/nomination-pools/src/lib.rs | 11 +- substrate/frame/safe-mode/src/benchmarking.rs | 28 +- substrate/frame/safe-mode/src/lib.rs | 10 +- substrate/frame/society/src/mock.rs | 40 +- .../frame/state-trie-migration/src/lib.rs | 259 ++++++----- .../frame/state-trie-migration/src/weights.rs | 207 +++++---- .../frame/transaction-storage/src/lib.rs | 13 +- .../frame/transaction-storage/src/mock.rs | 5 - 17 files changed, 312 insertions(+), 789 deletions(-) delete mode 100644 substrate/frame/nicks/Cargo.toml delete mode 100644 substrate/frame/nicks/README.md delete mode 100644 substrate/frame/nicks/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 1d45d620478e..0152391a4f2e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10222,21 +10222,6 @@ dependencies = [ "sp-std 8.0.0", ] -[[package]] -name = "pallet-nicks" -version = "4.0.0-dev" -dependencies = [ - "frame-support", - "frame-system", - "pallet-balances", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std 8.0.0", -] - [[package]] name = "pallet-nis" version = "4.0.0-dev" diff --git a/Cargo.toml b/Cargo.toml index 991b282ab158..20cc16039fe4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -352,7 +352,6 @@ members = [ "substrate/frame/nft-fractionalization", "substrate/frame/nfts", "substrate/frame/nfts/runtime-api", - "substrate/frame/nicks", "substrate/frame/nis", "substrate/frame/node-authorization", "substrate/frame/nomination-pools", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index a76e47074f6d..a6dd11250192 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -243,7 +243,8 @@ impl pallet_balances::Config for Runtime { type FreezeIdentifier = (); // We allow each account to have holds on it from: // - `NftFractionalization`: 1 - type MaxHolds = ConstU32<1>; + // - `StateTrieMigration`: 1 + type MaxHolds = ConstU32<2>; type MaxFreezes = ConstU32<0>; } @@ -1674,6 +1675,7 @@ parameter_types! { impl pallet_state_trie_migration::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Currency = Balances; + type RuntimeHoldReason = RuntimeHoldReason; type SignedDepositPerItem = MigrationSignedDepositPerItem; type SignedDepositBase = MigrationSignedDepositBase; // An origin that can control the whole pallet: should be Root, or a part of your council. diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 2d49f0b99e95..fcaf4a3fe533 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -314,7 +314,7 @@ impl pallet_balances::Config for Runtime { type MaxFreezes = ConstU32<1>; type RuntimeHoldReason = RuntimeHoldReason; type RuntimeFreezeReason = RuntimeFreezeReason; - type MaxHolds = ConstU32<2>; + type MaxHolds = ConstU32<3>; } parameter_types! { @@ -1167,7 +1167,7 @@ impl pallet_balances::Config for Runtime { type RuntimeHoldReason = RuntimeHoldReason; type RuntimeFreezeReason = RuntimeFreezeReason; type FreezeIdentifier = (); - type MaxHolds = ConstU32<2>; + type MaxHolds = ConstU32<3>; type MaxFreezes = ConstU32<1>; } @@ -1689,6 +1689,7 @@ parameter_types! { impl pallet_state_trie_migration::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Currency = Balances; + type RuntimeHoldReason = RuntimeHoldReason; type SignedDepositPerItem = MigrationSignedDepositPerItem; type SignedDepositBase = MigrationSignedDepositBase; type ControlOrigin = EnsureRoot; diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index d7598adb5a22..37b0d93de296 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -533,7 +533,7 @@ impl pallet_balances::Config for Runtime { type WeightInfo = pallet_balances::weights::SubstrateWeight; type FreezeIdentifier = RuntimeFreezeReason; type MaxFreezes = ConstU32<1>; - type MaxHolds = ConstU32<6>; + type MaxHolds = ConstU32<7>; } parameter_types! { @@ -1901,6 +1901,7 @@ impl pallet_state_trie_migration::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ControlOrigin = EnsureRoot; type Currency = Balances; + type RuntimeHoldReason = RuntimeHoldReason; type MaxKeyLen = MigrationMaxKeyLen; type SignedDepositPerItem = MigrationSignedDepositPerItem; type SignedDepositBase = MigrationSignedDepositBase; diff --git a/substrate/frame/alliance/src/mock.rs b/substrate/frame/alliance/src/mock.rs index 65cebb985d7d..3d44374c3eb3 100644 --- a/substrate/frame/alliance/src/mock.rs +++ b/substrate/frame/alliance/src/mock.rs @@ -51,7 +51,7 @@ parameter_types! { #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for Test { type Block = Block; - type AccountData = pallet_balances::AccountData; + type AccountData = pallet_balances::AccountData; } parameter_types! { diff --git a/substrate/frame/nicks/Cargo.toml b/substrate/frame/nicks/Cargo.toml deleted file mode 100644 index 7d43f64cfe23..000000000000 --- a/substrate/frame/nicks/Cargo.toml +++ /dev/null @@ -1,49 +0,0 @@ -[package] -name = "pallet-nicks" -version = "4.0.0-dev" -authors.workspace = true -edition.workspace = true -license = "Apache-2.0" -homepage = "https://substrate.io" -repository.workspace = true -description = "FRAME pallet for nick management" -readme = "README.md" - -[lints] -workspace = true - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } -frame-support = { path = "../support", default-features = false } -frame-system = { path = "../system", default-features = false } -sp-io = { path = "../../primitives/io", default-features = false } -sp-runtime = { path = "../../primitives/runtime", default-features = false } -sp-std = { path = "../../primitives/std", default-features = false } - -[dev-dependencies] -pallet-balances = { path = "../balances" } -sp-core = { path = "../../primitives/core" } - -[features] -default = ["std"] -std = [ - "codec/std", - "frame-support/std", - "frame-system/std", - "pallet-balances/std", - "scale-info/std", - "sp-core/std", - "sp-io/std", - "sp-runtime/std", - "sp-std/std", -] -try-runtime = [ - "frame-support/try-runtime", - "frame-system/try-runtime", - "pallet-balances/try-runtime", - "sp-runtime/try-runtime", -] diff --git a/substrate/frame/nicks/README.md b/substrate/frame/nicks/README.md deleted file mode 100644 index 2b05f32d3344..000000000000 --- a/substrate/frame/nicks/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# Nicks Module - -- [`Config`](https://docs.rs/pallet-nicks/latest/pallet_nicks/pallet/trait.Config.html) -- [`Call`](https://docs.rs/pallet-nicks/latest/pallet_nicks/pallet/enum.Call.html) - -## Overview - -Nicks is an example module for keeping track of account names on-chain. It makes no effort to -create a name hierarchy, be a DNS replacement or provide reverse lookups. Furthermore, the -weights attached to this module's dispatchable functions are for demonstration purposes only and -have not been designed to be economically secure. Do not use this pallet as-is in production. - -## Interface - -### Dispatchable Functions - -- `set_name` - Set the associated name of an account; a small deposit is reserved if not already - taken. -- `clear_name` - Remove an account's associated name; the deposit is returned. -- `kill_name` - Forcibly remove the associated name; the deposit is lost. - -[`Call`]: ./enum.Call.html -[`Config`]: ./trait.Config.html - -License: Apache-2.0 diff --git a/substrate/frame/nicks/src/lib.rs b/substrate/frame/nicks/src/lib.rs deleted file mode 100644 index 540777f87cab..000000000000 --- a/substrate/frame/nicks/src/lib.rs +++ /dev/null @@ -1,424 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! # Nicks Pallet -//! -//! - [`Config`] -//! - [`Call`] -//! -//! ## Overview -//! -//! Nicks is an example pallet for keeping track of account names on-chain. It makes no effort to -//! create a name hierarchy, be a DNS replacement or provide reverse lookups. Furthermore, the -//! weights attached to this pallet's dispatchable functions are for demonstration purposes only and -//! have not been designed to be economically secure. Do not use this pallet as-is in production. -//! -//! ## Interface -//! -//! ### Dispatchable Functions -//! -//! * `set_name` - Set the associated name of an account; a small deposit is reserved if not already -//! taken. -//! * `clear_name` - Remove an account's associated name; the deposit is returned. -//! * `kill_name` - Forcibly remove the associated name; the deposit is lost. - -#![deny(missing_docs)] -#![cfg_attr(not(feature = "std"), no_std)] - -use frame_support::traits::{Currency, OnUnbalanced, ReservableCurrency}; -pub use pallet::*; -use sp_runtime::traits::{StaticLookup, Zero}; -use sp_std::prelude::*; - -type AccountIdOf = ::AccountId; -type BalanceOf = <::Currency as Currency>>::Balance; -type NegativeImbalanceOf = - <::Currency as Currency>>::NegativeImbalance; -type AccountIdLookupOf = <::Lookup as StaticLookup>::Source; - -#[frame_support::pallet] -pub mod pallet { - use super::*; - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - - #[pallet::config] - pub trait Config: frame_system::Config { - /// The overarching event type. - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - - /// The currency trait. - type Currency: ReservableCurrency; - - /// Reservation fee. - #[pallet::constant] - type ReservationFee: Get>; - - /// What to do with slashed funds. - type Slashed: OnUnbalanced>; - - /// The origin which may forcibly set or remove a name. Root can always do this. - type ForceOrigin: EnsureOrigin; - - /// The minimum length a name may be. - #[pallet::constant] - type MinLength: Get; - - /// The maximum length a name may be. - #[pallet::constant] - type MaxLength: Get; - } - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - /// A name was set. - NameSet { - /// The account for which the name was set. - who: T::AccountId, - }, - /// A name was forcibly set. - NameForced { - /// The account whose name was forcibly set. - target: T::AccountId, - }, - /// A name was changed. - NameChanged { - /// The account for which the name was changed. - who: T::AccountId, - }, - /// A name was cleared, and the given balance returned. - NameCleared { - /// The account for which the name was cleared. - who: T::AccountId, - /// The deposit returned. - deposit: BalanceOf, - }, - /// A name was removed and the given balance slashed. - NameKilled { - /// The account for which the name was removed. - target: T::AccountId, - /// The deposit returned. - deposit: BalanceOf, - }, - } - - /// Error for the Nicks pallet. - #[pallet::error] - pub enum Error { - /// A name is too short. - TooShort, - /// A name is too long. - TooLong, - /// An account isn't named. - Unnamed, - } - - /// The lookup table for names. - #[pallet::storage] - pub(super) type NameOf = - StorageMap<_, Twox64Concat, T::AccountId, (BoundedVec, BalanceOf)>; - - #[pallet::pallet] - pub struct Pallet(_); - - #[pallet::call] - impl Pallet { - /// Set an account's name. The name should be a UTF-8-encoded string by convention, though - /// we don't check it. - /// - /// The name may not be more than `T::MaxLength` bytes, nor less than `T::MinLength` bytes. - /// - /// If the account doesn't already have a name, then a fee of `ReservationFee` is reserved - /// in the account. - /// - /// The dispatch origin for this call must be _Signed_. - /// - /// ## Complexity - /// - O(1). - #[pallet::call_index(0)] - #[pallet::weight({50_000_000})] - pub fn set_name(origin: OriginFor, name: Vec) -> DispatchResult { - let sender = ensure_signed(origin)?; - - let bounded_name: BoundedVec<_, _> = - name.try_into().map_err(|_| Error::::TooLong)?; - ensure!(bounded_name.len() >= T::MinLength::get() as usize, Error::::TooShort); - - let deposit = if let Some((_, deposit)) = >::get(&sender) { - Self::deposit_event(Event::::NameChanged { who: sender.clone() }); - deposit - } else { - let deposit = T::ReservationFee::get(); - T::Currency::reserve(&sender, deposit)?; - Self::deposit_event(Event::::NameSet { who: sender.clone() }); - deposit - }; - - >::insert(&sender, (bounded_name, deposit)); - Ok(()) - } - - /// Clear an account's name and return the deposit. Fails if the account was not named. - /// - /// The dispatch origin for this call must be _Signed_. - /// - /// ## Complexity - /// - O(1). - #[pallet::call_index(1)] - #[pallet::weight({70_000_000})] - pub fn clear_name(origin: OriginFor) -> DispatchResult { - let sender = ensure_signed(origin)?; - - let deposit = >::take(&sender).ok_or(Error::::Unnamed)?.1; - - let err_amount = T::Currency::unreserve(&sender, deposit); - debug_assert!(err_amount.is_zero()); - - Self::deposit_event(Event::::NameCleared { who: sender, deposit }); - Ok(()) - } - - /// Remove an account's name and take charge of the deposit. - /// - /// Fails if `target` has not been named. The deposit is dealt with through `T::Slashed` - /// imbalance handler. - /// - /// The dispatch origin for this call must match `T::ForceOrigin`. - /// - /// ## Complexity - /// - O(1). - #[pallet::call_index(2)] - #[pallet::weight({70_000_000})] - pub fn kill_name(origin: OriginFor, target: AccountIdLookupOf) -> DispatchResult { - T::ForceOrigin::ensure_origin(origin)?; - - // Figure out who we're meant to be clearing. - let target = T::Lookup::lookup(target)?; - // Grab their deposit (and check that they have one). - let deposit = >::take(&target).ok_or(Error::::Unnamed)?.1; - // Slash their deposit from them. - T::Slashed::on_unbalanced(T::Currency::slash_reserved(&target, deposit).0); - - Self::deposit_event(Event::::NameKilled { target, deposit }); - Ok(()) - } - - /// Set a third-party account's name with no deposit. - /// - /// No length checking is done on the name. - /// - /// The dispatch origin for this call must match `T::ForceOrigin`. - /// - /// ## Complexity - /// - O(1). - #[pallet::call_index(3)] - #[pallet::weight({70_000_000})] - pub fn force_name( - origin: OriginFor, - target: AccountIdLookupOf, - name: Vec, - ) -> DispatchResult { - T::ForceOrigin::ensure_origin(origin)?; - - let bounded_name: BoundedVec<_, _> = - name.try_into().map_err(|_| Error::::TooLong)?; - let target = T::Lookup::lookup(target)?; - let deposit = >::get(&target).map(|x| x.1).unwrap_or_else(Zero::zero); - >::insert(&target, (bounded_name, deposit)); - - Self::deposit_event(Event::::NameForced { target }); - Ok(()) - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate as pallet_nicks; - - use frame_support::{ - assert_noop, assert_ok, derive_impl, ord_parameter_types, - traits::{ConstU32, ConstU64}, - }; - use frame_system::EnsureSignedBy; - use sp_core::H256; - use sp_runtime::{ - traits::{BadOrigin, BlakeTwo256, IdentityLookup}, - BuildStorage, - }; - - type Block = frame_system::mocking::MockBlock; - - frame_support::construct_runtime!( - pub enum Test - { - System: frame_system, - Balances: pallet_balances, - Nicks: pallet_nicks, - } - ); - - #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] - impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); - type RuntimeOrigin = RuntimeOrigin; - type Nonce = u64; - type Hash = H256; - type RuntimeCall = RuntimeCall; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Block = Block; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = ConstU32<16>; - } - - impl pallet_balances::Config for Test { - type MaxLocks = (); - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; - type Balance = u64; - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ConstU64<1>; - type AccountStore = System; - type WeightInfo = (); - type FreezeIdentifier = (); - type MaxFreezes = (); - type RuntimeHoldReason = (); - type RuntimeFreezeReason = (); - type MaxHolds = (); - } - - ord_parameter_types! { - pub const One: u64 = 1; - } - impl Config for Test { - type RuntimeEvent = RuntimeEvent; - type Currency = Balances; - type ReservationFee = ConstU64<2>; - type Slashed = (); - type ForceOrigin = EnsureSignedBy; - type MinLength = ConstU32<3>; - type MaxLength = ConstU32<16>; - } - - fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - pallet_balances::GenesisConfig:: { balances: vec![(1, 10), (2, 10)] } - .assimilate_storage(&mut t) - .unwrap(); - t.into() - } - - #[test] - fn kill_name_should_work() { - new_test_ext().execute_with(|| { - assert_ok!(Nicks::set_name(RuntimeOrigin::signed(2), b"Dave".to_vec())); - assert_eq!(Balances::total_balance(&2), 10); - assert_ok!(Nicks::kill_name(RuntimeOrigin::signed(1), 2)); - assert_eq!(Balances::total_balance(&2), 8); - assert_eq!(>::get(2), None); - }); - } - - #[test] - fn force_name_should_work() { - new_test_ext().execute_with(|| { - assert_noop!( - Nicks::set_name(RuntimeOrigin::signed(2), b"Dr. David Brubeck, III".to_vec()), - Error::::TooLong, - ); - - assert_ok!(Nicks::set_name(RuntimeOrigin::signed(2), b"Dave".to_vec())); - assert_eq!(Balances::reserved_balance(2), 2); - assert_noop!( - Nicks::force_name(RuntimeOrigin::signed(1), 2, b"Dr. David Brubeck, III".to_vec()), - Error::::TooLong, - ); - assert_ok!(Nicks::force_name( - RuntimeOrigin::signed(1), - 2, - b"Dr. Brubeck, III".to_vec() - )); - assert_eq!(Balances::reserved_balance(2), 2); - let (name, amount) = >::get(2).unwrap(); - assert_eq!(name, b"Dr. Brubeck, III".to_vec()); - assert_eq!(amount, 2); - }); - } - - #[test] - fn normal_operation_should_work() { - new_test_ext().execute_with(|| { - assert_ok!(Nicks::set_name(RuntimeOrigin::signed(1), b"Gav".to_vec())); - assert_eq!(Balances::reserved_balance(1), 2); - assert_eq!(Balances::free_balance(1), 8); - assert_eq!(>::get(1).unwrap().0, b"Gav".to_vec()); - - assert_ok!(Nicks::set_name(RuntimeOrigin::signed(1), b"Gavin".to_vec())); - assert_eq!(Balances::reserved_balance(1), 2); - assert_eq!(Balances::free_balance(1), 8); - assert_eq!(>::get(1).unwrap().0, b"Gavin".to_vec()); - - assert_ok!(Nicks::clear_name(RuntimeOrigin::signed(1))); - assert_eq!(Balances::reserved_balance(1), 0); - assert_eq!(Balances::free_balance(1), 10); - }); - } - - #[test] - fn error_catching_should_work() { - new_test_ext().execute_with(|| { - assert_noop!(Nicks::clear_name(RuntimeOrigin::signed(1)), Error::::Unnamed); - - assert_noop!( - Nicks::set_name(RuntimeOrigin::signed(3), b"Dave".to_vec()), - pallet_balances::Error::::InsufficientBalance - ); - - assert_noop!( - Nicks::set_name(RuntimeOrigin::signed(1), b"Ga".to_vec()), - Error::::TooShort - ); - assert_noop!( - Nicks::set_name(RuntimeOrigin::signed(1), b"Gavin James Wood, Esquire".to_vec()), - Error::::TooLong - ); - assert_ok!(Nicks::set_name(RuntimeOrigin::signed(1), b"Dave".to_vec())); - assert_noop!(Nicks::kill_name(RuntimeOrigin::signed(2), 1), BadOrigin); - assert_noop!( - Nicks::force_name(RuntimeOrigin::signed(2), 1, b"Whatever".to_vec()), - BadOrigin - ); - }); - } -} diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index c538f12e20bf..c4e5ad1f700a 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -357,10 +357,7 @@ use frame_support::{ pallet_prelude::{MaxEncodedLen, *}, storage::bounded_btree_map::BoundedBTreeMap, traits::{ - fungible::{ - Inspect as FunInspect, InspectFreeze, Mutate as FunMutate, - MutateFreeze as FunMutateFreeze, - }, + fungible::{Inspect, InspectFreeze, Mutate, MutateFreeze}, tokens::{Fortitude, Preservation}, Defensive, DefensiveOption, DefensiveResult, DefensiveSaturating, Get, }, @@ -408,7 +405,7 @@ pub use weights::WeightInfo; /// The balance type used by the currency system. pub type BalanceOf = - <::Currency as FunInspect<::AccountId>>::Balance; + <::Currency as Inspect<::AccountId>>::Balance; /// Type used for unique identifier of each pool. pub type PoolId = u32; @@ -1608,8 +1605,8 @@ pub mod pallet { type WeightInfo: weights::WeightInfo; /// The currency type used for nomination pool. - type Currency: FunMutate - + FunMutateFreeze; + type Currency: Mutate + + MutateFreeze; /// The overarching freeze reason. type RuntimeFreezeReason: From; diff --git a/substrate/frame/safe-mode/src/benchmarking.rs b/substrate/frame/safe-mode/src/benchmarking.rs index 566150e982af..7561cf305f45 100644 --- a/substrate/frame/safe-mode/src/benchmarking.rs +++ b/substrate/frame/safe-mode/src/benchmarking.rs @@ -20,11 +20,11 @@ use super::{Pallet as SafeMode, *}; use frame_benchmarking::v2::*; -use frame_support::traits::{fungible::Mutate as FunMutate, UnfilteredDispatchable}; +use frame_support::traits::{fungible, UnfilteredDispatchable}; use frame_system::{Pallet as System, RawOrigin}; use sp_runtime::traits::{Bounded, One, Zero}; -#[benchmarks(where T::Currency: FunMutate)] +#[benchmarks(where T::Currency: fungible::Mutate)] mod benchmarks { use super::*; @@ -58,7 +58,7 @@ mod benchmarks { let caller: T::AccountId = whitelisted_caller(); let origin = RawOrigin::Signed(caller.clone()); - T::Currency::set_balance(&caller, init_bal::()); + >::set_balance(&caller, init_bal::()); #[extrinsic_call] _(origin); @@ -91,7 +91,7 @@ mod benchmarks { T::ExtendDepositAmount::get().ok_or_else(|| BenchmarkError::Weightless)?; let alice: T::AccountId = whitelisted_caller(); - T::Currency::set_balance(&alice, init_bal::()); + >::set_balance(&alice, init_bal::()); System::::set_block_number(1u32.into()); assert!(SafeMode::::do_enter(None, 1u32.into()).is_ok()); @@ -152,7 +152,7 @@ mod benchmarks { let alice: T::AccountId = whitelisted_caller(); let origin = RawOrigin::Signed(alice.clone()); - T::Currency::set_balance(&alice, init_bal::()); + >::set_balance(&alice, init_bal::()); // Mock the storage. This is needed in case the `EnterDepositAmount` is zero. let block: BlockNumberFor = 1u32.into(); let bal: BalanceOf = 1u32.into(); @@ -169,7 +169,7 @@ mod benchmarks { _(origin, alice.clone(), 1u32.into()); assert!(!Deposits::::contains_key(&alice, &block)); - assert_eq!(T::Currency::balance(&alice), init_bal::()); + assert_eq!(>::balance(&alice), init_bal::()); Ok(()) } @@ -180,7 +180,7 @@ mod benchmarks { .map_err(|_| BenchmarkError::Weightless)?; let alice: T::AccountId = whitelisted_caller(); - T::Currency::set_balance(&alice, init_bal::()); + >::set_balance(&alice, init_bal::()); // Mock the storage. This is needed in case the `EnterDepositAmount` is zero. let block: BlockNumberFor = 1u32.into(); @@ -189,7 +189,10 @@ mod benchmarks { T::Currency::hold(&&HoldReason::EnterOrExtend.into(), &alice, bal)?; EnteredUntil::::put(&block); - assert_eq!(T::Currency::balance(&alice), init_bal::() - 1u32.into()); + assert_eq!( + >::balance(&alice), + init_bal::() - 1u32.into() + ); assert!(SafeMode::::do_exit(ExitReason::Force).is_ok()); System::::set_block_number(System::::block_number() + One::one()); @@ -200,7 +203,7 @@ mod benchmarks { _(force_origin as T::RuntimeOrigin, alice.clone(), block); assert!(!Deposits::::contains_key(&alice, block)); - assert_eq!(T::Currency::balance(&alice), init_bal::()); + assert_eq!(>::balance(&alice), init_bal::()); Ok(()) } @@ -210,7 +213,7 @@ mod benchmarks { .map_err(|_| BenchmarkError::Weightless)?; let alice: T::AccountId = whitelisted_caller(); - T::Currency::set_balance(&alice, init_bal::()); + >::set_balance(&alice, init_bal::()); // Mock the storage. This is needed in case the `EnterDepositAmount` is zero. let block: BlockNumberFor = 1u32.into(); @@ -224,7 +227,10 @@ mod benchmarks { _(force_origin as T::RuntimeOrigin, alice.clone(), block); assert!(!Deposits::::contains_key(&alice, block)); - assert_eq!(T::Currency::balance(&alice), init_bal::() - 1u32.into()); + assert_eq!( + >::balance(&alice), + init_bal::() - 1u32.into() + ); Ok(()) } diff --git a/substrate/frame/safe-mode/src/lib.rs b/substrate/frame/safe-mode/src/lib.rs index 554f509db63e..325d751e17f6 100644 --- a/substrate/frame/safe-mode/src/lib.rs +++ b/substrate/frame/safe-mode/src/lib.rs @@ -84,8 +84,8 @@ use frame_support::{ pallet_prelude::*, traits::{ fungible::{ - hold::{Inspect as FunHoldInspect, Mutate as FunHoldMutate}, - Inspect as FunInspect, + self, + hold::{Inspect, Mutate}, }, tokens::{Fortitude, Precision}, CallMetadata, Contains, Defensive, GetCallMetadata, PalletInfoAccess, SafeModeNotify, @@ -102,7 +102,7 @@ pub use pallet::*; pub use weights::*; type BalanceOf = - <::Currency as FunInspect<::AccountId>>::Balance; + <::Currency as fungible::Inspect<::AccountId>>::Balance; #[frame_support::pallet] pub mod pallet { @@ -117,8 +117,8 @@ pub mod pallet { type RuntimeEvent: From> + IsType<::RuntimeEvent>; /// Currency type for this pallet, used for Deposits. - type Currency: FunHoldInspect - + FunHoldMutate; + type Currency: Inspect + + Mutate; /// The hold reason when reserving funds for entering or extending the safe-mode. type RuntimeHoldReason: From; diff --git a/substrate/frame/society/src/mock.rs b/substrate/frame/society/src/mock.rs index 749d196b6e1b..04f3e85f539a 100644 --- a/substrate/frame/society/src/mock.rs +++ b/substrate/frame/society/src/mock.rs @@ -26,11 +26,7 @@ use frame_support::{ }; use frame_support_test::TestRandomness; use frame_system::EnsureSignedBy; -use sp_core::H256; -use sp_runtime::{ - traits::{BlakeTwo256, IdentityLookup}, - BuildStorage, -}; +use sp_runtime::{traits::IdentityLookup, BuildStorage}; use RuntimeOrigin as Origin; @@ -60,46 +56,16 @@ ord_parameter_types! { #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); - type RuntimeOrigin = RuntimeOrigin; - type Nonce = u64; - type Hash = H256; - type RuntimeCall = RuntimeCall; - type Hashing = BlakeTwo256; type AccountId = u128; - type Lookup = IdentityLookup; type Block = Block; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; - type Version = (); - type PalletInfo = PalletInfo; - type OnNewAccount = (); - type OnKilledAccount = (); type AccountData = pallet_balances::AccountData; - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = ConstU32<16>; + type Lookup = IdentityLookup; } +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] impl pallet_balances::Config for Test { - type MaxLocks = (); - type MaxReserves = (); type ReserveIdentifier = [u8; 8]; - type Balance = u64; - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ConstU64<1>; type AccountStore = System; - type WeightInfo = (); - type FreezeIdentifier = (); - type MaxFreezes = (); - type RuntimeHoldReason = (); - type RuntimeFreezeReason = (); - type MaxHolds = (); } impl Config for Test { diff --git a/substrate/frame/state-trie-migration/src/lib.rs b/substrate/frame/state-trie-migration/src/lib.rs index c71002f420ce..6b3aa9934e07 100644 --- a/substrate/frame/state-trie-migration/src/lib.rs +++ b/substrate/frame/state-trie-migration/src/lib.rs @@ -79,7 +79,11 @@ pub mod pallet { dispatch::{DispatchErrorWithPostInfo, PostDispatchInfo}, ensure, pallet_prelude::*, - traits::{Currency, Get}, + traits::{ + fungible::{hold::Balanced, Inspect, InspectHold, Mutate, MutateHold}, + tokens::{Fortitude, Precision}, + Get, + }, }; use frame_system::{self, pallet_prelude::*}; use sp_core::{ @@ -92,7 +96,7 @@ pub mod pallet { use sp_std::{ops::Deref, prelude::*}; pub(crate) type BalanceOf = - <::Currency as Currency<::AccountId>>::Balance; + <::Currency as Inspect<::AccountId>>::Balance; /// The progress of either the top or child keys. #[derive( @@ -441,20 +445,58 @@ pub mod pallet { #[pallet::pallet] pub struct Pallet(_); + /// Default implementations of [`DefaultConfig`], which can be used to implement [`Config`]. + pub mod config_preludes { + use super::*; + use frame_support::derive_impl; + + pub struct TestDefaultConfig; + + #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig, no_aggregated_types)] + impl frame_system::DefaultConfig for TestDefaultConfig {} + + #[frame_support::register_default_impl(TestDefaultConfig)] + impl DefaultConfig for TestDefaultConfig { + #[inject_runtime_type] + type RuntimeEvent = (); + #[inject_runtime_type] + type RuntimeHoldReason = (); + } + } + + /// The reason for this pallet placing a hold on funds. + #[pallet::composite_enum] + pub enum HoldReason { + /// The funds are held as a deposit for slashing. + #[codec(index = 0)] + SlashForMigrate, + } + /// Configurations of this pallet. - #[pallet::config] + #[pallet::config(with_default)] pub trait Config: frame_system::Config { /// Origin that can control the configurations of this pallet. - type ControlOrigin: frame_support::traits::EnsureOrigin; + #[pallet::no_default] + type ControlOrigin: EnsureOrigin; /// Filter on which origin that trigger the manual migrations. + #[pallet::no_default] type SignedFilter: EnsureOrigin; /// The overarching event type. + #[pallet::no_default_bounds] type RuntimeEvent: From> + IsType<::RuntimeEvent>; /// The currency provider type. - type Currency: Currency; + #[pallet::no_default] + type Currency: InspectHold + + Mutate + + MutateHold + + Balanced; + + /// The overarching runtime hold reason. + #[pallet::no_default_bounds] + type RuntimeHoldReason: From; /// Maximal number of bytes that a key can have. /// @@ -479,19 +521,23 @@ pub mod pallet { /// #[pallet::constant] + #[pallet::no_default] type MaxKeyLen: Get; /// The amount of deposit collected per item in advance, for signed migrations. /// /// This should reflect the average storage value size in the worse case. + #[pallet::no_default] type SignedDepositPerItem: Get>; /// The base value of [`Config::SignedDepositPerItem`]. /// /// Final deposit is `items * SignedDepositPerItem + SignedDepositBase`. + #[pallet::no_default] type SignedDepositBase: Get>; /// The weight information of this pallet. + #[pallet::no_default] type WeightInfo: WeightInfo; } @@ -600,8 +646,11 @@ pub mod pallet { ); // ensure they can pay more than the fee. - let deposit = T::SignedDepositPerItem::get().saturating_mul(limits.item.into()); - ensure!(T::Currency::can_slash(&who, deposit), Error::::NotEnoughFunds); + let deposit = Self::calculate_deposit_for(limits.item); + ensure!( + T::Currency::can_hold(&HoldReason::SlashForMigrate.into(), &who, deposit), + Error::::NotEnoughFunds + ); let mut task = Self::migration_process(); ensure!( @@ -618,10 +667,7 @@ pub mod pallet { // ensure that the migration witness data was correct. if real_size_upper < task.dyn_size { - // let the imbalance burn. - let (_imbalance, _remainder) = T::Currency::slash(&who, deposit); - Self::deposit_event(Event::::Slashed { who, amount: deposit }); - debug_assert!(_remainder.is_zero()); + Self::slash(who, deposit)?; return Ok(().into()) } @@ -665,10 +711,11 @@ pub mod pallet { let who = T::SignedFilter::ensure_origin(origin)?; // ensure they can pay more than the fee. - let deposit = T::SignedDepositBase::get().saturating_add( - T::SignedDepositPerItem::get().saturating_mul((keys.len() as u32).into()), + let deposit = Self::calculate_deposit_for(keys.len() as u32); + ensure!( + T::Currency::can_hold(&HoldReason::SlashForMigrate.into(), &who, deposit), + Error::::NotEnoughFunds ); - ensure!(T::Currency::can_slash(&who, deposit), "not enough funds"); let mut dyn_size = 0u32; for key in &keys { @@ -679,9 +726,7 @@ pub mod pallet { } if dyn_size > witness_size { - let (_imbalance, _remainder) = T::Currency::slash(&who, deposit); - Self::deposit_event(Event::::Slashed { who, amount: deposit }); - debug_assert!(_remainder.is_zero()); + Self::slash(who, deposit)?; Ok(().into()) } else { Self::deposit_event(Event::::Migrated { @@ -724,13 +769,11 @@ pub mod pallet { let who = T::SignedFilter::ensure_origin(origin)?; // ensure they can pay more than the fee. - let deposit = T::SignedDepositBase::get().saturating_add( - T::SignedDepositPerItem::get().saturating_mul((child_keys.len() as u32).into()), + let deposit = Self::calculate_deposit_for(child_keys.len() as u32); + ensure!( + T::Currency::can_hold(&HoldReason::SlashForMigrate.into(), &who, deposit), + Error::::NotEnoughFunds ); - sp_std::if_std! { - println!("+ {:?} / {:?} / {:?}", who, deposit, T::Currency::free_balance(&who)); - } - ensure!(T::Currency::can_slash(&who, deposit), "not enough funds"); let mut dyn_size = 0u32; let transformed_child_key = Self::transform_child_key(&root).ok_or("bad child key")?; @@ -742,9 +785,7 @@ pub mod pallet { } if dyn_size != total_size { - let (_imbalance, _remainder) = T::Currency::slash(&who, deposit); - debug_assert!(_remainder.is_zero()); - Self::deposit_event(Event::::Slashed { who, amount: deposit }); + Self::slash(who, deposit)?; Ok(PostDispatchInfo { actual_weight: Some(T::WeightInfo::migrate_custom_child_fail()), pays_fee: Pays::Yes, @@ -887,20 +928,47 @@ pub mod pallet { string.extend_from_slice(root.as_ref()); string } + + /// Calculate the deposit required for migrating a specific number of keys. + pub(crate) fn calculate_deposit_for(keys_count: u32) -> BalanceOf { + T::SignedDepositBase::get() + .saturating_add(T::SignedDepositPerItem::get().saturating_mul(keys_count.into())) + } + + /// Slash an account for migration. + fn slash(who: T::AccountId, amount: BalanceOf) -> Result<(), DispatchError> { + T::Currency::hold(&HoldReason::SlashForMigrate.into(), &who, amount)?; + // let the imbalance burn. + let _burned = T::Currency::burn_all_held( + &HoldReason::SlashForMigrate.into(), + &who, + Precision::BestEffort, + Fortitude::Force, + )?; + debug_assert!(amount.saturating_sub(_burned).is_zero()); + Self::deposit_event(Event::::Slashed { who, amount }); + Ok(()) + } } } #[cfg(feature = "runtime-benchmarks")] mod benchmarks { use super::{pallet::Pallet as StateTrieMigration, *}; - use frame_support::traits::{Currency, Get}; - use sp_runtime::traits::Saturating; + use frame_support::traits::fungible::{Inspect, Mutate}; use sp_std::prelude::*; // The size of the key seemingly makes no difference in the read/write time, so we make it // constant. const KEY: &[u8] = b"key"; + fn set_balance_for_deposit(caller: &T::AccountId, item: u32) -> BalanceOf { + let deposit = StateTrieMigration::::calculate_deposit_for(item); + let stash = T::Currency::minimum_balance() * BalanceOf::::from(1000u32) + deposit; + T::Currency::set_balance(caller, stash); + stash + } + frame_benchmarking::benchmarks! { continue_migrate { // note that this benchmark should migrate nothing, as we only want the overhead weight @@ -908,11 +976,13 @@ mod benchmarks { // function. let null = MigrationLimits::default(); let caller = frame_benchmarking::whitelisted_caller(); + let stash = set_balance_for_deposit::(&caller, null.item); // Allow signed migrations. SignedMigrationMaxLimits::::put(MigrationLimits { size: 1024, item: 5 }); - }: _(frame_system::RawOrigin::Signed(caller), null, 0, StateTrieMigration::::migration_process()) + }: _(frame_system::RawOrigin::Signed(caller.clone()), null, 0, StateTrieMigration::::migration_process()) verify { - assert_eq!(StateTrieMigration::::migration_process(), Default::default()) + assert_eq!(StateTrieMigration::::migration_process(), Default::default()); + assert_eq!(T::Currency::balance(&caller), stash) } continue_migrate_wrong_witness { @@ -936,26 +1006,18 @@ mod benchmarks { migrate_custom_top_success { let null = MigrationLimits::default(); - let caller = frame_benchmarking::whitelisted_caller(); - let deposit = T::SignedDepositBase::get().saturating_add( - T::SignedDepositPerItem::get().saturating_mul(1u32.into()), - ); - let stash = T::Currency::minimum_balance() * BalanceOf::::from(1000u32) + deposit; - T::Currency::make_free_balance_be(&caller, stash); + let caller: T::AccountId = frame_benchmarking::whitelisted_caller(); + let stash = set_balance_for_deposit::(&caller, null.item); }: migrate_custom_top(frame_system::RawOrigin::Signed(caller.clone()), Default::default(), 0) verify { assert_eq!(StateTrieMigration::::migration_process(), Default::default()); - assert_eq!(T::Currency::free_balance(&caller), stash) + assert_eq!(T::Currency::balance(&caller), stash) } migrate_custom_top_fail { let null = MigrationLimits::default(); - let caller = frame_benchmarking::whitelisted_caller(); - let deposit = T::SignedDepositBase::get().saturating_add( - T::SignedDepositPerItem::get().saturating_mul(1u32.into()), - ); - let stash = T::Currency::minimum_balance() * BalanceOf::::from(1000u32) + deposit; - T::Currency::make_free_balance_be(&caller, stash); + let caller: T::AccountId = frame_benchmarking::whitelisted_caller(); + let stash = set_balance_for_deposit::(&caller, null.item); // for tests, we need to make sure there is _something_ in storage that is being // migrated. sp_io::storage::set(b"foo", vec![1u8;33].as_ref()); @@ -971,24 +1033,19 @@ mod benchmarks { frame_system::Pallet::::assert_last_event( ::RuntimeEvent::from(crate::Event::Slashed { who: caller.clone(), - amount: T::SignedDepositBase::get() - .saturating_add(T::SignedDepositPerItem::get().saturating_mul(1u32.into())), + amount: StateTrieMigration::::calculate_deposit_for(1u32), }).into(), ); } verify { assert_eq!(StateTrieMigration::::migration_process(), Default::default()); // must have gotten slashed - assert!(T::Currency::free_balance(&caller) < stash) + assert!(T::Currency::balance(&caller) < stash) } migrate_custom_child_success { - let caller = frame_benchmarking::whitelisted_caller(); - let deposit = T::SignedDepositBase::get().saturating_add( - T::SignedDepositPerItem::get().saturating_mul(1u32.into()), - ); - let stash = T::Currency::minimum_balance() * BalanceOf::::from(1000u32) + deposit; - T::Currency::make_free_balance_be(&caller, stash); + let caller: T::AccountId = frame_benchmarking::whitelisted_caller(); + let stash = set_balance_for_deposit::(&caller, 0); }: migrate_custom_child( frame_system::RawOrigin::Signed(caller.clone()), StateTrieMigration::::childify(Default::default()), @@ -997,16 +1054,12 @@ mod benchmarks { ) verify { assert_eq!(StateTrieMigration::::migration_process(), Default::default()); - assert_eq!(T::Currency::free_balance(&caller), stash); + assert_eq!(T::Currency::balance(&caller), stash); } migrate_custom_child_fail { - let caller = frame_benchmarking::whitelisted_caller(); - let deposit = T::SignedDepositBase::get().saturating_add( - T::SignedDepositPerItem::get().saturating_mul(1u32.into()), - ); - let stash = T::Currency::minimum_balance() * BalanceOf::::from(1000u32) + deposit; - T::Currency::make_free_balance_be(&caller, stash); + let caller: T::AccountId = frame_benchmarking::whitelisted_caller(); + let stash = set_balance_for_deposit::(&caller, 1); // for tests, we need to make sure there is _something_ in storage that is being // migrated. sp_io::default_child_storage::set(b"top", b"foo", vec![1u8;33].as_ref()); @@ -1023,7 +1076,7 @@ mod benchmarks { verify { assert_eq!(StateTrieMigration::::migration_process(), Default::default()); // must have gotten slashed - assert!(T::Currency::free_balance(&caller) < stash) + assert!(T::Currency::balance(&caller) < stash) } process_top_key { @@ -1052,7 +1105,7 @@ mod mock { use crate as pallet_state_trie_migration; use frame_support::{ derive_impl, parameter_types, - traits::{ConstU32, ConstU64, Hooks}, + traits::{ConstU32, Hooks}, weights::Weight, }; use frame_system::{EnsureRoot, EnsureSigned}; @@ -1060,10 +1113,7 @@ mod mock { storage::{ChildInfo, StateVersion}, H256, }; - use sp_runtime::{ - traits::{BlakeTwo256, Header as _, IdentityLookup}, - BuildStorage, StorageChild, - }; + use sp_runtime::{traits::Header as _, BuildStorage, StorageChild}; type Block = frame_system::mocking::MockBlockU32; @@ -1083,29 +1133,9 @@ mod mock { #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); - type BlockLength = (); - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type Nonce = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; type Block = Block; - type RuntimeEvent = RuntimeEvent; type BlockHashCount = ConstU32<250>; - type DbWeight = (); - type Version = (); - type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = SS58Prefix; - type OnSetCode = (); - type MaxConsumers = ConstU32<16>; } parameter_types! { @@ -1114,21 +1144,10 @@ mod mock { pub const MigrationMaxKeyLen: u32 = 512; } + #[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] impl pallet_balances::Config for Test { - type Balance = u64; - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ConstU64<1>; - type AccountStore = System; - type MaxLocks = (); - type MaxReserves = (); type ReserveIdentifier = [u8; 8]; - type WeightInfo = (); - type FreezeIdentifier = (); - type MaxFreezes = (); - type RuntimeHoldReason = (); - type RuntimeFreezeReason = (); - type MaxHolds = (); + type AccountStore = System; } /// Test only Weights for state migration. @@ -1158,8 +1177,8 @@ mod mock { } } + #[derive_impl(super::config_preludes::TestDefaultConfig as pallet_state_trie_migration::DefaultConfig)] impl pallet_state_trie_migration::Config for Test { - type RuntimeEvent = RuntimeEvent; type ControlOrigin = EnsureRoot; type Currency = Balances; type MaxKeyLen = MigrationMaxKeyLen; @@ -1270,6 +1289,7 @@ mod mock { #[cfg(test)] mod test { use super::{mock::*, *}; + use frame_support::assert_ok; use sp_runtime::{bounded_vec, traits::Bounded, StateVersion}; #[test] @@ -1499,10 +1519,9 @@ mod test { while !MigrationProcess::::get().finished() { // first we compute the task to get the accurate consumption. let mut task = StateTrieMigration::migration_process(); - let result = task.migrate_until_exhaustion( + assert_ok!(task.migrate_until_exhaustion( StateTrieMigration::signed_migration_max_limits().unwrap(), - ); - assert!(result.is_ok()); + )); frame_support::assert_ok!(StateTrieMigration::continue_migrate( RuntimeOrigin::signed(1), @@ -1513,6 +1532,7 @@ mod test { // no funds should remain reserved. assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Balances::free_balance(&1), 1000); // and the task should be updated assert!(matches!( @@ -1523,6 +1543,37 @@ mod test { }); } + #[test] + fn continue_migrate_slashing_works() { + new_test_ext(StateVersion::V0, true, None, None).execute_with(|| { + assert_eq!(MigrationProcess::::get(), Default::default()); + + // Allow signed migrations. + SignedMigrationMaxLimits::::put(MigrationLimits { size: 1024, item: 5 }); + + // first we compute the task to get the accurate consumption. + let mut task = StateTrieMigration::migration_process(); + assert_ok!(task.migrate_until_exhaustion( + StateTrieMigration::signed_migration_max_limits().unwrap(), + )); + + // can't submit with `real_size_upper` < `task.dyn_size` expect slashing + frame_support::assert_ok!(StateTrieMigration::continue_migrate( + RuntimeOrigin::signed(1), + StateTrieMigration::signed_migration_max_limits().unwrap(), + task.dyn_size - 1, + MigrationProcess::::get() + )); + // no funds should remain reserved. + assert_eq!(Balances::reserved_balance(&1), 0); + // user was slashed + assert_eq!( + Balances::free_balance(&1), + 1000 - StateTrieMigration::calculate_deposit_for(5) + ); + }); + } + #[test] fn custom_migrate_top_works() { let correct_witness = 3 + sp_core::storage::TRIE_VALUE_NODE_THRESHOLD * 3 + 1 + 2 + 3; @@ -1565,7 +1616,7 @@ mod test { assert_eq!(Balances::reserved_balance(&1), 0); assert_eq!( Balances::free_balance(&1), - 1000 - (3 * SignedDepositPerItem::get() + SignedDepositBase::get()) + 1000 - StateTrieMigration::calculate_deposit_for(3) ); }); } @@ -1600,7 +1651,7 @@ mod test { assert_eq!(Balances::reserved_balance(&1), 0); assert_eq!( Balances::free_balance(&1), - 1000 - (2 * SignedDepositPerItem::get() + SignedDepositBase::get()) + 1000 - StateTrieMigration::calculate_deposit_for(2) ); }); } diff --git a/substrate/frame/state-trie-migration/src/weights.rs b/substrate/frame/state-trie-migration/src/weights.rs index df3338fdc17d..8fa80b38957d 100644 --- a/substrate/frame/state-trie-migration/src/weights.rs +++ b/substrate/frame/state-trie-migration/src/weights.rs @@ -15,32 +15,29 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_state_trie_migration +//! Autogenerated weights for `pallet_state_trie_migration` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-01-24, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-e8ezs4ez-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! HOSTNAME: `runner-grjcggob-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate +// target/production/substrate-node // benchmark // pallet -// --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_state_trie_migration -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* -// --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/state-trie-migration/src/weights.rs -// --header=./HEADER-APACHE2 -// --template=./.maintain/frame-weight-template.hbs +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_state_trie_migration +// --chain=dev +// --header=./substrate/HEADER-APACHE2 +// --output=./substrate/frame/state-trie-migration/src/weights.rs +// --template=./substrate/.maintain/frame-weight-template.hbs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,7 +47,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; -/// Weight functions needed for pallet_state_trie_migration. +/// Weight functions needed for `pallet_state_trie_migration`. pub trait WeightInfo { fn continue_migrate() -> Weight; fn continue_migrate_wrong_witness() -> Weight; @@ -61,157 +58,181 @@ pub trait WeightInfo { fn process_top_key(v: u32, ) -> Weight; } -/// Weights for pallet_state_trie_migration using the Substrate node and recommended hardware. +/// Weights for `pallet_state_trie_migration` using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: StateTrieMigration SignedMigrationMaxLimits (r:1 w:0) - /// Proof: StateTrieMigration SignedMigrationMaxLimits (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: StateTrieMigration MigrationProcess (r:1 w:1) - /// Proof: StateTrieMigration MigrationProcess (max_values: Some(1), max_size: Some(1042), added: 1537, mode: MaxEncodedLen) + /// Storage: `StateTrieMigration::SignedMigrationMaxLimits` (r:1 w:0) + /// Proof: `StateTrieMigration::SignedMigrationMaxLimits` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:0) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) + /// Storage: `StateTrieMigration::MigrationProcess` (r:1 w:1) + /// Proof: `StateTrieMigration::MigrationProcess` (`max_values`: Some(1), `max_size`: Some(1042), added: 1537, mode: `MaxEncodedLen`) fn continue_migrate() -> Weight { // Proof Size summary in bytes: // Measured: `108` - // Estimated: `2527` - // Minimum execution time: 14_297_000 picoseconds. - Weight::from_parts(14_832_000, 2527) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Estimated: `3640` + // Minimum execution time: 18_520_000 picoseconds. + Weight::from_parts(19_171_000, 3640) + .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: StateTrieMigration SignedMigrationMaxLimits (r:1 w:0) - /// Proof: StateTrieMigration SignedMigrationMaxLimits (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: `StateTrieMigration::SignedMigrationMaxLimits` (r:1 w:0) + /// Proof: `StateTrieMigration::SignedMigrationMaxLimits` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) fn continue_migrate_wrong_witness() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `1493` - // Minimum execution time: 4_237_000 picoseconds. - Weight::from_parts(4_646_000, 1493) + // Minimum execution time: 3_786_000 picoseconds. + Weight::from_parts(4_038_000, 1493) .saturating_add(T::DbWeight::get().reads(1_u64)) } + /// Storage: `Balances::Holds` (r:1 w:0) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) fn migrate_custom_top_success() -> Weight { // Proof Size summary in bytes: // Measured: `0` - // Estimated: `0` - // Minimum execution time: 8_898_000 picoseconds. - Weight::from_parts(9_237_000, 0) + // Estimated: `3640` + // Minimum execution time: 11_144_000 picoseconds. + Weight::from_parts(11_556_000, 3640) + .saturating_add(T::DbWeight::get().reads(1_u64)) } - /// Storage: unknown `0x666f6f` (r:1 w:1) - /// Proof Skipped: unknown `0x666f6f` (r:1 w:1) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x666f6f` (r:1 w:1) + /// Proof: UNKNOWN KEY `0x666f6f` (r:1 w:1) fn migrate_custom_top_fail() -> Weight { // Proof Size summary in bytes: // Measured: `113` - // Estimated: `3578` - // Minimum execution time: 29_291_000 picoseconds. - Weight::from_parts(30_424_000, 3578) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Estimated: `3640` + // Minimum execution time: 59_288_000 picoseconds. + Weight::from_parts(60_276_000, 3640) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } + /// Storage: `Balances::Holds` (r:1 w:0) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) fn migrate_custom_child_success() -> Weight { // Proof Size summary in bytes: // Measured: `0` - // Estimated: `0` - // Minimum execution time: 9_094_000 picoseconds. - Weight::from_parts(9_544_000, 0) + // Estimated: `3640` + // Minimum execution time: 11_258_000 picoseconds. + Weight::from_parts(11_626_000, 3640) + .saturating_add(T::DbWeight::get().reads(1_u64)) } - /// Storage: unknown `0x666f6f` (r:1 w:1) - /// Proof Skipped: unknown `0x666f6f` (r:1 w:1) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x666f6f` (r:1 w:1) + /// Proof: UNKNOWN KEY `0x666f6f` (r:1 w:1) fn migrate_custom_child_fail() -> Weight { // Proof Size summary in bytes: - // Measured: `105` - // Estimated: `3570` - // Minimum execution time: 30_286_000 picoseconds. - Weight::from_parts(30_948_000, 3570) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Measured: `106` + // Estimated: `3640` + // Minimum execution time: 61_575_000 picoseconds. + Weight::from_parts(63_454_000, 3640) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: unknown `0x6b6579` (r:1 w:1) - /// Proof Skipped: unknown `0x6b6579` (r:1 w:1) + /// Storage: UNKNOWN KEY `0x6b6579` (r:1 w:1) + /// Proof: UNKNOWN KEY `0x6b6579` (r:1 w:1) /// The range of component `v` is `[1, 4194304]`. fn process_top_key(v: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `197 + v * (1 ±0)` // Estimated: `3662 + v * (1 ±0)` - // Minimum execution time: 5_420_000 picoseconds. - Weight::from_parts(5_560_000, 3662) + // Minimum execution time: 5_259_000 picoseconds. + Weight::from_parts(5_433_000, 3662) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_139, 0).saturating_mul(v.into())) + .saturating_add(Weight::from_parts(1_159, 0).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(v.into())) } } -// For backwards compatibility and tests +// For backwards compatibility and tests. impl WeightInfo for () { - /// Storage: StateTrieMigration SignedMigrationMaxLimits (r:1 w:0) - /// Proof: StateTrieMigration SignedMigrationMaxLimits (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) - /// Storage: StateTrieMigration MigrationProcess (r:1 w:1) - /// Proof: StateTrieMigration MigrationProcess (max_values: Some(1), max_size: Some(1042), added: 1537, mode: MaxEncodedLen) + /// Storage: `StateTrieMigration::SignedMigrationMaxLimits` (r:1 w:0) + /// Proof: `StateTrieMigration::SignedMigrationMaxLimits` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:0) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) + /// Storage: `StateTrieMigration::MigrationProcess` (r:1 w:1) + /// Proof: `StateTrieMigration::MigrationProcess` (`max_values`: Some(1), `max_size`: Some(1042), added: 1537, mode: `MaxEncodedLen`) fn continue_migrate() -> Weight { // Proof Size summary in bytes: // Measured: `108` - // Estimated: `2527` - // Minimum execution time: 14_297_000 picoseconds. - Weight::from_parts(14_832_000, 2527) - .saturating_add(RocksDbWeight::get().reads(2_u64)) + // Estimated: `3640` + // Minimum execution time: 18_520_000 picoseconds. + Weight::from_parts(19_171_000, 3640) + .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: StateTrieMigration SignedMigrationMaxLimits (r:1 w:0) - /// Proof: StateTrieMigration SignedMigrationMaxLimits (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + /// Storage: `StateTrieMigration::SignedMigrationMaxLimits` (r:1 w:0) + /// Proof: `StateTrieMigration::SignedMigrationMaxLimits` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) fn continue_migrate_wrong_witness() -> Weight { // Proof Size summary in bytes: // Measured: `76` // Estimated: `1493` - // Minimum execution time: 4_237_000 picoseconds. - Weight::from_parts(4_646_000, 1493) + // Minimum execution time: 3_786_000 picoseconds. + Weight::from_parts(4_038_000, 1493) .saturating_add(RocksDbWeight::get().reads(1_u64)) } + /// Storage: `Balances::Holds` (r:1 w:0) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) fn migrate_custom_top_success() -> Weight { // Proof Size summary in bytes: // Measured: `0` - // Estimated: `0` - // Minimum execution time: 8_898_000 picoseconds. - Weight::from_parts(9_237_000, 0) + // Estimated: `3640` + // Minimum execution time: 11_144_000 picoseconds. + Weight::from_parts(11_556_000, 3640) + .saturating_add(RocksDbWeight::get().reads(1_u64)) } - /// Storage: unknown `0x666f6f` (r:1 w:1) - /// Proof Skipped: unknown `0x666f6f` (r:1 w:1) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x666f6f` (r:1 w:1) + /// Proof: UNKNOWN KEY `0x666f6f` (r:1 w:1) fn migrate_custom_top_fail() -> Weight { // Proof Size summary in bytes: // Measured: `113` - // Estimated: `3578` - // Minimum execution time: 29_291_000 picoseconds. - Weight::from_parts(30_424_000, 3578) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Estimated: `3640` + // Minimum execution time: 59_288_000 picoseconds. + Weight::from_parts(60_276_000, 3640) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } + /// Storage: `Balances::Holds` (r:1 w:0) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) fn migrate_custom_child_success() -> Weight { // Proof Size summary in bytes: // Measured: `0` - // Estimated: `0` - // Minimum execution time: 9_094_000 picoseconds. - Weight::from_parts(9_544_000, 0) + // Estimated: `3640` + // Minimum execution time: 11_258_000 picoseconds. + Weight::from_parts(11_626_000, 3640) + .saturating_add(RocksDbWeight::get().reads(1_u64)) } - /// Storage: unknown `0x666f6f` (r:1 w:1) - /// Proof Skipped: unknown `0x666f6f` (r:1 w:1) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x666f6f` (r:1 w:1) + /// Proof: UNKNOWN KEY `0x666f6f` (r:1 w:1) fn migrate_custom_child_fail() -> Weight { // Proof Size summary in bytes: - // Measured: `105` - // Estimated: `3570` - // Minimum execution time: 30_286_000 picoseconds. - Weight::from_parts(30_948_000, 3570) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Measured: `106` + // Estimated: `3640` + // Minimum execution time: 61_575_000 picoseconds. + Weight::from_parts(63_454_000, 3640) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: unknown `0x6b6579` (r:1 w:1) - /// Proof Skipped: unknown `0x6b6579` (r:1 w:1) + /// Storage: UNKNOWN KEY `0x6b6579` (r:1 w:1) + /// Proof: UNKNOWN KEY `0x6b6579` (r:1 w:1) /// The range of component `v` is `[1, 4194304]`. fn process_top_key(v: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `197 + v * (1 ±0)` // Estimated: `3662 + v * (1 ±0)` - // Minimum execution time: 5_420_000 picoseconds. - Weight::from_parts(5_560_000, 3662) + // Minimum execution time: 5_259_000 picoseconds. + Weight::from_parts(5_433_000, 3662) // Standard Error: 1 - .saturating_add(Weight::from_parts(1_139, 0).saturating_mul(v.into())) + .saturating_add(Weight::from_parts(1_159, 0).saturating_mul(v.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(v.into())) diff --git a/substrate/frame/transaction-storage/src/lib.rs b/substrate/frame/transaction-storage/src/lib.rs index fb8ada0f5f99..d32cfe169ce0 100644 --- a/substrate/frame/transaction-storage/src/lib.rs +++ b/substrate/frame/transaction-storage/src/lib.rs @@ -32,10 +32,7 @@ use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{ dispatch::GetDispatchInfo, traits::{ - fungible::{ - hold::Balanced as FnBalanced, Inspect as FnInspect, Mutate as FnMutate, - MutateHold as FnMutateHold, - }, + fungible::{hold::Balanced, Inspect, Mutate, MutateHold}, tokens::fungible::Credit, OnUnbalanced, }, @@ -49,7 +46,7 @@ use sp_transaction_storage_proof::{ /// A type alias for the balance type from this pallet's point of view. type BalanceOf = - <::Currency as FnInspect<::AccountId>>::Balance; + <::Currency as Inspect<::AccountId>>::Balance; pub type CreditOf = Credit<::AccountId, ::Currency>; // Re-export pallet items so that they can be accessed from the crate namespace. @@ -111,9 +108,9 @@ pub mod pallet { + GetDispatchInfo + From>; /// The fungible type for this pallet. - type Currency: FnMutate - + FnMutateHold - + FnBalanced; + type Currency: Mutate + + MutateHold + + Balanced; /// The overarching runtime hold reason. type RuntimeHoldReason: From; /// Handler for the unbalanced decrease when fees are burned. diff --git a/substrate/frame/transaction-storage/src/mock.rs b/substrate/frame/transaction-storage/src/mock.rs index 4b2fe5a2a8ca..31f539327cda 100644 --- a/substrate/frame/transaction-storage/src/mock.rs +++ b/substrate/frame/transaction-storage/src/mock.rs @@ -50,12 +50,7 @@ impl frame_system::Config for Test { #[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] impl pallet_balances::Config for Test { - type Balance = u64; - type ExistentialDeposit = ConstU64<1>; type AccountStore = System; - type RuntimeHoldReason = RuntimeHoldReason; - type RuntimeFreezeReason = RuntimeFreezeReason; - type MaxHolds = ConstU32<128>; } impl pallet_transaction_storage::Config for Test {