From f562a95bbaca1902fba2731428079e8783256bf4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Moreau?= <cem.moreau@gmail.com>
Date: Fri, 2 Feb 2024 22:09:24 +0100
Subject: [PATCH] Resolve #152 "remove random_id mechanism which is heavy and
 that we do not use" (nodes/rust/duniter-v2s!235)

* remove unnecessary currency associated type

* WIP: rebase

* WIP: update docs

* WIP: clippy

* WIP: test pass

* WIP: // TODO: decrement consumers?
---
 Cargo.lock                                    |   1 -
 docs/api/runtime-events.md                    |  19 +----
 live-tests/tests/sanity_gdev.rs               |   6 +-
 node/src/chain_spec/gen_genesis_data.rs       |   7 +-
 pallets/README.md                             |   2 +-
 pallets/duniter-account/Cargo.toml            |   4 -
 pallets/duniter-account/README.md             |   8 +-
 pallets/duniter-account/src/benchmarking.rs   |  20 -----
 pallets/duniter-account/src/lib.rs            |  73 ++----------------
 pallets/duniter-account/src/types.rs          |   6 --
 pallets/duniter-account/src/weights.rs        |  29 -------
 resources/metadata.scale                      | Bin 112080 -> 111870 bytes
 runtime/common/src/pallets_config.rs          |   3 +-
 .../src/weights/pallet_duniter_account.rs     |  47 -----------
 runtime/gdev/tests/common/mod.rs              |   2 -
 runtime/gdev/tests/integration_tests.rs       |  59 ++++----------
 16 files changed, 32 insertions(+), 254 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 026013d64..45eec7591 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6603,7 +6603,6 @@ dependencies = [
  "maplit",
  "pallet-balances",
  "pallet-identity",
- "pallet-provide-randomness",
  "pallet-quota",
  "pallet-transaction-payment",
  "pallet-treasury",
diff --git a/docs/api/runtime-events.md b/docs/api/runtime-events.md
index 71abd3323..0787b7f5f 100644
--- a/docs/api/runtime-events.md
+++ b/docs/api/runtime-events.md
@@ -1,6 +1,6 @@
 # Runtime events
 
-There are **129** events from **35** pallets.
+There are **128** events from **35** pallets.
 
 <ul>
 <li>System - 0
@@ -112,20 +112,7 @@ balance: T::Balance
 <li>
 <details>
 <summary>
-<code>RandomIdAssigned(who, random_id)</code> - 1</summary>
-A random ID has been assigned to the account.
-
-```rust
-who: T::AccountId
-random_id: H256
-```
-
-</details>
-</li>
-<li>
-<details>
-<summary>
-<code>AccountLinked(who, identity)</code> - 2</summary>
+<code>AccountLinked(who, identity)</code> - 1</summary>
 account linked to identity
 
 ```rust
@@ -138,7 +125,7 @@ identity: IdtyIdOf<T>
 <li>
 <details>
 <summary>
-<code>AccountUnlinked()</code> - 3</summary>
+<code>AccountUnlinked()</code> - 2</summary>
 The account was unlinked from its identity.
 
 ```rust
diff --git a/live-tests/tests/sanity_gdev.rs b/live-tests/tests/sanity_gdev.rs
index 814af0786..86cec2524 100644
--- a/live-tests/tests/sanity_gdev.rs
+++ b/live-tests/tests/sanity_gdev.rs
@@ -235,10 +235,10 @@ mod verifier {
 
                 if account_id.as_slice() != TREASURY_ACCOUNT_ID {
                     // Rule 4: If the account is not a "special account",
-                    // it should have a random id or a consumer
+                    // it should have a consumer
                     self.assert(
-                        account_info.data.random_id.is_some() || account_info.consumers > 0,
-                        format!("Account {} has no random_id nor consumer.", account_id),
+                        account_info.consumers > 0,
+                        format!("Account {} has no consumer.", account_id),
                     );
                 }
             }
diff --git a/node/src/chain_spec/gen_genesis_data.rs b/node/src/chain_spec/gen_genesis_data.rs
index ba2609e03..b6ce08e5f 100644
--- a/node/src/chain_spec/gen_genesis_data.rs
+++ b/node/src/chain_spec/gen_genesis_data.rs
@@ -25,7 +25,7 @@ use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
 use sp_consensus_babe::AuthorityId as BabeId;
 use sp_consensus_grandpa::AuthorityId as GrandpaId;
 use sp_core::crypto::AccountId32;
-use sp_core::{blake2_256, ed25519, sr25519, Decode, Encode, H256};
+use sp_core::{ed25519, sr25519, Decode, Encode};
 use sp_runtime::traits::{IdentifyAccount, Verify};
 use sp_runtime::{MultiSignature, Perbill};
 use std::collections::{BTreeMap, HashMap};
@@ -1162,7 +1162,6 @@ fn v1_wallets_to_v2_accounts(
             accounts.insert(
                 owner_key.clone(),
                 GenesisAccountData {
-                    random_id: H256(blake2_256(&(balance, &owner_key).encode())),
                     balance,
                     idty_id: None,
                 },
@@ -1425,7 +1424,6 @@ fn feed_identities(
         accounts.insert(
             identity.owner_key.clone(),
             GenesisAccountData {
-                random_id: H256(blake2_256(&(identity.index, &identity.owner_key).encode())),
                 balance: identity.balance,
                 idty_id: Some(identity.index),
             },
@@ -1747,9 +1745,6 @@ where
             (
                 owner_key.clone(),
                 GenesisAccountData {
-                    random_id: H256(blake2_256(
-                        &(i as u32 + idty_index_start, owner_key).encode(),
-                    )),
                     // Should be sufficient for the overhead benchmark
                     balance: initial_idty_balance,
                     idty_id: Some(i as u32 + idty_index_start),
diff --git a/pallets/README.md b/pallets/README.md
index 4e229119e..e25c7907f 100644
--- a/pallets/README.md
+++ b/pallets/README.md
@@ -8,7 +8,7 @@ These pallets are at the core of Duniter/Äž1 currency
 
 - **`authority-members`** Duniter authorities are not selected with staking but through a smith web of trust.
 - **`certification`** Certifications are the "edges" of Duniter's dynamic directed graph. They mean the acceptation of a Licence.
-- **`duniter-account`** Duniter customized the `AccountData` defined in the `Balances` pallet to introduce a `RandomId`.
+- **`duniter-account`** Duniter customized the `AccountData` defined in the `Balances` pallet to introduce a `linked_idty`.
 - **`duniter-wot`** Merges identities, membership, certifications and distance pallets to implement Duniter Web of Trust.
 - **`distance`** Publishes median of distance computation results provided by inherents coming from `distance-oracle` workers.
 - **`identity`** Identities are the "nodes" of Duniter's dynamic directed graph. They are one-to-one mapping to human being.
diff --git a/pallets/duniter-account/Cargo.toml b/pallets/duniter-account/Cargo.toml
index 8e1dca7dc..304f5f331 100644
--- a/pallets/duniter-account/Cargo.toml
+++ b/pallets/duniter-account/Cargo.toml
@@ -17,7 +17,6 @@ runtime-benchmarks = [
     'frame-system/runtime-benchmarks',
     'sp-runtime/runtime-benchmarks',
     'pallet-identity/runtime-benchmarks',
-    'pallet-provide-randomness/runtime-benchmarks',
     'pallet-treasury/runtime-benchmarks',
     'pallet-quota/runtime-benchmarks',
     'pallet-balances/runtime-benchmarks',
@@ -30,7 +29,6 @@ std = [
     'pallet-balances/std',
     'pallet-transaction-payment/std',
     'pallet-identity/std',
-    'pallet-provide-randomness/std',
     'pallet-treasury/std',
     'pallet-quota/std',
     'serde/std',
@@ -46,7 +44,6 @@ try-runtime = [
     'frame-system/try-runtime',
     'sp-runtime/try-runtime',
     'pallet-identity/try-runtime',
-    'pallet-provide-randomness/try-runtime',
     'pallet-treasury/try-runtime',
     'pallet-quota/try-runtime',
     'pallet-balances/try-runtime',
@@ -57,7 +54,6 @@ try-runtime = [
 # local
 pallet-quota = { path = "../quota", default-features = false }
 pallet-identity = { path = "../identity", default-features = false }
-pallet-provide-randomness = { path = "../provide-randomness", default-features = false }
 
 # crates.io
 codec = { package = 'parity-scale-codec', version = "3.6.9", default-features = false, features = ["derive"] }
diff --git a/pallets/duniter-account/README.md b/pallets/duniter-account/README.md
index 5d9e73b14..185e37ce5 100644
--- a/pallets/duniter-account/README.md
+++ b/pallets/duniter-account/README.md
@@ -1,12 +1,6 @@
 # Duniter account pallet
 
-Duniter customizes the `AccountData` of the `Balances` Substrate pallet. In particular, it adds the fields `random_id` and `linked_idty`. 
-
-## RandomID
-
-The RandomId field was added with the idea to provide a unique id that can not be controlled by user to serve as a basis for robust identification. The discussion is available on the forum.
-
-https://forum.duniter.org/t/la-solution-pour-des-identicones-securisees-le-random-id/9126
+Duniter customizes the `AccountData` of the `Balances` Substrate pallet. In particular, it adds the field `linked_idty`. 
 
 ## Account creation fee
 
diff --git a/pallets/duniter-account/src/benchmarking.rs b/pallets/duniter-account/src/benchmarking.rs
index 27a839e1a..b5594e7d2 100644
--- a/pallets/duniter-account/src/benchmarking.rs
+++ b/pallets/duniter-account/src/benchmarking.rs
@@ -21,14 +21,9 @@ use super::*;
 use frame_benchmarking::{account, benchmarks, whitelisted_caller};
 use frame_support::sp_runtime::{traits::One, Saturating};
 use frame_support::traits::{Currency, Get};
-use pallet_provide_randomness::OnFilledRandomness;
 
 use crate::Pallet;
 
-fn assert_has_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
-    frame_system::Pallet::<T>::assert_has_event(generic_event.into());
-}
-
 fn create_pending_accounts<T: Config>(
     i: u32,
     is_balance: bool,
@@ -72,19 +67,4 @@ benchmarks! {
     on_initialize_no_balance {
         let i in 0 .. T::MaxNewAccountsPerBlock::get() => create_pending_accounts::<T>(i, false, false)?;
     }: { Pallet::<T>::on_initialize(BlockNumberFor::<T>::one()); }
-    on_filled_randomness_pending {
-        let caller: T::AccountId = whitelisted_caller();
-        let randomness = H256(T::AccountIdToSalt::convert(caller.clone()));
-        let request_id = pallet_provide_randomness::Pallet::<T>::force_request(pallet_provide_randomness::RandomnessType::RandomnessFromTwoEpochsAgo, randomness);
-        PendingRandomIdAssignments::<T>::insert(request_id, caller.clone());
-    }: { Pallet::<T>::on_filled_randomness(request_id,  randomness); }
-    verify {
-        assert_has_event::<T>(Event::<T>::RandomIdAssigned { who: caller, random_id: randomness }.into());
-    }
-    on_filled_randomness_no_pending {
-        let caller: T::AccountId = whitelisted_caller();
-        let randomness = H256(T::AccountIdToSalt::convert(caller.clone()));
-        let request_id = pallet_provide_randomness::Pallet::<T>::force_request(pallet_provide_randomness::RandomnessType::RandomnessFromTwoEpochsAgo, randomness);
-        assert!(!PendingRandomIdAssignments::<T>::contains_key(request_id));
-    }: { Pallet::<T>::on_filled_randomness(request_id,  randomness); }
 }
diff --git a/pallets/duniter-account/src/lib.rs b/pallets/duniter-account/src/lib.rs
index 05f0c69e3..596554ec7 100644
--- a/pallets/duniter-account/src/lib.rs
+++ b/pallets/duniter-account/src/lib.rs
@@ -32,10 +32,8 @@ use frame_support::pallet_prelude::*;
 use frame_support::traits::{Currency, ExistenceRequirement, StorageVersion};
 use frame_support::traits::{OnUnbalanced, StoredMap};
 use frame_system::pallet_prelude::*;
-use pallet_provide_randomness::RequestId;
 use pallet_quota::traits::RefundFee;
 use pallet_transaction_payment::OnChargeTransaction;
-use sp_core::H256;
 use sp_runtime::traits::{Convert, DispatchInfoOf, PostDispatchInfoOf, Saturating};
 use sp_std::fmt::Debug;
 
@@ -61,7 +59,6 @@ pub mod pallet {
     pub trait Config:
         frame_system::Config<AccountData = AccountData<Self::Balance, IdtyIdOf<Self>>>
         + pallet_balances::Config
-        + pallet_provide_randomness::Config<Currency = pallet_balances::Pallet<Self>>
         + pallet_transaction_payment::Config
         + pallet_treasury::Config<Currency = pallet_balances::Pallet<Self>>
         + pallet_quota::Config
@@ -75,6 +72,8 @@ pub mod pallet {
         type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
         /// Type representing the weight of this pallet
         type WeightInfo: WeightInfo;
+        /// Handler for the unbalanced reduction when the requestor pays fees.
+        type OnUnbalanced: OnUnbalanced<pallet_balances::NegativeImbalance<Self>>;
         /// wrapped type
         type InnerOnChargeTransaction: OnChargeTransaction<Self>;
         /// type implementing refund behavior
@@ -83,11 +82,6 @@ pub mod pallet {
 
     // STORAGE //
 
-    #[pallet::storage]
-    #[pallet::getter(fn pending_random_id_assignments)]
-    pub type PendingRandomIdAssignments<T: Config> =
-        StorageMap<_, Twox64Concat, RequestId, T::AccountId, OptionQuery>;
-
     #[pallet::storage]
     #[pallet::getter(fn pending_new_accounts)]
     pub type PendingNewAccounts<T: Config> =
@@ -120,7 +114,6 @@ pub mod pallet {
             frame_system::Account::<T>::mutate(
                 pallet_treasury::Pallet::<T>::account_id(),
                 |account| {
-                    account.data.random_id = None;
                     account.data.free = self.treasury_balance;
                     account.providers = 1;
                 },
@@ -139,20 +132,11 @@ pub mod pallet {
             );
 
             // Classic accounts
-            for (
-                account_id,
-                GenesisAccountData {
-                    random_id,
-                    balance,
-                    idty_id,
-                },
-            ) in &self.accounts
-            {
+            for (account_id, GenesisAccountData { balance, idty_id }) in &self.accounts {
                 // if the balance is below existential deposit, the account must be an identity
                 assert!(balance >= &T::ExistentialDeposit::get() || idty_id.is_some());
                 // mutate account
                 frame_system::Account::<T>::mutate(account_id, |account| {
-                    account.data.random_id = Some(*random_id);
                     account.data.free = *balance;
                     if idty_id.is_some() {
                         account.data.linked_idty = *idty_id;
@@ -179,8 +163,6 @@ pub mod pallet {
             who: T::AccountId,
             balance: T::Balance,
         },
-        /// A random ID has been assigned to the account.
-        RandomIdAssigned { who: T::AccountId, random_id: H256 },
         /// account linked to identity
         AccountLinked {
             who: T::AccountId,
@@ -243,11 +225,6 @@ pub mod pallet {
             {
                 if frame_system::Pallet::<T>::sufficients(&account_id) > 0 {
                     // If the account is self-sufficient, it is exempt from account creation fees
-                    let request_id = pallet_provide_randomness::Pallet::<T>::force_request(
-                        pallet_provide_randomness::RandomnessType::RandomnessFromTwoEpochsAgo,
-                        H256(T::AccountIdToSalt::convert(account_id.clone())),
-                    );
-                    PendingRandomIdAssignments::<T>::insert(request_id, account_id);
                     total_weight += <T as pallet::Config>::WeightInfo::on_initialize_sufficient(
                         T::MaxNewAccountsPerBlock::get(),
                     );
@@ -258,11 +235,7 @@ pub mod pallet {
                     if account_data.free >= T::ExistentialDeposit::get() + price {
                         // The account can pay the new account price, we should:
                         // 1. Withdraw the "new account price" amount
-                        // 2. Increment consumers to prevent the destruction of the account before
-                        // the random id is assigned
-                        // 3. Manage the funds collected
-                        // 4. Submit random id generation request
-                        // 5. Save the id of the random generation request.
+                        // 2. Manage the funds collected
                         let res = <pallet_balances::Pallet<T> as Currency<T::AccountId>>::withdraw(
                             &account_id,
                             price,
@@ -274,18 +247,7 @@ pub mod pallet {
                             "Cannot fail because we checked that the free balance was sufficient"
                         );
                         if let Ok(imbalance) = res {
-                            let res =
-                                frame_system::Pallet::<T>::inc_consumers_without_limit(&account_id);
-                            debug_assert!(
-                                res.is_ok(),
-                                "Cannot fail because any account with funds should have providers"
-                            );
                             T::OnUnbalanced::on_unbalanced(imbalance);
-                            let request_id = pallet_provide_randomness::Pallet::<T>::force_request(
-                                pallet_provide_randomness::RandomnessType::RandomnessFromTwoEpochsAgo,
-                                H256(T::AccountIdToSalt::convert(account_id.clone())),
-                            );
-                            PendingRandomIdAssignments::<T>::insert(request_id, account_id);
                             total_weight +=
                                 <T as pallet::Config>::WeightInfo::on_initialize_with_balance(
                                     T::MaxNewAccountsPerBlock::get(),
@@ -332,28 +294,6 @@ where
     }
 }
 
-// implement on filled randomness
-impl<T> pallet_provide_randomness::OnFilledRandomness for Pallet<T>
-where
-    T: Config,
-{
-    fn on_filled_randomness(request_id: RequestId, randomness: H256) -> Weight {
-        if let Some(account_id) = PendingRandomIdAssignments::<T>::take(request_id) {
-            frame_system::Account::<T>::mutate(&account_id, |account| {
-                account.consumers = account.consumers.saturating_sub(1);
-                account.data.random_id = Some(randomness);
-            });
-            Self::deposit_event(Event::RandomIdAssigned {
-                who: account_id,
-                random_id: randomness,
-            });
-            <T as pallet::Config>::WeightInfo::on_filled_randomness_pending()
-        } else {
-            <T as pallet::Config>::WeightInfo::on_filled_randomness_no_pending()
-        }
-    }
-}
-
 // implement accountdata storedmap
 impl<T, AccountId, Balance>
     frame_support::traits::StoredMap<AccountId, pallet_balances::AccountData<Balance>> for Pallet<T>
@@ -378,8 +318,7 @@ where
         + scale_info::TypeInfo,
     T: Config
         + frame_system::Config<AccountId = AccountId, AccountData = AccountData<Balance, IdtyIdOf<T>>>
-        + pallet_balances::Config<Balance = Balance>
-        + pallet_provide_randomness::Config,
+        + pallet_balances::Config<Balance = Balance>,
 {
     fn get(k: &AccountId) -> pallet_balances::AccountData<Balance> {
         frame_system::Account::<T>::get(k).data.into()
@@ -399,7 +338,7 @@ where
         let result = f(&mut some_data)?;
         let is_providing = some_data.is_some();
         match (was_providing, is_providing) {
-            // the account has just been created, increment its provider and request a random_id
+            // the account has just been created, increment its provider
             (false, true) => {
                 frame_system::Pallet::<T>::inc_providers(account_id);
                 PendingNewAccounts::<T>::insert(account_id, ());
diff --git a/pallets/duniter-account/src/types.rs b/pallets/duniter-account/src/types.rs
index 77553c4db..c44cb0873 100644
--- a/pallets/duniter-account/src/types.rs
+++ b/pallets/duniter-account/src/types.rs
@@ -17,15 +17,11 @@
 use codec::{Decode, Encode, MaxEncodedLen};
 use frame_support::pallet_prelude::*;
 use scale_info::TypeInfo;
-use sp_core::H256;
 use sp_runtime::traits::Zero;
 
 // see `struct AccountData` for details in substrate code
 #[derive(Clone, Decode, Encode, Eq, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)] // Default,
 pub struct AccountData<Balance, IdtyId> {
-    /// A random identifier that can not be chosen by the user
-    // this intends to be used as a robust identification system
-    pub(super) random_id: Option<H256>,
     // see Substrate AccountData
     pub(super) free: Balance,
     // see Substrate AccountData
@@ -43,7 +39,6 @@ impl<Balance: Zero, IdtyId> Default for AccountData<Balance, IdtyId> {
     fn default() -> Self {
         Self {
             linked_idty: None,
-            random_id: None,
             free: Balance::zero(),
             reserved: Balance::zero(),
             fee_frozen: Balance::zero(),
@@ -89,7 +84,6 @@ impl<Balance: Zero, IdtyId> From<AccountData<Balance, IdtyId>>
 )]
 #[serde(deny_unknown_fields)]
 pub struct GenesisAccountData<Balance, IdtyId> {
-    pub random_id: H256,
     pub balance: Balance,
     pub idty_id: Option<IdtyId>,
 }
diff --git a/pallets/duniter-account/src/weights.rs b/pallets/duniter-account/src/weights.rs
index d8ccf6bb5..f4bbe1588 100644
--- a/pallets/duniter-account/src/weights.rs
+++ b/pallets/duniter-account/src/weights.rs
@@ -23,8 +23,6 @@ pub trait WeightInfo {
     fn on_initialize_sufficient(i: u32) -> Weight;
     fn on_initialize_with_balance(i: u32) -> Weight;
     fn on_initialize_no_balance(i: u32) -> Weight;
-    fn on_filled_randomness_pending() -> Weight;
-    fn on_filled_randomness_no_pending() -> Weight;
     fn unlink_identity() -> Weight;
 }
 
@@ -43,13 +41,7 @@ impl WeightInfo for () {
     }
 
     // Storage: Account PendingNewAccounts (r:1 w:0)
-    // Storage: ProvideRandomness RequestIdProvider (r:1 w:1)
-    // Storage: ProvideRandomness RequestsIds (r:1 w:1)
-    // Storage: ProvideRandomness CounterForRequestsIds (r:1 w:1)
     // Storage: Babe EpochIndex (r:1 w:0)
-    // Storage: ProvideRandomness NexEpochHookIn (r:1 w:0)
-    // Storage: ProvideRandomness RequestsReadyAtEpoch (r:1 w:1)
-    // Storage: Account PendingRandomIdAssignments (r:0 w:1)
     /// The range of component `i` is `[0, 1]`.
     fn on_initialize_sufficient(i: u32) -> Weight {
         // Minimum execution time: 12_958 nanoseconds.
@@ -62,13 +54,7 @@ impl WeightInfo for () {
     }
 
     // Storage: Account PendingNewAccounts (r:1 w:0)
-    // Storage: ProvideRandomness RequestIdProvider (r:1 w:1)
-    // Storage: ProvideRandomness RequestsIds (r:1 w:1)
-    // Storage: ProvideRandomness CounterForRequestsIds (r:1 w:1)
     // Storage: Babe EpochIndex (r:1 w:0)
-    // Storage: ProvideRandomness NexEpochHookIn (r:1 w:0)
-    // Storage: ProvideRandomness RequestsReadyAtEpoch (r:1 w:1)
-    // Storage: Account PendingRandomIdAssignments (r:0 w:1)
     /// The range of component `i` is `[0, 1]`.
     fn on_initialize_with_balance(i: u32) -> Weight {
         // Minimum execution time: 12_965 nanoseconds.
@@ -90,19 +76,4 @@ impl WeightInfo for () {
             .saturating_add(RocksDbWeight::get().reads(1 as u64))
             .saturating_add(RocksDbWeight::get().writes((1 as u64).saturating_mul(i as u64)))
     }
-
-    // Storage: Account PendingRandomIdAssignments (r:1 w:1)
-    fn on_filled_randomness_pending() -> Weight {
-        // Minimum execution time: 66_963 nanoseconds.
-        Weight::from_parts(69_757_000 as u64, 0)
-            .saturating_add(RocksDbWeight::get().reads(1 as u64))
-            .saturating_add(RocksDbWeight::get().writes(1 as u64))
-    }
-
-    // Storage: Account PendingRandomIdAssignments (r:1 w:0)
-    fn on_filled_randomness_no_pending() -> Weight {
-        // Minimum execution time: 16_088 nanoseconds.
-        Weight::from_parts(27_963_000 as u64, 0)
-            .saturating_add(RocksDbWeight::get().reads(1 as u64))
-    }
 }
diff --git a/resources/metadata.scale b/resources/metadata.scale
index f963c977883e0d240b34d87f1b77b461ffcdee71..26b30e4664d0ced1c6e5a8bb586ccfd1ace71403 100644
GIT binary patch
delta 11514
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
PcDxtDJubtX4mtUMKvJJQ

delta 11613
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
b<`$c4z((dciDp3}``{!*xLtyZUOD+cI-;qX

diff --git a/runtime/common/src/pallets_config.rs b/runtime/common/src/pallets_config.rs
index d1893985c..a2262503e 100644
--- a/runtime/common/src/pallets_config.rs
+++ b/runtime/common/src/pallets_config.rs
@@ -108,6 +108,7 @@ type RuntimeTask = ();
             // does currency adapter in any case, but adds "refund with quota" feature
             type InnerOnChargeTransaction = CurrencyAdapter<Balances, HandleFees>;
             type Refund = Quota;
+            type OnUnbalanced = Treasury;
         }
 
         // QUOTA //
@@ -347,7 +348,7 @@ type RuntimeFreezeReason = ();
             type GetCurrentEpochIndex = GetCurrentEpochIndex<Self>;
             type MaxRequests = frame_support::traits::ConstU32<100>;
             type RequestPrice = frame_support::traits::ConstU64<2_000>;
-            type OnFilledRandomness = Account;
+            type OnFilledRandomness = ();
             type OnUnbalanced = Treasury;
             type ParentBlockRandomness = pallet_babe::ParentBlockRandomness<Self>;
             type RandomnessFromOneEpochAgo = pallet_babe::RandomnessFromOneEpochAgo<Self>;
diff --git a/runtime/common/src/weights/pallet_duniter_account.rs b/runtime/common/src/weights/pallet_duniter_account.rs
index 797603e66..3dcee20a0 100644
--- a/runtime/common/src/weights/pallet_duniter_account.rs
+++ b/runtime/common/src/weights/pallet_duniter_account.rs
@@ -61,20 +61,8 @@ impl<T: frame_system::Config> pallet_duniter_account::WeightInfo for WeightInfo<
 	}
 	/// Storage: `Account::PendingNewAccounts` (r:1 w:1)
 	/// Proof: `Account::PendingNewAccounts` (`max_values`: None, `max_size`: None, mode: `Measured`)
-	/// Storage: `ProvideRandomness::RequestIdProvider` (r:1 w:1)
-	/// Proof: `ProvideRandomness::RequestIdProvider` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ProvideRandomness::RequestsIds` (r:1 w:1)
-	/// Proof: `ProvideRandomness::RequestsIds` (`max_values`: None, `max_size`: None, mode: `Measured`)
-	/// Storage: `ProvideRandomness::CounterForRequestsIds` (r:1 w:1)
-	/// Proof: `ProvideRandomness::CounterForRequestsIds` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
 	/// Storage: `Babe::EpochIndex` (r:1 w:0)
 	/// Proof: `Babe::EpochIndex` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
-	/// Storage: `ProvideRandomness::NexEpochHookIn` (r:1 w:0)
-	/// Proof: `ProvideRandomness::NexEpochHookIn` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ProvideRandomness::RequestsReadyAtEpoch` (r:1 w:1)
-	/// Proof: `ProvideRandomness::RequestsReadyAtEpoch` (`max_values`: None, `max_size`: None, mode: `Measured`)
-	/// Storage: `Account::PendingRandomIdAssignments` (r:0 w:1)
-	/// Proof: `Account::PendingRandomIdAssignments` (`max_values`: None, `max_size`: None, mode: `Measured`)
 	/// The range of component `i` is `[0, 1]`.
 	fn on_initialize_sufficient(i: u32, ) -> Weight {
 		// Proof Size summary in bytes:
@@ -94,20 +82,8 @@ impl<T: frame_system::Config> pallet_duniter_account::WeightInfo for WeightInfo<
 	/// Proof: `Account::PendingNewAccounts` (`max_values`: None, `max_size`: None, mode: `Measured`)
 	/// Storage: `System::Account` (r:1 w:1)
 	/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(126), added: 2601, mode: `MaxEncodedLen`)
-	/// Storage: `ProvideRandomness::RequestIdProvider` (r:1 w:1)
-	/// Proof: `ProvideRandomness::RequestIdProvider` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ProvideRandomness::RequestsIds` (r:1 w:1)
-	/// Proof: `ProvideRandomness::RequestsIds` (`max_values`: None, `max_size`: None, mode: `Measured`)
-	/// Storage: `ProvideRandomness::CounterForRequestsIds` (r:1 w:1)
-	/// Proof: `ProvideRandomness::CounterForRequestsIds` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
 	/// Storage: `Babe::EpochIndex` (r:1 w:0)
 	/// Proof: `Babe::EpochIndex` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
-	/// Storage: `ProvideRandomness::NexEpochHookIn` (r:1 w:0)
-	/// Proof: `ProvideRandomness::NexEpochHookIn` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
-	/// Storage: `ProvideRandomness::RequestsReadyAtEpoch` (r:1 w:1)
-	/// Proof: `ProvideRandomness::RequestsReadyAtEpoch` (`max_values`: None, `max_size`: None, mode: `Measured`)
-	/// Storage: `Account::PendingRandomIdAssignments` (r:0 w:1)
-	/// Proof: `Account::PendingRandomIdAssignments` (`max_values`: None, `max_size`: None, mode: `Measured`)
 	/// The range of component `i` is `[0, 1]`.
 	fn on_initialize_with_balance(i: u32, ) -> Weight {
 		// Proof Size summary in bytes:
@@ -139,27 +115,4 @@ impl<T: frame_system::Config> pallet_duniter_account::WeightInfo for WeightInfo<
 			.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into())))
 			.saturating_add(Weight::from_parts(0, 74).saturating_mul(i.into()))
 	}
-	/// Storage: `Account::PendingRandomIdAssignments` (r:1 w:1)
-	/// Proof: `Account::PendingRandomIdAssignments` (`max_values`: None, `max_size`: None, mode: `Measured`)
-	fn on_filled_randomness_pending() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `116`
-		//  Estimated: `3581`
-		// Minimum execution time: 20_089_000 picoseconds.
-		Weight::from_parts(21_261_000, 0)
-			.saturating_add(Weight::from_parts(0, 3581))
-			.saturating_add(T::DbWeight::get().reads(1))
-			.saturating_add(T::DbWeight::get().writes(1))
-	}
-	/// Storage: `Account::PendingRandomIdAssignments` (r:1 w:0)
-	/// Proof: `Account::PendingRandomIdAssignments` (`max_values`: None, `max_size`: None, mode: `Measured`)
-	fn on_filled_randomness_no_pending() -> Weight {
-		// Proof Size summary in bytes:
-		//  Measured:  `42`
-		//  Estimated: `3507`
-		// Minimum execution time: 4_511_000 picoseconds.
-		Weight::from_parts(4_829_000, 0)
-			.saturating_add(Weight::from_parts(0, 3507))
-			.saturating_add(T::DbWeight::get().reads(1))
-	}
 }
diff --git a/runtime/gdev/tests/common/mod.rs b/runtime/gdev/tests/common/mod.rs
index 249653ec2..95933e525 100644
--- a/runtime/gdev/tests/common/mod.rs
+++ b/runtime/gdev/tests/common/mod.rs
@@ -73,7 +73,6 @@ impl ExtBuilder {
                     get_account_id_from_seed::<sr25519::Public>(NAMES[i]),
                     GenesisAccountData {
                         balance: 0,
-                        random_id: H256([i as u8; 32]),
                         idty_id: Some(i as u32 + 1),
                     },
                 )
@@ -123,7 +122,6 @@ impl ExtBuilder {
             self.initial_accounts
                 .entry(account_id.clone())
                 .or_insert(GenesisAccountData {
-                    random_id: H256(account_id.into()),
                     ..Default::default()
                 })
                 .balance = balance;
diff --git a/runtime/gdev/tests/integration_tests.rs b/runtime/gdev/tests/integration_tests.rs
index 4624094d4..bd6332369 100644
--- a/runtime/gdev/tests/integration_tests.rs
+++ b/runtime/gdev/tests/integration_tests.rs
@@ -1056,42 +1056,25 @@ fn test_create_new_account() {
             // 100 initial + 300 deposit
             assert_eq!(Balances::free_balance(Treasury::account_id()), 400);
 
-            // A random id request should be registered
-            assert_eq!(
-                Account::pending_random_id_assignments(0),
-                Some(AccountKeyring::Eve.to_account_id())
-            );
-
-            // We can't remove the account until the random id is assigned
             run_to_block(4);
-            // can not remove using transfer
-            assert_noop!(
-                Balances::transfer_allow_death(
-                    frame_system::RawOrigin::Signed(AccountKeyring::Eve.to_account_id()).into(),
-                    MultiAddress::Id(AccountKeyring::Alice.to_account_id()),
-                    200
-                ),
-                sp_runtime::DispatchError::ConsumerRemaining,
-            );
+            // can remove an account using transfer
+            assert_ok!(Balances::transfer_allow_death(
+                frame_system::RawOrigin::Signed(AccountKeyring::Eve.to_account_id()).into(),
+                MultiAddress::Id(AccountKeyring::Alice.to_account_id()),
+                200
+            ));
+            // Account reaped
             assert_eq!(
                 Balances::free_balance(AccountKeyring::Eve.to_account_id()),
-                200
-            );
-            // can not remove using transfer_all either
-            assert_noop!(
-                Balances::transfer_all(
-                    frame_system::RawOrigin::Signed(AccountKeyring::Eve.to_account_id()).into(),
-                    MultiAddress::Id(AccountKeyring::Alice.to_account_id()),
-                    false
-                ),
-                sp_runtime::DispatchError::ConsumerRemaining,
+                0
             );
-            // Transfer failed, so free_balance remains the same
             assert_eq!(
-                Balances::free_balance(AccountKeyring::Eve.to_account_id()),
-                200
+                frame_system::Pallet::<Runtime>::get(&AccountKeyring::Eve.to_account_id()),
+                pallet_duniter_account::AccountData::default()
             );
-            // TODO detail account removal
+            System::assert_has_event(RuntimeEvent::System(frame_system::Event::KilledAccount {
+                account: AccountKeyring::Eve.to_account_id(),
+            }));
         });
 }
 
@@ -1118,12 +1101,6 @@ fn test_create_new_idty() {
             run_to_block(3);
             let events = System::events();
             assert_eq!(events.len(), 0);
-
-            // A random id request should be registered
-            assert_eq!(
-                Account::pending_random_id_assignments(0),
-                Some(AccountKeyring::Eve.to_account_id())
-            );
         });
 }
 
@@ -1156,25 +1133,19 @@ fn test_create_new_idty_without_founds() {
             let events = System::events();
             assert_eq!(events.len(), 0);
 
-            // Deposit some founds on the identity account,
-            // this should trigger the random id assignemt
+            // Deposit some founds on the identity account
             assert_ok!(Balances::transfer_allow_death(
                 frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into(),
                 MultiAddress::Id(AccountKeyring::Eve.to_account_id()),
                 200
             ));
 
-            // At next block, nothing should be preleved,
-            // and a random id request should be registered
+            // At next block, nothing should be preleved
             run_to_block(4);
             assert_eq!(
                 Balances::free_balance(AccountKeyring::Eve.to_account_id()),
                 200
             );
-            assert_eq!(
-                Account::pending_random_id_assignments(0),
-                Some(AccountKeyring::Eve.to_account_id())
-            );
         });
 }
 
-- 
GitLab