mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-28 01:38:04 +00:00
Recovery Pallet benchmarking (#11176)
* Created benchmarks * Added recovery benchmarks * benchmark for `create_recovery` * benchmark for `initiate_recovery` * benchmark for `vouch_recovery` * benchmark for `claim_recovery` * benchmark for `close_recovery` * benchmark for `remove_recovery` * benchmark for `cancel_recovered` * benchmark for `as_recovered` * Some refactoring * Some refactoring * Fix create_recovery benchmark * fix close_recovery benchmark test * fixed issues with failing tests * Update frame/recovery/src/benchmarking.rs Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * removed repetitive code * create weights file * Used weights to annotate extrinsics * Added WeightInfo implementation to mock * Beauty fixes Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update frame/recovery/src/benchmarking.rs Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Update frame/recovery/src/benchmarking.rs Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Set vec to be mut * set delay_period to use non-zero amount * set delay default * Add weights Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,371 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2022 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.
|
||||
|
||||
#![cfg(feature = "runtime-benchmarks")]
|
||||
|
||||
use super::*;
|
||||
|
||||
use crate::Pallet;
|
||||
use frame_benchmarking::{account, benchmarks, whitelisted_caller};
|
||||
use frame_support::traits::{Currency, Get};
|
||||
use frame_system::RawOrigin;
|
||||
use sp_runtime::traits::Bounded;
|
||||
|
||||
const SEED: u32 = 0;
|
||||
const DEFAULT_DELAY: u32 = 0;
|
||||
|
||||
fn assert_last_event<T: Config>(generic_event: <T as Config>::Event) {
|
||||
frame_system::Pallet::<T>::assert_last_event(generic_event.into());
|
||||
}
|
||||
|
||||
fn get_total_deposit<T: Config>(
|
||||
bounded_friends: &FriendsOf<T>,
|
||||
) -> Option<<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance>
|
||||
{
|
||||
let friend_deposit = T::FriendDepositFactor::get()
|
||||
.checked_mul(&bounded_friends.len().saturated_into())
|
||||
.unwrap();
|
||||
|
||||
T::ConfigDepositBase::get().checked_add(&friend_deposit)
|
||||
}
|
||||
|
||||
fn generate_friends<T: Config>(num: u32) -> Vec<<T as frame_system::Config>::AccountId> {
|
||||
// Create friends
|
||||
let mut friends = (0..num).map(|x| account("friend", x, SEED)).collect::<Vec<_>>();
|
||||
// Sort
|
||||
friends.sort();
|
||||
|
||||
for friend in 0..friends.len() {
|
||||
// Top up accounts of friends
|
||||
T::Currency::make_free_balance_be(
|
||||
&friends.get(friend).unwrap(),
|
||||
BalanceOf::<T>::max_value(),
|
||||
);
|
||||
}
|
||||
|
||||
friends
|
||||
}
|
||||
|
||||
fn add_caller_and_generate_friends<T: Config>(
|
||||
caller: T::AccountId,
|
||||
num: u32,
|
||||
) -> Vec<<T as frame_system::Config>::AccountId> {
|
||||
// Create friends
|
||||
let mut friends = generate_friends::<T>(num - 1);
|
||||
|
||||
T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
|
||||
|
||||
friends.push(caller);
|
||||
|
||||
// Sort
|
||||
friends.sort();
|
||||
|
||||
friends
|
||||
}
|
||||
|
||||
fn insert_recovery_account<T: Config>(caller: &T::AccountId, account: &T::AccountId) {
|
||||
T::Currency::make_free_balance_be(&account, BalanceOf::<T>::max_value());
|
||||
|
||||
let n = T::MaxFriends::get();
|
||||
|
||||
let friends = generate_friends::<T>(n);
|
||||
|
||||
let bounded_friends: FriendsOf<T> = friends.try_into().unwrap();
|
||||
|
||||
// Get deposit for recovery
|
||||
let total_deposit = get_total_deposit::<T>(&bounded_friends).unwrap();
|
||||
|
||||
let recovery_config = RecoveryConfig {
|
||||
delay_period: DEFAULT_DELAY.into(),
|
||||
deposit: total_deposit,
|
||||
friends: bounded_friends,
|
||||
threshold: n as u16,
|
||||
};
|
||||
|
||||
// Reserve deposit for recovery
|
||||
T::Currency::reserve(&caller, total_deposit).unwrap();
|
||||
|
||||
<Recoverable<T>>::insert(&account, recovery_config);
|
||||
}
|
||||
|
||||
benchmarks! {
|
||||
as_recovered {
|
||||
let caller: T::AccountId = whitelisted_caller();
|
||||
let recovered_account: T::AccountId = account("recovered_account", 0, SEED);
|
||||
let call: <T as Config>::Call = frame_system::Call::<T>::remark { remark: vec![] }.into();
|
||||
|
||||
Proxy::<T>::insert(&caller, &recovered_account);
|
||||
}: _(
|
||||
RawOrigin::Signed(caller),
|
||||
recovered_account,
|
||||
Box::new(call)
|
||||
)
|
||||
|
||||
set_recovered {
|
||||
let lost: T::AccountId = whitelisted_caller();
|
||||
let rescuer: T::AccountId = whitelisted_caller();
|
||||
}: _(
|
||||
RawOrigin::Root,
|
||||
lost.clone(),
|
||||
rescuer.clone()
|
||||
) verify {
|
||||
assert_last_event::<T>(
|
||||
Event::AccountRecovered {
|
||||
lost_account: lost,
|
||||
rescuer_account: rescuer,
|
||||
}.into()
|
||||
);
|
||||
}
|
||||
|
||||
create_recovery {
|
||||
let n in 1 .. T::MaxFriends::get();
|
||||
|
||||
let caller: T::AccountId = whitelisted_caller();
|
||||
T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
|
||||
|
||||
// Create friends
|
||||
let friends = generate_friends::<T>(n);
|
||||
}: _(
|
||||
RawOrigin::Signed(caller.clone()),
|
||||
friends,
|
||||
n as u16,
|
||||
DEFAULT_DELAY.into()
|
||||
) verify {
|
||||
assert_last_event::<T>(Event::RecoveryCreated { account: caller }.into());
|
||||
}
|
||||
|
||||
initiate_recovery {
|
||||
let caller: T::AccountId = whitelisted_caller();
|
||||
T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
|
||||
|
||||
let lost_account: T::AccountId = account("lost_account", 0, SEED);
|
||||
|
||||
insert_recovery_account::<T>(&caller, &lost_account);
|
||||
}: _(
|
||||
RawOrigin::Signed(caller.clone()),
|
||||
lost_account.clone()
|
||||
) verify {
|
||||
assert_last_event::<T>(
|
||||
Event::RecoveryInitiated {
|
||||
lost_account: lost_account,
|
||||
rescuer_account: caller,
|
||||
}.into()
|
||||
);
|
||||
}
|
||||
|
||||
vouch_recovery {
|
||||
let n in 1 .. T::MaxFriends::get();
|
||||
|
||||
let caller: T::AccountId = whitelisted_caller();
|
||||
let lost_account: T::AccountId = account("lost_account", 0, SEED);
|
||||
let rescuer_account: T::AccountId = account("rescuer_account", 0, SEED);
|
||||
|
||||
// Create friends
|
||||
let friends = add_caller_and_generate_friends::<T>(caller.clone(), n);
|
||||
let bounded_friends: FriendsOf<T> = friends.try_into().unwrap();
|
||||
|
||||
// Get deposit for recovery
|
||||
let total_deposit = get_total_deposit::<T>(&bounded_friends).unwrap();
|
||||
|
||||
let recovery_config = RecoveryConfig {
|
||||
delay_period: DEFAULT_DELAY.into(),
|
||||
deposit: total_deposit.clone(),
|
||||
friends: bounded_friends.clone(),
|
||||
threshold: n as u16,
|
||||
};
|
||||
|
||||
// Create the recovery config storage item
|
||||
<Recoverable<T>>::insert(&lost_account, recovery_config.clone());
|
||||
|
||||
// Reserve deposit for recovery
|
||||
T::Currency::reserve(&caller, total_deposit).unwrap();
|
||||
|
||||
// Create an active recovery status
|
||||
let recovery_status = ActiveRecovery {
|
||||
created: DEFAULT_DELAY.into(),
|
||||
deposit: total_deposit,
|
||||
friends: generate_friends::<T>(n - 1).try_into().unwrap(),
|
||||
};
|
||||
|
||||
// Create the active recovery storage item
|
||||
<ActiveRecoveries<T>>::insert(&lost_account, &rescuer_account, recovery_status);
|
||||
|
||||
}: _(
|
||||
RawOrigin::Signed(caller.clone()),
|
||||
lost_account.clone(),
|
||||
rescuer_account.clone()
|
||||
) verify {
|
||||
assert_last_event::<T>(
|
||||
Event::RecoveryVouched {
|
||||
lost_account: lost_account,
|
||||
rescuer_account: rescuer_account,
|
||||
sender: caller,
|
||||
}.into()
|
||||
);
|
||||
}
|
||||
|
||||
claim_recovery {
|
||||
let n in 1 .. T::MaxFriends::get();
|
||||
|
||||
let caller: T::AccountId = whitelisted_caller();
|
||||
let lost_account: T::AccountId = account("lost_account", 0, SEED);
|
||||
|
||||
T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
|
||||
|
||||
// Create friends
|
||||
let friends = generate_friends::<T>(n);
|
||||
let bounded_friends: FriendsOf<T> = friends.try_into().unwrap();
|
||||
|
||||
// Get deposit for recovery
|
||||
let total_deposit = get_total_deposit::<T>(&bounded_friends).unwrap();
|
||||
|
||||
let recovery_config = RecoveryConfig {
|
||||
delay_period: 0u32.into(),
|
||||
deposit: total_deposit.clone(),
|
||||
friends: bounded_friends.clone(),
|
||||
threshold: n as u16,
|
||||
};
|
||||
|
||||
// Create the recovery config storage item
|
||||
<Recoverable<T>>::insert(&lost_account, recovery_config.clone());
|
||||
|
||||
// Reserve deposit for recovery
|
||||
T::Currency::reserve(&caller, total_deposit).unwrap();
|
||||
|
||||
// Create an active recovery status
|
||||
let recovery_status = ActiveRecovery {
|
||||
created: 0u32.into(),
|
||||
deposit: total_deposit,
|
||||
friends: bounded_friends.clone(),
|
||||
};
|
||||
|
||||
// Create the active recovery storage item
|
||||
<ActiveRecoveries<T>>::insert(&lost_account, &caller, recovery_status);
|
||||
}: _(
|
||||
RawOrigin::Signed(caller.clone()),
|
||||
lost_account.clone()
|
||||
) verify {
|
||||
assert_last_event::<T>(
|
||||
Event::AccountRecovered {
|
||||
lost_account: lost_account,
|
||||
rescuer_account: caller,
|
||||
}.into()
|
||||
);
|
||||
}
|
||||
|
||||
close_recovery {
|
||||
let caller: T::AccountId = whitelisted_caller();
|
||||
let rescuer_account: T::AccountId = account("rescuer_account", 0, SEED);
|
||||
|
||||
let n in 1 .. T::MaxFriends::get();
|
||||
|
||||
T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
|
||||
T::Currency::make_free_balance_be(&rescuer_account, BalanceOf::<T>::max_value());
|
||||
|
||||
// Create friends
|
||||
let friends = generate_friends::<T>(n);
|
||||
let bounded_friends: FriendsOf<T> = friends.try_into().unwrap();
|
||||
|
||||
// Get deposit for recovery
|
||||
let total_deposit = get_total_deposit::<T>(&bounded_friends).unwrap();
|
||||
|
||||
let recovery_config = RecoveryConfig {
|
||||
delay_period: DEFAULT_DELAY.into(),
|
||||
deposit: total_deposit.clone(),
|
||||
friends: bounded_friends.clone(),
|
||||
threshold: n as u16,
|
||||
};
|
||||
|
||||
// Create the recovery config storage item
|
||||
<Recoverable<T>>::insert(&caller, recovery_config.clone());
|
||||
|
||||
// Reserve deposit for recovery
|
||||
T::Currency::reserve(&caller, total_deposit).unwrap();
|
||||
|
||||
// Create an active recovery status
|
||||
let recovery_status = ActiveRecovery {
|
||||
created: DEFAULT_DELAY.into(),
|
||||
deposit: total_deposit,
|
||||
friends: bounded_friends.clone(),
|
||||
};
|
||||
|
||||
// Create the active recovery storage item
|
||||
<ActiveRecoveries<T>>::insert(&caller, &rescuer_account, recovery_status);
|
||||
}: _(
|
||||
RawOrigin::Signed(caller.clone()),
|
||||
rescuer_account.clone()
|
||||
) verify {
|
||||
assert_last_event::<T>(
|
||||
Event::RecoveryClosed {
|
||||
lost_account: caller,
|
||||
rescuer_account: rescuer_account,
|
||||
}.into()
|
||||
);
|
||||
}
|
||||
|
||||
remove_recovery {
|
||||
let n in 1 .. T::MaxFriends::get();
|
||||
|
||||
let caller: T::AccountId = whitelisted_caller();
|
||||
|
||||
T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
|
||||
|
||||
// Create friends
|
||||
let friends = generate_friends::<T>(n);
|
||||
let bounded_friends: FriendsOf<T> = friends.try_into().unwrap();
|
||||
|
||||
// Get deposit for recovery
|
||||
let total_deposit = get_total_deposit::<T>(&bounded_friends).unwrap();
|
||||
|
||||
let recovery_config = RecoveryConfig {
|
||||
delay_period: DEFAULT_DELAY.into(),
|
||||
deposit: total_deposit.clone(),
|
||||
friends: bounded_friends.clone(),
|
||||
threshold: n as u16,
|
||||
};
|
||||
|
||||
// Create the recovery config storage item
|
||||
<Recoverable<T>>::insert(&caller, recovery_config);
|
||||
|
||||
// Reserve deposit for recovery
|
||||
T::Currency::reserve(&caller, total_deposit).unwrap();
|
||||
}: _(
|
||||
RawOrigin::Signed(caller.clone())
|
||||
) verify {
|
||||
assert_last_event::<T>(
|
||||
Event::RecoveryRemoved {
|
||||
lost_account: caller
|
||||
}.into()
|
||||
);
|
||||
}
|
||||
|
||||
cancel_recovered {
|
||||
let caller: T::AccountId = whitelisted_caller();
|
||||
let account: T::AccountId = account("account", 0, SEED);
|
||||
|
||||
frame_system::Pallet::<T>::inc_providers(&caller);
|
||||
|
||||
frame_system::Pallet::<T>::inc_consumers(&caller)?;
|
||||
|
||||
Proxy::<T>::insert(&caller, &account);
|
||||
}: _(
|
||||
RawOrigin::Signed(caller),
|
||||
account
|
||||
)
|
||||
|
||||
impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
|
||||
}
|
||||
@@ -167,11 +167,16 @@ use frame_support::{
|
||||
};
|
||||
|
||||
pub use pallet::*;
|
||||
pub use weights::WeightInfo;
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
mod benchmarking;
|
||||
|
||||
#[cfg(test)]
|
||||
mod mock;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
pub mod weights;
|
||||
|
||||
type BalanceOf<T> =
|
||||
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
|
||||
@@ -222,10 +227,14 @@ pub mod pallet {
|
||||
/// The overarching event type.
|
||||
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
|
||||
|
||||
/// Weight information for extrinsics in this pallet.
|
||||
type WeightInfo: WeightInfo;
|
||||
|
||||
/// The overarching call type.
|
||||
type Call: Parameter
|
||||
+ Dispatchable<Origin = Self::Origin, PostInfo = PostDispatchInfo>
|
||||
+ GetDispatchInfo;
|
||||
+ GetDispatchInfo
|
||||
+ From<frame_system::Call<Self>>;
|
||||
|
||||
/// The currency mechanism.
|
||||
type Currency: ReservableCurrency<Self::AccountId>;
|
||||
@@ -365,21 +374,12 @@ pub mod pallet {
|
||||
/// Parameters:
|
||||
/// - `account`: The recovered account you want to make a call on-behalf-of.
|
||||
/// - `call`: The call you want to make with the recovered account.
|
||||
///
|
||||
/// # <weight>
|
||||
/// - The weight of the `call` + 10,000.
|
||||
/// - One storage lookup to check account is recovered by `who`. O(1)
|
||||
/// # </weight>
|
||||
#[pallet::weight({
|
||||
let dispatch_info = call.get_dispatch_info();
|
||||
(
|
||||
dispatch_info.weight
|
||||
.saturating_add(10_000)
|
||||
// AccountData for inner call origin accountdata.
|
||||
.saturating_add(T::DbWeight::get().reads_writes(1, 1)),
|
||||
T::WeightInfo::as_recovered().saturating_add(dispatch_info.weight),
|
||||
dispatch_info.class,
|
||||
)
|
||||
})]
|
||||
)})]
|
||||
pub fn as_recovered(
|
||||
origin: OriginFor<T>,
|
||||
account: T::AccountId,
|
||||
@@ -402,12 +402,7 @@ pub mod pallet {
|
||||
/// Parameters:
|
||||
/// - `lost`: The "lost account" to be recovered.
|
||||
/// - `rescuer`: The "rescuer account" which can call as the lost account.
|
||||
///
|
||||
/// # <weight>
|
||||
/// - One storage write O(1)
|
||||
/// - One event
|
||||
/// # </weight>
|
||||
#[pallet::weight(30_000_000)]
|
||||
#[pallet::weight(T::WeightInfo::set_recovered())]
|
||||
pub fn set_recovered(
|
||||
origin: OriginFor<T>,
|
||||
lost: T::AccountId,
|
||||
@@ -439,18 +434,7 @@ pub mod pallet {
|
||||
/// friends.
|
||||
/// - `delay_period`: The number of blocks after a recovery attempt is initialized that
|
||||
/// needs to pass before the account can be recovered.
|
||||
///
|
||||
/// # <weight>
|
||||
/// - Key: F (len of friends)
|
||||
/// - One storage read to check that account is not already recoverable. O(1).
|
||||
/// - A check that the friends list is sorted and unique. O(F)
|
||||
/// - One currency reserve operation. O(X)
|
||||
/// - One storage write. O(1). Codec O(F).
|
||||
/// - One event.
|
||||
///
|
||||
/// Total Complexity: O(F + X)
|
||||
/// # </weight>
|
||||
#[pallet::weight(100_000_000)]
|
||||
#[pallet::weight(T::WeightInfo::create_recovery(friends.len() as u32))]
|
||||
pub fn create_recovery(
|
||||
origin: OriginFor<T>,
|
||||
friends: Vec<T::AccountId>,
|
||||
@@ -501,18 +485,7 @@ pub mod pallet {
|
||||
/// Parameters:
|
||||
/// - `account`: The lost account that you want to recover. This account needs to be
|
||||
/// recoverable (i.e. have a recovery configuration).
|
||||
///
|
||||
/// # <weight>
|
||||
/// - One storage read to check that account is recoverable. O(F)
|
||||
/// - One storage read to check that this recovery process hasn't already started. O(1)
|
||||
/// - One currency reserve operation. O(X)
|
||||
/// - One storage read to get the current block number. O(1)
|
||||
/// - One storage write. O(1).
|
||||
/// - One event.
|
||||
///
|
||||
/// Total Complexity: O(F + X)
|
||||
/// # </weight>
|
||||
#[pallet::weight(100_000_000)]
|
||||
#[pallet::weight(T::WeightInfo::initiate_recovery())]
|
||||
pub fn initiate_recovery(origin: OriginFor<T>, account: T::AccountId) -> DispatchResult {
|
||||
let who = ensure_signed(origin)?;
|
||||
// Check that the account is recoverable
|
||||
@@ -552,19 +525,7 @@ pub mod pallet {
|
||||
///
|
||||
/// The combination of these two parameters must point to an active recovery
|
||||
/// process.
|
||||
///
|
||||
/// # <weight>
|
||||
/// Key: F (len of friends in config), V (len of vouching friends)
|
||||
/// - One storage read to get the recovery configuration. O(1), Codec O(F)
|
||||
/// - One storage read to get the active recovery process. O(1), Codec O(V)
|
||||
/// - One binary search to confirm caller is a friend. O(logF)
|
||||
/// - One binary search to confirm caller has not already vouched. O(logV)
|
||||
/// - One storage write. O(1), Codec O(V).
|
||||
/// - One event.
|
||||
///
|
||||
/// Total Complexity: O(F + logF + V + logV)
|
||||
/// # </weight>
|
||||
#[pallet::weight(100_000_000)]
|
||||
#[pallet::weight(T::WeightInfo::vouch_recovery(T::MaxFriends::get()))]
|
||||
pub fn vouch_recovery(
|
||||
origin: OriginFor<T>,
|
||||
lost: T::AccountId,
|
||||
@@ -605,18 +566,7 @@ pub mod pallet {
|
||||
/// Parameters:
|
||||
/// - `account`: The lost account that you want to claim has been successfully recovered by
|
||||
/// you.
|
||||
///
|
||||
/// # <weight>
|
||||
/// Key: F (len of friends in config), V (len of vouching friends)
|
||||
/// - One storage read to get the recovery configuration. O(1), Codec O(F)
|
||||
/// - One storage read to get the active recovery process. O(1), Codec O(V)
|
||||
/// - One storage read to get the current block number. O(1)
|
||||
/// - One storage write. O(1), Codec O(V).
|
||||
/// - One event.
|
||||
///
|
||||
/// Total Complexity: O(F + V)
|
||||
/// # </weight>
|
||||
#[pallet::weight(100_000_000)]
|
||||
#[pallet::weight(T::WeightInfo::claim_recovery(T::MaxFriends::get()))]
|
||||
pub fn claim_recovery(origin: OriginFor<T>, account: T::AccountId) -> DispatchResult {
|
||||
let who = ensure_signed(origin)?;
|
||||
// Get the recovery configuration for the lost account
|
||||
@@ -659,16 +609,7 @@ pub mod pallet {
|
||||
///
|
||||
/// Parameters:
|
||||
/// - `rescuer`: The account trying to rescue this recoverable account.
|
||||
///
|
||||
/// # <weight>
|
||||
/// Key: V (len of vouching friends)
|
||||
/// - One storage read/remove to get the active recovery process. O(1), Codec O(V)
|
||||
/// - One balance call to repatriate reserved. O(X)
|
||||
/// - One event.
|
||||
///
|
||||
/// Total Complexity: O(V + X)
|
||||
/// # </weight>
|
||||
#[pallet::weight(30_000_000)]
|
||||
#[pallet::weight(T::WeightInfo::close_recovery(T::MaxFriends::get()))]
|
||||
pub fn close_recovery(origin: OriginFor<T>, rescuer: T::AccountId) -> DispatchResult {
|
||||
let who = ensure_signed(origin)?;
|
||||
// Take the active recovery process started by the rescuer for this account.
|
||||
@@ -701,17 +642,7 @@ pub mod pallet {
|
||||
///
|
||||
/// The dispatch origin for this call must be _Signed_ and must be a
|
||||
/// recoverable account (i.e. has a recovery configuration).
|
||||
///
|
||||
/// # <weight>
|
||||
/// Key: F (len of friends)
|
||||
/// - One storage read to get the prefix iterator for active recoveries. O(1)
|
||||
/// - One storage read/remove to get the recovery configuration. O(1), Codec O(F)
|
||||
/// - One balance call to unreserved. O(X)
|
||||
/// - One event.
|
||||
///
|
||||
/// Total Complexity: O(F + X)
|
||||
/// # </weight>
|
||||
#[pallet::weight(30_000_000)]
|
||||
#[pallet::weight(T::WeightInfo::remove_recovery(T::MaxFriends::get()))]
|
||||
pub fn remove_recovery(origin: OriginFor<T>) -> DispatchResult {
|
||||
let who = ensure_signed(origin)?;
|
||||
// Check there are no active recoveries
|
||||
@@ -733,16 +664,13 @@ pub mod pallet {
|
||||
///
|
||||
/// Parameters:
|
||||
/// - `account`: The recovered account you are able to call on-behalf-of.
|
||||
///
|
||||
/// # <weight>
|
||||
/// - One storage mutation to check account is recovered by `who`. O(1)
|
||||
/// # </weight>
|
||||
#[pallet::weight(30_000_000)]
|
||||
#[pallet::weight(T::WeightInfo::cancel_recovered())]
|
||||
pub fn cancel_recovered(origin: OriginFor<T>, account: T::AccountId) -> DispatchResult {
|
||||
let who = ensure_signed(origin)?;
|
||||
// Check `who` is allowed to make a call on behalf of `account`
|
||||
ensure!(Self::proxy(&who) == Some(account), Error::<T>::NotAllowed);
|
||||
Proxy::<T>::remove(&who);
|
||||
|
||||
frame_system::Pallet::<T>::dec_consumers(&who);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -97,15 +97,18 @@ parameter_types! {
|
||||
pub const ConfigDepositBase: u64 = 10;
|
||||
pub const FriendDepositFactor: u64 = 1;
|
||||
pub const RecoveryDeposit: u64 = 10;
|
||||
// Large number of friends for benchmarking.
|
||||
pub const MaxFriends: u32 = 128;
|
||||
}
|
||||
|
||||
impl Config for Test {
|
||||
type Event = Event;
|
||||
type WeightInfo = ();
|
||||
type Call = Call;
|
||||
type Currency = Balances;
|
||||
type ConfigDepositBase = ConfigDepositBase;
|
||||
type FriendDepositFactor = FriendDepositFactor;
|
||||
type MaxFriends = ConstU32<3>;
|
||||
type MaxFriends = MaxFriends;
|
||||
type RecoveryDeposit = RecoveryDeposit;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
use super::*;
|
||||
use frame_support::{assert_noop, assert_ok, bounded_vec, traits::Currency};
|
||||
use mock::{
|
||||
new_test_ext, run_to_block, Balances, BalancesCall, Call, Origin, Recovery, RecoveryCall, Test,
|
||||
new_test_ext, run_to_block, Balances, BalancesCall, Call, MaxFriends, Origin, Recovery,
|
||||
RecoveryCall, Test,
|
||||
};
|
||||
use sp_runtime::traits::BadOrigin;
|
||||
|
||||
@@ -112,10 +113,13 @@ fn malicious_recovery_fails() {
|
||||
// Using account 1, the malicious user begins the recovery process on account 5
|
||||
assert_ok!(Recovery::initiate_recovery(Origin::signed(1), 5));
|
||||
// Off chain, the user **tricks** their friends and asks them to vouch for the recovery
|
||||
assert_ok!(Recovery::vouch_recovery(Origin::signed(2), 5, 1)); // shame on you
|
||||
assert_ok!(Recovery::vouch_recovery(Origin::signed(3), 5, 1)); // shame on you
|
||||
assert_ok!(Recovery::vouch_recovery(Origin::signed(4), 5, 1)); // shame on you
|
||||
// We met the threshold, lets try to recover the account...?
|
||||
assert_ok!(Recovery::vouch_recovery(Origin::signed(2), 5, 1));
|
||||
// shame on you
|
||||
assert_ok!(Recovery::vouch_recovery(Origin::signed(3), 5, 1));
|
||||
// shame on you
|
||||
assert_ok!(Recovery::vouch_recovery(Origin::signed(4), 5, 1));
|
||||
// shame on you
|
||||
// We met the threshold, lets try to recover the account...?
|
||||
assert_noop!(Recovery::claim_recovery(Origin::signed(1), 5), Error::<Test>::DelayPeriod);
|
||||
// Account 1 needs to wait...
|
||||
run_to_block(19);
|
||||
@@ -162,7 +166,12 @@ fn create_recovery_handles_basic_errors() {
|
||||
);
|
||||
// Too many friends
|
||||
assert_noop!(
|
||||
Recovery::create_recovery(Origin::signed(5), vec![1, 2, 3, 4], 4, 0),
|
||||
Recovery::create_recovery(
|
||||
Origin::signed(5),
|
||||
vec![1; (MaxFriends::get() + 1) as usize],
|
||||
1,
|
||||
0
|
||||
),
|
||||
Error::<Test>::MaxFriends
|
||||
);
|
||||
// Unsorted friends
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2022 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.
|
||||
|
||||
//! Autogenerated weights for pallet_recovery
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2022-04-26, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
|
||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// target/production/substrate
|
||||
// benchmark
|
||||
// pallet
|
||||
// --chain=dev
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pallet=pallet-recovery
|
||||
// --extrinsic=*
|
||||
// --execution=wasm
|
||||
// --wasm-execution=compiled
|
||||
// --heap-pages=4096
|
||||
// --output=./frame/recovery/src/weights.rs
|
||||
// --template=.maintain/frame-weight-template.hbs
|
||||
// --header=HEADER-APACHE2
|
||||
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
|
||||
use sp_std::marker::PhantomData;
|
||||
|
||||
/// Weight functions needed for pallet_recovery.
|
||||
pub trait WeightInfo {
|
||||
fn as_recovered() -> Weight;
|
||||
fn set_recovered() -> Weight;
|
||||
fn create_recovery(n: u32, ) -> Weight;
|
||||
fn initiate_recovery() -> Weight;
|
||||
fn vouch_recovery(n: u32, ) -> Weight;
|
||||
fn claim_recovery(n: u32, ) -> Weight;
|
||||
fn close_recovery(n: u32, ) -> Weight;
|
||||
fn remove_recovery(n: u32, ) -> Weight;
|
||||
fn cancel_recovered() -> Weight;
|
||||
}
|
||||
|
||||
/// Weights for pallet_recovery using the Substrate node and recommended hardware.
|
||||
pub struct SubstrateWeight<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
// Storage: Recovery Proxy (r:1 w:0)
|
||||
fn as_recovered() -> Weight {
|
||||
(3_667_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as Weight))
|
||||
}
|
||||
// Storage: Recovery Proxy (r:0 w:1)
|
||||
fn set_recovered() -> Weight {
|
||||
(10_149_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
// Storage: Recovery Recoverable (r:1 w:1)
|
||||
fn create_recovery(n: u32, ) -> Weight {
|
||||
(23_154_000 as Weight)
|
||||
// Standard Error: 16_000
|
||||
.saturating_add((235_000 as Weight).saturating_mul(n as Weight))
|
||||
.saturating_add(T::DbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
// Storage: Recovery Recoverable (r:1 w:0)
|
||||
// Storage: Recovery ActiveRecoveries (r:1 w:1)
|
||||
fn initiate_recovery() -> Weight {
|
||||
(28_857_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
// Storage: Recovery Recoverable (r:1 w:0)
|
||||
// Storage: Recovery ActiveRecoveries (r:1 w:1)
|
||||
fn vouch_recovery(n: u32, ) -> Weight {
|
||||
(17_841_000 as Weight)
|
||||
// Standard Error: 10_000
|
||||
.saturating_add((349_000 as Weight).saturating_mul(n as Weight))
|
||||
.saturating_add(T::DbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
// Storage: Recovery Recoverable (r:1 w:0)
|
||||
// Storage: Recovery ActiveRecoveries (r:1 w:0)
|
||||
// Storage: Recovery Proxy (r:1 w:1)
|
||||
fn claim_recovery(n: u32, ) -> Weight {
|
||||
(24_927_000 as Weight)
|
||||
// Standard Error: 14_000
|
||||
.saturating_add((222_000 as Weight).saturating_mul(n as Weight))
|
||||
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
// Storage: Recovery ActiveRecoveries (r:1 w:1)
|
||||
// Storage: System Account (r:1 w:1)
|
||||
fn close_recovery(n: u32, ) -> Weight {
|
||||
(28_201_000 as Weight)
|
||||
// Standard Error: 17_000
|
||||
.saturating_add((272_000 as Weight).saturating_mul(n as Weight))
|
||||
.saturating_add(T::DbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
// Storage: Recovery ActiveRecoveries (r:1 w:0)
|
||||
// Storage: Recovery Recoverable (r:1 w:1)
|
||||
fn remove_recovery(n: u32, ) -> Weight {
|
||||
(27_531_000 as Weight)
|
||||
// Standard Error: 10_000
|
||||
.saturating_add((218_000 as Weight).saturating_mul(n as Weight))
|
||||
.saturating_add(T::DbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
// Storage: Recovery Proxy (r:1 w:1)
|
||||
fn cancel_recovered() -> Weight {
|
||||
(9_015_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
}
|
||||
|
||||
// For backwards compatibility and tests
|
||||
impl WeightInfo for () {
|
||||
// Storage: Recovery Proxy (r:1 w:0)
|
||||
fn as_recovered() -> Weight {
|
||||
(3_667_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
|
||||
}
|
||||
// Storage: Recovery Proxy (r:0 w:1)
|
||||
fn set_recovered() -> Weight {
|
||||
(10_149_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
// Storage: Recovery Recoverable (r:1 w:1)
|
||||
fn create_recovery(n: u32, ) -> Weight {
|
||||
(23_154_000 as Weight)
|
||||
// Standard Error: 16_000
|
||||
.saturating_add((235_000 as Weight).saturating_mul(n as Weight))
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
// Storage: Recovery Recoverable (r:1 w:0)
|
||||
// Storage: Recovery ActiveRecoveries (r:1 w:1)
|
||||
fn initiate_recovery() -> Weight {
|
||||
(28_857_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
// Storage: Recovery Recoverable (r:1 w:0)
|
||||
// Storage: Recovery ActiveRecoveries (r:1 w:1)
|
||||
fn vouch_recovery(n: u32, ) -> Weight {
|
||||
(17_841_000 as Weight)
|
||||
// Standard Error: 10_000
|
||||
.saturating_add((349_000 as Weight).saturating_mul(n as Weight))
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
// Storage: Recovery Recoverable (r:1 w:0)
|
||||
// Storage: Recovery ActiveRecoveries (r:1 w:0)
|
||||
// Storage: Recovery Proxy (r:1 w:1)
|
||||
fn claim_recovery(n: u32, ) -> Weight {
|
||||
(24_927_000 as Weight)
|
||||
// Standard Error: 14_000
|
||||
.saturating_add((222_000 as Weight).saturating_mul(n as Weight))
|
||||
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
// Storage: Recovery ActiveRecoveries (r:1 w:1)
|
||||
// Storage: System Account (r:1 w:1)
|
||||
fn close_recovery(n: u32, ) -> Weight {
|
||||
(28_201_000 as Weight)
|
||||
// Standard Error: 17_000
|
||||
.saturating_add((272_000 as Weight).saturating_mul(n as Weight))
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
// Storage: Recovery ActiveRecoveries (r:1 w:0)
|
||||
// Storage: Recovery Recoverable (r:1 w:1)
|
||||
fn remove_recovery(n: u32, ) -> Weight {
|
||||
(27_531_000 as Weight)
|
||||
// Standard Error: 10_000
|
||||
.saturating_add((218_000 as Weight).saturating_mul(n as Weight))
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
// Storage: Recovery Proxy (r:1 w:1)
|
||||
fn cancel_recovered() -> Weight {
|
||||
(9_015_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user