infrablockchain-docs
en
en
  • InfraBlockchain
    • Learn
      • Architecture
        • Architecture
        • Network Participants
        • Parachain
          • System Parachains
      • Protocol
        • System Token
        • Transaction Fee
        • Proof of Transaction
      • Substrate
        • Learn
          • Basic
            • Cryptography
            • Blockchain Basics
            • Consensus
            • Networks and Nodes
            • Blockchain Transaction
            • Transaction Life Cycle
            • Offchain Operations
            • Light Client
            • Rust for Substrate
            • Introduction to Library
            • Architecture and Rust Libraries
            • File Architecture
            • Accounts, Addresses, and Keys
            • Transaction Format
            • Blockchain Randomness
          • FRAME
            • FRAME Pallets
            • FRAME Macros
            • Custom Pallets
            • Pallet Coupling
            • Origin
            • Events and Erros
            • Runtime Storage
            • State Transitions and Storage
            • SCALE Encoding
            • Weight and Fee
            • Runtime API
            • Runtime Development
          • Account
          • Address Format
          • Glossary
          • CLI
            • Archive
            • Memory Profiler
            • Node Template
            • sidecar
            • srtool
            • Subkey
            • subxt
            • try-runtime
            • tx-wrapper
          • Runtime Development
            • Basics
              • Configure Genesis State
              • Configure Runtime Constants
              • Customize a Chain Spec
              • Import a Pallet
              • Use Helper Function
            • Consensus Model
              • PoW
              • Create a Hybrid Node
            • Offchain Worker
              • Request Offchain HTTP
              • Offchain Indexing
              • Offchain Local Storage
            • Pallet Design
              • Create a Storage Structure
              • Implement Lockable Currency
              • Incorporate Randomness
              • Loose Coupling
              • Tight Coupling
            • Parachain Development
              • Add HRMP Channel
              • Add Paranodes
              • Connect to a Local Relay Chain
              • Convert a Solo Chain
              • Prepare to Launch
              • Select Collator
              • Upgrade a Parachain
            • Storage Migration
              • Basics
              • Trigger Migration
            • Test
              • Basics
              • Test a Transfer Transaction
            • Tools
              • Create a TxWrapper
              • Use Sidecar
              • try-runtime
              • Verify WASM
            • Weigths
              • Benchmark
              • Calculate Fees
              • Use Conditional Weights
              • Use Custom Weights
        • Build
          • Decide What to Build
          • Build Process
          • Determinisitc Runtime
          • Chain Spec
          • Genesis Configuration
          • Application Development
          • RPC
          • Troubleshoot Your Code
        • Tutorials
          • Install
            • Developer Tools
            • Linux
            • macOS
            • Rust Toolchain
            • Issues
            • Windows
          • Quick Start
            • Explore the Code
            • Modify Runtime
            • Start a Node
            • Substrate Basics
          • Build a Blockchain
            • Add Trusted Nodes
            • Authorize Specific Nodes
            • Build a Local Blockchain
            • Simulate Network
            • Upgrade a Running Network
          • Build Application Logic
            • Add a Pallet
            • Add Offchasin Workers
            • Publish Custom Pallets
            • Specify Origin for a Call
            • Use Macros in a Custom Pallet
          • Integrate with Tools
            • Access EVM Accounts
            • EVM Integration
            • Explore Sidecar Endpoints
            • Integrate a Light Client Node
          • Smart Contracts
            • Strategy
            • Build a Token Contract
            • Develop a Smart Contract
            • Prepare Your First Contract
            • Troubleshoot Smart Contracts
            • Use Maps for Storing Values
      • XCM
        • XCM
        • XCM Format
    • Service Chains
      • InfraDID
      • InfraEVM
      • URAuth(Universal Resource Auth)
    • DevOps
      • Build
      • Deploy
      • Monitoring
      • Runtime Upgrade
    • Tutorials
      • Basic
        • How to Interact with System Token
        • How To Pay Transaction Fee
        • How To Vote with TaaV
        • Hot to Get Validator Reward
      • Build
        • Build InfraRelayChain
        • Build Parachain
        • Open Message Passing Channels
        • Transfer Assets with XCM
      • Test
        • Benchmark
        • Check Runtime
        • Debug
        • Simulate Parachains
        • Unit Testing
      • Service Chains
        • Play with InfraDID
          • Build
          • Add Keys
          • Add Service Endpoint
          • Create InfraDID
        • Play with InfraEVM
          • Build
          • Deposit and Withdraw Token
          • Deploy ERC20 Contract
          • Deploy ERC721 Contract
          • Deploy ERC1155 Contract
  • Newnal Data Market
