diff --git a/pallets/universal-dividend/Cargo.toml b/pallets/universal-dividend/Cargo.toml index fd100ced2f0bfdd7608b2666e2130e6dc46cd1ae..8b939e5f7a307b0f8886f82668e39dab38fea024 100644 --- a/pallets/universal-dividend/Cargo.toml +++ b/pallets/universal-dividend/Cargo.toml @@ -10,7 +10,10 @@ version = '3.0.0' [features] default = ['std'] -runtime-benchmarks = ['frame-benchmarking'] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "pallet-balances" +] std = [ 'codec/std', 'frame-support/std', @@ -27,18 +30,16 @@ try-runtime = ['frame-support/try-runtime'] # substrate scale-info = { version = "1.0", default-features = false, features = ["derive"] } +# substrate bencharks +frame-benchmarking = { git = 'https://github.com/librelois/substrate.git', branch = 'duniter-monthly-2022-02', optional = true, default-features = false } +pallet-balances = { git = 'https://github.com/librelois/substrate.git', branch = 'duniter-monthly-2022-02', optional = true, default-features = false } + [dependencies.codec] default-features = false features = ['derive'] package = 'parity-scale-codec' version = '2.3.1' -[dependencies.frame-benchmarking] -default-features = false -git = 'https://github.com/librelois/substrate.git' -optional = true -branch = 'duniter-monthly-2022-02' - [dependencies.frame-support] default-features = false git = 'https://github.com/librelois/substrate.git' diff --git a/pallets/universal-dividend/src/benchmarking.rs b/pallets/universal-dividend/src/benchmarking.rs new file mode 100644 index 0000000000000000000000000000000000000000..530065d03650650b19268750a712ba53deb717a5 --- /dev/null +++ b/pallets/universal-dividend/src/benchmarking.rs @@ -0,0 +1,100 @@ +// Copyright 2021-2022 Axiom-Team +// +// This file is part of Duniter-v2S. +// +// Duniter-v2S is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, version 3 of the License. +// +// Duniter-v2S is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. + +#![cfg(feature = "runtime-benchmarks")] + +use super::*; + +use frame_benchmarking::{account, benchmarks, whitelisted_caller}; +use frame_support::pallet_prelude::IsType; +use frame_support::traits::{Get, OnInitialize}; +use frame_system::RawOrigin; +use pallet_balances::Pallet as Balances; +use sp_runtime::traits::Bounded; + +use crate::Pallet; + +const BLOCK_NUMBER: u32 = 2; +const ED_MULTIPLIER: u32 = 10; +const SEED: u32 = 0; + +/*fn fill_storage<T: Config>( + members_count: u32, +) -> Result<(), &'static str> { + Ok(()) +}*/ + +benchmarks! { + // TODO add on_initialize_ud_created and on_initialize_ud_reevalued (after manual UD impl) + on_initialize { + //let n in 1 .. 10_000; + //fill_storage::<T>(n)?; + }: { Pallet::<T>::on_initialize(BLOCK_NUMBER.into()); } + verify { + } + // Benchmark `transfer_ud` extrinsic with the worst possible conditions: + // * Transfer will kill the sender account. + // * Transfer will create the recipient account. + where_clause { where T: pallet_balances::Config, T::Balance: From<u64>, <T::Currency as Currency<T::AccountId>>::Balance: IsType<T::Balance> } + transfer_ud { + let existential_deposit = T::ExistentialDeposit::get(); + let caller = whitelisted_caller(); + + // Give some multiple of the existential deposit + let balance = existential_deposit.saturating_mul(ED_MULTIPLIER.into()); + let _ = T::Currency::make_free_balance_be(&caller, balance.into()); + + // Transfer `e - 1` existential deposits + 1 unit, which guarantees to create one account, + // and reap this user. + let recipient: T::AccountId = account("recipient", 0, SEED); + let recipient_lookup: <T::Lookup as StaticLookup>::Source = T::Lookup::unlookup(recipient.clone()); + let transfer_amount = existential_deposit.saturating_mul((ED_MULTIPLIER - 1).into()) + 1u32.into(); + let transfer_amount_ud = transfer_amount.saturating_mul(1_000.into()) / Pallet::<T>::current_ud().into(); + }: _(RawOrigin::Signed(caller.clone()), recipient_lookup, transfer_amount_ud.into()) + verify { + assert_eq!(Balances::<T>::free_balance(&caller), Zero::zero()); + assert_eq!(Balances::<T>::free_balance(&recipient), transfer_amount); + } + + // Benchmark `transfer_ud_keep_alive` with the worst possible condition: + // * The recipient account is created. + where_clause { where T: pallet_balances::Config, T::Balance: From<u64>, <T::Currency as Currency<T::AccountId>>::Balance: IsType<T::Balance> } + transfer_ud_keep_alive { + let caller = whitelisted_caller(); + let recipient: T::AccountId = account("recipient", 0, SEED); + let recipient_lookup: <T::Lookup as StaticLookup>::Source = T::Lookup::unlookup(recipient.clone()); + + // Give the sender account max funds, thus a transfer will not kill account. + let _ = T::Currency::make_free_balance_be(&caller, <T::Currency as Currency<T::AccountId>>::Balance::max_value()); + let existential_deposit = T::ExistentialDeposit::get(); + let transfer_amount = existential_deposit.saturating_mul(ED_MULTIPLIER.into()); + let transfer_amount_ud = transfer_amount.saturating_mul(1_000.into()) / Pallet::<T>::current_ud().into(); + }: _(RawOrigin::Signed(caller.clone()), recipient_lookup, transfer_amount_ud.into()) + verify { + assert!(!Balances::<T>::free_balance(&caller).is_zero()); + assert_eq!(Balances::<T>::free_balance(&recipient), transfer_amount); + } + + impl_benchmark_test_suite!( + Pallet, + crate::mock::new_test_ext(crate::mock::UniversalDividendConfig { + first_reeval: 8, + first_ud: 1_000, + initial_monetary_mass: 0, + }), + crate::mock::Test + ); +} diff --git a/pallets/universal-dividend/src/lib.rs b/pallets/universal-dividend/src/lib.rs index a34c7a0ce495d12fb4adcc63c4f2ff0939594b29..27b54cd2874c5e75b535a95d2aa7b11e6e8303ac 100644 --- a/pallets/universal-dividend/src/lib.rs +++ b/pallets/universal-dividend/src/lib.rs @@ -18,15 +18,12 @@ pub use pallet::*; +mod benchmarking; #[cfg(test)] mod mock; - #[cfg(test)] mod tests; -/*#[cfg(feature = "runtime-benchmarks")] -mod benchmarking;*/ - use frame_support::traits::{tokens::ExistenceRequirement, Currency}; use sp_arithmetic::{ per_things::Perbill, diff --git a/pallets/universal-dividend/src/mock.rs b/pallets/universal-dividend/src/mock.rs index 63738dcd57126b252752246dadd99e7746072418..a9ca7b29716fc2802644915a2c39a2391b15d834 100644 --- a/pallets/universal-dividend/src/mock.rs +++ b/pallets/universal-dividend/src/mock.rs @@ -79,7 +79,7 @@ impl system::Config for Test { } parameter_types! { - pub const ExistentialDeposit: Balance = 1; + pub const ExistentialDeposit: Balance = 10; pub const MaxLocks: u32 = 50; } diff --git a/runtime/common/src/apis.rs b/runtime/common/src/apis.rs index 7558a655649985d24865da9bd47cccf0442fe7cc..3e8c7d8ae33e26a4a4e255f18c01c874befc2333 100644 --- a/runtime/common/src/apis.rs +++ b/runtime/common/src/apis.rs @@ -235,12 +235,13 @@ macro_rules! runtime_apis { use frame_benchmarking::baseline::Pallet as Baseline; let mut list = Vec::<BenchmarkList>::new(); + list_benchmark!(list, extra, frame_system, SystemBench::<Runtime>); list_benchmark!(list, extra, pallet_balances, Balances); list_benchmark!(list, extra, pallet_multisig, Multisig); list_benchmark!(list, extra, pallet_proxy, Proxy); list_benchmark!(list, extra, pallet_scheduler, Scheduler); list_benchmark!(list, extra, pallet_timestamp, Timestamp); - list_benchmark!(list, extra, frame_system, SystemBench::<Runtime>); + list_benchmark!(list, extra, pallet_universal_dividend, UniversalDividend); list_benchmark!(list, extra, pallet_utility, Utility); let storage_info = AllPalletsWithSystem::storage_info(); @@ -279,12 +280,13 @@ macro_rules! runtime_apis { let mut batches = Vec::<BenchmarkBatch>::new(); let params = (&config, &whitelist); + add_benchmark!(params, batches, frame_system, SystemBench::<Runtime>); add_benchmark!(params, batches, pallet_balances, Balances); add_benchmark!(params, batches, pallet_multisig, Multisig); add_benchmark!(params, batches, pallet_proxy, Proxy); add_benchmark!(params, batches, pallet_scheduler, Scheduler); - add_benchmark!(params, batches, frame_system, SystemBench::<Runtime>); add_benchmark!(params, batches, pallet_timestamp, Timestamp); + add_benchmark!(params, batches, pallet_universal_dividend, UniversalDividend); add_benchmark!(params, batches, pallet_utility, Utility); if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }