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