chain-spec: getting ready for native-runtime-free world (#1256)

This PR prepares chains specs for _native-runtime-free_  world.

This PR has following changes:
- `substrate`:
  - adds support for:
- JSON based `GenesisConfig` to `ChainSpec` allowing interaction with
runtime `GenesisBuilder` API.
- interacting with arbitrary runtime wasm blob to[
`chain-spec-builder`](https://github.com/paritytech/substrate/blob/3ef576eaeb3f42610e85daecc464961cf1295570/bin/utils/chain-spec-builder/src/lib.rs#L46)
command line util,
- removes
[`code`](https://github.com/paritytech/substrate/blob/3ef576eaeb3f42610e85daecc464961cf1295570/frame/system/src/lib.rs#L660)
from `system_pallet`
  - adds `code` to the `ChainSpec`
- deprecates
[`ChainSpec::from_genesis`](https://github.com/paritytech/substrate/blob/3ef576eaeb3f42610e85daecc464961cf1295570/client/chain-spec/src/chain_spec.rs#L263),
but also changes the signature of this method extending it with `code`
argument.
[`ChainSpec::builder()`](https://github.com/paritytech/substrate/blob/20bee680ed098be7239cf7a6b804cd4de267983e/client/chain-spec/src/chain_spec.rs#L507)
should be used instead.
- `polkadot`:
- all references to `RuntimeGenesisConfig` in `node/service` are
removed,
- all
`(kusama|polkadot|versi|rococo|wococo)_(staging|dev)_genesis_config`
functions now return the JSON patch for default runtime `GenesisConfig`,
  - `ChainSpecBuilder` is used, `ChainSpec::from_genesis` is removed,

- `cumulus`:
  - `ChainSpecBuilder` is used, `ChainSpec::from_genesis` is removed,
- _JSON_ patch configuration used instead of `RuntimeGenesisConfig
struct` in all chain specs.
  
---------

Co-authored-by: command-bot <>
Co-authored-by: Javier Viola <javier@parity.io>
Co-authored-by: Davide Galassi <davxy@datawok.net>
Co-authored-by: Francisco Aguirre <franciscoaguirreperez@gmail.com>
Co-authored-by: Kevin Krone <kevin@parity.io>
Co-authored-by: Bastian Köcher <git@kchr.de>
This commit is contained in:
Michal Kucharczyk
2023-11-05 15:19:23 +01:00
committed by GitHub
parent c46a7dbb61
commit 8ba7a6aba8
90 changed files with 4833 additions and 3059 deletions
+246 -106
View File
@@ -16,38 +16,253 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//! Substrate chain configurations.
//! This crate includes structs and utilities for defining configuration files (known as chain
//! specification) for both runtime and node.
//!
//! This crate contains structs and utilities to declare
//! a runtime-specific configuration file (a.k.a chain spec).
//! # Intro: Chain Specification
//!
//! Basic chain spec type containing all required parameters is
//! [`GenericChainSpec`]. It can be extended with
//! additional options that contain configuration specific to your chain.
//! Usually the extension is going to be an amalgamate of types exposed
//! by Substrate core modules. To allow the core modules to retrieve
//! their configuration from your extension you should use `ChainSpecExtension`
//! macro exposed by this crate.
//! The chain specification comprises parameters and settings that define the properties and an
//! initial state of a chain. Users typically interact with the JSON representation of the chain
//! spec. Internally, the chain spec is embodied by the [`GenericChainSpec`] struct, and specific
//! properties can be accessed using the [`ChainSpec`] trait.
//!
//! In summary, although not restricted to, the primary role of the chain spec is to provide a list
//! of well-known boot nodes for the blockchain network and the means for initializing the genesis
//! storage. This initialization is necessary for creating a genesis block upon which subsequent
//! blocks are built. When the node is launched for the first time, it reads the chain spec,
//! initializes the genesis block, and establishes connections with the boot nodes.
//!
//! The JSON chain spec is divided into two main logical sections:
//! - one section details general chain properties,
//! - second explicitly or indirectly defines the genesis storage, which, in turn, determines the
//! genesis hash of the chain,
//!
//! The chain specification consists of the following fields:
//!
//! <table>
//! <thead>
//! <tr>
//! <th>Chain spec key</th>
//! <th>Description</th>
//! </tr>
//! </thead>
//! <tbody>
//! <tr>
//! <td>name</td>
//! <td>The human readable name of the chain.</td>
//! </tr>
//! <tr>
//! <td>id</td>
//! <td>The id of the chain.</td>
//! </tr>
//! <tr>
//! <td>chainType</td>
//! <td>The chain type of this chain
//! (refer to
//! <a href="enum.ChainType.html" title="enum sc_chain_spec::ChainType">
//! <code>ChainType</code>
//! </a>).
//! </td>
//! </tr>
//! <tr>
//! <td>bootNodes</td>
//! <td>A list of
//! <a href="https://github.com/multiformats/multiaddr">multi addresses</a>
//! that belong to boot nodes of the chain.</td>
//! </tr>
//! <tr>
//! <td>telemetryEndpoints</td>
//! <td>Optional list of <code>multi address, verbosity</code> of telemetry endpoints. The
//! verbosity goes from 0 to 9. With 0 being the mode with the lowest verbosity.</td>
//! </tr>
//! <tr>
//! <td>protocolId</td>
//! <td>Optional networking protocol id that identifies the chain.</td>
//! </tr>
//! <tr>
//! <td>forkId</td>
//! <td>Optional fork id. Should most likely be left empty. Can be used to signal a fork on
//! the network level when two chains have the same genesis hash.</td>
//! </tr>
//! <tr>
//! <td>properties</td>
//! <td>Custom properties. Shall be provided in the form of
//! <code>key</code>-<code>value</code> json object.
//! </td>
//! </tr>
//! <tr>
//! <td>consensusEngine</td>
//! <td>Deprecated field. Should be ignored.</td>
//! </tr>
//! <tr>
//! <td>codeSubstitutes</td>
//! <td>Optional map of <code>block_number</code> to <code>wasm_code</code>. More details in
//! material to follow.</td>
//! </tr>
//! <tr>
//! <td>genesis</td>
//! <td>Defines the initial state of the runtime. More details in material to follow.</td>
//! </tr>
//! </tbody>
//! </table>
//!
//! # `genesis`: Initial Runtime State
//!
//! All nodes in the network must build subsequent blocks upon exactly the same genesis block.
//!
//! The information configured in the `genesis` section of a chain specification is used to build
//! the genesis storage, which is essential for creating the genesis block, since the block header
//! includes the storage root hash.
//!
//! The `genesis` key of the chain specification definition describes the
//! initial state of the runtime. For example, it may contain:
//! - an initial list of funded accounts,
//! - the administrative account that controls the sudo key,
//! - an initial authorities set for consensus, etc.
//!
//! As the compiled WASM blob of the runtime code is stored in the chain's state, the initial
//! runtime must also be provided within the chain specification.
//!
//! In essence, the most important formats of genesis initial state are:
//!
//! <table>
//! <thead>
//! <tr>
//! <th>Format</th>
//! <th>Description</th>
//! </tr>
//! </thead>
//! <tbody>
//! <tr>
//! <td>
//! <code>runtime / full config</code>
//! </td>
//! <td>A JSON object that provides an explicit and comprehensive representation of the
//! <code>RuntimeGenesisConfig</code> struct, which is generated by <a
//! href="../frame_support_procedural/macro.construct_runtime.html"
//! ><code>frame::runtime::prelude::construct_runtime</code></a> macro (<a
//! href="../substrate_test_runtime/struct.RuntimeGenesisConfig.html#"
//! >example of generated struct</a>). Must contain all the keys of
//! the genesis config, no defaults will be used.
//!
//! This format explicitly provides the code of the runtime.
//! </td></tr>
//! <tr>
//! <td>
//! <code>patch</code>
//! </td>
//! <td>A JSON object that offers a partial representation of the
//! <code>RuntimeGenesisConfig</code> provided by the runtime. It contains a patch, which is
//! essentially a list of key-value pairs to customize in the default runtime's
//! <code>RuntimeGenesisConfig</code>.
//! This format explicitly provides the code of the runtime.
//! </td></tr>
//! <tr>
//! <td>
//! <code>raw</code>
//! </td>
//! <td>A JSON object with two fields: <code>top</code> and <code>children_default</code>.
//! Each field is a map of <code>key => value</code> pairs representing entries in a genesis storage
//! trie. The runtime code is one of such entries.</td>
//! </tr>
//! </tbody>
//! </table>
//!
//! For production or long-lasting blockchains, using the `raw` format in the chain specification is
//! recommended. Only the `raw` format guarantees that storage root hash will remain unchanged when
//! the `RuntimeGenesisConfig` format changes due to software upgrade.
//!
//! JSON examples in the [following section](#json-chain-specification-example) illustrate the `raw`
//! `patch` and full genesis fields.
//!
//! # From Initial State to Raw Genesis.
//!
//! To generate a raw genesis storage from the JSON representation of the runtime genesis config,
//! the node needs to interact with the runtime.
//!
//! This interaction involves passing the runtime genesis config JSON blob to the runtime using the
//! [`sp_genesis_builder::GenesisBuilder::build_config`] function. During this operation, the
//! runtime converts the JSON representation of the genesis config into [`sp_io::storage`] items. It
//! is a crucial step for computing the storage root hash, which is a key component in determining
//! the genesis hash.
//!
//! Consequently, the runtime must support the [`sp_genesis_builder::GenesisBuilder`] API to
//! utilize either `patch` or `full` formats.
//!
//! This entire process is encapsulated within the implementation of the [`BuildStorage`] trait,
//! which can be accessed through the [`ChainSpec::as_storage_builder`] method. There is an
//! intermediate internal helper that facilitates this interaction,
//! [`GenesisConfigBuilderRuntimeCaller`], which serves as a straightforward wrapper for
//! [`sc_executor::WasmExecutor`].
//!
//! In case of `raw` genesis state the node does not interact with the runtime regarding the
//! computation of initial state.
//!
//! The plain and `raw` chain specification JSON blobs can be found in
//! [JSON examples](#json-chain-specification-example) section.
//!
//! # Optional Code Mapping
//!
//! Optional map of `block_number` to `wasm_code`.
//!
//! The given `wasm_code` will be used to substitute the on-chain wasm code starting with the
//! given block number until the `spec_version` on-chain changes. The given `wasm_code` should
//! be as close as possible to the on-chain wasm code. A substitute should be used to fix a bug
//! that cannot be fixed with a runtime upgrade, if for example the runtime is constantly
//! panicking. Introducing new runtime APIs isn't supported, because the node
//! will read the runtime version from the on-chain wasm code.
//!
//! Use this functionality only when there is no other way around it, and only patch the problematic
//! bug; the rest should be done with an on-chain runtime upgrade.
//!
//! # Building a Chain Specification
//!
//! The [`ChainSpecBuilder`] should be used to create an instance of a chain specification. Its API
//! allows configuration of all fields of the chain spec. To generate a JSON representation of the
//! specification, use [`ChainSpec::as_json`].
//!
//! The sample code to generate a chain spec is as follows:
#![doc = docify::embed!("src/chain_spec.rs", build_chain_spec_with_patch_works)]
//! # JSON chain specification example
//!
//! The following are the plain and `raw` versions of the chain specification JSON files, resulting
//! from executing of the above [example](#building-a-chain-specification):
//! ```ignore
#![doc = include_str!("../res/substrate_test_runtime_from_patch.json")]
//! ```
//! ```ignore
#![doc = include_str!("../res/substrate_test_runtime_from_patch_raw.json")]
//! ```
//! The following example shows the plain full config version of chain spec:
//! ```ignore
#![doc = include_str!("../res/substrate_test_runtime_from_config.json")]
//! ```
//! The [`ChainSpec`] trait represents the API to access values defined in the JSON chain specification.
//!
//!
//! # Custom Chain Spec Extensions
//!
//! The basic chain spec type containing all required parameters is [`GenericChainSpec`]. It can be
//! extended with additional options containing configuration specific to your chain. Usually, the
//! extension will be a combination of types exposed by Substrate core modules.
//!
//! To allow the core modules to retrieve their configuration from your extension, you should use
//! `ChainSpecExtension` macro exposed by this crate.
//! ```rust
//! use std::collections::HashMap;
//! use sc_chain_spec::{GenericChainSpec, ChainSpecExtension};
//!
//! #[derive(Clone, Debug, serde::Serialize, serde::Deserialize, ChainSpecExtension)]
//! pub struct MyExtension {
//! pub known_blocks: HashMap<u64, String>,
//! pub known_blocks: HashMap<u64, String>,
//! }
//!
//! pub type MyChainSpec<G> = GenericChainSpec<G, MyExtension>;
//! ```
//!
//! Some parameters may require different values depending on the
//! current blockchain height (a.k.a. forks). You can use `ChainSpecGroup`
//! macro and provided [`Forks`](./struct.Forks.html) structure to put
//! such parameters to your chain spec.
//! This will allow to override a single parameter starting at specific
//! block number.
//!
//! Some parameters may require different values depending on the current blockchain height (a.k.a.
//! forks). You can use the [`ChainSpecGroup`](macro@ChainSpecGroup) macro and the provided [`Forks`]
//! structure to add such parameters to your chain spec. This will allow overriding a single
//! parameter starting at a specific block number.
//! ```rust
//! use sc_chain_spec::{Forks, ChainSpecGroup, ChainSpecExtension, GenericChainSpec};
//!
@@ -76,12 +291,9 @@
//! /// A chain spec supporting forkable `Extension`.
//! pub type MyChainSpec2<G> = GenericChainSpec<G, Forks<BlockNumber, Extension>>;
//! ```
//!
//! It's also possible to have a set of parameters that is allowed to change
//! with block numbers (i.e. is forkable), and another set that is not subject to changes.
//! This is also possible by declaring an extension that contains `Forks` within it.
//!
//!
//! It's also possible to have a set of parameters that are allowed to change with block numbers
//! (i.e., they are forkable), and another set that is not subject to changes. This can also be
//! achieved by declaring an extension that contains [`Forks`] within it.
//! ```rust
//! use serde::{Serialize, Deserialize};
//! use sc_chain_spec::{Forks, GenericChainSpec, ChainSpecGroup, ChainSpecExtension};
@@ -106,98 +318,26 @@
//!
//! pub type MyChainSpec<G> = GenericChainSpec<G, Extension>;
//! ```
//!
//! # Substrate chain specification format
//!
//! The Substrate chain specification is a `json` file that describes the basics of a chain. Most
//! importantly it lays out the genesis storage which leads to the genesis hash. The default
//! Substrate chain specification format is the following:
//!
//! ```json
//! // The human readable name of the chain.
//! "name": "Flaming Fir",
//!
//! // The id of the chain.
//! "id": "flamingfir9",
//!
//! // The chain type of this chain.
//! // Possible values are `Live`, `Development`, `Local`.
//! "chainType": "Live",
//!
//! // A list of multi addresses that belong to boot nodes of the chain.
//! "bootNodes": [
//! "/dns/0.flamingfir.paritytech.net/tcp/30333/p2p/12D3KooWLK2gMLhWsYJzjW3q35zAs9FDDVqfqVfVuskiGZGRSMvR",
//! ],
//!
//! // Optional list of "multi address, verbosity" of telemetry endpoints.
//! // The verbosity goes from `0` to `9`. With `0` being the mode with the lowest verbosity.
//! "telemetryEndpoints": [
//! [
//! "/dns/telemetry.polkadot.io/tcp/443/x-parity-wss/%2Fsubmit%2F",
//! 0
//! ]
//! ],
//!
//! // Optional networking protocol id that identifies the chain.
//! "protocolId": "fir9",
//!
//! // Optional fork id. Should most likely be left empty.
//! // Can be used to signal a fork on the network level when two chains have the
//! // same genesis hash.
//! "forkId": "random_fork",
//!
//! // Custom properties.
//! "properties": {
//! "tokenDecimals": 15,
//! "tokenSymbol": "FIR"
//! },
//!
//! // Deprecated field. Should be ignored.
//! "consensusEngine": null,
//!
//! // The genesis declaration of the chain.
//! //
//! // `runtime`, `raw`, `stateRootHash` denote the type of the genesis declaration.
//! //
//! // These declarations are in the following formats:
//! // - `runtime` is a `json` object that can be parsed by a compatible `GenesisConfig`. This
//! // `GenesisConfig` is declared by a runtime and opaque to the node.
//! // - `raw` is a `json` object with two fields `top` and `children_default`. Each of these
//! // fields is a map of `key => value`. These key/value pairs represent the genesis storage.
//! // - `stateRootHash` is a single hex encoded hash that represents the genesis hash. The hash
//! // type depends on the hash used by the chain.
//! //
//! "genesis": { "runtime": {} },
//!
//! /// Optional map of `block_number` to `wasm_code`.
//! ///
//! /// The given `wasm_code` will be used to substitute the on-chain wasm code starting with the
//! /// given block number until the `spec_version` on-chain changes. The given `wasm_code` should
//! /// be as close as possible to the on-chain wasm code. A substitute should be used to fix a bug
//! /// that can not be fixed with a runtime upgrade, if for example the runtime is constantly
//! /// panicking. Introducing new runtime apis isn't supported, because the node
//! /// will read the runtime version from the on-chain wasm code. Use this functionality only when
//! /// there is no other way around it and only patch the problematic bug, the rest should be done
//! /// with a on-chain runtime upgrade.
//! "codeSubstitutes": [],
//! ```
//!
//! See [`ChainSpec`] for a trait representation of the above.
//!
//! The chain spec can be extended with other fields that are opaque to the default chain spec.
//! Specific node implementations will need to be able to deserialize these extensions.
mod chain_spec;
mod extension;
mod genesis;
mod genesis_block;
mod genesis_config_builder;
mod json_patch;
pub use self::{
chain_spec::{ChainSpec as GenericChainSpec, NoExtension},
chain_spec::{
update_code_in_json_chain_spec, ChainSpec as GenericChainSpec, ChainSpecBuilder,
NoExtension,
},
extension::{get_extension, get_extension_mut, Extension, Fork, Forks, GetExtension, Group},
genesis::{
genesis_block::{
construct_genesis_block, resolve_state_version_from_wasm, BuildGenesisBlock,
GenesisBlockBuilder,
},
genesis_config_builder::GenesisConfigBuilderRuntimeCaller,
};
pub use sc_chain_spec_derive::{ChainSpecExtension, ChainSpecGroup};