#
pezkuwi_sdk_docs/reference_docs/
chain_spec_genesis.rs

    1//! # What is a chain specification
    2//!
    3//! A chain specification file defines the set of properties that are required to run the node as
    4//! part of the chain. The chain specification consists of two main parts:
    5//! - initial state of the runtime,
    6//! - network / logical properties of the chain, the most important property being the list of
    7//!   bootnodes.
    8//!
    9//! This document describes how the initial state is handled in pallets and runtime, and how to
    10//! interact with the runtime in order to build the genesis state.
    11//!
    12//! For more information on chain specification and its properties, refer to
    13//! [`pezsc_chain_spec#from-initial-state-to-raw-genesis`].
    14//!
    15//! The initial genesis state can be provided in the following formats:
    16//!   - full
    17//!   - patch
    18//!   - raw
    19//!
    20//! Each of the formats is explained in
    21//! [_chain-spec-format_][`pezsc_chain_spec#chain-spec-formats`].
    22//!
    23//!
    24//! # `GenesisConfig` for `pezpallet`
    25//!
    26//! Every frame pezpallet may have its initial state which is defined by the `GenesisConfig`
    27//! internal struct. It is a regular Rust struct, annotated with the [`pezpallet::genesis_config`]
    28//! attribute.
    29#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/pallets.rs", pezpallet_bar_GenesisConfig)]
    30//!
    31//! The struct shall be defined within the pezpallet `mod`, as in the following code:
    32#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/pallets.rs", pezpallet_bar)]
    33//!
    34//! The initial state conveyed in  the `GenesisConfig` struct is transformed into state storage
    35//! items by means of the [`BuildGenesisConfig`] trait, which shall be implemented for the
    36//! pezpallet's `GenesisConfig` struct. The [`pezpallet::genesis_build`] attribute shall be attached
    37//! to the `impl` block:
    38#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/pallets.rs", pezpallet_bar_build)]
    39//!
    40//! `GenesisConfig` may also contain more complicated types, including nested structs or enums, as
    41//! in the example for `pezpallet_foo`:
    42#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/pallets.rs", pezpallet_foo_GenesisConfig)]
    43//!
    44//! Note that [`serde`] attributes can be used to control how the data
    45//! structures are stored into JSON. In the following example, the [`pezsp_core::bytes`] function is
    46//! used to serialize the `values` field.
    47#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/pallets.rs", SomeFooData2)]
    48//!
    49//! Please note that fields of `GenesisConfig` may not be directly mapped to storage items. In the
    50//! following example, the initial struct fields are used to compute (sum) the value that will be
    51//! stored in the state as `ProcessedEnumValue`:
    52#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/pallets.rs", pezpallet_foo_build)]
    53//!
    54//! # `GenesisConfig` for `runtimes`
    55//!
    56//! The runtime genesis config struct consists of configs for every pezpallet. For the
    57//! [_demonstration runtime_][`pez_chain_spec_guide_runtime`] used in this guide, it consists of
    58//! `SystemConfig`, `BarConfig`, and `FooConfig`. This structure was automatically generated by a
    59//! macro and it can be sneak-peeked here: [`RuntimeGenesisConfig`]. For further reading on
    60//! generated runtime types, refer to [`frame_runtime_types`].
    61//!
    62//! The macro automatically adds an attribute that renames all the fields to [`camelCase`]. It is a
    63//! good practice to add it to nested structures too, to have the naming of the JSON keys consistent
    64//! across the chain-spec file.
    65//!
    66//! ## `Default` for `GenesisConfig`
    67//!
    68//! `GenesisConfig` of all pallets must implement the `Default` trait. These are aggregated into
    69//! the runtime's `RuntimeGenesisConfig`'s `Default`.
    70//!
    71//! The default value of `RuntimeGenesisConfig` can be queried by the [`GenesisBuilder::get_preset`]
    72//! function provided by the runtime with `id:None`.
    73//!
    74//! A default value for `RuntimeGenesisConfig` usually is not operational. This is because for some
    75//! pallets it is not possible to define good defaults (e.g. an initial set of authorities).
    76//!
    77//! A default value is a base upon which a patch for `GenesisConfig` is applied. A good description
    78//! of how it exactly works is provided in [`get_storage_for_patch`] (and also in
    79//! [`GenesisBuilder::get_preset`]). A patch can be provided as an external file (manually created)
    80//! or as a built-in runtime preset. More info on presets is in the material to follow.
    81//!
    82//! ## Implementing `GenesisBuilder` for runtime
    83//!
    84//! The runtime exposes a dedicated runtime API for interacting with its genesis config:
    85//! [`pezsp_genesis_builder::GenesisBuilder`]. The implementation shall be provided within
    86//! the [`pezsp_api::impl_runtime_apis`] macro, typically making use of some helpers provided:
    87//! [`build_state`], [`get_preset`].
    88//! A typical implementation of [`pezsp_genesis_builder::GenesisBuilder`] looks as follows:
    89#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/runtime.rs", runtime_impl)]
    90//!
    91//! Please note that two functions are customized: `preset_names` and `get_preset`. The first one
    92//! just provides a `Vec` of the names of supported presets, while the latter delegates the call
    93//! to a function that maps the name to an actual preset:
    94//! [`pez_chain_spec_guide_runtime::presets::get_builtin_preset`]
    95#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/presets.rs", get_builtin_preset)]
    96//!
    97//! ## Genesis state presets for runtime
    98//!
    99//! The runtime may provide many flavors of initial genesis state. This may be useful for predefined
    100//! testing networks, local development, or CI integration tests. Predefined genesis state may
    101//! contain a list of pre-funded accounts, predefined authorities for consensus, sudo key, and many
    102//! others useful for testing.
    103//!
    104//! Internally, presets can be provided in a number of ways:
    105//! - using [`build_struct_json_patch`] macro (**recommended**):
    106#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/presets.rs", preset_2)]
    107//! - JSON using runtime types to serialize values:
    108#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/presets.rs", preset_3)]
    109//! - JSON in string form:
    110#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/presets.rs", preset_1)]
    111//!
    112//! It is worth noting that a preset does not have to be the full `RuntimeGenesisConfig`, in that
    113//! sense that it does not have to contain all the keys of the struct. The preset is actually a JSON
    114//! patch that will be merged with the default value of `RuntimeGenesisConfig`. This approach should
    115//! simplify maintenance of built-in presets. The following example illustrates a runtime genesis
    116//! config patch with a single key built using [`build_struct_json_patch`] macro:
    117#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/presets.rs", preset_4)]
    118//! This results in the following JSON blob:
    119#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/tests/chain_spec_builder_tests.rs", preset_4_json)]
    120//!
    121//!
    122//! ## Note on the importance of testing presets
    123//!
    124//! It is recommended to always test presets by adding tests that convert the preset into the
    125//! raw storage. Converting to raw storage involves the deserialization of the provided JSON blob,
    126//! which enforces the verification of the preset. The following code shows one of the approaches
    127//! that can be taken for testing:
    128#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/presets.rs", check_presets)]
    129//!
    130//! ## Note on the importance of using the `deny_unknown_fields` attribute
    131//!
    132//! It is worth noting that when manually building preset JSON blobs it is easy to make a
    133//! hard-to-spot mistake, as in the following example ([`FooStruct`] does not contain `fieldC`):
    134#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/presets.rs", preset_invalid)]
    135//! Even though `preset_invalid` contains a key that does not exist, the deserialization of the JSON
    136//! blob does not fail. The misspelling is silently ignored due to the lack of the
    137//! [`deny_unknown_fields`] attribute on the [`FooStruct`] struct, which is internally used in
    138//! `GenesisConfig`.
    139#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/src/presets.rs", invalid_preset_works)]
    140//!
    141//! To avoid this problem [`build_struct_json_patch`] macro shall be used whenever possible (it
    142//! internally instantiates the struct before serializang it JSON blob, so all unknown fields shall
    143//! be caught at compilation time).
    144//!
    145//! ## Runtime `GenesisConfig` raw format
    146//!
    147//! A raw format of genesis config contains just the state's keys and values as they are stored in
    148//! the storage. This format is used to directly initialize the genesis storage. This format is
    149//! useful for long-term running chains, where the `GenesisConfig` structure for pallets may be
    150//! evolving over time. The JSON representation created at some point in time may no longer be
    151//! deserializable in the future, making a chain specification useless. The raw format is
    152//! recommended for production chains.
    153//!
    154//! For a detailed description of how the raw format is built, please refer to
    155//! [_chain-spec-raw-genesis_][`pezsc_chain_spec#from-initial-state-to-raw-genesis`]. Plain and
    156//! corresponding raw examples of chain-spec are given in
    157//! [_chain-spec-examples_][`pezsc_chain_spec#json-chain-specification-example`].
    158//! The [`chain_spec_builder`] util supports building the raw storage.
    159//!
    160//! # Interacting with the tool
    161//!
    162//! The [`chain_spec_builder`] util allows interaction with the runtime in order to list or display
    163//! presets and build the chain specification file. It is possible to use the tool with the
    164//! [_demonstration runtime_][`pez_chain_spec_guide_runtime`]. To build the required packages, just
    165//! run the following command:
    166//!
    167//! ```ignore
    168//! cargo build -p pezstaging-chain-spec-builder -p pez-chain-spec-guide-runtime --release
    169//! ```
    170//!
    171//! The `chain-spec-builder` util can also be installed with `cargo install`:
    172//!
    173//! ```ignore
    174//! cargo install pezstaging-chain-spec-builder
    175//! cargo build -p pez-chain-spec-guide-runtime --release
    176//! ```
    177//! Here are some examples in the form of rust tests:
    178//! ## Listing available preset names:
    179#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/tests/chain_spec_builder_tests.rs", cmd_list_presets)]
    180//! ## Displaying preset with given name
    181#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/tests/chain_spec_builder_tests.rs", cmd_get_preset)]
    182//! ## Building a solo chain-spec (the default) using given preset
    183#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/tests/chain_spec_builder_tests.rs", cmd_generate_chain_spec)]
    184//! ## Building a teyrchain chain-spec using given preset
    185#![doc = docify::embed!("./src/reference_docs/chain_spec_runtime/tests/chain_spec_builder_tests.rs", cmd_generate_para_chain_spec)]
    186//!
    187//! [`RuntimeGenesisConfig`]:
    188//!     pez_chain_spec_guide_runtime::runtime::RuntimeGenesisConfig
    189//! [`FooStruct`]:
    190//!     pez_chain_spec_guide_runtime::pallets::FooStruct
    191//! [`impl_runtime_apis`]: pezframe::runtime::prelude::impl_runtime_apis
    192//! [`build_state`]: pezframe_support::genesis_builder_helper::build_state
    193//! [`get_preset`]: pezframe_support::genesis_builder_helper::get_preset
    194//! [`pezpallet::genesis_build`]: pezframe_support::pezpallet_macros::genesis_build
    195//! [`pezpallet::genesis_config`]: pezframe_support::pezpallet_macros::genesis_config
    196//! [`build_struct_json_patch`]: pezframe_support::build_struct_json_patch
    197//! [`BuildGenesisConfig`]: pezframe_support::traits::BuildGenesisConfig
    198//! [`serde`]: https://serde.rs/field-attrs.html
    199//! [`get_storage_for_patch`]: pezsc_chain_spec::GenesisConfigBuilderRuntimeCaller::get_storage_for_patch
    200//! [`GenesisBuilder::get_preset`]: pezsp_genesis_builder::GenesisBuilder::get_preset
    201//! [`deny_unknown_fields`]: https://serde.rs/container-attrs.html#deny_unknown_fields
    202//! [`camelCase`]: https://serde.rs/container-attrs.html#rename_all