#
pezkuwi_sdk_docs/guides/
your_first_runtime.rs

    1//! # Your first Runtime
    2//!
    3//! This guide will walk you through the steps to add your pezpallet 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 pezpallet:
    11//!
    12//! * importing [`frame`], [`codec`], and [`scale_info`] crates.
    13//! * following the [`std` feature-gating](crate::pezkuwi_sdk::bizinikiwi#wasm-build) pattern.
    14//!
    15//! But, more specifically, it also contains:
    16//!
    17//! * a `build.rs` that uses [`bizinikiwi_wasm_builder`]. This entails declaring
    18//!   `[build-dependencies]` in the Cargo manifest file:
    19//!
    20//! ```ignore
    21//! [build-dependencies]
    22//! bizinikiwi-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//! [`pezframe::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 [`pezframe::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 [`pezframe::pezpallet_macros::derive_impl`] to provide "default" configuration
    53//! items for each pezpallet. Feel free to dive into the definition of each default prelude (eg.
    54//! [`pezframe::prelude::pezframe_system::pezpallet::config_preludes`]) to learn more which types are
    55//! exactly used.
    56//!
    57//! Recall that in test runtime in [`crate::guides::your_first_pallet`], we provided `type AccountId
    58//! = u64` to `pezframe_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//! [`pezframe::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 [`pezframe::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::pezkuwi_sdk::bizinikiwi#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 [`pezsp_genesis_builder`], and are re-exposed as a part of
    114//! [`pezframe::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 [`pezsp_genesis_builder::DEV_RUNTIME_PRESET`]. This
    140//!    means our runtime has two "presets" of genesis state in total: `DEV_RUNTIME_PRESET` and
    141//!    `None`.
    142#![doc = docify::embed!("./packages/guides/first-runtime/src/lib.rs", preset_names)]
    143//!
    144//! For `build_state` and `get_preset`, we use the helper functions provide by frame:
    145//!
    146//! * [`pezframe::runtime::prelude::build_state`] and [`pezframe::runtime::prelude::get_preset`].
    147//!
    148//! Indeed, our runtime needs to specify what its `DEV_RUNTIME_PRESET` genesis state should be like:
    149#![doc = docify::embed!("./packages/guides/first-runtime/src/lib.rs", development_config_genesis)]
    150//!
    151//! For more in-depth information about `GenesisConfig`, `ChainSpec`, the `GenesisBuilder` API and
    152//! `chain-spec-builder`, see [`crate::reference_docs::chain_spec_genesis`].
    153//!
    154//! ## Next Step
    155//!
    156//! See [`crate::guides::your_first_node`].
    157//!
    158//! ## Further Reading
    159//!
    160//! 1. To learn more about signed extensions, see [`crate::reference_docs::signed_extensions`].
    161//! 2. `AllPalletsWithSystem` is also generated by `construct_runtime`, as explained in
    162//!    [`crate::reference_docs::frame_runtime_types`].
    163//! 3. `Executive` supports more generics, most notably allowing the runtime to configure more
    164//!    runtime migrations, as explained in
    165//!    [`crate::reference_docs::frame_runtime_upgrades_and_migrations`].
    166//! 4. Learn more about adding and implementing runtime apis in
    167//!    [`crate::reference_docs::custom_runtime_api_rpc`].
    168//! 5. To see a complete example of a runtime+pezpallet that is similar to this guide, please see
    169//!    [`crate::pezkuwi_sdk::templates`].
    170//!
    171//! [`SolochainDefaultConfig`]: struct@pezframe_system::pezpallet::config_preludes::SolochainDefaultConfig
    172//! [`frame`]: crate::pezkuwi_sdk::frame_runtime
    173
    174#[cfg(test)]
    175mod tests {
    176	use cmd_lib::run_cmd;
    177
    178	const FIRST_RUNTIME: &'static str = "pezkuwi-sdk-docs-first-runtime";
    179
    180	#[docify::export_content]
    181	#[test]
    182	fn build_runtime() {
    183		run_cmd!(
    184			cargo build --release -p $FIRST_RUNTIME
    185		)
    186		.expect("Failed to run command");
    187	}
    188}