From 10170f2aaab7e2d3e0b8bf887c2ada0e831c6e8e Mon Sep 17 00:00:00 2001
From: Benjamin Gallois <business@gallois.cc>
Date: Mon, 8 May 2023 16:00:32 +0200
Subject: [PATCH] Membership pallet benchmark (nodes/rust/duniter-v2s!147)

* fix after rebase

* add comment warning about hardcoded smith metadata

* feat(runtimes): use our benchmarks for pallet membership

* feat(pallet_membership): add weights info

* feat: add pallet membership benchmark
---
 pallets/duniter-wot/src/mock.rs               |   4 +
 pallets/membership/Cargo.toml                 |   5 +-
 pallets/membership/src/benchmarking.rs        | 101 ++++++++++++++++
 pallets/membership/src/lib.rs                 |  20 ++--
 pallets/membership/src/mock.rs                |   2 +
 pallets/membership/src/weights.rs             |  84 +++++++++++++
 runtime/common/src/entities.rs                |  30 ++++-
 runtime/common/src/pallets_config.rs          |   4 +
 runtime/common/src/weights.rs                 |   2 +
 .../pallet_certification_smith_cert.rs        |  20 ++--
 .../weights/pallet_membership_membership.rs   | 101 ++++++++++++++++
 .../pallet_membership_smith_membership.rs     | 111 ++++++++++++++++++
 runtime/gdev/src/lib.rs                       |   4 +-
 13 files changed, 468 insertions(+), 20 deletions(-)
 create mode 100644 pallets/membership/src/benchmarking.rs
 create mode 100644 pallets/membership/src/weights.rs
 create mode 100644 runtime/common/src/weights/pallet_membership_membership.rs
 create mode 100644 runtime/common/src/weights/pallet_membership_smith_membership.rs

diff --git a/pallets/duniter-wot/src/mock.rs b/pallets/duniter-wot/src/mock.rs
index 1b8087b21..6b9bf90cf 100644
--- a/pallets/duniter-wot/src/mock.rs
+++ b/pallets/duniter-wot/src/mock.rs
@@ -146,10 +146,12 @@ impl pallet_membership::Config<Instance1> for Test {
     type CheckCallAllowed = DuniterWot;
     type IdtyId = IdtyIndex;
     type IdtyIdOf = IdentityIndexOf<Self>;
+    type AccountIdOf = ();
     type MembershipPeriod = MembershipPeriod;
     type MetaData = ();
     type OnEvent = DuniterWot;
     type RuntimeEvent = RuntimeEvent;
+    type WeightInfo = ();
     type PendingMembershipPeriod = PendingMembershipPeriod;
 }
 
@@ -199,10 +201,12 @@ impl pallet_membership::Config<Instance2> for Test {
     type CheckCallAllowed = SmithSubWot;
     type IdtyId = IdtyIndex;
     type IdtyIdOf = IdentityIndexOf<Self>;
+    type AccountIdOf = ();
     type MembershipPeriod = SmithMembershipPeriod;
     type MetaData = ();
     type OnEvent = SmithSubWot;
     type PendingMembershipPeriod = SmithPendingMembershipPeriod;
+    type WeightInfo = ();
     type RuntimeEvent = RuntimeEvent;
 }
 
diff --git a/pallets/membership/Cargo.toml b/pallets/membership/Cargo.toml
index 2d0c23a9d..a0beee752 100644
--- a/pallets/membership/Cargo.toml
+++ b/pallets/membership/Cargo.toml
@@ -11,7 +11,9 @@ version = '3.0.0'
 
 [features]
 default = ['std']
