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 <>
This commit is contained in:
Branislav Kontur
2024-01-24 14:18:54 +01:00
committed by GitHub
parent a989ddfab9
commit 4374b5d598
17 changed files with 312 additions and 789 deletions
Generated
-15
View File
@@ -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"
-1
View File
@@ -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",
@@ -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.
+3 -2
View File
@@ -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<NisCounterpartInstance> 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<AccountId>;
+2 -1
View File
@@ -533,7 +533,7 @@ impl pallet_balances::Config for Runtime {
type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
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<AccountId>;
type Currency = Balances;
type RuntimeHoldReason = RuntimeHoldReason;
type MaxKeyLen = MigrationMaxKeyLen;
type SignedDepositPerItem = MigrationSignedDepositPerItem;
type SignedDepositBase = MigrationSignedDepositBase;
+1 -1
View File
@@ -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<AccountId>;
type AccountData = pallet_balances::AccountData<u64>;
}
parameter_types! {
-49
View File
@@ -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",
]
-25
View File
@@ -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
-424
View File
@@ -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<T> = <T as frame_system::Config>::AccountId;
type BalanceOf<T> = <<T as Config>::Currency as Currency<AccountIdOf<T>>>::Balance;
type NegativeImbalanceOf<T> =
<<T as Config>::Currency as Currency<AccountIdOf<T>>>::NegativeImbalance;
type AccountIdLookupOf<T> = <<T as frame_system::Config>::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<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
/// The currency trait.
type Currency: ReservableCurrency<Self::AccountId>;
/// Reservation fee.
#[pallet::constant]
type ReservationFee: Get<BalanceOf<Self>>;
/// What to do with slashed funds.
type Slashed: OnUnbalanced<NegativeImbalanceOf<Self>>;
/// The origin which may forcibly set or remove a name. Root can always do this.
type ForceOrigin: EnsureOrigin<Self::RuntimeOrigin>;
/// The minimum length a name may be.
#[pallet::constant]
type MinLength: Get<u32>;
/// The maximum length a name may be.
#[pallet::constant]
type MaxLength: Get<u32>;
}
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
/// 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<T>,
},
/// 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<T>,
},
}
/// Error for the Nicks pallet.
#[pallet::error]
pub enum Error<T> {
/// 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<T: Config> =
StorageMap<_, Twox64Concat, T::AccountId, (BoundedVec<u8, T::MaxLength>, BalanceOf<T>)>;
#[pallet::pallet]
pub struct Pallet<T>(_);
#[pallet::call]
impl<T: Config> Pallet<T> {
/// 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<T>, name: Vec<u8>) -> DispatchResult {
let sender = ensure_signed(origin)?;
let bounded_name: BoundedVec<_, _> =
name.try_into().map_err(|_| Error::<T>::TooLong)?;
ensure!(bounded_name.len() >= T::MinLength::get() as usize, Error::<T>::TooShort);
let deposit = if let Some((_, deposit)) = <NameOf<T>>::get(&sender) {
Self::deposit_event(Event::<T>::NameChanged { who: sender.clone() });
deposit
} else {
let deposit = T::ReservationFee::get();
T::Currency::reserve(&sender, deposit)?;
Self::deposit_event(Event::<T>::NameSet { who: sender.clone() });
deposit
};
<NameOf<T>>::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<T>) -> DispatchResult {
let sender = ensure_signed(origin)?;
let deposit = <NameOf<T>>::take(&sender).ok_or(Error::<T>::Unnamed)?.1;
let err_amount = T::Currency::unreserve(&sender, deposit);
debug_assert!(err_amount.is_zero());
Self::deposit_event(Event::<T>::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<T>, target: AccountIdLookupOf<T>) -> 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 = <NameOf<T>>::take(&target).ok_or(Error::<T>::Unnamed)?.1;
// Slash their deposit from them.
T::Slashed::on_unbalanced(T::Currency::slash_reserved(&target, deposit).0);
Self::deposit_event(Event::<T>::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<T>,
target: AccountIdLookupOf<T>,
name: Vec<u8>,
) -> DispatchResult {
T::ForceOrigin::ensure_origin(origin)?;
let bounded_name: BoundedVec<_, _> =
name.try_into().map_err(|_| Error::<T>::TooLong)?;
let target = T::Lookup::lookup(target)?;
let deposit = <NameOf<T>>::get(&target).map(|x| x.1).unwrap_or_else(Zero::zero);
<NameOf<T>>::insert(&target, (bounded_name, deposit));
Self::deposit_event(Event::<T>::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<Test>;
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<Self::AccountId>;
type Block = Block;
type RuntimeEvent = RuntimeEvent;
type BlockHashCount = ConstU64<250>;
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = pallet_balances::AccountData<u64>;
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<One, u64>;
type MinLength = ConstU32<3>;
type MaxLength = ConstU32<16>;
}
fn new_test_ext() -> sp_io::TestExternalities {
let mut t = frame_system::GenesisConfig::<Test>::default().build_storage().unwrap();
pallet_balances::GenesisConfig::<Test> { 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!(<NameOf<Test>>::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::<Test>::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::<Test>::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) = <NameOf<Test>>::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!(<NameOf<Test>>::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!(<NameOf<Test>>::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::<Test>::Unnamed);
assert_noop!(
Nicks::set_name(RuntimeOrigin::signed(3), b"Dave".to_vec()),
pallet_balances::Error::<Test, _>::InsufficientBalance
);
assert_noop!(
Nicks::set_name(RuntimeOrigin::signed(1), b"Ga".to_vec()),
Error::<Test>::TooShort
);
assert_noop!(
Nicks::set_name(RuntimeOrigin::signed(1), b"Gavin James Wood, Esquire".to_vec()),
Error::<Test>::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
);
});
}
}
+4 -7
View File
@@ -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<T> =
<<T as Config>::Currency as FunInspect<<T as frame_system::Config>::AccountId>>::Balance;
<<T as Config>::Currency as Inspect<<T as frame_system::Config>::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<Self::AccountId>
+ FunMutateFreeze<Self::AccountId, Id = Self::RuntimeFreezeReason>;
type Currency: Mutate<Self::AccountId>
+ MutateFreeze<Self::AccountId, Id = Self::RuntimeFreezeReason>;
/// The overarching freeze reason.
type RuntimeFreezeReason: From<FreezeReason>;
+17 -11
View File
@@ -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<T::AccountId>)]
#[benchmarks(where T::Currency: fungible::Mutate<T::AccountId>)]
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::<T>());
<T::Currency as fungible::Mutate<_>>::set_balance(&caller, init_bal::<T>());
#[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::<T>());
<T::Currency as fungible::Mutate<_>>::set_balance(&alice, init_bal::<T>());
System::<T>::set_block_number(1u32.into());
assert!(SafeMode::<T>::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::<T>());
<T::Currency as fungible::Mutate<_>>::set_balance(&alice, init_bal::<T>());
// Mock the storage. This is needed in case the `EnterDepositAmount` is zero.
let block: BlockNumberFor<T> = 1u32.into();
let bal: BalanceOf<T> = 1u32.into();
@@ -169,7 +169,7 @@ mod benchmarks {
_(origin, alice.clone(), 1u32.into());
assert!(!Deposits::<T>::contains_key(&alice, &block));
assert_eq!(T::Currency::balance(&alice), init_bal::<T>());
assert_eq!(<T::Currency as fungible::Inspect<_>>::balance(&alice), init_bal::<T>());
Ok(())
}
@@ -180,7 +180,7 @@ mod benchmarks {
.map_err(|_| BenchmarkError::Weightless)?;
let alice: T::AccountId = whitelisted_caller();
T::Currency::set_balance(&alice, init_bal::<T>());
<T::Currency as fungible::Mutate<_>>::set_balance(&alice, init_bal::<T>());
// Mock the storage. This is needed in case the `EnterDepositAmount` is zero.
let block: BlockNumberFor<T> = 1u32.into();
@@ -189,7 +189,10 @@ mod benchmarks {
T::Currency::hold(&&HoldReason::EnterOrExtend.into(), &alice, bal)?;
EnteredUntil::<T>::put(&block);
assert_eq!(T::Currency::balance(&alice), init_bal::<T>() - 1u32.into());
assert_eq!(
<T::Currency as fungible::Inspect<_>>::balance(&alice),
init_bal::<T>() - 1u32.into()
);
assert!(SafeMode::<T>::do_exit(ExitReason::Force).is_ok());
System::<T>::set_block_number(System::<T>::block_number() + One::one());
@@ -200,7 +203,7 @@ mod benchmarks {
_(force_origin as T::RuntimeOrigin, alice.clone(), block);
assert!(!Deposits::<T>::contains_key(&alice, block));
assert_eq!(T::Currency::balance(&alice), init_bal::<T>());
assert_eq!(<T::Currency as fungible::Inspect<_>>::balance(&alice), init_bal::<T>());
Ok(())
}
@@ -210,7 +213,7 @@ mod benchmarks {
.map_err(|_| BenchmarkError::Weightless)?;
let alice: T::AccountId = whitelisted_caller();
T::Currency::set_balance(&alice, init_bal::<T>());
<T::Currency as fungible::Mutate<_>>::set_balance(&alice, init_bal::<T>());
// Mock the storage. This is needed in case the `EnterDepositAmount` is zero.
let block: BlockNumberFor<T> = 1u32.into();
@@ -224,7 +227,10 @@ mod benchmarks {
_(force_origin as T::RuntimeOrigin, alice.clone(), block);
assert!(!Deposits::<T>::contains_key(&alice, block));
assert_eq!(T::Currency::balance(&alice), init_bal::<T>() - 1u32.into());
assert_eq!(
<T::Currency as fungible::Inspect<_>>::balance(&alice),
init_bal::<T>() - 1u32.into()
);
Ok(())
}
+5 -5
View File
@@ -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<T> =
<<T as Config>::Currency as FunInspect<<T as frame_system::Config>::AccountId>>::Balance;
<<T as Config>::Currency as fungible::Inspect<<T as frame_system::Config>::AccountId>>::Balance;
#[frame_support::pallet]
pub mod pallet {
@@ -117,8 +117,8 @@ pub mod pallet {
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
/// Currency type for this pallet, used for Deposits.
type Currency: FunHoldInspect<Self::AccountId>
+ FunHoldMutate<Self::AccountId, Reason = Self::RuntimeHoldReason>;
type Currency: Inspect<Self::AccountId>
+ Mutate<Self::AccountId, Reason = Self::RuntimeHoldReason>;
/// The hold reason when reserving funds for entering or extending the safe-mode.
type RuntimeHoldReason: From<HoldReason>;
+3 -37
View File
@@ -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<Self::AccountId>;
type Block = Block;
type RuntimeEvent = RuntimeEvent;
type BlockHashCount = ConstU64<250>;
type Version = ();
type PalletInfo = PalletInfo;
type OnNewAccount = ();
type OnKilledAccount = ();
type AccountData = pallet_balances::AccountData<u64>;
type SystemWeightInfo = ();
type SS58Prefix = ();
type OnSetCode = ();
type MaxConsumers = ConstU32<16>;
type Lookup = IdentityLookup<Self::AccountId>;
}
#[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 {
+155 -104
View File
@@ -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<T> =
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
<<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance;
/// The progress of either the top or child keys.
#[derive(
@@ -441,20 +445,58 @@ pub mod pallet {
#[pallet::pallet]
pub struct Pallet<T>(_);
/// 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<Self::RuntimeOrigin>;
#[pallet::no_default]
type ControlOrigin: EnsureOrigin<Self::RuntimeOrigin>;
/// Filter on which origin that trigger the manual migrations.
#[pallet::no_default]
type SignedFilter: EnsureOrigin<Self::RuntimeOrigin, Success = Self::AccountId>;
/// The overarching event type.
#[pallet::no_default_bounds]
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
/// The currency provider type.
type Currency: Currency<Self::AccountId>;
#[pallet::no_default]
type Currency: InspectHold<Self::AccountId>
+ Mutate<Self::AccountId>
+ MutateHold<Self::AccountId, Reason = Self::RuntimeHoldReason>
+ Balanced<Self::AccountId>;
/// The overarching runtime hold reason.
#[pallet::no_default_bounds]
type RuntimeHoldReason: From<HoldReason>;
/// Maximal number of bytes that a key can have.
///
@@ -479,19 +521,23 @@ pub mod pallet {
/// <https://www.shawntabrizi.com/blog/substrate/querying-substrate-storage-via-rpc/>
#[pallet::constant]
#[pallet::no_default]
type MaxKeyLen: Get<u32>;
/// 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<BalanceOf<Self>>;
/// The base value of [`Config::SignedDepositPerItem`].
///
/// Final deposit is `items * SignedDepositPerItem + SignedDepositBase`.
#[pallet::no_default]
type SignedDepositBase: Get<BalanceOf<Self>>;
/// 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::<T>::NotEnoughFunds);
let deposit = Self::calculate_deposit_for(limits.item);
ensure!(
T::Currency::can_hold(&HoldReason::SlashForMigrate.into(), &who, deposit),
Error::<T>::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::<T>::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::<T>::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::<T>::Slashed { who, amount: deposit });
debug_assert!(_remainder.is_zero());
Self::slash(who, deposit)?;
Ok(().into())
} else {
Self::deposit_event(Event::<T>::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::<T>::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::<T>::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> {
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<T>) -> 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::<T>::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<T: Config>(caller: &T::AccountId, item: u32) -> BalanceOf<T> {
let deposit = StateTrieMigration::<T>::calculate_deposit_for(item);
let stash = T::Currency::minimum_balance() * BalanceOf::<T>::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::<T>(&caller, null.item);
// Allow signed migrations.
SignedMigrationMaxLimits::<T>::put(MigrationLimits { size: 1024, item: 5 });
}: _(frame_system::RawOrigin::Signed(caller), null, 0, StateTrieMigration::<T>::migration_process())
}: _(frame_system::RawOrigin::Signed(caller.clone()), null, 0, StateTrieMigration::<T>::migration_process())
verify {
assert_eq!(StateTrieMigration::<T>::migration_process(), Default::default())
assert_eq!(StateTrieMigration::<T>::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::<T>::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::<T>(&caller, null.item);
}: migrate_custom_top(frame_system::RawOrigin::Signed(caller.clone()), Default::default(), 0)
verify {
assert_eq!(StateTrieMigration::<T>::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::<T>::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::<T>(&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::<T>::assert_last_event(
<T as Config>::RuntimeEvent::from(crate::Event::Slashed {
who: caller.clone(),
amount: T::SignedDepositBase::get()
.saturating_add(T::SignedDepositPerItem::get().saturating_mul(1u32.into())),
amount: StateTrieMigration::<T>::calculate_deposit_for(1u32),
}).into(),
);
}
verify {
assert_eq!(StateTrieMigration::<T>::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::<T>::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::<T>(&caller, 0);
}: migrate_custom_child(
frame_system::RawOrigin::Signed(caller.clone()),
StateTrieMigration::<T>::childify(Default::default()),
@@ -997,16 +1054,12 @@ mod benchmarks {
)
verify {
assert_eq!(StateTrieMigration::<T>::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::<T>::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::<T>(&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::<T>::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<Test>;
@@ -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<Self::AccountId>;
type Block = Block;
type RuntimeEvent = RuntimeEvent;
type BlockHashCount = ConstU32<250>;
type DbWeight = ();
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = pallet_balances::AccountData<u64>;
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<u64>;
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::<Test>::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::<Test>::get(), Default::default());
// Allow signed migrations.
SignedMigrationMaxLimits::<Test>::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::<Test>::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)
);
});
}
+114 -93
View File
@@ -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<T>(PhantomData<T>);
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
/// 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()))
@@ -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<T> =
<<T as Config>::Currency as FnInspect<<T as frame_system::Config>::AccountId>>::Balance;
<<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance;
pub type CreditOf<T> = Credit<<T as frame_system::Config>::AccountId, <T as Config>::Currency>;
// Re-export pallet items so that they can be accessed from the crate namespace.
@@ -111,9 +108,9 @@ pub mod pallet {
+ GetDispatchInfo
+ From<frame_system::Call<Self>>;
/// The fungible type for this pallet.
type Currency: FnMutate<Self::AccountId>
+ FnMutateHold<Self::AccountId, Reason = Self::RuntimeHoldReason>
+ FnBalanced<Self::AccountId>;
type Currency: Mutate<Self::AccountId>
+ MutateHold<Self::AccountId, Reason = Self::RuntimeHoldReason>
+ Balanced<Self::AccountId>;
/// The overarching runtime hold reason.
type RuntimeHoldReason: From<HoldReason>;
/// Handler for the unbalanced decrease when fees are burned.
@@ -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 {