From e137b60410d6f68fc7536009e2ec23e1fb2a6f83 Mon Sep 17 00:00:00 2001
From: bgallois <benjamin@gallois.cc>
Date: Fri, 17 Mar 2023 18:54:10 +0100
Subject: [PATCH] feat: add pallet provide-randomness benchmark

---
 pallets/provide-randomness/Cargo.toml         | 10 ++-
 .../provide-randomness/src/benchmarking.rs    | 85 +++++++++++++++++++
 pallets/provide-randomness/src/lib.rs         |  5 +-
 runtime/gdev/src/lib.rs                       |  1 +
 4 files changed, 98 insertions(+), 3 deletions(-)
 create mode 100644 pallets/provide-randomness/src/benchmarking.rs

diff --git a/pallets/provide-randomness/Cargo.toml b/pallets/provide-randomness/Cargo.toml
index 5caab0b72..e4d56db8b 100644
--- a/pallets/provide-randomness/Cargo.toml
+++ b/pallets/provide-randomness/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,6 +30,9 @@ try-runtime = ['frame-support/try-runtime']
 # substrate
 scale-info = { version = "2.1.1", default-features = false, features = ["derive"] }
 
+# benchmarks
+pallet-balances = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.32', optional = true, default-features = false }
+
 [dependencies.codec]
 default-features = false
 features = ['derive']
@@ -72,4 +78,4 @@ branch = 'duniter-substrate-v0.9.32'
 ### DOC ###
 
 [package.metadata.docs.rs]
-targets = ['x86_64-unknown-linux-gnu']
+targets = ['x86_64-unknown-linux-gnu']
\ No newline at end of file
diff --git a/pallets/provide-randomness/src/benchmarking.rs b/pallets/provide-randomness/src/benchmarking.rs
new file mode 100644
index 000000000..164636324
--- /dev/null
+++ b/pallets/provide-randomness/src/benchmarking.rs
@@ -0,0 +1,85 @@
+// Copyright 2021-2023 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::{benchmarks, whitelisted_caller};
+use frame_support::ensure;
+use frame_support::pallet_prelude::IsType;
+use frame_support::sp_runtime::{traits::One, Saturating};
+use frame_support::traits::{Currency, Get, OnInitialize};
+use frame_system::RawOrigin;
+use sp_core::H256;
+
+use crate::Pallet;
+
+fn assert_has_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
+    frame_system::Pallet::<T>::assert_has_event(generic_event.into());
+}
+
+fn add_requests_next_block<T: Config>(i: u32) -> Result<(), &'static str> {
+    for _ in 0..i {
+        let salt: H256 = H256([0; 32]);
+        let request_id = RequestIdProvider::<T>::mutate(|next_request_id| {
+            core::mem::replace(next_request_id, next_request_id.saturating_add(1))
+        });
+        RequestsIds::<T>::insert(request_id, ());
+        RequestsReadyAtNextBlock::<T>::append(Request { request_id, salt });
+    }
+    Ok(())
+}
+
+benchmarks! {
+    where_clause { where
+        T: pallet_balances::Config,
+        T::Balance: From<u64>,
+        <T::Currency as Currency<T::AccountId>>::Balance: IsType<T::Balance>
+    }
+    request {
+        // Get account
+        let caller: T::AccountId = whitelisted_caller();
+        let caller_origin: <T as frame_system::Config>::RuntimeOrigin =
+            RawOrigin::Signed(caller.clone()).into();
+
+        // Provide deposit
+        let existential_deposit = T::ExistentialDeposit::get();
+        let balance = existential_deposit.saturating_mul((200).into());
+        let _ = T::Currency::make_free_balance_be(&caller, balance.into());
+
+        // Set randomness parameters
+        let random = RandomnessType::RandomnessFromOneEpochAgo;
+        let salt: H256 = H256([1; 32]);
+    }: _<T::RuntimeOrigin>(caller_origin.clone(), random, salt.clone())
+    verify {
+        let request_id = RequestIdProvider::<T>::get() - 1;
+        assert_has_event::<T>(Event::RequestedRandomness {
+              request_id: request_id, salt: salt, r#type: random }.into() );
+    }
+
+    // Complexity depends on number of requests in RequestsReadyAtNextBlock and
+    // in the RequestsReadyAtEpoch(at current epoch) and the sum of the two are bounded by MaxRequests.
+    // The complexity is reduced to the number of elements in RequestsIds since the processing
+    // of the two lists is quasi-identical.
+    on_initialize {
+        let i in 1 .. T::MaxRequests::get() => add_requests_next_block::<T>(i)?;
+        ensure!(RequestsIds::<T>::count() == i, "List not filled properly.");
+    }: { Pallet::<T>::on_initialize(T::BlockNumber::one()); }
+    verify {
+        ensure!(RequestsIds::<T>::count() == 0, "List not processed.");
+    }
+}
diff --git a/pallets/provide-randomness/src/lib.rs b/pallets/provide-randomness/src/lib.rs
index 545cf81a8..4985d5b42 100644
--- a/pallets/provide-randomness/src/lib.rs
+++ b/pallets/provide-randomness/src/lib.rs
@@ -1,4 +1,4 @@
-// Copyright 2021 Axiom-Team
+// Copyright 2021-2023 Axiom-Team
 //
 // This file is part of Duniter-v2S.
 //
@@ -17,6 +17,9 @@
 #![cfg_attr(not(feature = "std"), no_std)]
 #![allow(clippy::boxed_local)]
 
+#[cfg(feature = "runtime-benchmarks")]
+mod benchmarking;
+
 mod types;
 
 use frame_support::pallet_prelude::Weight;
diff --git a/runtime/gdev/src/lib.rs b/runtime/gdev/src/lib.rs
index 9d6eb62e1..7620c2ce8 100644
--- a/runtime/gdev/src/lib.rs
+++ b/runtime/gdev/src/lib.rs
@@ -144,6 +144,7 @@ mod benches {
         // the that path resolves correctly in the generated file.
         [common_runtime::oneshot_account, OneshotAccount]
         [common_runtime::universal_dividend, UniversalDividend]
+        [common_runtime::provide_randomness, ProvideRandomness]
         [common_runtime::upgrade_origin, UpgradeOrigin]
         // Substrate
         [pallet_balances, Balances]
-- 
GitLab