-runtime-benchmarks = ['frame-benchmarking']
+runtime-benchmarks = [
+	"frame-benchmarking/runtime-benchmarks",
+]
 std = [
     'codec/std',
     'frame-support/std',
@@ -73,6 +75,7 @@ default-features = false
 git = 'https://github.com/duniter/substrate'
 branch = 'duniter-substrate-v0.9.32'
 
+
 ### DOC ###
 
 [package.metadata.docs.rs]
diff --git a/pallets/membership/src/benchmarking.rs b/pallets/membership/src/benchmarking.rs
new file mode 100644
index 000000000..0e0daff56
--- /dev/null
+++ b/pallets/membership/src/benchmarking.rs
@@ -0,0 +1,101 @@
+// 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::benchmarks_instance_pallet;
+use frame_support::dispatch::UnfilteredDispatchable;
+use frame_system::RawOrigin;
+use sp_runtime::traits::Convert;
+
+#[cfg(test)]
+use maplit::btreemap;
+
+use crate::Pallet;
+
+fn assert_has_event<T: Config<I>, I: 'static>(generic_event: <T as Config<I>>::RuntimeEvent) {
+    frame_system::Pallet::<T>::assert_has_event(generic_event.into());
+}
+
+benchmarks_instance_pallet! {
+    where_clause {
+        where
+            T::IdtyId: From<u32>,
+    }
+    force_request_membership {
+        let idty: T::IdtyId = 5.into();
+    }: _<T::RuntimeOrigin>(RawOrigin::Root.into(), idty, T::MetaData ::default() )
+    verify {
+        assert_has_event::<T, I>(Event::<T, I>::MembershipRequested(idty).into());
+    }
+    request_membership {
+        // Dave identity (4)
+        // for main wot, no constraints
+        // for smith subwot, his pubkey is hardcoded in default metadata
+        let idty: T::IdtyId = 4.into();
+        Membership::<T, I>::take(idty);
+        let caller: T::AccountId = T::AccountIdOf::convert(idty.clone()).unwrap();
+        let caller_origin: <T as frame_system::Config>::RuntimeOrigin = RawOrigin::Signed(caller.clone()).into();
+        // Lazily prepare call as this extrinsic will always return an errror when in subwot
+        let call = Call::<T, I>::request_membership { metadata: T::MetaData ::default()};
+    }: {
+        call.dispatch_bypass_filter(caller_origin).ok();
+    }
+    verify {
+        if T::CheckCallAllowed::check_idty_allowed_to_request_membership(&idty).is_ok() {
+            assert_has_event::<T, I>(Event::<T, I>::MembershipRequested(idty).into());
+        }
+    }
+    claim_membership {
+        let idty: T::IdtyId = 3.into();
+        Membership::<T, I>::take(idty);
+        PendingMembership::<T, I>::insert(idty.clone(), T::MetaData::default());
+        let caller: T::AccountId = T::AccountIdOf::convert(idty.clone()).unwrap();
+        let caller_origin: <T as frame_system::Config>::RuntimeOrigin = RawOrigin::Signed(caller.clone()).into();
+    }: _<T::RuntimeOrigin>(caller_origin, Some(idty))
+    verify {
+        assert_has_event::<T, I>(Event::<T, I>::MembershipAcquired(idty).into());
+    }
+    renew_membership {
+        let idty: T::IdtyId = 3.into();
+        let caller: T::AccountId = T::AccountIdOf::convert(idty.clone()).unwrap();
+        let caller_origin: <T as frame_system::Config>::RuntimeOrigin = RawOrigin::Signed(caller.clone()).into();
+    }: _<T::RuntimeOrigin>(caller_origin, Some(idty))
+    verify {
+        assert_has_event::<T, I>(Event::<T, I>::MembershipRenewed(idty).into());
+    }
+    revoke_membership {
+        let idty: T::IdtyId = 3.into();
+        let caller: T::AccountId = T::AccountIdOf::convert(idty.clone()).unwrap();
+        let caller_origin: <T as frame_system::Config>::RuntimeOrigin = RawOrigin::Signed(caller.clone()).into();
+    }: _<T::RuntimeOrigin>(caller_origin, Some(idty))
+    verify {
+        assert_has_event::<T, I>(Event::<T, I>::MembershipRevoked(idty).into());
+    }
+
+    impl_benchmark_test_suite!(
+        Pallet,
+        crate::mock::new_test_ext(crate::mock::DefaultMembershipConfig {
+        memberships: btreemap![
+            3 => MembershipData {
+                expire_on: 3,
+            },
+        ],}),
+        crate::mock::Test
+    );
+}
diff --git a/pallets/membership/src/lib.rs b/pallets/membership/src/lib.rs
index 475287c40..b8beaa20e 100644
--- a/pallets/membership/src/lib.rs
+++ b/pallets/membership/src/lib.rs
@@ -23,10 +23,13 @@ mod mock;
 #[cfg(test)]
 mod tests;
 
-/*#[cfg(feature = "runtime-benchmarks")]
-mod benchmarking;*/
+#[cfg(feature = "runtime-benchmarks")]
+mod benchmarking;
+
+pub mod weights;
 
 pub use pallet::*;
+pub use weights::WeightInfo;
 
 use frame_support::dispatch::Weight;
 use frame_support::error::BadOrigin;