Powered by GitBook
On this page
  • Configure a simple storage value
  • Adding genesis configuration to the runtime
  • Initialize storage items within a pallet
  1. InfraBlockchain
  2. Learn
  3. Substrate
  4. Build

Genesis Configuration

PreviousChain SpecNextApplication Development

Last updated 1 year ago

The first block produced by any blockchain is referred to as the genesis block. The hash associated with this block is the top-level parent of all blocks produced after that first block.

The Substrate node template provides the genesis configuration—the initial state—for a subset of pallets by default. As you add custom logic to the runtime—for example, by adding predefined or custom pallets—you might find that you want to modify the genesis configuration to include other storage items or set different initial values.

As you learned in , the chain specification you use to start a node determines the genesis configuration for that node. However, the chain specification doesn't create the storage items that get initialized when you start a node. Instead, the storage items are defined in the pallets included in the runtime as described in .

After you create storage items for the runtime, you can choose whether they should be set to some initial value as part of the genesis configuration and included in the genesis block. To specify the storage items that you want to set an initial state for, Substrate provides two specialized FRAME attribute macros.

The macros you can use to initialize storage items as part of the genesis configuration for a chain are:

  • The #[pallet::genesis_config] macro defines the GenesisConfig data type and initializes storage items.

  • The #[pallet::genesis_build] macro builds the genesis configuration.

These macros are used in combination with the chain specification to define the initial state of the runtime.

Configure a simple storage value

The following example demonstrates adding a single storage value to the genesis configuration for the pallet_template. By default, the pallet_template has one storage item that isn't initialized in the genesis block. This example illustrates how you can use the #[pallet::genesis_config] and #[pallet::genesis_build] macros to set an initial value for the storage value as part of the genesis configuration for your chain.

Configure macros in the pallet

To initialize a storage item for the pallet_template:

  1. Open a new terminal shell and navigate to the root directory for the node template.

  2. Open the pallets/template/src/lib.rs file in a text editor.

  3. Add the #[pallet::genesis_config] macro and add the storage value something as the GenesisConfig storage item for the pallet. For example, add the following macro to the file:

    // Test Genesis Configuration
    #[pallet::genesis_config]
    #[derive(Default)]
     pub struct GenesisConfig {
           pub something: u32,
    }

In this example, the `#[derive(Default)]` macro is required to satisfy a trait bound requirement in `frame_support::traits::GenesisBuild`.

