From 38dca822bb54053f8e26cf74e728481dd11f2d7c Mon Sep 17 00:00:00 2001
From: librelois <c@elo.tf>
Date: Fri, 21 Jan 2022 00:10:19 +0100
Subject: [PATCH] feat: integrate smiths sub-wot in all runtimes

---
 Cargo.lock                                 |   3 +
 node/src/chain_spec.rs                     |   2 +
 node/src/chain_spec/gdev.rs                |  86 +++++++--
 node/src/chain_spec/gtest.rs               | 206 +++++++--------------
 node/src/command.rs                        |   6 +-
 pallets/authority-members/src/lib.rs       | 128 +++++++++----
 pallets/authority-members/src/mock.rs      |  13 +-
 pallets/authority-members/src/tests.rs     |  11 +-
 pallets/authority-members/src/types.rs     |   3 -
 pallets/duniter-test-parameters/src/lib.rs |  12 +-
 pallets/duniter-wot/src/lib.rs             |  37 ++--
 pallets/duniter-wot/src/tests.rs           |   2 +-
 pallets/membership/src/lib.rs              |  24 +--
 pallets/membership/src/tests.rs            |  30 ++-
 primitives/membership/src/lib.rs           |   4 +-
 primitives/membership/src/traits.rs        |  20 +-
 runtime/common/Cargo.toml                  |   2 +
 runtime/common/src/handlers.rs             |  78 +++++++-
 runtime/common/src/lib.rs                  |  46 ++---
 runtime/common/src/pallets_config.rs       |  74 ++++++--
 runtime/g1/Cargo.toml                      |   2 +
 runtime/g1/src/lib.rs                      |  16 +-
 runtime/g1/src/parameters.rs               |  38 +++-
 runtime/gdev/src/lib.rs                    |  45 +++--
 runtime/gtest/Cargo.toml                   |   2 +
 runtime/gtest/src/lib.rs                   |  24 ++-
 runtime/gtest/src/parameters.rs            |  38 +++-
 27 files changed, 582 insertions(+), 370 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 3e2a94d01..15e89cff4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -835,6 +835,7 @@ version = "0.8.0-dev"
 dependencies = [
  "frame-support",
  "frame-system",
+ "pallet-authority-members",
  "pallet-certification",
  "pallet-duniter-wot",
  "pallet-identity",
@@ -1869,6 +1870,7 @@ dependencies = [
  "frame-system-rpc-runtime-api",
  "hex-literal",
  "pallet-authority-discovery",
+ "pallet-authority-members",
  "pallet-authorship",
  "pallet-babe",
  "pallet-balances",
@@ -2108,6 +2110,7 @@ dependencies = [
  "frame-system-rpc-runtime-api",
  "hex-literal",
  "pallet-authority-discovery",
+ "pallet-authority-members",
  "pallet-authorship",
  "pallet-babe",
  "pallet-balances",
diff --git a/node/src/chain_spec.rs b/node/src/chain_spec.rs
index e414858c2..bb7421458 100644
--- a/node/src/chain_spec.rs
+++ b/node/src/chain_spec.rs
@@ -28,6 +28,8 @@ use std::collections::BTreeMap;
 
 pub type AccountPublic = <Signature as Verify>::Signer;
 
+pub const NAMES: [&str; 6] = ["Alice", "Bob", "Charlie", "Dave", "Eve", "Ferdie"];
+
 /// Generate a crypto pair from seed.
 pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
     TPublic::Pair::from_string(&format!("//{}", seed), None)
diff --git a/node/src/chain_spec/gdev.rs b/node/src/chain_spec/gdev.rs
index e2263ed41..56a250e97 100644
--- a/node/src/chain_spec/gdev.rs
+++ b/node/src/chain_spec/gdev.rs
@@ -18,12 +18,11 @@ use super::*;
 use common_runtime::constants::*;
 use common_runtime::entities::IdtyName;
 use gdev_runtime::{
-    opaque::SessionKeys, AccountId, BabeConfig, BalancesConfig, CertConfig, GenesisConfig,
-    GenesisParameters, IdentityConfig, IdtyValue, ImOnlineId, MembershipConfig, ParametersConfig,
-    SessionConfig, SudoConfig, SystemConfig, UdAccountsStorageConfig, UniversalDividendConfig,
-    WASM_BINARY,
+    opaque::SessionKeys, AccountId, AuthorityMembersConfig, BabeConfig, BalancesConfig, CertConfig,
+    GenesisConfig, GenesisParameters, IdentityConfig, IdtyValue, ImOnlineId, MembershipConfig,
+    ParametersConfig, SessionConfig, SmithsCertConfig, SmithsMembershipConfig, SudoConfig,
+    SystemConfig, UdAccountsStorageConfig, UniversalDividendConfig, WASM_BINARY,
 };
-use maplit::btreemap;
 use sc_service::ChainType;
 use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
 use sp_consensus_babe::AuthorityId as BabeId;
@@ -70,14 +69,12 @@ pub fn development_chain_spec() -> Result<ChainSpec, String> {
         move || {
             devnet_genesis(
                 wasm_binary,
-                // Initial authorities
-                vec![get_authority_keys_from_seed("Alice")],
-                // Inital identities
-                btreemap![
-                    IdtyName::from("Alice") => get_account_id_from_seed::<sr25519::Public>("Alice"),
-                    IdtyName::from("Bob") => get_account_id_from_seed::<sr25519::Public>("Bob"),
-                    IdtyName::from("Charlie") => get_account_id_from_seed::<sr25519::Public>("Charlie"),
-                ],
+                // Initial authorities len
+                1,
+                // Initial smiths members len
+                3,
+                // Inital identities len
+                4,
                 // Sudo account
                 get_account_id_from_seed::<sr25519::Public>("Alice"),
                 true,
@@ -106,14 +103,35 @@ pub fn development_chain_spec() -> Result<ChainSpec, String> {
 
 fn devnet_genesis(
     wasm_binary: &[u8],
-    initial_authorities: Vec<AuthorityKeys>,
-    initial_identities: BTreeMap<IdtyName, AccountId>,
+    initial_authorities_len: usize,
+    initial_smiths_len: usize,
+    initial_identities_len: usize,
     root_key: AccountId,
     _enable_println: bool,
 ) -> gdev_runtime::GenesisConfig {
+    assert!(initial_identities_len <= 6);
+    assert!(initial_smiths_len <= initial_identities_len);
+    assert!(initial_authorities_len <= initial_smiths_len);
+
     let cert_validity_period = get_env_u32("DUNITER_CERT_VALIDITY_PERIOD", 1_000);
     let membership_period = get_env_u32("DUNITER_MEMBERSHIP_PERIOD", 1_000);
     let membership_renewable_period = get_env_u32("DUNITER_MEMBERSHIP_RENEWABLE_PERIOD", 50);
+    let smith_cert_validity_period = get_env_u32("DUNITER_SMITH_CERT_VALIDITY_PERIOD", 1_000);
+    let smith_membership_renewable_period =
+        get_env_u32("DUNITER_SMITH_MEMBERSHIP_RENEWABLE_PERIOD", 20);
+    let smith_membership_period = get_env_u32("DUNITER_SMITH_MEMBERSHIP_PERIOD", 1_000);
+
+    let initial_smiths = (0..initial_smiths_len)
+        .map(|i| get_authority_keys_from_seed(NAMES[i]))
+        .collect::<Vec<AuthorityKeys>>();
+    let initial_identities = (0..initial_smiths_len)
+        .map(|i| {
+            (
+                IdtyName::from(NAMES[i]),
+                get_account_id_from_seed::<sr25519::Public>(NAMES[i]),
+            )
+        })
+        .collect::<BTreeMap<IdtyName, AccountId>>();
 
     gdev_runtime::GenesisConfig {
         system: SystemConfig {
@@ -124,6 +142,7 @@ fn devnet_genesis(
             parameters: GenesisParameters {
                 cert_period: 15,
                 cert_max_by_issuer: 10,
+                cert_min_received_cert_to_issue_cert: 2,
                 cert_renewable_period: 50,
                 cert_validity_period,
                 idty_confirm_period: 40,
@@ -136,13 +155,29 @@ fn devnet_genesis(
                 ud_first_reeval: 100,
                 ud_reeval_period: 20,
                 ud_reeval_period_in_blocks: 200,
+                smith_cert_period: 15,
+                smith_cert_max_by_issuer: 8,
+                smith_cert_min_received_cert_to_issue_cert: 3,
+                smith_cert_renewable_period: 50,
+                smith_cert_validity_period: 1_000,
+                smith_membership_period: 1_000,
+                smith_membership_renewable_period: 50,
+                smith_pending_membership_period: 500,
+                smiths_wot_first_cert_issuable_on: 20,
+                smiths_wot_min_cert_for_membership: 2,
                 wot_first_cert_issuable_on: 20,
-                wot_min_cert_for_cert_right: 2,
                 wot_min_cert_for_create_idty_right: 2,
                 wot_min_cert_for_membership: 2,
             },
         },
         authority_discovery: Default::default(),
+        authority_members: AuthorityMembersConfig {
+            initial_authorities: initial_smiths
+                .iter()
+                .enumerate()
+                .map(|(i, keys)| (i as u32 + 1, (keys.0.clone(), i < initial_authorities_len)))
+                .collect(),
+        },
         balances: BalancesConfig {
             balances: Default::default(),
         },
@@ -153,7 +188,7 @@ fn devnet_genesis(
         grandpa: Default::default(),
         im_online: Default::default(),
         session: SessionConfig {
-            keys: initial_authorities
+            keys: initial_smiths
                 .iter()
                 .map(|x| {
                     (
@@ -198,6 +233,23 @@ fn devnet_genesis(
             apply_cert_period_at_genesis: false,
             certs_by_issuer: clique_wot(initial_identities.len(), cert_validity_period),
         },
+        smiths_membership: SmithsMembershipConfig {
+            memberships: (1..=initial_smiths_len)
+                .map(|i| {
+                    (
+                        i as u32,
+                        MembershipData {
+                            expire_on: smith_membership_period,
+                            renewable_on: smith_membership_renewable_period,
+                        },
+                    )
+                })
+                .collect(),
+        },
+        smiths_cert: SmithsCertConfig {
+            apply_cert_period_at_genesis: false,
+            certs_by_issuer: clique_wot(initial_smiths_len, smith_cert_validity_period),
+        },
         ud_accounts_storage: UdAccountsStorageConfig {
             ud_accounts: initial_identities.values().cloned().collect(),
         },
diff --git a/node/src/chain_spec/gtest.rs b/node/src/chain_spec/gtest.rs
index 185da92ef..c3e03c358 100644
--- a/node/src/chain_spec/gtest.rs
+++ b/node/src/chain_spec/gtest.rs
@@ -18,11 +18,11 @@ use super::*;
 use common_runtime::constants::*;
 use common_runtime::entities::IdtyName;
 use gtest_runtime::{
-    opaque::SessionKeys, AccountId, BabeConfig, BalancesConfig, CertConfig, GenesisConfig,
-    IdentityConfig, IdtyValue, ImOnlineId, MembershipConfig, SessionConfig, SudoConfig,
-    SystemConfig, UdAccountsStorageConfig, UniversalDividendConfig, WASM_BINARY,
+    opaque::SessionKeys, AccountId, AuthorityMembersConfig, BabeConfig, BalancesConfig, CertConfig,
+    GenesisConfig, IdentityConfig, IdtyValue, ImOnlineId, MembershipConfig, SessionConfig,
+    SmithsCertConfig, SmithsMembershipConfig, SudoConfig, SystemConfig, UdAccountsStorageConfig,
+    UniversalDividendConfig, WASM_BINARY,
 };
-use maplit::btreemap;
 use sc_service::ChainType;
 use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
 use sp_consensus_babe::AuthorityId as BabeId;
@@ -67,16 +67,12 @@ pub fn development_chain_spec() -> Result<ChainSpec, String> {
         "gtest_dev",
         ChainType::Development,
         move || {
-            devnet_genesis(
+            gen_genesis_conf(
                 wasm_binary,
                 // Initial authorities
-                vec![get_authority_keys_from_seed("Alice")],
+                1,
                 // Inital identities
-                btreemap![
-                    IdtyName::from("Alice") => get_account_id_from_seed::<sr25519::Public>("Alice"),
-                    IdtyName::from("Bob") => get_account_id_from_seed::<sr25519::Public>("Bob"),
-                    IdtyName::from("Charlie") => get_account_id_from_seed::<sr25519::Public>("Charlie"),
-                ],
+                3,
                 // Sudo account
                 get_account_id_from_seed::<sr25519::Public>("Alice"),
                 true,
@@ -103,100 +99,12 @@ pub fn development_chain_spec() -> Result<ChainSpec, String> {
     ))
 }
 
-fn devnet_genesis(
-    wasm_binary: &[u8],
-    initial_authorities: Vec<AuthorityKeys>,
-    initial_identities: BTreeMap<IdtyName, AccountId>,
-    root_key: AccountId,
-    _enable_println: bool,
-) -> GenesisConfig {
-    GenesisConfig {
-        system: SystemConfig {
-            // Add Wasm runtime to storage.
-            code: wasm_binary.to_vec(),
-        },
-        authority_discovery: Default::default(),
-        balances: BalancesConfig {
-            balances: Vec::with_capacity(0),
-        },
-        babe: BabeConfig {
-            authorities: Vec::with_capacity(0),
-            epoch_config: Some(BABE_GENESIS_EPOCH_CONFIG),
-        },
-        grandpa: Default::default(),
-        im_online: Default::default(),
-        session: SessionConfig {
-            keys: initial_authorities
-                .iter()
-                .map(|x| {
-                    (
-                        x.0.clone(),
-                        x.0.clone(),
-                        session_keys(x.1.clone(), x.2.clone(), x.3.clone(), x.4.clone()),
-                    )
-                })
-                .collect::<Vec<_>>(),
-        },
-        sudo: SudoConfig {
-            // Assign network admin rights.
-            key: Some(root_key),
-        },
-        identity: IdentityConfig {
-            identities: initial_identities
-                .iter()
-                .map(|(name, account)| IdtyValue {
-                    data: Default::default(),
-                    name: name.clone(),
-                    next_creatable_identity_on: Default::default(),
-                    owner_key: account.clone(),
-                    removable_on: 0,
-                    status: gtest_runtime::IdtyStatus::Validated,
-                })
-                .collect(),
-        },
-        membership: MembershipConfig {
-            memberships: (1..=initial_identities.len())
-                .map(|i| {
-                    (
-                        i as u32,
-                        MembershipData {
-                            expire_on: gtest_runtime::MembershipPeriod::get(),
-                            renewable_on: gtest_runtime::RenewablePeriod::get(),
-                        },
-                    )
-                })
-                .collect(),
-        },
-        cert: CertConfig {
-            apply_cert_period_at_genesis: false,
-            certs_by_issuer: clique_wot(
-                initial_identities.len(),
-                gtest_runtime::parameters::ValidityPeriod::get(),
-            ),
-        },
-        ud_accounts_storage: UdAccountsStorageConfig {
-            ud_accounts: initial_identities.values().cloned().collect(),
-        },
-        universal_dividend: UniversalDividendConfig {
-            first_ud: 1_000,
-            initial_monetary_mass: 0,
-        },
-    }
-}
-
-pub fn local_testnet_config(authorities_count: usize) -> Result<ChainSpec, String> {
+pub fn local_testnet_config(
+    initial_authorities_len: usize,
+    initial_identities_len: usize,
+) -> Result<ChainSpec, String> {
     let wasm_binary = WASM_BINARY.ok_or_else(|| "wasm not available".to_string())?;
 
-    let mut authorities = vec![
-        get_authority_keys_from_seed("Alice"),
-        get_authority_keys_from_seed("Bob"),
-        get_authority_keys_from_seed("Charlie"),
-        get_authority_keys_from_seed("Dave"),
-        get_authority_keys_from_seed("Eve"),
-        get_authority_keys_from_seed("Ferdie"),
-    ];
-    authorities.truncate(authorities_count);
-
     Ok(ChainSpec::from_genesis(
         // Name
         "Äžtest Local Testnet",
@@ -204,19 +112,12 @@ pub fn local_testnet_config(authorities_count: usize) -> Result<ChainSpec, Strin
         "gtest_local_testnet",
         ChainType::Local,
         move || {
-            testnet_genesis(
+            gen_genesis_conf(
                 wasm_binary,
-                // Initial authorities
-                authorities.clone(),
-                // Initial identities
-                btreemap![
-                    IdtyName::from("Alice") => get_account_id_from_seed::<sr25519::Public>("Alice"),
-                    IdtyName::from("Bob") => get_account_id_from_seed::<sr25519::Public>("Bob"),
-                    IdtyName::from("Charlie") => get_account_id_from_seed::<sr25519::Public>("Charlie"),
-                    IdtyName::from("Dave") => get_account_id_from_seed::<sr25519::Public>("Dave"),
-                    IdtyName::from("Eve") => get_account_id_from_seed::<sr25519::Public>("Eve"),
-                    IdtyName::from("Ferdie") => get_account_id_from_seed::<sr25519::Public>("Ferdie"),
-                ],
+                // Initial authorities len
+                initial_authorities_len,
+                // Initial identities len
+                initial_identities_len,
                 // Sudo account
                 get_account_id_from_seed::<sr25519::Public>("Alice"),
                 true,
@@ -243,35 +144,39 @@ pub fn local_testnet_config(authorities_count: usize) -> Result<ChainSpec, Strin
     ))
 }
 
-fn session_keys(
-    babe: BabeId,
-    grandpa: GrandpaId,
-    im_online: ImOnlineId,
-    authority_discovery: AuthorityDiscoveryId,
-) -> SessionKeys {
-    SessionKeys {
-        babe,
-        grandpa,
-        im_online,
-        authority_discovery,
-    }
-}
-
-fn testnet_genesis(
+fn gen_genesis_conf(
     wasm_binary: &[u8],
-    initial_authorities: Vec<AuthorityKeys>,
-    initial_identities: BTreeMap<IdtyName, AccountId>,
+    initial_authorities_len: usize,
+    initial_identities_len: usize,
     root_key: AccountId,
     _enable_println: bool,
 ) -> GenesisConfig {
+    let initial_authorities = (0..initial_authorities_len)
+        .map(|i| get_authority_keys_from_seed(NAMES[i]))
+        .collect::<Vec<AuthorityKeys>>();
+    let initial_identities = (0..initial_identities_len)
+        .map(|i| {
+            (
+                IdtyName::from(NAMES[i]),
+                get_account_id_from_seed::<sr25519::Public>(NAMES[i]),
+            )
+        })
+        .collect::<BTreeMap<IdtyName, AccountId>>();
+
     GenesisConfig {
         system: SystemConfig {
             // Add Wasm runtime to storage.
             code: wasm_binary.to_vec(),
         },
         authority_discovery: Default::default(),
+        authority_members: AuthorityMembersConfig {
+            initial_authorities: initial_authorities
+                .iter()
+                .enumerate()
+                .map(|(i, keys)| (i as u32 + 1, (keys.0.clone(), true)))
+                .collect(),
+        },
         balances: BalancesConfig {
-            // Configure endowed accounts with initial balance of INITIAL_BALANCE.
             balances: Vec::with_capacity(0),
         },
         babe: BabeConfig {
@@ -305,7 +210,6 @@ fn testnet_genesis(
                     next_creatable_identity_on: Default::default(),
                     owner_key: account.clone(),
                     removable_on: 0,
-
                     status: gtest_runtime::IdtyStatus::Validated,
                 })
                 .collect(),
@@ -330,6 +234,26 @@ fn testnet_genesis(
                 gtest_runtime::parameters::ValidityPeriod::get(),
             ),
         },
+        smiths_membership: SmithsMembershipConfig {
+            memberships: (1..=initial_authorities_len)
+                .map(|i| {
+                    (
+                        i as u32,
+                        MembershipData {
+                            expire_on: gtest_runtime::SmithMembershipPeriod::get(),
+                            renewable_on: gtest_runtime::SmithRenewablePeriod::get(),
+                        },
+                    )
+                })
+                .collect(),
+        },
+        smiths_cert: SmithsCertConfig {
+            apply_cert_period_at_genesis: false,
+            certs_by_issuer: clique_wot(
+                initial_authorities_len,
+                gtest_runtime::parameters::SmithValidityPeriod::get(),
+            ),
+        },
         ud_accounts_storage: UdAccountsStorageConfig {
             ud_accounts: initial_identities.values().cloned().collect(),
         },
@@ -339,3 +263,17 @@ fn testnet_genesis(
         },
     }
 }
+
+fn session_keys(
+    babe: BabeId,
+    grandpa: GrandpaId,
+    im_online: ImOnlineId,
+    authority_discovery: AuthorityDiscoveryId,
+) -> SessionKeys {
+    SessionKeys {
+        babe,
+        grandpa,
+        im_online,
+        authority_discovery,
+    }
+}
diff --git a/node/src/command.rs b/node/src/command.rs
index 4a07a82a2..b0e3847fa 100644
--- a/node/src/command.rs
+++ b/node/src/command.rs
@@ -58,9 +58,11 @@ impl SubstrateCli for Cli {
             #[cfg(feature = "gtest")]
             "gtest_dev" => Box::new(chain_spec::gtest::development_chain_spec()?),
             #[cfg(feature = "gtest")]
-            "local" | "gtest_local" => Box::new(chain_spec::gtest::local_testnet_config(2)?),
+            "local" | "gtest_local" => Box::new(chain_spec::gtest::local_testnet_config(2, 3)?),
             #[cfg(feature = "gtest")]
-            "local4" | "gtest_local4" => Box::new(chain_spec::gtest::local_testnet_config(4)?),
+            "local3" | "gtest_local3" => Box::new(chain_spec::gtest::local_testnet_config(3, 4)?),
+            #[cfg(feature = "gtest")]
+            "local4" | "gtest_local4" => Box::new(chain_spec::gtest::local_testnet_config(4, 5)?),
             // Specs provided as json specify which runtime to use in their file name. For example,
             // `g1-custom.json` uses the g1 runtime.
             // `gdev-workshop.json` uses the gdev runtime.
diff --git a/pallets/authority-members/src/lib.rs b/pallets/authority-members/src/lib.rs
index f9795a9c3..44a26d949 100644
--- a/pallets/authority-members/src/lib.rs
+++ b/pallets/authority-members/src/lib.rs
@@ -41,6 +41,7 @@ pub mod pallet {
     use super::*;
     use crate::traits::OnRemovedMember;
     use frame_support::pallet_prelude::*;
+    use frame_support::traits::ValidatorRegistration;
     use frame_support::traits::{StorageVersion, UnfilteredDispatchable};
     use frame_system::pallet_prelude::*;
     use sp_runtime::traits::{Convert, IsMember};
@@ -57,7 +58,9 @@ pub mod pallet {
     // CONFIG //
 
     #[pallet::config]
-    pub trait Config: frame_system::Config + pallet_session::Config {
+    pub trait Config:
+        frame_system::Config + pallet_session::Config + pallet_session::historical::Config
+    {
         type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
         type IsMember: IsMember<Self::MemberId>;
         type OnRemovedMember: OnRemovedMember<Self::MemberId>;
@@ -73,7 +76,7 @@ pub mod pallet {
 
     #[pallet::genesis_config]
     pub struct GenesisConfig<T: Config> {
-        pub initial_authorities: BTreeMap<T::MemberId, T::ValidatorId>,
+        pub initial_authorities: BTreeMap<T::MemberId, (T::ValidatorId, bool)>,
     }
 
     #[cfg(feature = "std")]
@@ -88,13 +91,21 @@ pub mod pallet {
     #[pallet::genesis_build]
     impl<T: Config> GenesisBuild<T> for GenesisConfig<T> {
         fn build(&self) {
-            for (member_id, validator_id) in &self.initial_authorities {
+            for (member_id, (validator_id, _is_online)) in &self.initial_authorities {
                 Members::<T>::insert(member_id, MemberData::new_genesis(validator_id.clone()));
             }
             let mut members_ids = self
                 .initial_authorities
-                .keys()
-                .copied()
+                .iter()
+                .filter_map(
+                    |(member_id, (_validator_id, is_online))| {
+                        if *is_online {
+                            Some(*member_id)
+                        } else {
+                            None
+                        }
+                    },
+                )
                 .collect::<Vec<T::MemberId>>();
             members_ids.sort();
 
@@ -163,6 +174,8 @@ pub mod pallet {
         AlreadyOutgoing,
         /// Not found owner key
         OwnerKeyNotFound,
+        /// Member not found
+        MemberNotFound,
         /// Neither online nor scheduled
         NotOnlineNorIncoming,
         /// Not owner
@@ -186,22 +199,26 @@ pub mod pallet {
             let who = ensure_signed(origin)?;
             Self::verify_ownership_and_membership(&who, member_id)?;
 
-            let member_data =
-                Members::<T>::try_get(member_id).map_err(|_| Error::<T>::SessionKeysNotProvided)?;
-            if !member_data.session_keys_provided {
+            let member_data = Members::<T>::get(member_id).ok_or(Error::<T>::MemberNotFound)?;
+            if !pallet_session::Pallet::<T>::is_registered(&member_data.validator_id) {
                 return Err(Error::<T>::SessionKeysNotProvided.into());
             }
-            if !Self::is_online(member_id) && !Self::is_incoming(member_id) {
+            if Self::is_outgoing(member_id) {
+                return Err(Error::<T>::AlreadyOutgoing.into());
+            }
+            let is_incoming = Self::is_incoming(member_id);
+            if !is_incoming && !Self::is_online(member_id) {
                 return Err(Error::<T>::NotOnlineNorIncoming.into());
             }
 
             // Apply phase //
-            if !Self::insert_out(member_id) {
-                Err(Error::<T>::AlreadyOutgoing.into())
-            } else {
+            if is_incoming {
                 Self::remove_in(member_id);
-                Ok(().into())
+            } else {
+                Self::insert_out(member_id);
             }
+
+            Ok(().into())
         }
         #[pallet::weight(0)]
         pub fn go_online(
@@ -212,28 +229,27 @@ pub mod pallet {
             let who = ensure_signed(origin)?;
             Self::verify_ownership_and_membership(&who, member_id)?;
 
-            let member_data =
-                Members::<T>::try_get(member_id).map_err(|_| Error::<T>::SessionKeysNotProvided)?;
-            if !member_data.session_keys_provided {
+            let member_data = Members::<T>::get(member_id).ok_or(Error::<T>::MemberNotFound)?;
+            if !pallet_session::Pallet::<T>::is_registered(&member_data.validator_id) {
                 return Err(Error::<T>::SessionKeysNotProvided.into());
             }
 
+			if Self::is_incoming(member_id) {
+                return Err(Error::<T>::AlreadyIncoming.into());
+            }
+			let is_outgoing = Self::is_outgoing(member_id);
+            if Self::is_online(member_id) && !is_outgoing {
+                return Err(Error::<T>::AlreadyOnline.into());
+            }
+
             // Apply phase //
-            if Self::is_online(member_id) {
-                if Self::is_outgoing(member_id) {
-                    Self::remove_out(member_id);
-                    Ok(().into())
-                } else {
-                    Err(Error::<T>::AlreadyOnline.into())
-                }
-            } else if Self::is_outgoing(member_id) {
+            if is_outgoing {
                 Self::remove_out(member_id);
-                Ok(().into())
-            } else if !Self::insert_in(member_id) {
-                Err(Error::<T>::AlreadyIncoming.into())
             } else {
-                Ok(().into())
+                Self::insert_in(member_id);
             }
+
+            Ok(().into())
         }
 
         #[pallet::weight(0)]
@@ -260,10 +276,8 @@ pub mod pallet {
             Members::<T>::mutate_exists(member_id, |member_data_opt| {
                 let mut member_data = member_data_opt.get_or_insert(MemberData {
                     expire_on_session,
-                    session_keys_provided: true,
                     validator_id: validator_id.clone(),
                 });
-                member_data.session_keys_provided = true;
                 member_data.validator_id = validator_id;
             });
 
@@ -394,7 +408,7 @@ pub mod pallet {
                 if let Ok(index) = members_ids.binary_search(&member_id) {
                     members_ids.remove(index);
                 }
-            });
+            })
         }
         fn remove_online(member_id: T::MemberId) {
             OnlineAuthorities::<T>::mutate(|members_ids| {
@@ -491,11 +505,14 @@ impl<T: Config> pallet_session::SessionManager<T::ValidatorId> for Pallet<T> {
         )
     }
     /// Same as `new_session`, but it this should only be called at genesis.
-    ///
-    /// The session manager might decide to treat this in a different way. Default impl is simply
-    /// using [`new_session`](Self::new_session).
     fn new_session_genesis(_new_index: SessionIndex) -> Option<Vec<T::ValidatorId>> {
-        None
+        Some(
+            OnlineAuthorities::<T>::get()
+                .iter()
+                .filter_map(Members::<T>::get)
+                .map(|member_data| member_data.validator_id)
+                .collect(),
+        )
     }
     /// End the session.
     ///
@@ -509,3 +526,44 @@ impl<T: Config> pallet_session::SessionManager<T::ValidatorId> for Pallet<T> {
         Self::expire_memberships(start_index);
     }
 }
+
+fn add_full_identification<T: Config>(
+    validator_id: T::ValidatorId,
+) -> Option<(T::ValidatorId, T::FullIdentification)> {
+    use sp_runtime::traits::Convert as _;
+    T::FullIdentificationOf::convert(validator_id.clone())
+        .map(|full_ident| (validator_id, full_ident))
+}
+
+impl<T: Config> pallet_session::historical::SessionManager<T::ValidatorId, T::FullIdentification>
+    for Pallet<T>
+{
+    fn new_session(
+        new_index: SessionIndex,
+    ) -> Option<sp_std::vec::Vec<(T::ValidatorId, T::FullIdentification)>> {
+        <Self as pallet_session::SessionManager<_>>::new_session(new_index).map(|validators_ids| {
+            validators_ids
+                .into_iter()
+                .filter_map(add_full_identification::<T>)
+                .collect()
+        })
+    }
+    fn new_session_genesis(
+        new_index: SessionIndex,
+    ) -> Option<sp_std::vec::Vec<(T::ValidatorId, T::FullIdentification)>> {
+        <Self as pallet_session::SessionManager<_>>::new_session_genesis(new_index).map(
+            |validators_ids| {
+                validators_ids
+                    .into_iter()
+                    .filter_map(add_full_identification::<T>)
+                    .collect()
+            },
+        )
+    }
+    fn start_session(start_index: SessionIndex) {
+        <Self as pallet_session::SessionManager<_>>::start_session(start_index)
+    }
+    fn end_session(end_index: SessionIndex) {
+        <Self as pallet_session::SessionManager<_>>::end_session(end_index)
+    }
+}
diff --git a/pallets/authority-members/src/mock.rs b/pallets/authority-members/src/mock.rs
index a2b2faa49..a2e8f036a 100644
--- a/pallets/authority-members/src/mock.rs
+++ b/pallets/authority-members/src/mock.rs
@@ -129,6 +129,17 @@ impl pallet_session::Config for Test {
     type WeightInfo = ();
 }
 
+pub struct FullIdentificationOfImpl;
+impl sp_runtime::traits::Convert<AccountId, Option<()>> for FullIdentificationOfImpl {
+    fn convert(_: AccountId) -> Option<()> {
+        Some(())
+    }
+}
+impl pallet_session::historical::Config for Test {
+    type FullIdentification = ();
+    type FullIdentificationOf = FullIdentificationOfImpl;
+}
+
 pub struct TestIsSmithMember;
 impl IsMember<u64> for TestIsSmithMember {
     fn is_member(member_id: &u64) -> bool {
@@ -150,7 +161,7 @@ impl pallet_authority_members::Config for Test {
 // Build genesis storage according to the mock runtime.
 pub fn new_test_ext(initial_authorities_len: u64) -> sp_io::TestExternalities {
     let initial_authorities = (1..=initial_authorities_len)
-        .map(|i| (i * 3, i * 3))
+        .map(|i| (i * 3, (i * 3, true)))
         .collect();
     let keys: Vec<_> = (1..=initial_authorities_len)
         .map(|i| (i * 3, i * 3, UintAuthorityId(i * 3).into()))
diff --git a/pallets/authority-members/src/tests.rs b/pallets/authority-members/src/tests.rs
index 7674aa8d7..dcd20ebf1 100644
--- a/pallets/authority-members/src/tests.rs
+++ b/pallets/authority-members/src/tests.rs
@@ -34,7 +34,6 @@ fn test_genesis_build() {
             AuthorityMembers::member(3),
             Some(MemberData {
                 expire_on_session: 0,
-                session_keys_provided: true,
                 validator_id: 3,
             })
         );
@@ -42,7 +41,6 @@ fn test_genesis_build() {
             AuthorityMembers::member(6),
             Some(MemberData {
                 expire_on_session: 0,
-                session_keys_provided: true,
                 validator_id: 6,
             })
         );
@@ -50,7 +48,6 @@ fn test_genesis_build() {
             AuthorityMembers::member(9),
             Some(MemberData {
                 expire_on_session: 0,
-                session_keys_provided: true,
                 validator_id: 9,
             })
         );
@@ -87,7 +84,6 @@ fn test_go_offline() {
             AuthorityMembers::member(9),
             Some(MemberData {
                 expire_on_session: 0,
-                session_keys_provided: true,
                 validator_id: 9,
             })
         );
@@ -98,7 +94,6 @@ fn test_go_offline() {
             AuthorityMembers::member(9),
             Some(MemberData {
                 expire_on_session: 4,
-                session_keys_provided: true,
                 validator_id: 9,
             })
         );
@@ -138,7 +133,6 @@ fn test_go_online() {
             AuthorityMembers::member(12),
             Some(MemberData {
                 expire_on_session: 2,
-                session_keys_provided: true,
                 validator_id: 12,
             })
         );
@@ -154,7 +148,6 @@ fn test_go_online() {
             AuthorityMembers::member(12),
             Some(MemberData {
                 expire_on_session: 2,
-                session_keys_provided: true,
                 validator_id: 12,
             })
         );
@@ -198,12 +191,11 @@ fn test_go_online_then_go_offline_in_same_session() {
         // Verify state
         assert_eq!(AuthorityMembers::incoming(), EMPTY);
         assert_eq!(AuthorityMembers::online(), vec![3, 6, 9]);
-        assert_eq!(AuthorityMembers::outgoing(), vec![12]);
+        assert_eq!(AuthorityMembers::outgoing(), EMPTY);
         assert_eq!(
             AuthorityMembers::member(12),
             Some(MemberData {
                 expire_on_session: 2,
-                session_keys_provided: true,
                 validator_id: 12,
             })
         );
@@ -231,7 +223,6 @@ fn test_go_offline_then_go_online_in_same_session() {
             AuthorityMembers::member(9),
             Some(MemberData {
                 expire_on_session: 0,
-                session_keys_provided: true,
                 validator_id: 9,
             })
         );
diff --git a/pallets/authority-members/src/types.rs b/pallets/authority-members/src/types.rs
index dd04dc862..e22484a07 100644
--- a/pallets/authority-members/src/types.rs
+++ b/pallets/authority-members/src/types.rs
@@ -26,7 +26,6 @@ use sp_staking::SessionIndex;
 #[derive(Encode, Decode, Clone, PartialEq, Eq, TypeInfo)]
 pub struct MemberData<ValidatorId: Decode + Encode + TypeInfo> {
     pub expire_on_session: SessionIndex,
-    pub session_keys_provided: bool,
     pub validator_id: ValidatorId,
 }
 
@@ -34,14 +33,12 @@ impl<ValidatorId: Decode + Encode + TypeInfo> MemberData<ValidatorId> {
     pub fn new(validator_id: ValidatorId, expire_on_session: SessionIndex) -> Self {
         MemberData {
             expire_on_session,
-            session_keys_provided: false,
             validator_id,
         }
     }
     pub fn new_genesis(validator_id: ValidatorId) -> Self {
         MemberData {
             expire_on_session: 0,
-            session_keys_provided: true,
             validator_id,
         }
     }
diff --git a/pallets/duniter-test-parameters/src/lib.rs b/pallets/duniter-test-parameters/src/lib.rs
index fb3585be3..3f310c552 100644
--- a/pallets/duniter-test-parameters/src/lib.rs
+++ b/pallets/duniter-test-parameters/src/lib.rs
@@ -38,6 +38,7 @@ pub mod types {
     > {
         pub cert_period: BlockNumber,
         pub cert_max_by_issuer: CertCount,
+        pub cert_min_received_cert_to_issue_cert: CertCount,
         pub cert_renewable_period: BlockNumber,
         pub cert_validity_period: BlockNumber,
         pub idty_confirm_period: BlockNumber,
@@ -50,8 +51,17 @@ pub mod types {
         pub ud_first_reeval: BlockNumber,
         pub ud_reeval_period: PeriodCount,
         pub ud_reeval_period_in_blocks: BlockNumber,
+        pub smith_cert_period: BlockNumber,
+        pub smith_cert_max_by_issuer: CertCount,
+        pub smith_cert_min_received_cert_to_issue_cert: CertCount,
+        pub smith_cert_renewable_period: BlockNumber,
+        pub smith_cert_validity_period: BlockNumber,
+        pub smith_membership_period: BlockNumber,
+        pub smith_membership_renewable_period: BlockNumber,
+        pub smith_pending_membership_period: BlockNumber,
+        pub smiths_wot_first_cert_issuable_on: BlockNumber,
+        pub smiths_wot_min_cert_for_membership: CertCount,
         pub wot_first_cert_issuable_on: BlockNumber,
-        pub wot_min_cert_for_cert_right: CertCount,
         pub wot_min_cert_for_create_idty_right: CertCount,
         pub wot_min_cert_for_membership: CertCount,
     }
diff --git a/pallets/duniter-wot/src/lib.rs b/pallets/duniter-wot/src/lib.rs
index 3790c6798..0c5e8087c 100644
--- a/pallets/duniter-wot/src/lib.rs
+++ b/pallets/duniter-wot/src/lib.rs
@@ -61,7 +61,7 @@ pub mod pallet {
         frame_system::Config
         + pallet_certification::Config<I, IdtyIndex = IdtyIndex>
         + pallet_identity::Config<IdtyIndex = IdtyIndex>
-        + pallet_membership::Config<I, IdtyId = IdtyIndex, MetaData = ()>
+        + pallet_membership::Config<I, IdtyId = IdtyIndex>
     {
         type FirstIssuableOn: Get<Self::BlockNumber>;
         type IsSubWot: Get<bool>;
@@ -93,7 +93,10 @@ pub mod pallet {
     }
 }
 
-impl<T: Config<I>, I: 'static> pallet_identity::traits::EnsureIdtyCallAllowed<T> for Pallet<T, I> {
+impl<T: Config<I>, I: 'static> pallet_identity::traits::EnsureIdtyCallAllowed<T> for Pallet<T, I>
+where
+    T: pallet_membership::Config<I, MetaData = ()>,
+{
     fn can_create_identity(creator: IdtyIndex) -> bool {
         if let Some(cert_meta) = pallet_certification::Pallet::<T, I>::idty_cert_meta(creator) {
             cert_meta.received_count >= T::MinCertForCreateIdtyRight::get()
@@ -104,15 +107,11 @@ impl<T: Config<I>, I: 'static> pallet_identity::traits::EnsureIdtyCallAllowed<T>
         }
     }
     fn can_confirm_identity(idty_index: IdtyIndex) -> bool {
-        pallet_membership::Pallet::<T, I>::request_membership(
-            RawOrigin::Root.into(),
-            idty_index,
-            (),
-        )
-        .is_ok()
+        pallet_membership::Pallet::<T, I>::request_membership(RawOrigin::Root.into(), idty_index)
+            .is_ok()
     }
     fn can_validate_identity(idty_index: IdtyIndex) -> bool {
-        pallet_membership::Pallet::<T, I>::claim_membership(RawOrigin::Root.into(), idty_index)
+        pallet_membership::Pallet::<T, I>::claim_membership(RawOrigin::Root.into(), idty_index, ())
             .is_ok()
     }
 }
@@ -186,17 +185,21 @@ impl<T: Config<I>, I: 'static> sp_membership::traits::IsOriginAllowedToUseIdty<T
     }
 }
 
-impl<T: Config<I>, I: 'static> sp_membership::traits::OnEvent<IdtyIndex, ()> for Pallet<T, I> {
-    fn on_event(membership_event: &sp_membership::Event<IdtyIndex>) -> Weight {
+impl<T: Config<I>, I: 'static, MetaData> sp_membership::traits::OnEvent<IdtyIndex, MetaData>
+    for Pallet<T, I>
+where
+    T: pallet_membership::Config<I, MetaData = MetaData>,
+{
+    fn on_event(membership_event: &sp_membership::Event<IdtyIndex, MetaData>) -> Weight {
         match membership_event {
-            sp_membership::Event::<IdtyIndex>::MembershipAcquired(_) => {}
-            sp_membership::Event::<IdtyIndex>::MembershipExpired(idty_index) => {
+            sp_membership::Event::<IdtyIndex, MetaData>::MembershipAcquired(_, _) => {}
+            sp_membership::Event::<IdtyIndex, MetaData>::MembershipExpired(idty_index) => {
                 Self::dispath_idty_call(pallet_identity::Call::disable_identity {
                     idty_index: *idty_index,
                 });
             }
-            sp_membership::Event::<IdtyIndex>::MembershipRenewed(_) => {}
-            sp_membership::Event::<IdtyIndex>::MembershipRequested(idty_index, _) => {
+            sp_membership::Event::<IdtyIndex, MetaData>::MembershipRenewed(_) => {}
+            sp_membership::Event::<IdtyIndex, MetaData>::MembershipRequested(idty_index) => {
                 if let Some(idty_cert_meta) =
                     pallet_certification::Pallet::<T, I>::idty_cert_meta(idty_index)
                 {
@@ -214,8 +217,8 @@ impl<T: Config<I>, I: 'static> sp_membership::traits::OnEvent<IdtyIndex, ()> for
                     }
                 }
             }
-            sp_membership::Event::<IdtyIndex>::MembershipRevoked(_) => {}
-            sp_membership::Event::<IdtyIndex>::PendingMembershipExpired(idty_index) => {
+            sp_membership::Event::<IdtyIndex, MetaData>::MembershipRevoked(_) => {}
+            sp_membership::Event::<IdtyIndex, MetaData>::PendingMembershipExpired(idty_index) => {
                 Self::dispath_idty_call(pallet_identity::Call::remove_identity {
                     idty_index: *idty_index,
                 });
diff --git a/pallets/duniter-wot/src/tests.rs b/pallets/duniter-wot/src/tests.rs
index a688a06d7..d87f3bb9f 100644
--- a/pallets/duniter-wot/src/tests.rs
+++ b/pallets/duniter-wot/src/tests.rs
@@ -237,7 +237,7 @@ fn test_idty_membership_expire_them_requested() {
 
         // Charlie should be able to request membership
         run_to_block(6);
-        assert_ok!(Membership::request_membership(Origin::signed(3), 3, ()));
+        assert_ok!(Membership::request_membership(Origin::signed(3), 3));
 
         // Charlie should re-enter in the wot immediatly
         let events = System::events();
diff --git a/pallets/membership/src/lib.rs b/pallets/membership/src/lib.rs
index 7a7f58a5f..14d5f189f 100644
--- a/pallets/membership/src/lib.rs
+++ b/pallets/membership/src/lib.rs
@@ -226,7 +226,6 @@ pub mod pallet {
         pub fn request_membership(
             origin: OriginFor<T>,
             idty_id: T::IdtyId,
-            metadata: T::MetaData,
         ) -> DispatchResultWithPostInfo {
             let allowed =
                 match T::IsOriginAllowedToUseIdty::is_origin_allowed_to_use_idty(&origin, &idty_id)
@@ -260,9 +259,7 @@ pub mod pallet {
             PendingMembership::<T, I>::insert(idty_id, expire_on);
             PendingMembershipsExpireOn::<T, I>::append(expire_on, idty_id);
             Self::deposit_event(Event::MembershipRequested(idty_id));
-            T::OnEvent::on_event(&sp_membership::Event::MembershipRequested(
-                idty_id, metadata,
-            ));
+            T::OnEvent::on_event(&sp_membership::Event::MembershipRequested(idty_id));
 
             Ok(().into())
         }
@@ -271,6 +268,7 @@ pub mod pallet {
         pub fn claim_membership(
             origin: OriginFor<T>,
             idty_id: T::IdtyId,
+            metadata: T::MetaData,
         ) -> DispatchResultWithPostInfo {
             if Membership::<T, I>::contains_key(&idty_id) {
                 return Err(Error::<T, I>::MembershipAlreadyAcquired.into());
@@ -296,7 +294,7 @@ pub mod pallet {
                 return Err(Error::<T, I>::MembershipRequestNotFound.into());
             }
 
-            let _ = Self::do_claim_membership(idty_id);
+            let _ = Self::do_claim_membership(idty_id, metadata);
 
             Ok(().into())
         }
@@ -357,12 +355,12 @@ pub mod pallet {
     // INTERNAL FUNCTIONS //
 
     impl<T: Config<I>, I: 'static> Pallet<T, I> {
-        pub(super) fn do_claim_membership(idty_id: T::IdtyId) -> Weight {
+        pub(super) fn do_claim_membership(idty_id: T::IdtyId, metadata: T::MetaData) -> Weight {
             let mut total_weight = 1;
             PendingMembership::<T, I>::remove(&idty_id);
             total_weight += Self::do_renew_membership_inner(idty_id);
             Self::deposit_event(Event::MembershipAcquired(idty_id));
-            T::OnEvent::on_event(&sp_membership::Event::MembershipAcquired(idty_id));
+            T::OnEvent::on_event(&sp_membership::Event::MembershipAcquired(idty_id, metadata));
             total_weight
         }
         pub(super) fn do_renew_membership(idty_id: T::IdtyId) -> Weight {
@@ -495,15 +493,3 @@ impl<T: Config<I>, I: 'static> sp_runtime::traits::IsMember<T::IdtyId> for Palle
         Self::is_member_inner(idty_id)
     }
 }
-
-impl<T: Config<I>, I: 'static> MembershipAction<T::IdtyId, T::Origin> for Pallet<T, I> {
-    fn claim_membership_(origin: T::Origin, idty_id: T::IdtyId) -> DispatchResultWithPostInfo {
-        Pallet::<T, I>::claim_membership(origin, idty_id)
-    }
-    fn renew_membership_(origin: T::Origin, idty_id: T::IdtyId) -> DispatchResultWithPostInfo {
-        Pallet::<T, I>::renew_membership(origin, idty_id)
-    }
-    fn revoke_membership_(origin: T::Origin, idty_id: T::IdtyId) -> DispatchResultWithPostInfo {
-        Pallet::<T, I>::revoke_membership(origin, idty_id)
-    }
-}
diff --git a/pallets/membership/src/tests.rs b/pallets/membership/src/tests.rs
index 6482949bd..5e28a39e6 100644
--- a/pallets/membership/src/tests.rs
+++ b/pallets/membership/src/tests.rs
@@ -67,7 +67,7 @@ fn test_membership_already_acquired() {
         run_to_block(1);
         // Merbership 0 cannot be reclaimed
         assert_eq!(
-            DefaultMembership::claim_membership(Origin::signed(0), 0),
+            DefaultMembership::claim_membership(Origin::signed(0), 0, ()),
             Err(Error::<Test, _>::MembershipAlreadyAcquired.into())
         );
     });
@@ -79,7 +79,7 @@ fn test_membership_request_not_found() {
         run_to_block(1);
         // Merbership 0 cannot be reclaimed
         assert_eq!(
-            DefaultMembership::claim_membership(Origin::signed(1), 1),
+            DefaultMembership::claim_membership(Origin::signed(1), 1, ()),
             Err(Error::<Test, _>::MembershipRequestNotFound.into())
         );
     });
@@ -128,17 +128,13 @@ fn test_membership_revocation() {
         // Membership 0 can't request membership before the end of RevokePeriod (1 + 4 = 5)
         run_to_block(2);
         assert_eq!(
-            DefaultMembership::request_membership(Origin::signed(0), 0, ()),
+            DefaultMembership::request_membership(Origin::signed(0), 0),
             Err(Error::<Test, _>::MembershipRevokedRecently.into())
         );
 
         // Membership 0 can request membership after the end of RevokePeriod (1 + 4 = 5)
         run_to_block(5);
-        assert_ok!(DefaultMembership::request_membership(
-            Origin::signed(0),
-            0,
-            ()
-        ),);
+        assert_ok!(DefaultMembership::request_membership(Origin::signed(0), 0,),);
         assert_eq!(
             System::events()[0].event,
             RuntimeEvent::DefaultMembership(Event::MembershipRequested(0))
@@ -151,11 +147,7 @@ fn test_pending_membership_expiration() {
     new_test_ext(Default::default()).execute_with(|| {
         // Idty 0 request membership
         run_to_block(1);
-        assert_ok!(DefaultMembership::request_membership(
-            Origin::signed(0),
-            0,
-            ()
-        ),);
+        assert_ok!(DefaultMembership::request_membership(Origin::signed(0), 0,),);
         assert_eq!(
             System::events()[0].event,
             RuntimeEvent::DefaultMembership(Event::MembershipRequested(0))
@@ -180,11 +172,7 @@ fn test_membership_workflow() {
     new_test_ext(Default::default()).execute_with(|| {
         // Idty 0 request membership
         run_to_block(1);
-        assert_ok!(DefaultMembership::request_membership(
-            Origin::signed(0),
-            0,
-            ()
-        ),);
+        assert_ok!(DefaultMembership::request_membership(Origin::signed(0), 0,),);
         assert_eq!(
             System::events()[0].event,
             RuntimeEvent::DefaultMembership(Event::MembershipRequested(0))
@@ -192,7 +180,11 @@ fn test_membership_workflow() {
 
         // Then, idty 0 claim membership
         run_to_block(2);
-        assert_ok!(DefaultMembership::claim_membership(Origin::signed(0), 0),);
+        assert_ok!(DefaultMembership::claim_membership(
+            Origin::signed(0),
+            0,
+            ()
+        ),);
         assert_eq!(
             System::events()[0].event,
             RuntimeEvent::DefaultMembership(Event::MembershipAcquired(0))
diff --git a/primitives/membership/src/lib.rs b/primitives/membership/src/lib.rs
index 1a0914f27..150d436f2 100644
--- a/primitives/membership/src/lib.rs
+++ b/primitives/membership/src/lib.rs
@@ -29,13 +29,13 @@ use serde::{Deserialize, Serialize};
 
 pub enum Event<IdtyId, MetaData = ()> {
     /// A membership has acquired
-    MembershipAcquired(IdtyId),
+    MembershipAcquired(IdtyId, MetaData),
     /// A membership has expired
     MembershipExpired(IdtyId),
     /// A membership has renewed
     MembershipRenewed(IdtyId),
     /// An identity requested membership
-    MembershipRequested(IdtyId, MetaData),
+    MembershipRequested(IdtyId),
     /// A membership has revoked
     MembershipRevoked(IdtyId),
     /// A pending membership request has expired
diff --git a/primitives/membership/src/traits.rs b/primitives/membership/src/traits.rs
index c671ba6bf..9406861d4 100644
--- a/primitives/membership/src/traits.rs
+++ b/primitives/membership/src/traits.rs
@@ -15,7 +15,7 @@
 // along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>.
 
 use crate::*;
-use frame_support::pallet_prelude::{DispatchResultWithPostInfo, TypeInfo, Weight};
+use frame_support::pallet_prelude::{TypeInfo, Weight};
 
 pub trait IsIdtyAllowedToClaimMembership<IdtyId> {
     fn is_idty_allowed_to_claim_membership(idty_id: &IdtyId) -> bool;
@@ -71,24 +71,6 @@ impl<IdtyId, MetaData> OnEvent<IdtyId, MetaData> for () {
     }
 }
 
-pub trait MembershipAction<IdtyId, Origin> {
-    fn claim_membership_(origin: Origin, idty_id: IdtyId) -> DispatchResultWithPostInfo;
-    fn renew_membership_(origin: Origin, idty_id: IdtyId) -> DispatchResultWithPostInfo;
-    fn revoke_membership_(origin: Origin, idty_id: IdtyId) -> DispatchResultWithPostInfo;
-}
-
-impl<IdtyId, Origin> MembershipAction<IdtyId, Origin> for () {
-    fn claim_membership_(_: Origin, _: IdtyId) -> DispatchResultWithPostInfo {
-        Ok(().into())
-    }
-    fn renew_membership_(_: Origin, _: IdtyId) -> DispatchResultWithPostInfo {
-        Ok(().into())
-    }
-    fn revoke_membership_(_: Origin, _: IdtyId) -> DispatchResultWithPostInfo {
-        Ok(().into())
-    }
-}
-
 pub trait MembershipExternalStorage<BlockNumber: Decode + Encode + TypeInfo, IdtyId>:
     sp_runtime::traits::IsMember<IdtyId>
 {
diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml
index baaa300ee..2d94dcaf2 100644
--- a/runtime/common/Cargo.toml
+++ b/runtime/common/Cargo.toml
@@ -21,6 +21,7 @@ std = [
     'codec/std',
     'frame-support/std',
     'frame-system/std',
+    'pallet-authority-members/std',
     'pallet-certification/std',
     'pallet-duniter-wot/std',
     'pallet-identity/std',
@@ -35,6 +36,7 @@ std = [
 ]
 
 [dependencies]
+pallet-authority-members = { path = '../../pallets/authority-members', default-features = false }
 pallet-certification = { path = '../../pallets/certification', default-features = false }
 pallet-duniter-wot = { path = '../../pallets/duniter-wot', default-features = false }
 pallet-identity = { path = '../../pallets/identity', default-features = false }
diff --git a/runtime/common/src/handlers.rs b/runtime/common/src/handlers.rs
index ebfb913df..401fba2d5 100644
--- a/runtime/common/src/handlers.rs
+++ b/runtime/common/src/handlers.rs
@@ -14,6 +14,9 @@
 // You should have received a copy of the GNU Affero General Public License
 // along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>.
 
+use super::IdtyIndex;
+use frame_support::dispatch::UnfilteredDispatchable;
+use frame_support::instances::Instance2;
 use frame_support::pallet_prelude::Weight;
 use frame_support::Parameter;
 
@@ -27,7 +30,7 @@ impl<
 {
     fn on_event(membership_event: &sp_membership::Event<IdtyIndex>) -> Weight {
         (match membership_event {
-            sp_membership::Event::<IdtyIndex>::MembershipAcquired(idty_index) => {
+            sp_membership::Event::<IdtyIndex>::MembershipAcquired(idty_index, ()) => {
                 if let Some(idty_value) = pallet_identity::Pallet::<Runtime>::identity(idty_index) {
                     <pallet_ud_accounts_storage::Pallet<Runtime>>::replace_account(
                         None,
@@ -51,3 +54,76 @@ impl<
         }) + Inner::on_event(membership_event)
     }
 }
+
+pub struct OnSmithMembershipEventHandler<Inner, Runtime>(
+    core::marker::PhantomData<(Inner, Runtime)>,
+);
+
+impl<
+        IdtyIndex: Copy + Parameter,
+        SessionKeys: Clone,
+        Inner: sp_membership::traits::OnEvent<IdtyIndex, SessionKeys>,
+        Runtime: pallet_identity::Config<IdtyIndex = IdtyIndex>
+            + pallet_authority_members::Config<MemberId = IdtyIndex>
+            + pallet_membership::Config<Instance2, MetaData = SessionKeys>
+            + pallet_session::Config<Keys = SessionKeys>,
+    > sp_membership::traits::OnEvent<IdtyIndex, SessionKeys>
+    for OnSmithMembershipEventHandler<Inner, Runtime>
+{
+    fn on_event(membership_event: &sp_membership::Event<IdtyIndex, SessionKeys>) -> Weight {
+        (match membership_event {
+            sp_membership::Event::<IdtyIndex, SessionKeys>::MembershipAcquired(
+                idty_index,
+                session_keys,
+            ) => {
+                if let Some(idty_value) = pallet_identity::Pallet::<Runtime>::identity(idty_index) {
+                    let call = pallet_authority_members::Call::<Runtime>::set_session_keys {
+                        member_id: *idty_index,
+                        keys: session_keys.clone(),
+                    };
+                    if let Err(e) = call.dispatch_bypass_filter(
+                        frame_system::Origin::<Runtime>::Signed(idty_value.owner_key).into(),
+                    ) {
+                        sp_std::if_std! {
+                            println!("{:?}", e)
+                        }
+                    }
+                }
+                0
+            }
+            sp_membership::Event::MembershipRevoked(idty_index) => {
+                let call = pallet_authority_members::Call::<Runtime>::remove_member {
+                    member_id: *idty_index,
+                };
+                if let Err(e) =
+                    call.dispatch_bypass_filter(frame_system::Origin::<Runtime>::Root.into())
+                {
+                    sp_std::if_std! {
+                        println!("{:?}", e)
+                    }
+                }
+                0
+            }
+            _ => 0,
+        }) + Inner::on_event(membership_event)
+    }
+}
+
+pub struct OnRemovedAUthorityMemberHandler<Runtime>(core::marker::PhantomData<Runtime>);
+impl<Runtime> pallet_authority_members::traits::OnRemovedMember<IdtyIndex>
+    for OnRemovedAUthorityMemberHandler<Runtime>
+where
+    Runtime: frame_system::Config + pallet_membership::Config<Instance2, IdtyId = IdtyIndex>,
+{
+    fn on_removed_member(idty_index: IdtyIndex) -> Weight {
+        if let Err(e) = pallet_membership::Pallet::<Runtime, Instance2>::revoke_membership(
+            frame_system::RawOrigin::Root.into(),
+            idty_index,
+        ) {
+            sp_std::if_std! {
+                println!("{:?}", e)
+            }
+        }
+        0
+    }
+}
diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs
index e7f9d336f..88b16d498 100644
--- a/runtime/common/src/lib.rs
+++ b/runtime/common/src/lib.rs
@@ -60,13 +60,6 @@ pub type Index = u32;
 /// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
 pub type Signature = sp_runtime::MultiSignature;
 
-pub struct IdtyNameValidatorImpl;
-impl pallet_identity::traits::IdtyNameValidator for IdtyNameValidatorImpl {
-    fn validate(idty_name: &pallet_identity::IdtyName) -> bool {
-        idty_name.0.len() >= 3 && idty_name.0.len() <= 64
-    }
-}
-
 pub struct FullIdentificationOfImpl;
 impl sp_runtime::traits::Convert<AccountId, Option<entities::ValidatorFullIdentification>>
     for FullIdentificationOfImpl
@@ -76,35 +69,22 @@ impl sp_runtime::traits::Convert<AccountId, Option<entities::ValidatorFullIdenti
     }
 }
 
-/// The implementation of SessionManager traits
-/// For the moment, the implementation does nothing, which means that the set of authorities
-/// remains eternally the same as the one defined in the chain spec.
-// TODO: When we will have implemented the smith sub-wot, we will have to fill this implementation
-// with a real logic based on the smith sub-wot.
-pub struct SessionManagerImpl;
-use crate::entities::ValidatorFullIdentification;
-use sp_staking::SessionIndex;
-impl pallet_session::SessionManager<AccountId> for SessionManagerImpl {
-    fn new_session(_new_index: SessionIndex) -> Option<sp_std::vec::Vec<AccountId>> {
-        None
+pub struct IdtyNameValidatorImpl;
+impl pallet_identity::traits::IdtyNameValidator for IdtyNameValidatorImpl {
+    fn validate(idty_name: &pallet_identity::IdtyName) -> bool {
+        idty_name.0.len() >= 3 && idty_name.0.len() <= 64
     }
-    fn start_session(_start_index: SessionIndex) {}
-    fn end_session(_end_index: SessionIndex) {}
 }
 
-impl pallet_session::historical::SessionManager<AccountId, ValidatorFullIdentification>
-    for SessionManagerImpl
+pub struct OwnerKeyOfImpl<Runtime>(core::marker::PhantomData<Runtime>);
+
+impl<
+        Runtime: frame_system::Config<AccountId = AccountId>
+            + pallet_identity::Config<IdtyIndex = IdtyIndex>,
+    > sp_runtime::traits::Convert<IdtyIndex, Option<AccountId>> for OwnerKeyOfImpl<Runtime>
 {
-    fn new_session(
-        _new_index: SessionIndex,
-    ) -> Option<sp_std::vec::Vec<(AccountId, ValidatorFullIdentification)>> {
-        None
-    }
-    fn new_session_genesis(
-        new_index: SessionIndex,
-    ) -> Option<sp_std::vec::Vec<(AccountId, ValidatorFullIdentification)>> {
-        <Self as pallet_session::historical::SessionManager<_, _>>::new_session(new_index)
+    fn convert(idty_index: IdtyIndex) -> Option<AccountId> {
+        pallet_identity::Pallet::<Runtime>::identity(idty_index)
+            .map(|idty_value| idty_value.owner_key)
     }
-    fn start_session(_start_index: SessionIndex) {}
-    fn end_session(_end_index: SessionIndex) {}
 }
diff --git a/runtime/common/src/pallets_config.rs b/runtime/common/src/pallets_config.rs
index a106ad141..2b151ea50 100644
--- a/runtime/common/src/pallets_config.rs
+++ b/runtime/common/src/pallets_config.rs
@@ -206,7 +206,7 @@ macro_rules! pallets_config {
 			type ValidatorIdOf = sp_runtime::traits::ConvertInto;
 			type ShouldEndSession = Babe;
 			type NextSessionRotation = Babe;
-			type SessionManager = pallet_session::historical::NoteHistoricalRoot<Self, SessionManagerImpl>;
+			type SessionManager = pallet_session::historical::NoteHistoricalRoot<Self, AuthorityMembers>;
 			type SessionHandler = <opaque::SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
 			type Keys = opaque::SessionKeys;
 			type WeightInfo = ();
@@ -237,6 +237,17 @@ macro_rules! pallets_config {
 			type MaxAuthorities = MaxAuthorities;
         }
 
+		impl pallet_authority_members::Config for Runtime {
+			type Event = Event;
+			type IsMember = SmithsMembership;
+			type OnRemovedMember = OnRemovedAUthorityMemberHandler<Runtime>;
+			type OwnerKeyOf = OwnerKeyOfImpl<Runtime>;
+			type MemberId = IdtyIndex;
+			type MaxOfflineSessions = frame_support::pallet_prelude::ConstU32<100>;
+			type RefreshValidatorIdOrigin = EnsureRoot<Self::AccountId>;
+			type RemoveMemberOrigin = EnsureRoot<Self::AccountId>;
+		}
+
 		// UTILITIES //
 
 		impl pallet_utility::Config for Runtime {
@@ -268,7 +279,7 @@ macro_rules! pallets_config {
 		use frame_support::instances::Instance1;
 		impl pallet_duniter_wot::Config<Instance1> for Runtime {
 			type FirstIssuableOn = WotFirstCertIssuableOn;
-			type IsSubWot = frame_support::traits::ConstBool<true>;
+			type IsSubWot = frame_support::traits::ConstBool<false>;
 			type MinCertForMembership = WotMinCertForMembership;
 			type MinCertForCreateIdtyRight = WotMinCertForCreateIdtyRight;
 		}
@@ -276,7 +287,7 @@ macro_rules! pallets_config {
 		impl pallet_identity::Config for Runtime {
             type ConfirmPeriod = ConfirmPeriod;
             type Event = Event;
-            type EnsureIdtyCallAllowed = DuniterWot;
+            type EnsureIdtyCallAllowed = Wot;
 			type IdtyCreationPeriod = IdtyCreationPeriod;
 			type IdtyDataProvider = ();
             type IdtyData = ();
@@ -284,22 +295,22 @@ macro_rules! pallets_config {
             type IdtyNameValidator = IdtyNameValidatorImpl;
             type IdtyValidationOrigin = EnsureRoot<Self::AccountId>;
 			type IsMember = Membership;
-            type OnIdtyChange = DuniterWot;
+            type OnIdtyChange = Wot;
             type MaxDisabledPeriod = MaxDisabledPeriod;
         }
 
 		impl pallet_membership::Config<frame_support::instances::Instance1> for Runtime {
-			type IsIdtyAllowedToClaimMembership = DuniterWot;
-			type IsIdtyAllowedToRenewMembership = DuniterWot;
-			type IsIdtyAllowedToRequestMembership = DuniterWot;
-			type IsOriginAllowedToUseIdty = DuniterWot;
+			type IsIdtyAllowedToClaimMembership = Wot;
+			type IsIdtyAllowedToRenewMembership = Wot;
+			type IsIdtyAllowedToRequestMembership = Wot;
+			type IsOriginAllowedToUseIdty = Wot;
 			type Event = Event;
 			type ExternalizeMembershipStorage = frame_support::traits::ConstBool<false>;
 			type IdtyId = IdtyIndex;
 			type MembershipExternalStorage = sp_membership::traits::NoExternalStorage;
 			type MembershipPeriod = MembershipPeriod;
 			type MetaData = ();
-			type OnEvent = OnMembershipEventHandler<DuniterWot, Runtime>;
+			type OnEvent = OnMembershipEventHandler<Wot, Runtime>;
 			type PendingMembershipPeriod = PendingMembershipPeriod;
 			type RenewablePeriod = RenewablePeriod;
 			type RevocationPeriod = frame_support::traits::ConstU32<0>;
@@ -313,12 +324,53 @@ macro_rules! pallets_config {
             type IdtyIndex = IdtyIndex;
             type MaxByIssuer = MaxByIssuer;
 			type MinReceivedCertToBeAbleToIssueCert = MinReceivedCertToBeAbleToIssueCert;
-            type OnNewcert = DuniterWot;
-            type OnRemovedCert = DuniterWot;
+            type OnNewcert = Wot;
+            type OnRemovedCert = Wot;
             type CertRenewablePeriod = CertRenewablePeriod;
             type ValidityPeriod = ValidityPeriod;
         }
 
+		// SMITHS SUB-WOT //
+
+		use frame_support::instances::Instance2;
+		impl pallet_duniter_wot::Config<Instance2> for Runtime {
+			type FirstIssuableOn = SmithsWotFirstCertIssuableOn;
+			type IsSubWot = frame_support::traits::ConstBool<true>;
+			type MinCertForMembership = SmithsWotMinCertForMembership;
+			type MinCertForCreateIdtyRight = frame_support::traits::ConstU32<0>;
+		}
+
+		impl pallet_membership::Config<Instance2> for Runtime {
+			type IsIdtyAllowedToClaimMembership = ();
+			type IsIdtyAllowedToRenewMembership = ();
+			type IsIdtyAllowedToRequestMembership = ();
+			type IsOriginAllowedToUseIdty = Wot;
+			type Event = Event;
+			type ExternalizeMembershipStorage = frame_support::traits::ConstBool<false>;
+			type IdtyId = IdtyIndex;
+			type MembershipExternalStorage = sp_membership::traits::NoExternalStorage;
+			type MembershipPeriod = SmithMembershipPeriod;
+			type MetaData = opaque::SessionKeys;
+			type OnEvent = OnSmithMembershipEventHandler<SmithsSubWot, Runtime>;
+			type PendingMembershipPeriod = SmithPendingMembershipPeriod;
+			type RenewablePeriod = SmithRenewablePeriod;
+			type RevocationPeriod = frame_support::traits::ConstU32<0>;
+		}
+
+        impl pallet_certification::Config<Instance2> for Runtime {
+            type AddCertOrigin = pallet_duniter_wot::AddCertOrigin<Runtime, Instance2>;
+            type CertPeriod = SmithCertPeriod;
+            type DelCertOrigin = pallet_duniter_wot::DelCertOrigin<Runtime, Instance2>;
+            type Event = Event;
+            type IdtyIndex = IdtyIndex;
+            type MaxByIssuer = SmithMaxByIssuer;
+			type MinReceivedCertToBeAbleToIssueCert = SmithMinReceivedCertToBeAbleToIssueCert;
+            type OnNewcert = SmithsSubWot;
+            type OnRemovedCert = SmithsSubWot;
+            type CertRenewablePeriod = SmithCertRenewablePeriod;
+            type ValidityPeriod = SmithValidityPeriod;
+        }
+
 		// MULTISIG //
 
 		impl pallet_multisig::Config for Runtime {
diff --git a/runtime/g1/Cargo.toml b/runtime/g1/Cargo.toml
index 46997fc48..8d4aaa9ec 100644
--- a/runtime/g1/Cargo.toml
+++ b/runtime/g1/Cargo.toml
@@ -33,6 +33,7 @@ std = [
     'frame-system-rpc-runtime-api/std',
     'frame-system/std',
 	'pallet-authority-discovery/std',
+    'pallet-authority-members/std',
     'pallet-babe/std',
     'pallet-balances/std',
     'pallet-certification/std',
@@ -68,6 +69,7 @@ std = [
 
 [dependencies]
 common-runtime = { path = "../common", default-features = false }
+pallet-authority-members = { path = '../../pallets/authority-members', default-features = false }
 pallet-certification = { path = '../../pallets/certification', default-features = false }
 pallet-duniter-wot = { path = '../../pallets/duniter-wot', default-features = false }
 pallet-identity = { path = '../../pallets/identity', default-features = false }
diff --git a/runtime/g1/src/lib.rs b/runtime/g1/src/lib.rs
index 1011efef8..987edc2c3 100644
--- a/runtime/g1/src/lib.rs
+++ b/runtime/g1/src/lib.rs
@@ -26,9 +26,8 @@ pub mod parameters;
 
 pub use self::parameters::*;
 pub use common_runtime::{
-    constants::*, entities::ValidatorFullIdentification, handlers::OnMembershipEventHandler,
-    AccountId, Address, Balance, BlockNumber, FullIdentificationOfImpl, Hash, Header, IdtyIndex,
-    IdtyNameValidatorImpl, Index, SessionManagerImpl, Signature,
+    constants::*, entities::ValidatorFullIdentification, handlers::*, AccountId, Address, Balance,
+    BlockNumber, FullIdentificationOfImpl, Hash, Header, IdtyIndex, Index, Signature,
 };
 pub use pallet_balances::Call as BalancesCall;
 pub use pallet_identity::{IdtyStatus, IdtyValue};
@@ -41,6 +40,7 @@ pub use pallet_universal_dividend;
 pub use sp_runtime::BuildStorage;
 pub use sp_runtime::{KeyTypeId, Perbill, Permill};
 
+use common_runtime::{IdtyNameValidatorImpl, OwnerKeyOfImpl};
 use frame_system::EnsureRoot;
 use pallet_grandpa::fg_primitives;
 use pallet_grandpa::{AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList};
@@ -179,6 +179,7 @@ construct_runtime!(
         Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event} = 14,
         ImOnline: pallet_im_online::{Pallet, Call, Storage, Event<T>, ValidateUnsigned, Config<T>} = 15,
         AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config} = 16,
+        AuthorityMembers: pallet_authority_members::{Pallet, Call, Storage, Config<T>, Event<T>} = 17,
 
         // Governance stuff.
         Sudo: pallet_sudo::{Pallet, Call, Config<T>, Storage, Event<T>} = 20,
@@ -191,13 +192,18 @@ construct_runtime!(
         UniversalDividend: pallet_universal_dividend::{Pallet, Call, Config<T>, Storage, Event<T>} = 41,
 
         // Web Of Trust
-        DuniterWot: pallet_duniter_wot::<Instance1>::{Pallet} = 50,
+        Wot: pallet_duniter_wot::<Instance1>::{Pallet} = 50,
         Identity: pallet_identity::{Pallet, Call, Config<T>, Storage, Event<T>} = 51,
         Membership: pallet_membership::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>} = 52,
         Cert: pallet_certification::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>} = 53,
 
+        // Smiths Sub-Wot
+        SmithsSubWot: pallet_duniter_wot::<Instance2>::{Pallet} = 60,
+        SmithsMembership: pallet_membership::<Instance2>::{Pallet, Call, Config<T>, Storage, Event<T>} = 62,
+        SmithsCert: pallet_certification::<Instance2>::{Pallet, Call, Config<T>, Storage, Event<T>} = 63,
+
         // Multisig dispatch.
-        Multisig: pallet_multisig::{Pallet, Call, Storage, Event<T>} = 60,
+        Multisig: pallet_multisig::{Pallet, Call, Storage, Event<T>} = 70,
     }
 );
 
diff --git a/runtime/g1/src/parameters.rs b/runtime/g1/src/parameters.rs
index 96e782125..5affcfb45 100644
--- a/runtime/g1/src/parameters.rs
+++ b/runtime/g1/src/parameters.rs
@@ -97,14 +97,12 @@ parameter_types! {
 /*******/
 
 parameter_types! {
-    pub WotFirstCertIssuableOn: BlockNumber = 30* DAYS;
-    pub WotMinCertForMembership: u8 = 5;
-    pub MinReceivedCertToBeAbleToIssueCert: u8 = 5;
-    pub WotMinCertForCreateIdtyRight: u8 = 5;
+    pub const WotFirstCertIssuableOn: BlockNumber = 30 * DAYS;
+    pub const WotMinCertForMembership: u32 = 5;
+    pub const WotMinCertForCreateIdtyRight: u32 = 5;
 }
 
 // Identity
-pub const IDTY_CREATE_PERIOD: BlockNumber = 100;
 parameter_types! {
     pub const ConfirmPeriod: BlockNumber = 14 * DAYS;
     pub const IdtyCreationPeriod: BlockNumber = MONTHS;
@@ -120,15 +118,39 @@ parameter_types! {
 }
 
 // Certification
-pub const MIN_STRONG_CERT_FOR_UD: u32 = 5;
-pub const MIN_STRONG_CERT_FOR_STRONG_CERT: u32 = 5;
 parameter_types! {
     pub const CertPeriod: BlockNumber = 5 * DAYS;
-    pub const MaxByIssuer: u8 = 100;
+    pub const MaxByIssuer: u32 = 100;
+    pub const MinReceivedCertToBeAbleToIssueCert: u32 = 5;
     pub const CertRenewablePeriod: BlockNumber = 6 * MONTHS;
     pub const ValidityPeriod: BlockNumber = 2 * YEARS;
 }
 
+/******************/
+/* SMITHS SUB-WOT */
+/******************/
+
+parameter_types! {
+    pub const SmithsWotFirstCertIssuableOn: BlockNumber = 30 * DAYS;
+    pub const SmithsWotMinCertForMembership: u32 = 3;
+}
+
+// Membership
+parameter_types! {
+    pub const SmithMembershipPeriod: BlockNumber = 73 * DAYS;
+    pub const SmithPendingMembershipPeriod: BlockNumber = 12 * DAYS;
+    pub const SmithRenewablePeriod: BlockNumber = 12 * DAYS;
+}
+
+// Certification
+parameter_types! {
+    pub const SmithCertPeriod: BlockNumber = 5 * DAYS;
+    pub const SmithMaxByIssuer: u32 = 12;
+    pub const SmithMinReceivedCertToBeAbleToIssueCert: u32 = 5;
+    pub const SmithCertRenewablePeriod: BlockNumber = 12 * DAYS;
+    pub const SmithValidityPeriod: BlockNumber = 146 * DAYS;
+}
+
 // Multisig
 parameter_types! {
     pub const DepositBase: Balance = 1000;
diff --git a/runtime/gdev/src/lib.rs b/runtime/gdev/src/lib.rs
index 15729d0c7..26e05354e 100644
--- a/runtime/gdev/src/lib.rs
+++ b/runtime/gdev/src/lib.rs
@@ -26,9 +26,8 @@ pub mod parameters;
 
 pub use self::parameters::*;
 pub use common_runtime::{
-    constants::*, entities::ValidatorFullIdentification, handlers::OnMembershipEventHandler,
-    AccountId, Address, Balance, BlockNumber, FullIdentificationOfImpl, Hash, Header, IdtyIndex,
-    IdtyNameValidatorImpl, Index, Signature,
+    constants::*, entities::ValidatorFullIdentification, handlers::*, AccountId, Address, Balance,
+    BlockNumber, FullIdentificationOfImpl, Hash, Header, IdtyIndex, Index, Signature,
 };
 pub use pallet_balances::Call as BalancesCall;
 pub use pallet_duniter_test_parameters::Parameters as GenesisParameters;
@@ -42,7 +41,7 @@ pub use pallet_universal_dividend;
 pub use sp_runtime::BuildStorage;
 pub use sp_runtime::{KeyTypeId, Perbill, Permill};
 
-use common_runtime::SessionManagerImpl;
+use common_runtime::{IdtyNameValidatorImpl, OwnerKeyOfImpl};
 use frame_system::EnsureRoot;
 use pallet_grandpa::fg_primitives;
 use pallet_grandpa::{AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList};
@@ -153,13 +152,13 @@ common_runtime::pallets_config! {
     // Dynamic parameters
     pub type CertPeriod = pallet_duniter_test_parameters::CertPeriod<Runtime>;
     pub type MaxByIssuer = pallet_duniter_test_parameters::CertMaxByIssuer<Runtime>;
+    pub type MinReceivedCertToBeAbleToIssueCert = pallet_duniter_test_parameters::CertMinReceivedCertToIssueCert<Runtime>;
     pub type CertRenewablePeriod = pallet_duniter_test_parameters::CertRenewablePeriod<Runtime>;
     pub type ValidityPeriod = pallet_duniter_test_parameters::CertValidityPeriod<Runtime>;
     pub type ConfirmPeriod = pallet_duniter_test_parameters::IdtyConfirmPeriod<Runtime>;
     pub type IdtyCreationPeriod = pallet_duniter_test_parameters::IdtyCreationPeriod<Runtime>;
     pub type MaxDisabledPeriod = pallet_duniter_test_parameters::IdtyMaxDisabledPeriod<Runtime>;
     pub type MembershipPeriod = pallet_duniter_test_parameters::MembershipPeriod<Runtime>;
-    pub type MinReceivedCertToBeAbleToIssueCert = pallet_duniter_test_parameters::WotMinCertForCertRight<Runtime>;
     pub type RenewablePeriod = pallet_duniter_test_parameters::MembershipRenewablePeriod<Runtime>;
     pub type PendingMembershipPeriod = pallet_duniter_test_parameters::PendingMembershipPeriod<Runtime>;
     pub type UdCreationPeriod = pallet_duniter_test_parameters::UdCreationPeriod<Runtime>;
@@ -169,6 +168,16 @@ common_runtime::pallets_config! {
     pub type WotFirstCertIssuableOn = pallet_duniter_test_parameters::WotFirstCertIssuableOn<Runtime>;
     pub type WotMinCertForMembership = pallet_duniter_test_parameters::WotMinCertForMembership<Runtime>;
     pub type WotMinCertForCreateIdtyRight = pallet_duniter_test_parameters::WotMinCertForCreateIdtyRight<Runtime>;
+    pub type SmithCertPeriod = pallet_duniter_test_parameters::SmithCertPeriod<Runtime>;
+    pub type SmithMaxByIssuer = pallet_duniter_test_parameters::SmithCertMaxByIssuer<Runtime>;
+    pub type SmithMinReceivedCertToBeAbleToIssueCert = pallet_duniter_test_parameters::SmithCertMinReceivedCertToIssueCert<Runtime>;
+    pub type SmithCertRenewablePeriod = pallet_duniter_test_parameters::SmithCertRenewablePeriod<Runtime>;
+    pub type SmithValidityPeriod = pallet_duniter_test_parameters::SmithCertValidityPeriod<Runtime>;
+    pub type SmithMembershipPeriod = pallet_duniter_test_parameters::SmithMembershipPeriod<Runtime>;
+    pub type SmithPendingMembershipPeriod = pallet_duniter_test_parameters::SmithPendingMembershipPeriod<Runtime>;
+    pub type SmithRenewablePeriod = pallet_duniter_test_parameters::SmithMembershipRenewablePeriod<Runtime>;
+    pub type SmithsWotFirstCertIssuableOn = pallet_duniter_test_parameters::SmithsWotFirstCertIssuableOn<Runtime>;
+    pub type SmithsWotMinCertForMembership = pallet_duniter_test_parameters::SmithsWotMinCertForMembership<Runtime>;
 
     impl pallet_duniter_test_parameters::Config for Runtime {
         type CertCount = u32;
@@ -203,13 +212,14 @@ construct_runtime!(
         TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 32,
 
         // Consensus support
-        Authorship: pallet_authorship::{Pallet, Call, Storage} = 10,
-        Offences: pallet_offences::{Pallet, Storage, Event} = 11,
-        Historical: session_historical::{Pallet} = 12,
-        Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>} = 13,
-        Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event} = 14,
-        ImOnline: pallet_im_online::{Pallet, Call, Storage, Event<T>, ValidateUnsigned, Config<T>} = 15,
-        AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config} = 16,
+        AuthorityMembers: pallet_authority_members::{Pallet, Call, Storage, Config<T>, Event<T>} = 10,
+        Authorship: pallet_authorship::{Pallet, Call, Storage} = 11,
+        Offences: pallet_offences::{Pallet, Storage, Event} = 12,
+        Historical: session_historical::{Pallet} = 13,
+        Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>} = 14,
+        Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event} = 15,
+        ImOnline: pallet_im_online::{Pallet, Call, Storage, Event<T>, ValidateUnsigned, Config<T>} = 16,
+        AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config} = 17,
 
         // Governance stuff
         Sudo: pallet_sudo::{Pallet, Call, Config<T>, Storage, Event<T>} = 20,
@@ -222,13 +232,18 @@ construct_runtime!(
         UniversalDividend: pallet_universal_dividend::{Pallet, Call, Config<T>, Storage, Event<T>} = 41,
 
         // Web Of Trust
-        DuniterWot: pallet_duniter_wot::<Instance1>::{Pallet} = 50,
+        Wot: pallet_duniter_wot::<Instance1>::{Pallet} = 50,
         Identity: pallet_identity::{Pallet, Call, Config<T>, Storage, Event<T>} = 51,
         Membership: pallet_membership::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>} = 52,
         Cert: pallet_certification::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>} = 53,
 
-        // Multisig dispatch
-        Multisig: pallet_multisig::{Pallet, Call, Storage, Event<T>} = 60,
+        // Smiths Sub-Wot
+        SmithsSubWot: pallet_duniter_wot::<Instance2>::{Pallet} = 60,
+        SmithsMembership: pallet_membership::<Instance2>::{Pallet, Call, Config<T>, Storage, Event<T>} = 62,
+        SmithsCert: pallet_certification::<Instance2>::{Pallet, Call, Config<T>, Storage, Event<T>} = 63,
+
+        // Multisig dispatch.
+        Multisig: pallet_multisig::{Pallet, Call, Storage, Event<T>} = 70,
     }
 );
 
diff --git a/runtime/gtest/Cargo.toml b/runtime/gtest/Cargo.toml
index 2d685e77a..64cb9051d 100644
--- a/runtime/gtest/Cargo.toml
+++ b/runtime/gtest/Cargo.toml
@@ -33,6 +33,7 @@ std = [
     'frame-system-rpc-runtime-api/std',
     'frame-system/std',
 	'pallet-authority-discovery/std',
+    'pallet-authority-members/std',
     'pallet-babe/std',
     'pallet-balances/std',
     'pallet-certification/std',
@@ -68,6 +69,7 @@ std = [
 
 [dependencies]
 common-runtime = { path = "../common", default-features = false }
+pallet-authority-members = { path = '../../pallets/authority-members', default-features = false }
 pallet-certification = { path = '../../pallets/certification', default-features = false }
 pallet-duniter-wot = { path = '../../pallets/duniter-wot', default-features = false }
 pallet-identity = { path = '../../pallets/identity', default-features = false }
diff --git a/runtime/gtest/src/lib.rs b/runtime/gtest/src/lib.rs
index 2e7431689..2b9876905 100644
--- a/runtime/gtest/src/lib.rs
+++ b/runtime/gtest/src/lib.rs
@@ -26,9 +26,8 @@ pub mod parameters;
 
 pub use self::parameters::*;
 pub use common_runtime::{
-    constants::*, entities::ValidatorFullIdentification, handlers::OnMembershipEventHandler,
-    AccountId, Address, Balance, BlockNumber, FullIdentificationOfImpl, Hash, Header, IdtyIndex,
-    IdtyNameValidatorImpl, Index, SessionManagerImpl, Signature,
+    constants::*, entities::ValidatorFullIdentification, handlers::*, AccountId, Address, Balance,
+    BlockNumber, FullIdentificationOfImpl, Hash, Header, IdtyIndex, Index, Signature,
 };
 pub use pallet_balances::Call as BalancesCall;
 pub use pallet_identity::{IdtyStatus, IdtyValue};
@@ -41,6 +40,7 @@ pub use pallet_universal_dividend;
 pub use sp_runtime::BuildStorage;
 pub use sp_runtime::{KeyTypeId, Perbill, Permill};
 
+use common_runtime::{IdtyNameValidatorImpl, OwnerKeyOfImpl};
 use frame_system::EnsureRoot;
 use pallet_grandpa::fg_primitives;
 use pallet_grandpa::{AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList};
@@ -146,10 +146,10 @@ impl frame_support::traits::Contains<Call> for BaseCallFilter {
 }
 
 common_runtime::pallets_config! {
-    impl pallet_sudo::Config for Runtime {
-        type Event = Event;
-        type Call = Call;
-    }
+impl pallet_sudo::Config for Runtime {
+    type Event = Event;
+    type Call = Call;
+}
 }
 
 // Create the runtime by composing the FRAME pallets that were previously configured.
@@ -179,6 +179,7 @@ construct_runtime!(
         Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event} = 14,
         ImOnline: pallet_im_online::{Pallet, Call, Storage, Event<T>, ValidateUnsigned, Config<T>} = 15,
         AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config} = 16,
+        AuthorityMembers: pallet_authority_members::{Pallet, Call, Storage, Config<T>, Event<T>} = 17,
 
         // Governance stuff.
         Sudo: pallet_sudo::{Pallet, Call, Config<T>, Storage, Event<T>} = 20,
@@ -191,13 +192,18 @@ construct_runtime!(
         UniversalDividend: pallet_universal_dividend::{Pallet, Call, Config<T>, Storage, Event<T>} = 41,
 
         // Web Of Trust
-        DuniterWot: pallet_duniter_wot::<Instance1>::{Pallet} = 50,
+        Wot: pallet_duniter_wot::<Instance1>::{Pallet} = 50,
         Identity: pallet_identity::{Pallet, Call, Config<T>, Storage, Event<T>} = 51,
         Membership: pallet_membership::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>} = 52,
         Cert: pallet_certification::<Instance1>::{Pallet, Call, Config<T>, Storage, Event<T>} = 53,
 
+        // Smiths Sub-Wot
+        SmithsSubWot: pallet_duniter_wot::<Instance2>::{Pallet} = 60,
+        SmithsMembership: pallet_membership::<Instance2>::{Pallet, Call, Config<T>, Storage, Event<T>} = 62,
+        SmithsCert: pallet_certification::<Instance2>::{Pallet, Call, Config<T>, Storage, Event<T>} = 63,
+
         // Multisig dispatch.
-        Multisig: pallet_multisig::{Pallet, Call, Storage, Event<T>} = 60,
+        Multisig: pallet_multisig::{Pallet, Call, Storage, Event<T>} = 70,
     }
 );
 
diff --git a/runtime/gtest/src/parameters.rs b/runtime/gtest/src/parameters.rs
index c7f7ce476..c76c95863 100644
--- a/runtime/gtest/src/parameters.rs
+++ b/runtime/gtest/src/parameters.rs
@@ -96,14 +96,13 @@ parameter_types! {
 /*******/
 
 parameter_types! {
-    pub WotFirstCertIssuableOn: BlockNumber = DAYS;
-    pub WotMinCertForMembership: u8 = 5;
-    pub MinReceivedCertToBeAbleToIssueCert: u8 = 5;
-    pub WotMinCertForCreateIdtyRight: u8 = 5;
+    pub const WotFirstCertIssuableOn: BlockNumber = DAYS;
+    pub const WotMinCertForMembership: u32 = 5;
+    pub const MinReceivedCertToBeAbleToIssueCert: u32 = 5;
+    pub const WotMinCertForCreateIdtyRight: u32 = 5;
 }
 
 // Identity
-pub const IDTY_CREATE_PERIOD: BlockNumber = 100;
 frame_support::parameter_types! {
     pub const ConfirmPeriod: BlockNumber = 8 * HOURS;
     pub const IdtyCreationPeriod: BlockNumber = DAYS;
@@ -118,15 +117,38 @@ parameter_types! {
 }
 
 // Certification
-pub const MIN_STRONG_CERT_FOR_UD: u32 = 5;
-pub const MIN_STRONG_CERT_FOR_STRONG_CERT: u32 = 5;
 parameter_types! {
     pub const CertPeriod: BlockNumber = DAYS;
-    pub const MaxByIssuer: u8 = 100;
+    pub const MaxByIssuer: u32 = 100;
     pub const CertRenewablePeriod: BlockNumber = 12 * DAYS;
     pub const ValidityPeriod: BlockNumber = 146 * DAYS;
 }
 
+/******************/
+/* SMITHS SUB-WOT */
+/******************/
+
+parameter_types! {
+    pub const SmithsWotFirstCertIssuableOn: BlockNumber = DAYS;
+    pub const SmithsWotMinCertForMembership: u32 = 3;
+}
+
+// Membership
+parameter_types! {
+    pub const SmithMembershipPeriod: BlockNumber = 73 * DAYS;
+    pub const SmithPendingMembershipPeriod: BlockNumber = 12 * DAYS;
+    pub const SmithRenewablePeriod: BlockNumber = 12 * DAYS;
+}
+
+// Certification
+parameter_types! {
+    pub const SmithCertPeriod: BlockNumber = DAYS;
+    pub const SmithMaxByIssuer: u32 = 100;
+    pub const SmithMinReceivedCertToBeAbleToIssueCert: u32 = 5;
+    pub const SmithCertRenewablePeriod: BlockNumber = 12 * DAYS;
+    pub const SmithValidityPeriod: BlockNumber = 146 * DAYS;
+}
+
 // Multisig
 parameter_types! {
     pub const DepositBase: Balance = 1000;
-- 
GitLab