What are the macros #[pallet::genesis_config] and #[pallet::genesis_build] doing on the sudo pallet?

Viewed 212
#[pallet::genesis_config]
    pub struct GenesisConfig<T: Config> {
        /// The `AccountId` of the sudo key.
        pub key: T::AccountId,
    }

    #[cfg(feature = "std")]
    impl<T: Config> Default for GenesisConfig<T> {
        fn default() -> Self {
            Self { key: Default::default() }
        }
    }

    #[pallet::genesis_build]
    impl<T: Config> GenesisBuild<T> for GenesisConfig<T> {
        fn build(&self) {
            <Key<T>>::put(&self.key);
        }
    }

What is happening here with genesis_config and genesis_build macros here? Some reading seemed to suggest that implement the trait GenesisBuild<T,I = ()> but I am confused as the docs read: "T and I are placeholder for pallet trait and pallet instance."

What are pallet instances? I also assume pallet trait means the Config trait for the sudo pallet. Is it some how related to configuring a unique StorageValue for the Genesis block so that each instance of a running node can verify that the same Account is Root? Can someone help break it down for me.

2 Answers

What are pallet instances?

Pallets can be made instantiable. This means a Pallet can be used multiple times in a runtime. Each instance will use the same code (modulo different configuration through the configuration trait), but the storage will be different for each instance.

See: https://docs.substrate.io/how-to-guides/v3/basics/instantiable-pallets/

I also assume pallet trait means the Config trait for the sudo pallet. Is it some how related to configuring a unique StorageValue for the Genesis block so that each instance of a running node can verify that the same Account is Root? Can someone help break it down for me.

Yes Pallet trait means the Config trait.

The point here with GenesisBuild taking two generic arguments is to support all kinds of Pallets. Every Pallet is configurable through the trait, so the GenesisBuild trait needs to take the Config generic parameter T. Some Pallets can be instantiable, so it also needs to take I.

This all boils down to some Rust "quirks" to support instantiable Pallets that are using the default instance and custom instances and also to support Pallets that don't use any instancing at all.

#[pallet::genesis_build] implements the trait sp_runtime::BuildModuleGenesisStorage which puts the initial state into the pallet's storage at genesis time.
(The pallet can put state into child storage also at that point.)

The pub enum/struct with #[pallet::genesis_config] holds the fields that genesis_build reads in order to set up the storage. For example there may be investors at genesis that need a vesting schedule set up (See the vesting pallet: https://github.com/paritytech/substrate/blob/3cdb30e1ecbafe8a866317d4550c921b4d686869/frame/vesting/src/lib.rs#L231 ). So for the sudo pallet, the genesis_config struct holds the root key which is set here:

GenesisConfig {
        sudo: SudoConfig {
            // Assign network admin rights.
            key: root_key,
        },
        ...
}

( https://github.com/paritytech/substrate/blob/3cdb30e1ecbafe8a866317d4550c921b4d686869/bin/node-template/node/src/chain_spec.rs#L150 )

Docs for genesis_config are here: https://docs.substrate.io/rustdocs/latest/frame_support/attr.pallet.html#genesis-config-palletgenesis_config-optional

Related