@@ -65,6 +68,8 @@ pub mod pallet {
         type IdtyId: Copy + MaybeSerializeDeserialize + Parameter + Ord;
         /// Something that give the IdtyId on an account id
         type IdtyIdOf: Convert<Self::AccountId, Option<Self::IdtyId>>;
+        /// Something that give the  account id on an OdtyId
+        type AccountIdOf: Convert<Self::IdtyId, Option<Self::AccountId>>;
         /// Optional metadata
         type MetaData: Default + Parameter + Validate<Self::AccountId>;
         #[pallet::constant]
@@ -78,6 +83,7 @@ pub mod pallet {
         /// Because this pallet emits events, it depends on the runtime's definition of an event.
         type RuntimeEvent: From<Event<Self, I>>
             + IsType<<Self as frame_system::Config>::RuntimeEvent>;
+        type WeightInfo: WeightInfo;
     }
 
     // GENESIS STUFFĂ‚ //
@@ -195,8 +201,8 @@ pub mod pallet {
 
     #[pallet::call]
     impl<T: Config<I>, I: 'static> Pallet<T, I> {
-        #[pallet::weight(1_000_000_000)]
         /// request membership without checks
+        #[pallet::weight(T::WeightInfo::force_request_membership())]
         pub fn force_request_membership(
             origin: OriginFor<T>,
             idty_id: T::IdtyId,
@@ -207,9 +213,9 @@ pub mod pallet {
             Self::do_request_membership(idty_id, metadata)
         }
 
-        #[pallet::weight(1_000_000_000)]
         /// submit a membership request (must have a declared identity)
         /// (only available for sub wot, automatic for main wot)
+        #[pallet::weight(T::WeightInfo::request_membership())]
         pub fn request_membership(
             origin: OriginFor<T>,
             metadata: T::MetaData,
@@ -225,9 +231,9 @@ pub mod pallet {
             Self::do_request_membership(idty_id, metadata)
         }
 
-        #[pallet::weight(1_000_000_000)]
         /// claim that the previously requested membership fullfills the requirements
         /// (only available for sub wot, automatic for main wot)
+        #[pallet::weight(T::WeightInfo::claim_membership())]
         pub fn claim_membership(
             origin: OriginFor<T>,
             maybe_idty_id: Option<T::IdtyId>,
@@ -253,8 +259,8 @@ pub mod pallet {
             Ok(().into())
         }
 
-        #[pallet::weight(1_000_000_000)]
         /// extend the validity period of an active membership
+        #[pallet::weight(T::WeightInfo::renew_membership())]
         pub fn renew_membership(
             origin: OriginFor<T>,
             maybe_idty_id: Option<T::IdtyId>,
@@ -274,9 +280,9 @@ pub mod pallet {
             Ok(().into())
         }
 
-        #[pallet::weight(1_000_000_000)]
         /// revoke an active membership
         /// (only available for sub wot, automatic for main wot)
+        #[pallet::weight(T::WeightInfo::revoke_membership())]
         pub fn revoke_membership(
             origin: OriginFor<T>,
             maybe_idty_id: Option<T::IdtyId>,
diff --git a/pallets/membership/src/mock.rs b/pallets/membership/src/mock.rs
index 93bb61d0d..e51038e9a 100644
--- a/pallets/membership/src/mock.rs
+++ b/pallets/membership/src/mock.rs
@@ -86,11 +86,13 @@ impl pallet_membership::Config for Test {
     type CheckCallAllowed = ();
     type IdtyId = IdtyId;
     type IdtyIdOf = ConvertInto;
+    type AccountIdOf = ConvertInto;
     type MembershipPeriod = MembershipPeriod;
     type MetaData = ();
     type OnEvent = ();
     type PendingMembershipPeriod = PendingMembershipPeriod;
     type RuntimeEvent = RuntimeEvent;
+    type WeightInfo = ();
 }
 
 // Build genesis storage according to the mock runtime.
diff --git a/pallets/membership/src/weights.rs b/pallets/membership/src/weights.rs
new file mode 100644
index 000000000..efd18e457
--- /dev/null
+++ b/pallets/membership/src/weights.rs
@@ -0,0 +1,84 @@
+// 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/>.
+
+#![allow(clippy::unnecessary_cast)]
+
+use frame_support::weights::{constants::RocksDbWeight, Weight};
+
+/// Weight functions needed for pallet_universal_dividend.
+pub trait WeightInfo {
+    fn force_request_membership() -> Weight;
+    fn request_membership() -> Weight;
+    fn claim_membership() -> Weight;
+    fn renew_membership() -> Weight;
+    fn revoke_membership() -> Weight;
+}
+
+// Insecure weights implementation, use it for tests only!
+impl WeightInfo for () {
+    // Storage: Membership PendingMembership (r:1 w:1)
+    // Storage: Membership Membership (r:1 w:0)
+    // Storage: Parameters ParametersStorage (r:1 w:0)
+    // Storage: Membership PendingMembershipsExpireOn (r:1 w:1)
+    fn force_request_membership() -> Weight {
+        // Minimum execution time: 89_725 nanoseconds.
+        Weight::from_ref_time(98_333_000 as u64)
+            .saturating_add(RocksDbWeight::get().reads(4 as u64))
+            .saturating_add(RocksDbWeight::get().writes(2 as u64))
+    }
+    // Storage: Identity IdentityIndexOf (r:1 w:0)
+    // Storage: Identity Identities (r:1 w:0)
+    fn request_membership() -> Weight {
+        // Minimum execution time: 48_477 nanoseconds.
+        Weight::from_ref_time(50_689_000 as u64)
+            .saturating_add(RocksDbWeight::get().reads(2 as u64))
+    }
+    // Storage: Identity IdentityIndexOf (r:1 w:0)
+    // Storage: Membership Membership (r:1 w:1)
+    // Storage: Cert StorageIdtyCertMeta (r:1 w:0)
+    // Storage: Parameters ParametersStorage (r:1 w:0)
+    // Storage: Membership PendingMembership (r:1 w:1)
+    // Storage: Membership CounterForMembership (r:1 w:1)
+    // Storage: Membership MembershipsExpireOn (r:1 w:1)
+    fn claim_membership() -> Weight {
+        // Minimum execution time: 144_079 nanoseconds.
+        Weight::from_ref_time(146_565_000 as u64)
+            .saturating_add(RocksDbWeight::get().reads(7 as u64))
+            .saturating_add(RocksDbWeight::get().writes(4 as u64))
+    }
+    // Storage: Identity IdentityIndexOf (r:1 w:0)
+    // Storage: Membership Membership (r:1 w:1)
+    // Storage: Identity Identities (r:1 w:0)
+    // Storage: Parameters ParametersStorage (r:1 w:0)
+    // Storage: Membership MembershipsExpireOn (r:1 w:1)
+    fn renew_membership() -> Weight {
+        // Minimum execution time: 120_859 nanoseconds.
+        Weight::from_ref_time(124_222_000 as u64)
+            .saturating_add(RocksDbWeight::get().reads(5 as u64))
+            .saturating_add(RocksDbWeight::get().writes(2 as u64))
+    }
+    // Storage: Identity IdentityIndexOf (r:1 w:0)
+    // Storage: Membership Membership (r:1 w:1)
+    // Storage: Membership CounterForMembership (r:1 w:1)
+    // Storage: Identity Identities (r:1 w:0)
+    // Storage: UniversalDividend CurrentUdIndex (r:1 w:0)
+    fn revoke_membership() -> Weight {
+        // Minimum execution time: 109_486 nanoseconds.
+        Weight::from_ref_time(113_303_000 as u64)
+            .saturating_add(RocksDbWeight::get().reads(5 as u64))
+            .saturating_add(RocksDbWeight::get().writes(2 as u64))
+    }
+}
diff --git a/runtime/common/src/entities.rs b/runtime/common/src/entities.rs
index 81a358911..3cfb7bbb3 100644
--- a/runtime/common/src/entities.rs
+++ b/runtime/common/src/entities.rs
@@ -51,6 +51,18 @@ macro_rules! declare_session_keys {
                     Self::Identity::type_info()
                 }
             }
+
+            // Dummy implementation only for benchmarking
+            impl Default for SessionKeysWrapper {
+                fn default() -> Self {
+                    SessionKeysWrapper(SessionKeys{
+                        grandpa: sp_core::ed25519::Public([0u8; 32]).into(),
+                        babe: sp_core::sr25519::Public([0u8; 32]).into(),
+                        im_online: sp_core::sr25519::Public([0u8; 32]).into(),
+                        authority_discovery: sp_core::sr25519::Public([0u8; 32]).into(),
+                    })
+                }
+            }
         }
     }
 }
@@ -112,11 +124,27 @@ pub struct SmithMembershipMetaData<SessionKeysWrapper> {
     pub p2p_endpoint: sp_runtime::RuntimeString,
     pub session_keys: SessionKeysWrapper,
 }
-impl<SessionKeysWrapper> Default for SmithMembershipMetaData<SessionKeysWrapper> {
+
+impl<SessionKeysWrapper: Default> Default for SmithMembershipMetaData<SessionKeysWrapper> {
+    #[cfg(not(feature = "runtime-benchmarks"))]
     fn default() -> Self {
         unreachable!()
     }
+    #[cfg(feature = "runtime-benchmarks")]
+    // dummy implementation for benchmarking
+    fn default() -> Self {
+        SmithMembershipMetaData {
+            owner_key: AccountId::from([
+                // Dave (FIXME avoid stupid metadata)
+                48, 103, 33, 33, 29, 84, 4, 189, 157, 168, 142, 2, 4, 54, 10, 26, 154, 184, 184,
+                124, 102, 193, 188, 47, 205, 211, 127, 60, 34, 34, 204, 32,
+            ]),
+            p2p_endpoint: sp_runtime::RuntimeString::default(),
+            session_keys: SessionKeysWrapper::default(),
+        }
+    }
 }
+
 impl<SessionKeysWrapper> sp_membership::traits::Validate<AccountId>
     for SmithMembershipMetaData<SessionKeysWrapper>
 {
diff --git a/runtime/common/src/pallets_config.rs b/runtime/common/src/pallets_config.rs
index 69323965e..ffde06ea2 100644
--- a/runtime/common/src/pallets_config.rs
+++ b/runtime/common/src/pallets_config.rs
@@ -448,11 +448,13 @@ macro_rules! pallets_config {
             type CheckCallAllowed = Wot;
             type IdtyId = IdtyIndex;
             type IdtyIdOf = common_runtime::providers::IdentityIndexOf<Self>;
+            type AccountIdOf = common_runtime::providers::IdentityAccountIdProvider<Self>;
             type MembershipPeriod = MembershipPeriod;
             type MetaData = ();
             type OnEvent = OnMembershipEventHandler<Wot, Runtime>;
             type PendingMembershipPeriod = PendingMembershipPeriod;
             type RuntimeEvent = RuntimeEvent;
+            type WeightInfo = common_runtime::weights::pallet_membership_membership::WeightInfo<Runtime>;
         }
 
         impl pallet_certification::Config<Instance1> for Runtime {
@@ -483,11 +485,13 @@ macro_rules! pallets_config {
             type CheckCallAllowed = SmithSubWot;
             type IdtyId = IdtyIndex;
             type IdtyIdOf = common_runtime::providers::IdentityIndexOf<Self>;
+            type AccountIdOf = common_runtime::providers::IdentityAccountIdProvider<Self>;
             type MembershipPeriod = SmithMembershipPeriod;
             type MetaData = SmithMembershipMetaData<opaque::SessionKeysWrapper>;
             type OnEvent = OnSmithMembershipEventHandler<SmithSubWot, Runtime>;
             type PendingMembershipPeriod = SmithPendingMembershipPeriod;
             type RuntimeEvent = RuntimeEvent;
+            type WeightInfo = common_runtime::weights::pallet_membership_smith_membership::WeightInfo<Runtime>;
         }
 
         impl pallet_certification::Config<Instance2> for Runtime {
diff --git a/runtime/common/src/weights.rs b/runtime/common/src/weights.rs
index 97903b4e1..c595875ad 100644
--- a/runtime/common/src/weights.rs
+++ b/runtime/common/src/weights.rs
@@ -36,4 +36,6 @@ pub mod pallet_duniter_account;
 pub mod pallet_oneshot_account;
 pub mod pallet_certification_cert;
 pub mod pallet_certification_smith_cert;
+pub mod pallet_membership_membership;
+pub mod pallet_membership_smith_membership;
 pub mod paritydb_weights;
diff --git a/runtime/common/src/weights/pallet_certification_smith_cert.rs b/runtime/common/src/weights/pallet_certification_smith_cert.rs
index 52ec20435..024b4b8a5 100644
--- a/runtime/common/src/weights/pallet_certification_smith_cert.rs
+++ b/runtime/common/src/weights/pallet_certification_smith_cert.rs
@@ -46,10 +46,10 @@ use sp_std::marker::PhantomData;
 /// Weight functions for `common_runtime::certification`.
 pub struct WeightInfo<T>(PhantomData<T>);
 impl<T: frame_system::Config> pallet_certification::WeightInfo for WeightInfo<T> {
-	// Storage: SmithsCert StorageIdtyCertMeta (r:2 w:2)
+	// Storage: SmithCert StorageIdtyCertMeta (r:2 w:2)
 	// Storage: Parameters ParametersStorage (r:1 w:0)
-	// Storage: SmithsCert StorageCertsRemovableOn (r:1 w:1)
-	// Storage: SmithsCert CertsByReceiver (r:1 w:1)
+	// Storage: SmithCert StorageCertsRemovableOn (r:1 w:1)
+	// Storage: SmithCert CertsByReceiver (r:1 w:1)
 	fn force_add_cert() -> Weight {
 		// Minimum execution time: 125_287 nanoseconds.
 		Weight::from_ref_time(128_059_000 as u64)
@@ -57,18 +57,18 @@ impl<T: frame_system::Config> pallet_certification::WeightInfo for WeightInfo<T>
 			.saturating_add(T::DbWeight::get().writes(4 as u64))
 	}
 	// Storage: Identity Identities (r:2 w:0)
-	// Storage: SmithsCert StorageIdtyCertMeta (r:2 w:2)
+	// Storage: SmithCert StorageIdtyCertMeta (r:2 w:2)
 	// Storage: Parameters ParametersStorage (r:1 w:0)
-	// Storage: SmithsCert StorageCertsRemovableOn (r:1 w:1)
-	// Storage: SmithsCert CertsByReceiver (r:1 w:1)
+	// Storage: SmithCert StorageCertsRemovableOn (r:1 w:1)
+	// Storage: SmithCert CertsByReceiver (r:1 w:1)
 	fn add_cert() -> Weight {
 		// Minimum execution time: 147_626 nanoseconds.
 		Weight::from_ref_time(152_571_000 as u64)
 			.saturating_add(T::DbWeight::get().reads(7 as u64))
 			.saturating_add(T::DbWeight::get().writes(4 as u64))
 	}
-	// Storage: SmithsCert CertsByReceiver (r:1 w:1)
-	// Storage: SmithsCert StorageIdtyCertMeta (r:2 w:2)
+	// Storage: SmithCert CertsByReceiver (r:1 w:1)
+	// Storage: SmithCert StorageIdtyCertMeta (r:2 w:2)
 	// Storage: Parameters ParametersStorage (r:1 w:0)
 	// Storage: SmithMembership Membership (r:1 w:0)
 	fn del_cert() -> Weight {
@@ -77,8 +77,8 @@ impl<T: frame_system::Config> pallet_certification::WeightInfo for WeightInfo<T>
 			.saturating_add(T::DbWeight::get().reads(5 as u64))
 			.saturating_add(T::DbWeight::get().writes(3 as u64))
 	}
-	// Storage: SmithsCert CertsByReceiver (r:1 w:1)
-	// Storage: SmithsCert StorageIdtyCertMeta (r:2 w:2)
+	// Storage: SmithCert CertsByReceiver (r:1 w:1)
+	// Storage: SmithCert StorageIdtyCertMeta (r:2 w:2)
 	// Storage: Parameters ParametersStorage (r:1 w:0)
 	// Storage: SmithMembership Membership (r:1 w:0)
 	/// The range of component `i` is `[2, 1000]`.
diff --git a/runtime/common/src/weights/pallet_membership_membership.rs b/runtime/common/src/weights/pallet_membership_membership.rs
new file mode 100644
index 000000000..799f51a0c
--- /dev/null
+++ b/runtime/common/src/weights/pallet_membership_membership.rs
@@ -0,0 +1,101 @@
+// 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/>.
+
+//! Autogenerated weights for `pallet_membership`
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
+//! DATE: 2023-04-26, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! HOSTNAME: `benjamin-xps139380`, CPU: `Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz`
+//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024
+
+// Executed Command:
+// target/release/duniter
+// benchmark
+// pallet
+// --chain=dev
+// --steps=50
+// --repeat=20
+// --pallet=pallet_membership
+// --extrinsic=*
+// --execution=wasm
+// --wasm-execution=compiled
+// --heap-pages=4096
+// --header=./file_header.txt
+// --output=./runtime/common/src/weights/
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+
+use frame_support::{traits::Get, weights::Weight};
+use sp_std::marker::PhantomData;
+
+/// Weight functions for `pallet_membership`.
+pub struct WeightInfo<T>(PhantomData<T>);
+impl<T: frame_system::Config> pallet_membership::WeightInfo for WeightInfo<T> {
+	// Storage: Membership PendingMembership (r:1 w:1)
+	// Storage: Membership Membership (r:1 w:0)
+	// Storage: Parameters ParametersStorage (r:1 w:0)
+	// Storage: Membership PendingMembershipsExpireOn (r:1 w:1)
+	fn force_request_membership() -> Weight {
+		// Minimum execution time: 89_725 nanoseconds.
+		Weight::from_ref_time(98_333_000 as u64)
+			.saturating_add(T::DbWeight::get().reads(4 as u64))
+			.saturating_add(T::DbWeight::get().writes(2 as u64))
+	}
+	// Storage: Identity IdentityIndexOf (r:1 w:0)
+	// Storage: Identity Identities (r:1 w:0)
+	fn request_membership() -> Weight {
+		// Minimum execution time: 48_477 nanoseconds.
+		Weight::from_ref_time(50_689_000 as u64)
+			.saturating_add(T::DbWeight::get().reads(2 as u64))
+	}
+	// Storage: Identity IdentityIndexOf (r:1 w:0)
+	// Storage: Membership Membership (r:1 w:1)
+	// Storage: Cert StorageIdtyCertMeta (r:1 w:0)
+	// Storage: Parameters ParametersStorage (r:1 w:0)
+	// Storage: Membership PendingMembership (r:1 w:1)
+	// Storage: Membership CounterForMembership (r:1 w:1)
+	// Storage: Membership MembershipsExpireOn (r:1 w:1)
+	fn claim_membership() -> Weight {
+		// Minimum execution time: 144_079 nanoseconds.
+		Weight::from_ref_time(146_565_000 as u64)
+			.saturating_add(T::DbWeight::get().reads(7 as u64))
+			.saturating_add(T::DbWeight::get().writes(4 as u64))
+	}
+	// Storage: Identity IdentityIndexOf (r:1 w:0)
+	// Storage: Membership Membership (r:1 w:1)
+	// Storage: Identity Identities (r:1 w:0)
+	// Storage: Parameters ParametersStorage (r:1 w:0)
+	// Storage: Membership MembershipsExpireOn (r:1 w:1)
+	fn renew_membership() -> Weight {
+		// Minimum execution time: 120_859 nanoseconds.
+		Weight::from_ref_time(124_222_000 as u64)
+			.saturating_add(T::DbWeight::get().reads(5 as u64))
+			.saturating_add(T::DbWeight::get().writes(2 as u64))
+	}
+	// Storage: Identity IdentityIndexOf (r:1 w:0)
+	// Storage: Membership Membership (r:1 w:1)
+	// Storage: Membership CounterForMembership (r:1 w:1)
+	// Storage: Identity Identities (r:1 w:0)
+	// Storage: UniversalDividend CurrentUdIndex (r:1 w:0)
+	fn revoke_membership() -> Weight {
+		// Minimum execution time: 109_486 nanoseconds.
+		Weight::from_ref_time(113_303_000 as u64)
+			.saturating_add(T::DbWeight::get().reads(5 as u64))
+			.saturating_add(T::DbWeight::get().writes(2 as u64))
+	}
+}
diff --git a/runtime/common/src/weights/pallet_membership_smith_membership.rs b/runtime/common/src/weights/pallet_membership_smith_membership.rs
new file mode 100644
index 000000000..2ecd9b61e
--- /dev/null
+++ b/runtime/common/src/weights/pallet_membership_smith_membership.rs
@@ -0,0 +1,111 @@
+// 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/>.
+
+//! Autogenerated weights for `pallet_membership`
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
+//! DATE: 2023-04-26, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! HOSTNAME: `benjamin-xps139380`, CPU: `Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz`
+//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024
+
+// Executed Command:
+// target/release/duniter
+// benchmark
+// pallet
+// --chain=dev
+// --steps=50
+// --repeat=20
+// --pallet=pallet_membership
+// --extrinsic=*
+// --execution=wasm
+// --wasm-execution=compiled
+// --heap-pages=4096
+// --header=./file_header.txt
+// --output=./runtime/common/src/weights/
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+
+use frame_support::{traits::Get, weights::Weight};
+use sp_std::marker::PhantomData;
+
+/// Weight functions for `pallet_membership`.
+pub struct WeightInfo<T>(PhantomData<T>);
+impl<T: frame_system::Config> pallet_membership::WeightInfo for WeightInfo<T> {
+	// Storage: SmithMembership PendingMembership (r:1 w:1)
+	// Storage: SmithMembership Membership (r:1 w:0)
+	// Storage: Parameters ParametersStorage (r:1 w:0)
+	// Storage: SmithMembership PendingMembershipsExpireOn (r:1 w:1)
+	fn force_request_membership() -> Weight {
+		// Minimum execution time: 96_077 nanoseconds.
+		Weight::from_ref_time(98_570_000 as u64)
+			.saturating_add(T::DbWeight::get().reads(4 as u64))
+			.saturating_add(T::DbWeight::get().writes(2 as u64))
+	}
+	// Storage: Identity IdentityIndexOf (r:1 w:0)
+	// Storage: Identity Identities (r:1 w:0)
+	// Storage: SmithMembership PendingMembership (r:1 w:1)
+	// Storage: SmithMembership Membership (r:1 w:0)
+	// Storage: Parameters ParametersStorage (r:1 w:0)
+	// Storage: SmithMembership PendingMembershipsExpireOn (r:1 w:1)
+	fn request_membership() -> Weight {
+		// Minimum execution time: 122_839 nanoseconds.
+		Weight::from_ref_time(125_861_000 as u64)
+			.saturating_add(T::DbWeight::get().reads(6 as u64))
+			.saturating_add(T::DbWeight::get().writes(2 as u64))
+	}
+	// Storage: Identity IdentityIndexOf (r:2 w:0)
+	// Storage: SmithMembership Membership (r:2 w:1)
+	// Storage: SmithCert StorageIdtyCertMeta (r:1 w:0)
+	// Storage: Parameters ParametersStorage (r:1 w:0)
+	// Storage: SmithMembership PendingMembership (r:1 w:1)
+	// Storage: SmithMembership CounterForMembership (r:1 w:1)
+	// Storage: SmithMembership MembershipsExpireOn (r:1 w:1)
+	fn claim_membership() -> Weight {
+		// Minimum execution time: 165_369 nanoseconds.
+		Weight::from_ref_time(167_607_000 as u64)
+			.saturating_add(T::DbWeight::get().reads(9 as u64))
+			.saturating_add(T::DbWeight::get().writes(4 as u64))
+	}
+	// Storage: Identity IdentityIndexOf (r:1 w:0)
+	// Storage: SmithMembership Membership (r:1 w:1)
+	// Storage: Identity Identities (r:1 w:0)
+	// Storage: Parameters ParametersStorage (r:1 w:0)
+	// Storage: SmithMembership MembershipsExpireOn (r:1 w:1)
+	fn renew_membership() -> Weight {
+		// Minimum execution time: 121_761 nanoseconds.
+		Weight::from_ref_time(125_210_000 as u64)
+			.saturating_add(T::DbWeight::get().reads(5 as u64))
+			.saturating_add(T::DbWeight::get().writes(2 as u64))
+	}
+	// Storage: Identity IdentityIndexOf (r:1 w:0)
+	// Storage: SmithMembership Membership (r:1 w:1)
+	// Storage: SmithMembership CounterForMembership (r:1 w:1)
+	// Storage: AuthorityMembers Members (r:1 w:1)
+	// Storage: AuthorityMembers OnlineAuthorities (r:1 w:1)
+	// Storage: AuthorityMembers AuthoritiesCounter (r:1 w:1)
+	// Storage: AuthorityMembers IncomingAuthorities (r:1 w:1)
+	// Storage: Session NextKeys (r:1 w:1)
+	// Storage: System Account (r:1 w:1)
+	// Storage: Session KeyOwner (r:0 w:4)
+	fn revoke_membership() -> Weight {
+		// Minimum execution time: 234_173 nanoseconds.
+		Weight::from_ref_time(239_334_000 as u64)
+			.saturating_add(T::DbWeight::get().reads(9 as u64))
+			.saturating_add(T::DbWeight::get().writes(12 as u64))
+	}
+}
diff --git a/runtime/gdev/src/lib.rs b/runtime/gdev/src/lib.rs
index 554d71af9..cfaada2ad 100644
--- a/runtime/gdev/src/lib.rs
+++ b/runtime/gdev/src/lib.rs
@@ -140,13 +140,15 @@ pub type TechnicalCommitteeInstance = Instance2;
 mod benches {
     define_benchmarks!(
         [pallet_certification, Cert]
-        [pallet_certification, SmithsCert]
+        [pallet_certification, SmithCert]
         [pallet_oneshot_account, OneshotAccount]
         [pallet_universal_dividend, UniversalDividend]
         [pallet_provide_randomness, ProvideRandomness]
         [pallet_upgrade_origin, UpgradeOrigin]
         [pallet_duniter_account, Account]
         [pallet_identity, Identity]
+        [pallet_membership, Membership]
+        [pallet_membership, SmithMembership]
         // Substrate
         [pallet_balances, Balances]
         [frame_benchmarking::baseline, Baseline::<Runtime>]
-- 
GitLab