4. Add the `#[pallet::genesis_build]` macro:

 ```rust
 #[pallet::genesis_build]
 impl<T: Config> GenesisBuild<T> for GenesisConfig {
    fn build(&self) { }
 }

In this example, there's no special handling for the build function to perform.

  1. Save your changes and close the file.

  2. Verify that the pallet compiles by running the following command:

    cargo build --package pallet-template

Configure the chain specification

Now that you have configured the pallet to initialize a storage value in the genesis block, you can set an initial value for that storage item in the chain specification.

  1. Open the node/src/chain_spec.rs file in a text editor.

  2. Add the TemplateModuleConfig to the node_template_runtime.

    For example:

    use node_template_runtime::{
       AccountId, AuraConfig, BalancesConfig, RuntimeGenesisConfig, GrandpaConfig, Signature, SudoConfig, SystemConfig, TemplateModuleConfig, WASM_BINARY,
    };
  3. Locate the GenesisConfig and set the initial value for the something storage item.

    For example, in the node/src/chain_spec.rs file:

    -> GenesisConfig {
         GenesisConfig {
                 system: SystemConfig {
                         // Add Wasm runtime to storage.
                         code: wasm_binary.to_vec(),
                 },
    
                 template_module: TemplateModuleConfig {
                        something: 221u32,
                 },
    
                 transaction_payment: Default::default(),
         }
       }

Adding genesis configuration to the runtime

All of the GenesisConfig types for the pallets that included in the construction of the runtime are then aggregated into a single RuntimeGenesisConfig type for that runtime.

System pallet

#[pallet::genesis_config]
	pub struct GenesisConfig {
		#[serde(with = "sp_core::bytes")]
		pub code: Vec<u8>,
	}

Aura pallet

#[pallet::genesis_config]
	pub struct GenesisConfig<T: Config> {
		pub authorities: Vec<T::AuthorityId>,
	}

Grandpa pallet

#[pallet::genesis_config]
	pub struct GenesisConfig {
		pub authorities: AuthorityList,
	}

Balances pallet

#[pallet::genesis_config]
	pub struct GenesisConfig<T: Config<I>, I: 'static = ()> {
		pub balances: Vec<(T::AccountId, T::Balance)>,
	}

TransactionPayment pallet

#[pallet::genesis_config]
	pub struct GenesisConfig {
		pub multiplier: Multiplier,
	}

Sudo pallet

#[pallet::genesis_config]
	pub struct GenesisConfig<T: Config> {
		/// The `AccountId` of the sudo key.
		pub key: Option<T::AccountId>,
	}
pub struct RuntimeGenesisConfig {
    pub system: SystemConfig,
    pub aura: AuraConfig,
    pub grandpa: GrandpaConfig,
    pub balances: BalancesConfig,
    pub transaction_payment: TransactionPaymentConfig,
    pub sudo: SudoConfig,
}

Initialize storage items within a pallet

The following example demonstrates using #[pallet::genesis_config] and #[pallet::genesis_build] to set the initial value of a storage item. In this example, there are two storage items:

  • A list of member account identifiers.

  • A specific account identifier that designates a member from the list to be the prime member.

The macros and data types for this example are defined in the my_pallet/src/lib.rs file:

#[pallet::genesis_config]
struct GenesisConfig {
    members: Vec<T::AccountId>,
    prime: T::AccountId,
}

#[pallet::genesis_build]
impl<T: Config> GenesisBuild<T> for GenesisConfig {
    fn build(&self) {
        Pallet::<T>::initialize_members(&self.members);
        SomeStorageItem::<T>::put(self.prime);
    }
}

The genesis configuration is defined in the node/src/chain_spec.rs file:

GenesisConfig {
    my_pallet: MyPalletConfig {
        members: LIST_OF_IDS,
        prime: ID,
    },
}

You can also use the genesis_build macro to define a GenesisConfig attribute that is not bound to a particular storage item. This can be useful if you want to invoke a private helper function within your pallet that sets several storage items, or to invoke a function defined in some other pallets included within your pallet. For example, using an imaginary private function called intitialize_members, the code might look like this:

In my_pallet/src/lib.rs:

#[pallet::genesis_config]
struct GenesisConfig {
    members: Vec<T::AccountId>,
    prime: T::AccountId,
}

#[pallet::genesis_build]
impl<T: Config> GenesisBuild<T> for GenesisConfig {
    fn build(&self) {
        Pallet::<T>::initialize_members(&config.members);
        SomeStorageItem::<T>::put(self.prime);
    }
}

In chain_spec.rs:

GenesisConfig {
    my_pallet: MyPalletConfig {
        members: LIST_OF_IDS,
        prime: ID,
    },
}

After you use the macro to add the GenesisConfig to each pallet where it's needed, you must include the Config trait for each pallet in the runtime to enable the runtime to initialize storage items in the genesis block.

The aggregated RuntimeGenesisConfig implements the trait to build all of the initial storage items for the runtime. For example, the node template runtime builds storage items for the following pallets that have a RuntimeGenesisConfig specified by default:

Because these pallets include the #[pallet::genesis_config] macro with a GenesisConfig and have the Config trait defined in the runtime, they are aggregated into struct for the runtime:

Ultimately, the RuntimeGenesisConfig is exposed by way of the trait.

For a more complete example of genesis storage configuration for Substrate, see the .

You can use the macro to define the initial state of storage items within the pallet itself. Defining the genesis configuration within a pallet allows you to access the pallet's private functions.

Chain specification
Runtime storage
#[pallet::genesis_config]
BuildStorage
node_template_runtime::RuntimeGenesisConfig
ChainSpec
chain specification that ships with the Substrate code base
#[pallet::genesis_build]
Configure a simple storage value
Configure macros in the pallet
Configure the chain specification
Adding genesis configuration to the runtime
System pallet
Aura pallet
Grandpa pallet
Balances pallet
TransactionPayment pallet
Sudo pallet
Initialize storage items within a pallet