referrerpolicy=no-referrer-when-downgrade

polkadot_sdk_docs/guides/
your_first_runtime.rs

1//! # Your first Runtime
2//!
3//! This guide will walk you through the steps to add your pallet to a runtime.
4//!
5//! The good news is, in [`crate::guides::your_first_pallet`], we have already created a _test_
6//! runtime that was used for testing, and a real runtime is not that much different!
7//!
8//! ## Setup
9//!
10//! A runtime shares a few similar setup requirements as with a pallet:
11//!
12//! * importing [`frame`], [`codec`], and [`scale_info`] crates.
13//! * following the [`std` feature-gating](crate::polkadot_sdk::substrate#wasm-build) pattern.
14//!
15//! But, more specifically, it also contains:
16//!
17//! * a `build.rs` that uses [`substrate_wasm_builder`]. This entails declaring
18//!   `[build-dependencies]` in the Cargo manifest file:
19//!
20//! ```ignore
21//! [build-dependencies]
22//! substrate-wasm-builder = { ... }
23//! ```
24//!
25//! >Note that a runtime must always be one-runtime-per-crate. You cannot define multiple runtimes
26//! per rust crate.
27//!
28//! You can find the full code of this guide in [`first_runtime`].
29//!
30//! ## Your First Runtime
31//!
32//! The first new property of a real runtime that it must define its
33//! [`frame::runtime::prelude::RuntimeVersion`]:
34#![doc = docify::embed!("./packages/guides/first-runtime/src/lib.rs", VERSION)]
35//! The version contains a number of very important fields, such as `spec_version` and `spec_name`
36//! that play an important role in identifying your runtime and its version, more importantly in
37//! runtime upgrades. More about runtime upgrades in
38//! [`crate::reference_docs::frame_runtime_upgrades_and_migrations`].
39//!
40//! Then, a real runtime also contains the `impl` of all individual pallets' `trait Config` for
41//! `struct Runtime`, and a [`frame::runtime::prelude::construct_runtime`] macro that amalgamates
42//! them all.
43//!
44//! In the case of our example:
45#![doc = docify::embed!("./packages/guides/first-runtime/src/lib.rs", our_config_impl)]
46//! In this example, we bring in a number of other pallets from [`frame`] into the runtime, each of
47//! their `Config` need to be implemented for `struct Runtime`:
48#![doc = docify::embed!("./packages/guides/first-runtime/src/lib.rs", config_impls)]
49//! Notice how we use [`frame::pallet_macros::derive_impl`] to provide "default" configuration items
50//! for each pallet. Feel free to dive into the definition of each default prelude (eg.
51//! [`frame::prelude::frame_system::pallet::config_preludes`]) to learn more which types are exactly
52//! used.
53//!
54//! Recall that in test runtime in [`crate::guides::your_first_pallet`], we provided `type AccountId
55//! = u64` to `frame_system`, while in this case we rely on whatever is provided by
56//! [`SolochainDefaultConfig`], which is indeed a "real" 32 byte account id.
57//!
58//! Then, a familiar instance of `construct_runtime` amalgamates all of the pallets:
59#![doc = docify::embed!("./packages/guides/first-runtime/src/lib.rs", cr)]
60//! Recall from [`crate::reference_docs::wasm_meta_protocol`] that every (real) runtime needs to
61//! implement a set of runtime APIs that will then let the node to communicate with it. The final
62//! steps of crafting a runtime are related to achieving exactly this.
63//!
64//! First, we define a number of types that eventually lead to the creation of an instance of
65//! [`frame::runtime::prelude::Executive`]. The executive is a handy FRAME utility that, through
66//! amalgamating all pallets and further types, implements some of the very very core pieces of the
67//! runtime logic, such as how blocks are executed and other runtime-api implementations.
68#![doc = docify::embed!("./packages/guides/first-runtime/src/lib.rs", runtime_types)]
69//! Finally, we use [`frame::runtime::prelude::impl_runtime_apis`] to implement all of the runtime
70//! APIs that the runtime wishes to expose. As you will see in the code, most of these runtime API
71//! implementations are merely forwarding calls to `RuntimeExecutive` which handles the actual
72//! logic. Given that the implementation block is somewhat large, we won't repeat it here. You can
73//! look for `impl_runtime_apis!` in [`first_runtime`].
74//!
75//! ```ignore
76//! impl_runtime_apis! {
77//! 	impl apis::Core<Block> for Runtime {
78//! 		fn version() -> RuntimeVersion {
79//! 			VERSION
80//! 		}
81//!
82//! 		fn execute_block(block: Block) {
83//! 			RuntimeExecutive::execute_block(block)
84//! 		}
85//!
86//! 		fn initialize_block(header: &Header) -> ExtrinsicInclusionMode {
87//! 			RuntimeExecutive::initialize_block(header)
88//! 		}
89//! 	}
90//!
91//! 	// many more trait impls...
92//! }
93//! ```
94//!
95//! And that more or less covers the details of how you would write a real runtime!
96//!
97//! Once you compile a crate that contains a runtime as above, simply running `cargo build` will
98//! generate the wasm blobs and place them under `./target/release/wbuild`, as explained
99//! [here](crate::polkadot_sdk::substrate#wasm-build).
100//!
101//! ## Genesis Configuration
102//!
103//! Every runtime specifies a number of runtime APIs that help the outer world (most notably, a
104//! `node`) know what is the genesis state of this runtime. These APIs are then used to generate
105//! what is known as a  **Chain Specification, or chain spec for short**. A chain spec is the
106//! primary way to run a new chain.
107//!
108//! These APIs are defined in [`sp_genesis_builder`], and are re-exposed as a part of
109//! [`frame::runtime::apis`]. Therefore, the implementation blocks can be found inside of
110//! `impl_runtime_apis!` similar to:
111//!
112//! ```ignore
113//! impl_runtime_apis! {
114//!  	impl apis::GenesisBuilder<Block> for Runtime {
115//! 			fn build_state(config: Vec<u8>) -> GenesisBuilderResult {
116//! 				build_state::<RuntimeGenesisConfig>(config)
117//! 			}
118//!
119//! 			fn get_preset(id: &Option<PresetId>) -> Option<Vec<u8>> {
120//! 				get_preset::<RuntimeGenesisConfig>(id, self::genesis_config_presets::get_preset)
121//! 			}
122//!
123//! 			fn preset_names() -> Vec<PresetId> {
124//! 				crate::genesis_config_presets::preset_names()
125//! 			}
126//! 		}
127//!
128//! }
129//! ```
130//!
131//! The implementation of these function can naturally vary from one runtime to the other, but the
132//! overall pattern is common. For the case of this runtime, we do the following:
133//!
134//! 1. Expose one non-default preset, namely [`sp_genesis_builder::DEV_RUNTIME_PRESET`]. This means
135//!    our runtime has two "presets" of genesis state in total: `DEV_RUNTIME_PRESET` and `None`.
136#![doc = docify::embed!("./packages/guides/first-runtime/src/lib.rs", preset_names)]
137//! For `build_state` and `get_preset`, we use the helper functions provide by frame:
138//!
139//! * [`frame::runtime::prelude::build_state`] and [`frame::runtime::prelude::get_preset`].
140//!
141//! Indeed, our runtime needs to specify what its `DEV_RUNTIME_PRESET` genesis state should be like:
142#![doc = docify::embed!("./packages/guides/first-runtime/src/lib.rs", development_config_genesis)]
143//! For more in-depth information about `GenesisConfig`, `ChainSpec`, the `GenesisBuilder` API and
144//! `chain-spec-builder`, see [`crate::reference_docs::chain_spec_genesis`].
145//!
146//! ## Next Step
147//!
148//! See [`crate::guides::your_first_node`].
149//!
150//! ## Further Reading
151//!
152//! 1. To learn more about signed extensions, see [`crate::reference_docs::signed_extensions`].
153//! 2. `AllPalletsWithSystem` is also generated by `construct_runtime`, as explained in
154//!    [`crate::reference_docs::frame_runtime_types`].
155//! 3. `Executive` supports more generics, most notably allowing the runtime to configure more
156//!    runtime migrations, as explained in
157//!    [`crate::reference_docs::frame_runtime_upgrades_and_migrations`].
158//! 4. Learn more about adding and implementing runtime apis in
159//!    [`crate::reference_docs::custom_runtime_api_rpc`].
160//! 5. To see a complete example of a runtime+pallet that is similar to this guide, please see
161//!    [`crate::polkadot_sdk::templates`].
162//!
163//! [`SolochainDefaultConfig`]: struct@frame_system::pallet::config_preludes::SolochainDefaultConfig
164
165#[cfg(test)]
166mod tests {
167	use cmd_lib::run_cmd;
168
169	const FIRST_RUNTIME: &'static str = "polkadot-sdk-docs-first-runtime";
170
171	#[docify::export_content]
172	#[test]
173	fn build_runtime() {
174		run_cmd!(
175			cargo build --release -p $FIRST_RUNTIME
176		)
177		.expect("Failed to run command");
178	}
179}