referrerpolicy=no-referrer-when-downgrade

sc_chain_spec/
lib.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19//! This crate includes structs and utilities for defining configuration files (known as chain
20//! specification) for both runtime and node.
21//!
22//! # Intro: Chain Specification
23//!
24//! The chain specification comprises parameters and settings that define the properties and an
25//! initial state of a chain. Users typically interact with the JSON representation of the chain
26//! spec. Internally, the chain spec is embodied by the [`GenericChainSpec`] struct, and specific
27//! properties can be accessed using the [`ChainSpec`] trait.
28//!
29//! In summary, although not restricted to, the primary role of the chain spec is to provide a list
30//! of well-known boot nodes for the blockchain network and the means for initializing the genesis
31//! storage. This initialization is necessary for creating a genesis block upon which subsequent
32//! blocks are built. When the node is launched for the first time, it reads the chain spec,
33//! initializes the genesis block, and establishes connections with the boot nodes.
34//!
35//! The JSON chain spec is divided into two main logical sections:
36//! - one section details general chain properties,
37//! - second explicitly or indirectly defines the genesis storage, which, in turn, determines the
38//!   genesis hash of the chain,
39//!
40//! The chain specification consists of the following fields:
41//!
42//! <table>
43//!   <thead>
44//!     <tr>
45//!       <th>Chain spec key</th>
46//!       <th>Description</th>
47//!     </tr>
48//!   </thead>
49//!   <tbody>
50//!     <tr>
51//!       <td>name</td>
52//!       <td>The human readable name of the chain.</td>
53//!     </tr>
54//!     <tr>
55//!       <td>id</td>
56//!       <td>The id of the chain.</td>
57//!     </tr>
58//!     <tr>
59//!       <td>chainType</td>
60//!       <td>The chain type of this chain
61//!           (refer to
62//!            <a href="enum.ChainType.html" title="enum sc_chain_spec::ChainType">
63//!              <code>ChainType</code>
64//!            </a>).
65//!       </td>
66//!     </tr>
67//!     <tr>
68//!       <td>bootNodes</td>
69//!       <td>A list of
70//!       <a href="https://github.com/multiformats/multiaddr">multi addresses</a>
71//!       that belong to boot nodes of the chain.</td>
72//!     </tr>
73//!     <tr>
74//!       <td>telemetryEndpoints</td>
75//!       <td>Optional list of <code>multi address, verbosity</code> of telemetry endpoints. The
76//! verbosity goes from 0 to 9. With 0 being the mode with the lowest verbosity.</td>
77//!     </tr>
78//!     <tr>
79//!       <td>protocolId</td>
80//!       <td>Optional networking protocol id that identifies the chain.</td>
81//!     </tr>
82//!     <tr>
83//!       <td>forkId</td>
84//!       <td>Optional fork id. Should most likely be left empty. Can be used to signal a fork on
85//! the network level when two chains have the same genesis hash.</td>
86//!     </tr>
87//!     <tr>
88//!       <td>properties</td>
89//!       <td>Custom properties. Shall be provided in the form of
90//! <code>key</code>-<code>value</code> json object.
91//!     </td>
92//!     </tr>
93//!     <tr>
94//!       <td>consensusEngine</td>
95//!       <td>Deprecated field. Should be ignored.</td>
96//!     </tr>
97//!     <tr>
98//!       <td>codeSubstitutes</td>
99//!       <td>Optional map of <code>block_number</code> to <code>wasm_code</code>. More details in
100//! material to follow.</td>
101//!     </tr>
102//!     <tr>
103//!       <td>genesis</td>
104//!       <td>Defines the initial state of the runtime. More details in material to follow.</td>
105//!     </tr>
106//!   </tbody>
107//! </table>
108//!
109//! # `genesis`: Initial Runtime State
110//!
111//! All nodes in the network must build subsequent blocks upon exactly the same genesis block.
112//!
113//! The information configured in the `genesis` section of a chain specification is used to build
114//! the genesis storage, which is essential for creating the genesis block, since the block header
115//! includes the storage root hash.
116//!
117//! The `genesis` key of the chain specification definition describes the
118//! initial state of the runtime. For example, it may contain:
119//! - an initial list of funded accounts,
120//! - the administrative account that controls the sudo key,
121//! - an initial authorities set for consensus, etc.
122//!
123//! As the compiled WASM blob of the runtime code is stored in the chain's state, the initial
124//! runtime must also be provided within the chain specification.
125//!
126//! # `chain-spec` formats
127//!
128//! In essence, the most important formats of genesis initial state in chain specification files
129//! are:
130//!
131//! <table>
132//!   <thead>
133//!     <tr>
134//!       <th>Format</th>
135//!       <th>Description</th>
136//!     </tr>
137//!   </thead>
138//!   <tbody>
139//!     <tr>
140//!       <td>
141//! 		<code>full config</code>
142//!       </td>
143//!       <td>A JSON object that provides an explicit and comprehensive representation of the
144//! <code>RuntimeGenesisConfig</code> struct, which is generated by <a
145//! href="../frame_support_procedural/macro.construct_runtime.html"
146//! ><code>polkadot_sdk_frame::runtime::prelude::construct_runtime</code></a> macro (<a
147//! href="../substrate_test_runtime/struct.RuntimeGenesisConfig.html#"
148//! >example of generated struct</a>). Must contain *all* the keys of
149//! the genesis config, no defaults will be used.
150//!
151//! This format explicitly provides the code of the runtime.
152//! </td></tr>
153//!     <tr>
154//!       <td>
155//! 		<code>patch</code>
156//!       </td>
157//!       <td>A JSON object that offers a partial representation of the
158//!       <code>RuntimeGenesisConfig</code> provided by the runtime. It contains a patch, which is
159//! essentially a list of key-value pairs to customize in the default runtime's
160//! <code>RuntimeGenesisConfig</code>: `full = default + patch`. Please note that `default`
161//! `RuntimeGenesisConfig` may not be functional.
162//! This format explicitly provides the code of the runtime.
163//! </td></tr>
164//!     <tr>
165//!       <td>
166//! 		<code>raw</code>
167//!       </td>
168//!       <td>A JSON object with two fields: <code>top</code> and <code>children_default</code>.
169//! Each field is a map of <code>key => value</code> pairs representing entries in a genesis storage
170//! trie. The runtime code is one of such entries.</td>
171//!     </tr>
172//!   </tbody>
173//! </table>
174//!
175//! The main purpose of the `RuntimeGenesisConfig` patch is to:
176//! - minimize the maintenance effort when RuntimeGenesisConfig is changed in the future (e.g. new
177//!   pallets added to the runtime or pallet's genesis config changed),
178//! - increase the readability - it only contains the relevant fields,
179//! - allow to apply numerous changes in distinct domains (e.g. for zombienet).
180//!
181//! For production or long-lasting blockchains, using the `raw` format in the chain specification is
182//! recommended. Only the `raw` format guarantees that storage root hash will remain unchanged when
183//! the `RuntimeGenesisConfig` format changes due to software upgrade.
184//!
185//! JSON examples in the [following section](#json-chain-specification-example) illustrate the `raw`
186//! `patch` and full genesis fields.
187//!
188//! # From Initial State to Raw Genesis.
189//!
190//! To generate a raw genesis storage from the JSON representation of the runtime genesis config,
191//! the node needs to interact with the runtime.
192//!
193//! This interaction involves passing the runtime genesis config JSON blob to the runtime using the
194//! [`sp_genesis_builder::GenesisBuilder::build_state`] function. During this operation, the
195//! runtime converts the JSON representation of the genesis config into [`sp_io::storage`] items. It
196//! is a crucial step for computing the storage root hash, which is a key component in determining
197//! the genesis hash.
198//!
199//! Consequently, the runtime must support the [`sp_genesis_builder::GenesisBuilder`] API to
200//! utilize either `patch` or `full` formats.
201//!
202//! This entire process is encapsulated within the implementation of the [`BuildStorage`] trait,
203//! which can be accessed through the [`ChainSpec::as_storage_builder`] method. There is an
204//! intermediate internal helper that facilitates this interaction,
205//! [`GenesisConfigBuilderRuntimeCaller`], which serves as a straightforward wrapper for
206//! [`sc_executor::WasmExecutor`].
207//!
208//! In case of `raw` genesis state the node does not interact with the runtime regarding the
209//! computation of initial state.
210//!
211//! The plain and `raw` chain specification JSON blobs can be found in
212//! [JSON examples](#json-chain-specification-example) section.
213//!
214//! # Optional Code Mapping
215//!
216//! Optional map of `block_number` to `wasm_code`.
217//!
218//! The given `wasm_code` will be used to substitute the on-chain wasm code starting with the
219//! given block number until the `spec_version` on-chain changes. The given `wasm_code` should
220//! be as close as possible to the on-chain wasm code. A substitute should be used to fix a bug
221//! that cannot be fixed with a runtime upgrade, if for example the runtime is constantly
222//! panicking. Introducing new runtime APIs isn't supported, because the node
223//! will read the runtime version from the on-chain wasm code.
224//!
225//! Use this functionality only when there is no other way around it, and only patch the problematic
226//! bug; the rest should be done with an on-chain runtime upgrade.
227//!
228//! # Building a Chain Specification
229//!
230//! The [`ChainSpecBuilder`] should be used to create an instance of a chain specification. Its API
231//! allows configuration of all fields of the chain spec. To generate a JSON representation of the
232//! specification, use [`ChainSpec::as_json`].
233//!
234//! The sample code to generate a chain spec is as follows:
235#![doc = docify::embed!("src/chain_spec.rs", build_chain_spec_with_patch_works)]
236//! # JSON chain specification example
237//!
238//! The following are the plain and `raw` versions of the chain specification JSON files, resulting
239//! from executing of the above [example](#building-a-chain-specification):
240//! ```ignore
241#![doc = include_str!("../res/substrate_test_runtime_from_patch.json")]
242//! ```
243//! ```ignore
244#![doc = include_str!("../res/substrate_test_runtime_from_patch_raw.json")]
245//! ```
246//! The following example shows the plain full config version of chain spec:
247//! ```ignore
248#![doc = include_str!("../res/substrate_test_runtime_from_config.json")]
249//! ```
250//! The [`ChainSpec`] trait represents the API to access values defined in the JSON chain specification.
251//!
252//!
253//! # Custom Chain Spec Extensions
254//!
255//! The basic chain spec type containing all required parameters is [`GenericChainSpec`]. It can be
256//! extended with additional options containing configuration specific to your chain. Usually, the
257//! extension will be a combination of types exposed by Substrate core modules.
258//!
259//! To allow the core modules to retrieve their configuration from your extension, you should use
260//! `ChainSpecExtension` macro exposed by this crate.
261//! ```rust
262//! use std::collections::HashMap;
263//! use sc_chain_spec::{GenericChainSpec, ChainSpecExtension};
264//!
265//! #[derive(Clone, Debug, serde::Serialize, serde::Deserialize, ChainSpecExtension)]
266//! pub struct MyExtension {
267//! 	pub known_blocks: HashMap<u64, String>,
268//! }
269//!
270//! pub type MyChainSpec = GenericChainSpec<MyExtension>;
271//! ```
272//! Some parameters may require different values depending on the current blockchain height (a.k.a.
273//! forks). You can use the [`ChainSpecGroup`](macro@ChainSpecGroup) macro and the provided [`Forks`]
274//! structure to add such parameters to your chain spec. This will allow overriding a single
275//! parameter starting at a specific block number.
276//! ```rust
277//! use sc_chain_spec::{Forks, ChainSpecGroup, ChainSpecExtension, GenericChainSpec};
278//!
279//! #[derive(Clone, Debug, serde::Serialize, serde::Deserialize, ChainSpecGroup)]
280//! pub struct ClientParams {
281//! 	max_block_size: usize,
282//! 	max_extrinsic_size: usize,
283//! }
284//!
285//! #[derive(Clone, Debug, serde::Serialize, serde::Deserialize, ChainSpecGroup)]
286//! pub struct PoolParams {
287//! 	max_transaction_size: usize,
288//! }
289//!
290//! #[derive(Clone, Debug, serde::Serialize, serde::Deserialize, ChainSpecGroup, ChainSpecExtension)]
291//! pub struct Extension {
292//! 	pub client: ClientParams,
293//! 	pub pool: PoolParams,
294//! }
295//!
296//! pub type BlockNumber = u64;
297//!
298//! /// A chain spec supporting forkable `ClientParams`.
299//! pub type MyChainSpec1 = GenericChainSpec<Forks<BlockNumber, ClientParams>>;
300//!
301//! /// A chain spec supporting forkable `Extension`.
302//! pub type MyChainSpec2 = GenericChainSpec<Forks<BlockNumber, Extension>>;
303//! ```
304//! It's also possible to have a set of parameters that are allowed to change with block numbers
305//! (i.e., they are forkable), and another set that is not subject to changes. This can also be
306//! achieved by declaring an extension that contains [`Forks`] within it.
307//! ```rust
308//! use serde::{Serialize, Deserialize};
309//! use sc_chain_spec::{Forks, GenericChainSpec, ChainSpecGroup, ChainSpecExtension};
310//!
311//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup)]
312//! pub struct ClientParams {
313//! 	max_block_size: usize,
314//! 	max_extrinsic_size: usize,
315//! }
316//!
317//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup)]
318//! pub struct PoolParams {
319//! 	max_transaction_size: usize,
320//! }
321//!
322//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecExtension)]
323//! pub struct Extension {
324//! 	pub client: ClientParams,
325//! 	#[forks]
326//! 	pub pool: Forks<u64, PoolParams>,
327//! }
328//!
329//! pub type MyChainSpec = GenericChainSpec<Extension>;
330//! ```
331//! The chain spec can be extended with other fields that are opaque to the default chain spec.
332//! Specific node implementations will need to be able to deserialize these extensions.
333
334mod chain_spec;
335mod extension;
336mod genesis_block;
337mod genesis_config_builder;
338pub mod json_patch;
339
340pub use self::{
341	chain_spec::{
342		set_code_substitute_in_json_chain_spec, update_code_in_json_chain_spec,
343		ChainSpec as GenericChainSpec, ChainSpecBuilder, NoExtension,
344	},
345	extension::{get_extension, get_extension_mut, Extension, Fork, Forks, GetExtension, Group},
346	genesis_block::{
347		construct_genesis_block, resolve_state_version_from_wasm, BuildGenesisBlock,
348		GenesisBlockBuilder,
349	},
350	genesis_config_builder::{
351		GenesisConfigBuilderRuntimeCaller, DEV_RUNTIME_PRESET, LOCAL_TESTNET_RUNTIME_PRESET,
352	},
353	json_patch::merge as json_merge,
354};
355pub use sc_chain_spec_derive::{ChainSpecExtension, ChainSpecGroup};
356
357use sc_network::config::MultiaddrWithPeerId;
358use sc_telemetry::TelemetryEndpoints;
359use sp_core::storage::Storage;
360use sp_runtime::BuildStorage;
361
362/// The type of chain.
363///
364/// This can be used by tools to determine the type of chain for displaying
365/// additional information or enabling additional features.
366#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
367#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
368pub enum ChainType {
369	/// A development chain that runs mainly on one node.
370	Development,
371	/// A local chain that runs locally on multiple nodes for testing purposes.
372	Local,
373	/// A live chain.
374	Live,
375	/// Some custom chain type.
376	#[cfg_attr(feature = "clap", clap(skip))]
377	Custom(String),
378}
379
380impl Default for ChainType {
381	fn default() -> Self {
382		Self::Live
383	}
384}
385
386/// Arbitrary properties defined in chain spec as a JSON object
387pub type Properties = serde_json::map::Map<String, serde_json::Value>;
388
389/// Common interface of a chain specification.
390pub trait ChainSpec: BuildStorage + Send + Sync {
391	/// Spec name.
392	fn name(&self) -> &str;
393	/// Spec id.
394	fn id(&self) -> &str;
395	/// Type of the chain.
396	fn chain_type(&self) -> ChainType;
397	/// A list of bootnode addresses.
398	fn boot_nodes(&self) -> &[MultiaddrWithPeerId];
399	/// Telemetry endpoints (if any)
400	fn telemetry_endpoints(&self) -> &Option<TelemetryEndpoints>;
401	/// Network protocol id.
402	fn protocol_id(&self) -> Option<&str>;
403	/// Optional network fork identifier. `None` by default.
404	fn fork_id(&self) -> Option<&str>;
405	/// Additional loosely-typed properties of the chain.
406	///
407	/// Returns an empty JSON object if 'properties' not defined in config
408	fn properties(&self) -> Properties;
409	/// Returns a reference to the defined chain spec extensions.
410	fn extensions(&self) -> &dyn GetExtension;
411	/// Returns a mutable reference to the defined chain spec extensions.
412	fn extensions_mut(&mut self) -> &mut dyn GetExtension;
413	/// Add a bootnode to the list.
414	fn add_boot_node(&mut self, addr: MultiaddrWithPeerId);
415	/// Return spec as JSON.
416	fn as_json(&self, raw: bool) -> Result<String, String>;
417	/// Return StorageBuilder for this spec.
418	fn as_storage_builder(&self) -> &dyn BuildStorage;
419	/// Returns a cloned `Box<dyn ChainSpec>`.
420	fn cloned_box(&self) -> Box<dyn ChainSpec>;
421	/// Set the storage that should be used by this chain spec.
422	///
423	/// This will be used as storage at genesis.
424	fn set_storage(&mut self, storage: Storage);
425	/// Returns code substitutes that should be used for the on chain wasm.
426	fn code_substitutes(&self) -> std::collections::BTreeMap<String, Vec<u8>>;
427}
428
429impl std::fmt::Debug for dyn ChainSpec {
430	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
431		write!(f, "ChainSpec(name = {:?}, id = {:?})", self.name(), self.id())
432	}
433}