Search code examples
accountsubstrate

How does the configuration of `AccountStore` in the Balances pallet work?


In the Balances pallet, the config trait has one item that is defined like type AccountStore: StoredMap<Self::AccountId, AccountData<Self::Balance>>;. This was a bit strange to me as I was expecting a normal storage map to store a mapping from AccountId to AccountData but after I looked at the docs for StoredMap I realised that it's a trait implemented on StorageMaps as well. That makes more sense now, so I go on to look at how the runtime defines this field, and to my surprise I find this in the runtime/src/lib.rs : type AccountStore = System;. Now I've never seen a runtime definition like this before because if I'm correct, System is supposed to represent the frame_system pallet. So I go to look at frame_system::Config for Runtime and I find this defintion :

type AccountData = pallet_balances::AccountData<Balance>;.

Now I don't know how these definitions are getting into the pallet_balances's Config impl, but I can see that the FRAME System pallet contains both types namely : one type AccountData and one AccountId.

In the end my two questions that stand are:

  1. What are the reasons for such a convoluting design?
  2. How does type AccountStore = System; figure out the concrete types?

Solution

    1. Storing account balances in the system pallet also maintains some other frame_system information that may be important to keep around for a certain runtime configuration. But having consumers, providers and sufficients inside a runtime with multiple pallets and potentially interacting with other runtimes becomes quite crucial.
    2. AccountStore defines where this balance is going to be stored, for this case is frame_system::Pallet<Runtime>. If we follow the lead and check the configuration of frame_system we will see that the type for AccountData is defined as
    type AccountData = pallet_balances::AccountData<Balance>
    

    Good, now we know that the AccountData stored in frame_system will be the one defined in pallet_balances.

    So the information living in system concerning accounts will end up looking like the following:

    /// Information of an account.
    #[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo)]
    pub struct AccountInfo<Index, AccountData> {
        /// The number of transactions this account has sent.
        pub nonce: Index,
        /// The number of other modules that currently depend on this account's existence. The account
        /// cannot be reaped until this is zero.
        pub consumers: RefCount,
        /// The number of other modules that allow this account to exist. The account may not be reaped
        /// until this and `sufficients` are both zero.
        pub providers: RefCount,
        /// The number of modules that allow this account to exist for their own purposes only. The
        /// account may not be reaped until this and `providers` are both zero.
        pub sufficients: RefCount,
        /// The additional data that belongs to this account. Used to store the balance(s) in a lot of
        /// chains.
        pub data: AccountData,
    }
    

    Where AccountData fits the previous mentioned definition in pallet_balances.

    Please, check this commit too for further information on how this may be tweaked -> https://github.com/paritytech/substrate/commit/31d90c202d6df9ce3837ee55587b604619a912ba