::ExistentialDeposit;
+}
diff --git a/docs/sdk/src/guides/enable_elastic_scaling_mvp.rs b/docs/sdk/src/guides/enable_elastic_scaling_mvp.rs
index 812e674d163b..2339088abed4 100644
--- a/docs/sdk/src/guides/enable_elastic_scaling_mvp.rs
+++ b/docs/sdk/src/guides/enable_elastic_scaling_mvp.rs
@@ -70,10 +70,11 @@
//! - Ensure enough coretime is assigned to the parachain. For maximum throughput the upper bound is
//! 3 cores.
//!
-//! Phase 1 is not needed if using the polkadot-parachain
binary
-//! built from the latest polkadot-sdk release! Simply pass the
-//! --experimental-use-slot-based
parameter to the command line and jump to Phase
-//! 2.
+//! Phase 1 is NOT needed if using the polkadot-parachain
or
+//! polkadot-omni-node
binary, or polkadot-omni-node-lib
built from the
+//! latest polkadot-sdk release! Simply pass the --experimental-use-slot-based
+//! ([`polkadot_omni_node_lib::cli::Cli::experimental_use_slot_based`]) parameter to the command
+//! line and jump to Phase 2.
//!
//! The following steps assume using the cumulus parachain template.
//!
diff --git a/docs/sdk/src/guides/mod.rs b/docs/sdk/src/guides/mod.rs
index a7fd146ccdf3..747128a728d0 100644
--- a/docs/sdk/src/guides/mod.rs
+++ b/docs/sdk/src/guides/mod.rs
@@ -1,14 +1,22 @@
//! # Polkadot SDK Docs Guides
//!
-//! This crate contains a collection of guides that are foundational to the developers of Polkadot
-//! SDK. They are common user-journeys that are traversed in the Polkadot ecosystem.
+//! This crate contains a collection of guides that are foundational to the developers of
+//! Polkadot SDK. They are common user-journeys that are traversed in the Polkadot ecosystem.
//!
-//! 1. [`crate::guides::your_first_pallet`] is your starting point with Polkadot SDK. It contains
-//! the basics of
-//! building a simple crypto currency with FRAME.
-//! 2. [`crate::guides::your_first_runtime`] is the next step in your journey. It contains the
-//! basics of building a runtime that contains this pallet, plus a few common pallets from FRAME.
+//! The main user-journey covered by these guides is:
//!
+//! * [`your_first_pallet`], where you learn what a FRAME pallet is, and write your first
+//! application logic.
+//! * [`your_first_runtime`], where you learn how to compile your pallets into a WASM runtime.
+//! * [`your_first_node`], where you learn how to run the said runtime in a node.
+//!
+//! > By this step, you have already launched a full Polkadot-SDK-based blockchain!
+//!
+//! Once done, feel free to step up into one of our templates: [`crate::polkadot_sdk::templates`].
+//!
+//! [`your_first_pallet`]: crate::guides::your_first_pallet
+//! [`your_first_runtime`]: crate::guides::your_first_runtime
+//! [`your_first_node`]: crate::guides::your_first_node
//!
//! Other guides are related to other miscellaneous topics and are listed as modules below.
@@ -19,19 +27,12 @@ pub mod your_first_pallet;
/// compiling it to [WASM](crate::polkadot_sdk::substrate#wasm-build).
pub mod your_first_runtime;
-// /// Running the given runtime with a node. No specific consensus mechanism is used at this stage.
-// TODO
-// pub mod your_first_node;
-
-// /// How to enhance a given runtime and node to be cumulus-enabled, run it as a parachain
-// /// and connect it to a relay-chain.
-// TODO
-// pub mod cumulus_enabled_parachain;
+/// Running the given runtime with a node. No specific consensus mechanism is used at this stage.
+pub mod your_first_node;
-// /// How to make a given runtime XCM-enabled, capable of sending messages (`Transact`) between
-// /// itself and the relay chain to which it is connected.
-// TODO
-// pub mod xcm_enabled_parachain;
+/// How to enhance a given runtime and node to be cumulus-enabled, run it as a parachain
+/// and connect it to a relay-chain.
+// pub mod your_first_parachain;
/// How to enable storage weight reclaiming in a parachain node and runtime.
pub mod enable_pov_reclaim;
diff --git a/docs/sdk/src/guides/your_first_node.rs b/docs/sdk/src/guides/your_first_node.rs
index d12349c99063..da37c11c206f 100644
--- a/docs/sdk/src/guides/your_first_node.rs
+++ b/docs/sdk/src/guides/your_first_node.rs
@@ -1 +1,314 @@
//! # Your first Node
+//!
+//! In this guide, you will learn how to run a runtime, such as the one created in
+//! [`your_first_runtime`], in a node. Within the context of this guide, we will focus on running
+//! the runtime with an [`omni-node`]. Please first read this page to learn about the OmniNode, and
+//! other options when it comes to running a node.
+//!
+//! [`your_first_runtime`] is a runtime with no consensus related code, and therefore can only be
+//! executed with a node that also expects no consensus ([`sc_consensus_manual_seal`]).
+//! `polkadot-omni-node`'s [`--dev-block-time`] precisely does this.
+//!
+//! > All of the following steps are coded as unit tests of this module. Please see `Source` of the
+//! > page for more information.
+//!
+//! ## Running The Omni Node
+//!
+//! ### Installs
+//!
+//! The `polkadot-omni-node` can either be downloaded from the latest [Release](https://github.com/paritytech/polkadot-sdk/releases/) of `polkadot-sdk`,
+//! or installed using `cargo`:
+//!
+//! ```text
+//! cargo install polkadot-omni-node
+//! ```
+//!
+//! Next, we need to install the [`chain-spec-builder`]. This is the tool that allows us to build
+//! chain-specifications, through interacting with the genesis related APIs of the runtime, as
+//! described in [`crate::guides::your_first_runtime#genesis-configuration`].
+//!
+//! ```text
+//! cargo install staging-chain-spec-builder
+//! ```
+//!
+//! > The name of the crate is prefixed with `staging` as the crate name `chain-spec-builder` on
+//! > crates.io is already taken and is not controlled by `polkadot-sdk` developers.
+//!
+//! ### Building Runtime
+//!
+//! Next, we need to build the corresponding runtime that we wish to interact with.
+//!
+//! ```text
+//! cargo build --release -p path-to-runtime
+//! ```
+//! Equivalent code in tests:
+#![doc = docify::embed!("./src/guides/your_first_node.rs", build_runtime)]
+//!
+//! This creates the wasm file under `./target/{release}/wbuild/release` directory.
+//!
+//! ### Building Chain Spec
+//!
+//! Next, we can generate the corresponding chain-spec file. For this example, we will use the
+//! `development` (`sp_genesis_config::DEVELOPMENT`) preset.
+//!
+//! Note that we intend to run this chain-spec with `polkadot-omni-node`, which is tailored for
+//! running parachains. This requires the chain-spec to always contain the `para_id` and a
+//! `relay_chain` fields, which are provided below as CLI arguments.
+//!
+//! ```text
+//! chain-spec-builder \
+//! -c \
+//! create \
+//! --para-id 42 \
+//! --relay-chain dontcare \
+//! --runtime polkadot_sdk_docs_first_runtime.wasm \
+//! named-preset development
+//! ```
+//!
+//! Equivalent code in tests:
+#![doc = docify::embed!("./src/guides/your_first_node.rs", csb)]
+//!
+//!
+//! ### Running `polkadot-omni-node`
+//!
+//! Finally, we can run the node with the generated chain-spec file. We can also specify the block
+//! time using the `--dev-block-time` flag.
+//!
+//! ```text
+//! polkadot-omni-node \
+//! --tmp \
+//! --dev-block-time 1000 \
+//! --chain .json
+//! ```
+//!
+//! > Note that we always prefer to use `--tmp` for testing, as it will save the chain state to a
+//! > temporary folder, allowing the chain-to be easily restarted without `purge-chain`. See
+//! > [`sc_cli::commands::PurgeChainCmd`] and [`sc_cli::commands::RunCmd::tmp`] for more info.
+//!
+//! This will start the node and import the blocks. Note while using `--dev-block-time`, the node
+//! will use the testing-specific manual-seal consensus. This is an efficient way to test the
+//! application logic of your runtime, without needing to yet care about consensus, block
+//! production, relay-chain and so on.
+//!
+//! ### Next Steps
+//!
+//! * See the rest of the steps in [`crate::reference_docs::omni_node#user-journey`].
+//!
+//! [`runtime`]: crate::reference_docs::glossary#runtime
+//! [`node`]: crate::reference_docs::glossary#node
+//! [`build_config`]: first_runtime::Runtime#method.build_config
+//! [`omni-node`]: crate::reference_docs::omni_node
+//! [`--dev-block-time`]: (polkadot_omni_node_lib::cli::Cli::dev_block_time)
+
+#[cfg(test)]
+mod tests {
+ use assert_cmd::Command;
+ use rand::Rng;
+ use sc_chain_spec::{DEV_RUNTIME_PRESET, LOCAL_TESTNET_RUNTIME_PRESET};
+ use sp_genesis_builder::PresetId;
+ use std::path::PathBuf;
+
+ const PARA_RUNTIME: &'static str = "parachain-template-runtime";
+ const FIRST_RUNTIME: &'static str = "polkadot-sdk-docs-first-runtime";
+ const MINIMAL_RUNTIME: &'static str = "minimal-template-runtime";
+
+ const CHAIN_SPEC_BUILDER: &'static str = "chain-spec-builder";
+ const OMNI_NODE: &'static str = "polkadot-omni-node";
+
+ fn cargo() -> Command {
+ Command::new(std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()))
+ }
+
+ fn get_target_directory() -> Option {
+ let output = cargo().arg("metadata").arg("--format-version=1").output().ok()?;
+
+ if !output.status.success() {
+ return None;
+ }
+
+ let metadata: serde_json::Value = serde_json::from_slice(&output.stdout).ok()?;
+ let target_directory = metadata["target_directory"].as_str()?;
+
+ Some(PathBuf::from(target_directory))
+ }
+
+ fn find_release_binary(name: &str) -> Option {
+ let target_dir = get_target_directory()?;
+ let release_path = target_dir.join("release").join(name);
+
+ if release_path.exists() {
+ Some(release_path)
+ } else {
+ None
+ }
+ }
+
+ fn find_wasm(runtime_name: &str) -> Option {
+ let target_dir = get_target_directory()?;
+ let wasm_path = target_dir
+ .join("release")
+ .join("wbuild")
+ .join(runtime_name)
+ .join(format!("{}.wasm", runtime_name.replace('-', "_")));
+
+ if wasm_path.exists() {
+ Some(wasm_path)
+ } else {
+ None
+ }
+ }
+
+ fn maybe_build_runtimes() {
+ if find_wasm(&PARA_RUNTIME).is_none() {
+ println!("Building parachain-template-runtime...");
+ Command::new("cargo")
+ .arg("build")
+ .arg("--release")
+ .arg("-p")
+ .arg(PARA_RUNTIME)
+ .assert()
+ .success();
+ }
+ if find_wasm(&FIRST_RUNTIME).is_none() {
+ println!("Building polkadot-sdk-docs-first-runtime...");
+ #[docify::export_content]
+ fn build_runtime() {
+ Command::new("cargo")
+ .arg("build")
+ .arg("--release")
+ .arg("-p")
+ .arg(FIRST_RUNTIME)
+ .assert()
+ .success();
+ }
+ build_runtime()
+ }
+
+ assert!(find_wasm(PARA_RUNTIME).is_some());
+ assert!(find_wasm(FIRST_RUNTIME).is_some());
+ }
+
+ fn maybe_build_chain_spec_builder() {
+ if find_release_binary(CHAIN_SPEC_BUILDER).is_none() {
+ println!("Building chain-spec-builder...");
+ Command::new("cargo")
+ .arg("build")
+ .arg("--release")
+ .arg("-p")
+ .arg("staging-chain-spec-builder")
+ .assert()
+ .success();
+ }
+ assert!(find_release_binary(CHAIN_SPEC_BUILDER).is_some());
+ }
+
+ fn maybe_build_omni_node() {
+ if find_release_binary(OMNI_NODE).is_none() {
+ println!("Building polkadot-omni-node...");
+ Command::new("cargo")
+ .arg("build")
+ .arg("--release")
+ .arg("-p")
+ .arg("polkadot-omni-node")
+ .assert()
+ .success();
+ }
+ }
+
+ fn test_runtime_preset(runtime: &'static str, block_time: u64, maybe_preset: Option) {
+ sp_tracing::try_init_simple();
+ maybe_build_runtimes();
+ maybe_build_chain_spec_builder();
+ maybe_build_omni_node();
+
+ let chain_spec_builder =
+ find_release_binary(&CHAIN_SPEC_BUILDER).expect("we built it above; qed");
+ let omni_node = find_release_binary(OMNI_NODE).expect("we built it above; qed");
+ let runtime_path = find_wasm(runtime).expect("we built it above; qed");
+
+ let random_seed: u32 = rand::thread_rng().gen();
+ let chain_spec_file = std::env::current_dir()
+ .unwrap()
+ .join(format!("{}_{}_{}.json", runtime, block_time, random_seed));
+
+ Command::new(chain_spec_builder)
+ .args(["-c", chain_spec_file.to_str().unwrap()])
+ .arg("create")
+ .args(["--para-id", "1000", "--relay-chain", "dontcare"])
+ .args(["-r", runtime_path.to_str().unwrap()])
+ .args(match maybe_preset {
+ Some(preset) => vec!["named-preset".to_string(), preset.to_string()],
+ None => vec!["default".to_string()],
+ })
+ .assert()
+ .success();
+
+ let output = Command::new(omni_node)
+ .arg("--tmp")
+ .args(["--chain", chain_spec_file.to_str().unwrap()])
+ .args(["--dev-block-time", block_time.to_string().as_str()])
+ .timeout(std::time::Duration::from_secs(10))
+ .output()
+ .unwrap();
+
+ std::fs::remove_file(chain_spec_file).unwrap();
+
+ // uncomment for debugging.
+ // println!("output: {:?}", output);
+
+ let expected_blocks = (10_000 / block_time).saturating_div(2);
+ assert!(expected_blocks > 0, "test configuration is bad, should give it more time");
+ assert!(String::from_utf8(output.stderr)
+ .unwrap()
+ .contains(format!("Imported #{}", expected_blocks).to_string().as_str()));
+ }
+
+ #[test]
+ fn works_with_different_block_times() {
+ test_runtime_preset(PARA_RUNTIME, 100, Some(DEV_RUNTIME_PRESET.into()));
+ test_runtime_preset(PARA_RUNTIME, 3000, Some(DEV_RUNTIME_PRESET.into()));
+
+ // we need this snippet just for docs
+ #[docify::export_content(csb)]
+ fn build_para_chain_spec_works() {
+ let chain_spec_builder = find_release_binary(&CHAIN_SPEC_BUILDER).unwrap();
+ let runtime_path = find_wasm(PARA_RUNTIME).unwrap();
+ let output = "/tmp/demo-chain-spec.json";
+ Command::new(chain_spec_builder)
+ .args(["-c", output])
+ .arg("create")
+ .args(["--para-id", "1000", "--relay-chain", "dontcare"])
+ .args(["-r", runtime_path.to_str().unwrap()])
+ .args(["named-preset", "development"])
+ .assert()
+ .success();
+ std::fs::remove_file(output).unwrap();
+ }
+ build_para_chain_spec_works();
+ }
+
+ #[test]
+ fn parachain_runtime_works() {
+ // TODO: None doesn't work. But maybe it should? it would be misleading as many users might
+ // use it.
+ [Some(DEV_RUNTIME_PRESET.into()), Some(LOCAL_TESTNET_RUNTIME_PRESET.into())]
+ .into_iter()
+ .for_each(|preset| {
+ test_runtime_preset(PARA_RUNTIME, 1000, preset);
+ });
+ }
+
+ #[test]
+ fn minimal_runtime_works() {
+ [None, Some(DEV_RUNTIME_PRESET.into())].into_iter().for_each(|preset| {
+ test_runtime_preset(MINIMAL_RUNTIME, 1000, preset);
+ });
+ }
+
+ #[test]
+ fn guide_first_runtime_works() {
+ [Some(DEV_RUNTIME_PRESET.into())].into_iter().for_each(|preset| {
+ test_runtime_preset(FIRST_RUNTIME, 1000, preset);
+ });
+ }
+}
diff --git a/docs/sdk/src/guides/your_first_pallet/mod.rs b/docs/sdk/src/guides/your_first_pallet/mod.rs
index fcfaab00e552..aef8981b4d4a 100644
--- a/docs/sdk/src/guides/your_first_pallet/mod.rs
+++ b/docs/sdk/src/guides/your_first_pallet/mod.rs
@@ -47,7 +47,7 @@
//!
//! [`pallet::config`] and [`pallet::pallet`] are both mandatory parts of any
//! pallet. Refer to the documentation of each to get an overview of what they do.
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", shell_pallet)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", shell_pallet)]
//!
//! All of the code that follows in this guide should live inside of the `mod pallet`.
//!
@@ -61,17 +61,17 @@
//! > For the rest of this guide, we will opt for a balance type of `u128`. For the sake of
//! > simplicity, we are hardcoding this type. In a real pallet is best practice to define it as a
//! > generic bounded type in the `Config` trait, and then specify it in the implementation.
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", Balance)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", Balance)]
//!
//! The definition of these two storage items, based on [`pallet::storage`] details, is as follows:
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", TotalIssuance)]
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", Balances)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", TotalIssuance)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", Balances)]
//!
//! ### Dispatchables
//!
//! Next, we will define the dispatchable functions. As per [`pallet::call`], these will be defined
//! as normal `fn`s attached to `struct Pallet`.
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", impl_pallet)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", impl_pallet)]
//!
//! The logic of these functions is self-explanatory. Instead, we will focus on the FRAME-related
//! details:
@@ -108,14 +108,14 @@
//! How we handle error in the above snippets is fairly rudimentary. Let's look at how this can be
//! improved. First, we can use [`frame::prelude::ensure`] to express the error slightly better.
//! This macro will call `.into()` under the hood.
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", transfer_better)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", transfer_better)]
//!
//! Moreover, you will learn in the [Defensive Programming
//! section](crate::reference_docs::defensive_programming) that it is always recommended to use
//! safe arithmetic operations in your runtime. By using [`frame::traits::CheckedSub`], we can not
//! only take a step in that direction, but also improve the error handing and make it slightly more
//! ergonomic.
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", transfer_better_checked)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", transfer_better_checked)]
//!
//! This is more or less all the logic that there is in this basic currency pallet!
//!
@@ -145,7 +145,7 @@
//! through [`frame::runtime::prelude::construct_runtime`]. All runtimes also have to include
//! [`frame::prelude::frame_system`]. So we expect to see a runtime with two pallet, `frame_system`
//! and the one we just wrote.
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", runtime)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", runtime)]
//!
//! > [`frame::pallet_macros::derive_impl`] is a FRAME feature that enables developers to have
//! > defaults for associated types.
@@ -182,7 +182,7 @@
//! to learn is that all of your pallet testing code should be wrapped in
//! [`frame::testing_prelude::TestState`]. This is a type that provides access to an in-memory state
//! to be used in our tests.
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", first_test)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", first_test)]
//!
//! In the first test, we simply assert that there is no total issuance, and no balance associated
//! with Alice's account. Then, we mint some balance into Alice's, and re-check.
@@ -206,16 +206,16 @@
//!
//! Let's see how we can implement a better test setup using this pattern. First, we define a
//! `struct StateBuilder`.
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", StateBuilder)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", StateBuilder)]
//!
//! This struct is meant to contain the same list of accounts and balances that we want to have at
//! the beginning of each block. We hardcoded this to `let accounts = vec![(ALICE, 100), (2, 100)];`
//! so far. Then, if desired, we attach a default value for this struct.
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", default_state_builder)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", default_state_builder)]
//!
//! Like any other builder pattern, we attach functions to the type to mutate its internal
//! properties.
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", impl_state_builder_add)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", impl_state_builder_add)]
//!
//! Finally --the useful part-- we write our own custom `build_and_execute` function on
//! this type. This function will do multiple things:
@@ -227,23 +227,23 @@
//! after each test. For example, in this test, we do some additional checking about the
//! correctness of the `TotalIssuance`. We leave it up to you as an exercise to learn why the
//! assertion should always hold, and how it is checked.
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", impl_state_builder_build)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", impl_state_builder_build)]
//!
//! We can write tests that specifically check the initial state, and making sure our `StateBuilder`
//! is working exactly as intended.
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", state_builder_works)]
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", state_builder_add_balance)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", state_builder_works)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", state_builder_add_balance)]
//!
//! ### More Tests
//!
//! Now that we have a more ergonomic test setup, let's see how a well written test for transfer and
//! mint would look like.
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", transfer_works)]
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", mint_works)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", transfer_works)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", mint_works)]
//!
//! It is always a good idea to build a mental model where you write *at least* one test for each
//! "success path" of a dispatchable, and one test for each "failure path", such as:
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", transfer_from_non_existent_fails)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", transfer_from_non_existent_fails)]
//!
//! We leave it up to you to write a test that triggers the `InsufficientBalance` error.
//!
@@ -272,8 +272,8 @@
//! With the explanation out of the way, let's see how these components can be added. Both follow a
//! fairly familiar syntax: normal Rust enums, with extra [`pallet::event`] and [`pallet::error`]
//! attributes attached.
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", Event)]
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", Error)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", Event)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", Error)]
//!
//! One slightly custom part of this is the [`pallet::generate_deposit`] part. Without going into
//! too much detail, in order for a pallet to emit events to the rest of the system, it needs to do
@@ -288,17 +288,17 @@
//! 2. But, doing this conversion and storing is too much to expect each pallet to define. FRAME
//! provides a default way of storing events, and this is what [`pallet::generate_deposit`] is
//! doing.
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", config_v2)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", config_v2)]
//!
//! > These `Runtime*` types are better explained in
//! > [`crate::reference_docs::frame_runtime_types`].
//!
//! Then, we can rewrite the `transfer` dispatchable as such:
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", transfer_v2)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", transfer_v2)]
//!
//! Then, notice how now we would need to provide this `type RuntimeEvent` in our test runtime
//! setup.
-#![doc = docify::embed!("./src/guides/your_first_pallet/mod.rs", runtime_v2)]
+#![doc = docify::embed!("./packages/guides/first-pallet/src/lib.rs", runtime_v2)]
//!
//! In this snippet, the actual `RuntimeEvent` type (right hand side of `type RuntimeEvent =
//! RuntimeEvent`) is generated by
diff --git a/docs/sdk/src/guides/your_first_pallet/with_event.rs b/docs/sdk/src/guides/your_first_pallet/with_event.rs
deleted file mode 100644
index a5af29c9c319..000000000000
--- a/docs/sdk/src/guides/your_first_pallet/with_event.rs
+++ /dev/null
@@ -1,101 +0,0 @@
-#[frame::pallet(dev_mode)]
-pub mod pallet {
- use frame::prelude::*;
-
- #[docify::export]
- pub type Balance = u128;
-
- #[pallet::config]
- pub trait Config: frame_system::Config {}
-
- #[pallet::pallet]
- pub struct Pallet(_);
-
- #[docify::export]
- /// Single storage item, of type `Balance`.
- #[pallet::storage]
- pub type TotalIssuance = StorageValue<_, Balance>;
-
- #[docify::export]
- /// A mapping from `T::AccountId` to `Balance`
- #[pallet::storage]
- pub type Balances = StorageMap<_, _, T::AccountId, Balance>;
-
- #[docify::export(impl_pallet)]
- #[pallet::call]
- impl Pallet {
- /// An unsafe mint that can be called by anyone. Not a great idea.
- pub fn mint_unsafe(
- origin: T::RuntimeOrigin,
- dest: T::AccountId,
- amount: Balance,
- ) -> DispatchResult {
- // ensure that this is a signed account, but we don't really check `_anyone`.
- let _anyone = ensure_signed(origin)?;
-
- // update the balances map. Notice how all `` remains as ``.
- Balances::::mutate(dest, |b| *b = Some(b.unwrap_or(0) + amount));
- // update total issuance.
- TotalIssuance::::mutate(|t| *t = Some(t.unwrap_or(0) + amount));
-
- Ok(())
- }
-
- /// Transfer `amount` from `origin` to `dest`.
- pub fn transfer(
- origin: T::RuntimeOrigin,
- dest: T::AccountId,
- amount: Balance,
- ) -> DispatchResult {
- let sender = ensure_signed(origin)?;
-
- // ensure sender has enough balance, and if so, calculate what is left after `amount`.
- let sender_balance = Balances::::get(&sender).ok_or("NonExistentAccount")?;
- if sender_balance < amount {
- return Err("NotEnoughBalance".into())
- }
- let remainder = sender_balance - amount;
-
- // update sender and dest balances.
- Balances::::mutate(dest, |b| *b = Some(b.unwrap_or(0) + amount));
- Balances::::insert(&sender, remainder);
-
- Ok(())
- }
- }
-
- #[allow(unused)]
- impl Pallet {
- #[docify::export]
- pub fn transfer_better(
- origin: T::RuntimeOrigin,
- dest: T::AccountId,
- amount: Balance,
- ) -> DispatchResult {
- let sender = ensure_signed(origin)?;
-
- let sender_balance = Balances::::get(&sender).ok_or("NonExistentAccount")?;
- ensure!(sender_balance >= amount, "NotEnoughBalance");
- let remainder = sender_balance - amount;
-
- // .. snip
- Ok(())
- }
-
- #[docify::export]
- /// Transfer `amount` from `origin` to `dest`.
- pub fn transfer_better_checked(
- origin: T::RuntimeOrigin,
- dest: T::AccountId,
- amount: Balance,
- ) -> DispatchResult {
- let sender = ensure_signed(origin)?;
-
- let sender_balance = Balances::::get(&sender).ok_or("NonExistentAccount")?;
- let remainder = sender_balance.checked_sub(amount).ok_or("NotEnoughBalance")?;
-
- // .. snip
- Ok(())
- }
- }
-}
diff --git a/docs/sdk/src/guides/your_first_runtime.rs b/docs/sdk/src/guides/your_first_runtime.rs
index c58abc1120c1..79f01e66979a 100644
--- a/docs/sdk/src/guides/your_first_runtime.rs
+++ b/docs/sdk/src/guides/your_first_runtime.rs
@@ -1,3 +1,170 @@
//! # Your first Runtime
//!
-//! 🚧
+//! This guide will walk you through the steps to add your pallet to a runtime.
+//!
+//! The good news is, in [`crate::guides::your_first_pallet`], we have already created a _test_
+//! runtime that was used for testing, and a real runtime is not that much different!
+//!
+//! ## Setup
+//!
+//! A runtime shares a few similar setup requirements as with a pallet:
+//!
+//! * importing [`frame`], [`codec`], and [`scale_info`] crates.
+//! * following the [`std` feature-gating](crate::polkadot_sdk::substrate#wasm-build) pattern.
+//!
+//! But, more specifically, it also contains:
+//!
+//! * a `build.rs` that uses [`substrate_wasm_builder`]. This entails declaring
+//! `[build-dependencies]` in the Cargo manifest file:
+//!
+//! ```ignore
+//! [build-dependencies]
+//! substrate-wasm-builder = { ... }
+//! ```
+//!
+//! >Note that a runtime must always be one-runtime-per-crate. You cannot define multiple runtimes
+//! per rust crate.
+//!
+//! You can find the full code of this guide in [`first_runtime`].
+//!
+//! ## Your First Runtime
+//!
+//! The first new property of a real runtime that it must define its
+//! [`frame::runtime::prelude::RuntimeVersion`]:
+#![doc = docify::embed!("./packages/guides/first-runtime/src/lib.rs", VERSION)]
+//!
+//! The version contains a number of very important fields, such as `spec_version` and `spec_name`
+//! that play an important role in identifying your runtime and its version, more importantly in
+//! runtime upgrades. More about runtime upgrades in
+//! [`crate::reference_docs::frame_runtime_upgrades_and_migrations`].
+//!
+//! Then, a real runtime also contains the `impl` of all individual pallets' `trait Config` for
+//! `struct Runtime`, and a [`frame::runtime::prelude::construct_runtime`] macro that amalgamates
+//! them all.
+//!
+//! In the case of our example:
+#![doc = docify::embed!("./packages/guides/first-runtime/src/lib.rs", our_config_impl)]
+//!
+//! In this example, we bring in a number of other pallets from [`frame`] into the runtime, each of
+//! their `Config` need to be implemented for `struct Runtime`:
+#![doc = docify::embed!("./packages/guides/first-runtime/src/lib.rs", config_impls)]
+//!
+//! Notice how we use [`frame::pallet_macros::derive_impl`] to provide "default" configuration items
+//! for each pallet. Feel free to dive into the definition of each default prelude (eg.
+//! [`frame::prelude::frame_system::pallet::config_preludes`]) to learn more which types are exactly
+//! used.
+//!
+//! Recall that in test runtime in [`crate::guides::your_first_pallet`], we provided `type AccountId
+//! = u64` to `frame_system`, while in this case we rely on whatever is provided by
+//! [`SolochainDefaultConfig`], which is indeed a "real" 32 byte account id.
+//!
+//! Then, a familiar instance of `construct_runtime` amalgamates all of the pallets:
+#![doc = docify::embed!("./packages/guides/first-runtime/src/lib.rs", cr)]
+//!
+//! Recall from [`crate::reference_docs::wasm_meta_protocol`] that every (real) runtime needs to
+//! implement a set of runtime APIs that will then let the node to communicate with it. The final
+//! steps of crafting a runtime are related to achieving exactly this.
+//!
+//! First, we define a number of types that eventually lead to the creation of an instance of
+//! [`frame::runtime::prelude::Executive`]. The executive is a handy FRAME utility that, through
+//! amalgamating all pallets and further types, implements some of the very very core pieces of the
+//! runtime logic, such as how blocks are executed and other runtime-api implementations.
+#![doc = docify::embed!("./packages/guides/first-runtime/src/lib.rs", runtime_types)]
+//!
+//! Finally, we use [`frame::runtime::prelude::impl_runtime_apis`] to implement all of the runtime
+//! APIs that the runtime wishes to expose. As you will see in the code, most of these runtime API
+//! implementations are merely forwarding calls to `RuntimeExecutive` which handles the actual
+//! logic. Given that the implementation block is somewhat large, we won't repeat it here. You can
+//! look for `impl_runtime_apis!` in [`first_runtime`].
+//!
+//! ```ignore
+//! impl_runtime_apis! {
+//! impl apis::Core for Runtime {
+//! fn version() -> RuntimeVersion {
+//! VERSION
+//! }
+//!
+//! fn execute_block(block: Block) {
+//! RuntimeExecutive::execute_block(block)
+//! }
+//!
+//! fn initialize_block(header: &Header) -> ExtrinsicInclusionMode {
+//! RuntimeExecutive::initialize_block(header)
+//! }
+//! }
+//!
+//! // many more trait impls...
+//! }
+//! ```
+//!
+//! And that more or less covers the details of how you would write a real runtime!
+//!
+//! Once you compile a crate that contains a runtime as above, simply running `cargo build` will
+//! generate the wasm blobs and place them under `./target/release/wbuild`, as explained
+//! [here](crate::polkadot_sdk::substrate#wasm-build).
+//!
+//! ## Genesis Configuration
+//!
+//! Every runtime specifies a number of runtime APIs that help the outer world (most notably, a
+//! `node`) know what is the genesis state of this runtime. These APIs are then used to generate
+//! what is known as a **Chain Specification, or chain spec for short**. A chain spec is the
+//! primary way to run a new chain.
+//!
+//! These APIs are defined in [`sp_genesis_builder`], and are re-exposed as a part of
+//! [`frame::runtime::apis`]. Therefore, the implementation blocks can be found inside of
+//! `impl_runtime_apis!` similar to:
+//!
+//! ```ignore
+//! impl_runtime_apis! {
+//! impl apis::GenesisBuilder for Runtime {
+//! fn build_state(config: Vec) -> GenesisBuilderResult {
+//! build_state::(config)
+//! }
+//!
+//! fn get_preset(id: &Option) -> Option> {
+//! get_preset::(id, self::genesis_config_presets::get_preset)
+//! }
+//!
+//! fn preset_names() -> Vec {
+//! crate::genesis_config_presets::preset_names()
+//! }
+//! }
+//!
+//! }
+//! ```
+//!
+//! The implementation of these function can naturally vary from one runtime to the other, but the
+//! overall pattern is common. For the case of this runtime, we do the following:
+//!
+//! 1. Expose one non-default preset, namely [`sp_genesis_builder::DEV_RUNTIME_PRESET`]. This means
+//! our runtime has two "presets" of genesis state in total: `DEV_RUNTIME_PRESET` and `None`.
+#![doc = docify::embed!("./packages/guides/first-runtime/src/lib.rs", preset_names)]
+//!
+//! For `build_state` and `get_preset`, we use the helper functions provide by frame:
+//!
+//! * [`frame::runtime::prelude::build_state`] and [`frame::runtime::prelude::get_preset`].
+//!
+//! Indeed, our runtime needs to specify what its `DEV_RUNTIME_PRESET` genesis state should be like:
+#![doc = docify::embed!("./packages/guides/first-runtime/src/lib.rs", development_config_genesis)]
+//!
+//! For more in-depth information about `GenesisConfig`, `ChainSpec`, the `GenesisBuilder` API and
+//! `chain-spec-builder`, see [`crate::reference_docs::chain_spec_genesis`].
+//!
+//! ## Next Step
+//!
+//! See [`crate::guides::your_first_node`].
+//!
+//! ## Further Reading
+//!
+//! 1. To learn more about signed extensions, see [`crate::reference_docs::signed_extensions`].
+//! 2. `AllPalletsWithSystem` is also generated by `construct_runtime`, as explained in
+//! [`crate::reference_docs::frame_runtime_types`].
+//! 3. `Executive` supports more generics, most notably allowing the runtime to configure more
+//! runtime migrations, as explained in
+//! [`crate::reference_docs::frame_runtime_upgrades_and_migrations`].
+//! 4. Learn more about adding and implementing runtime apis in
+//! [`crate::reference_docs::custom_runtime_api_rpc`].
+//! 5. To see a complete example of a runtime+pallet that is similar to this guide, please see
+//! [`crate::polkadot_sdk::templates`].
+//!
+//! [`SolochainDefaultConfig`]: struct@frame_system::pallet::config_preludes::SolochainDefaultConfig
diff --git a/docs/sdk/src/lib.rs b/docs/sdk/src/lib.rs
index 86ca677d7cef..e2c5fc93479c 100644
--- a/docs/sdk/src/lib.rs
+++ b/docs/sdk/src/lib.rs
@@ -12,7 +12,8 @@
//! - Start by learning about the the [`polkadot_sdk`], its structure and context.
//! - Then, head over to the [`guides`]. This modules contains in-depth guides about the most
//! important user-journeys of the Polkadot SDK.
-//! - Whilst reading the guides, you might find back-links to [`reference_docs`].
+//! - Whilst reading the guides, you might find back-links to [`reference_docs`].
+//! - [`external_resources`] for a list of 3rd party guides and tutorials.
//! - Finally, is the parent website of this crate that contains the
//! list of further tools related to the Polkadot SDK.
//!
diff --git a/docs/sdk/src/meta_contributing.rs b/docs/sdk/src/meta_contributing.rs
index e1297151b231..d68d9bca18b1 100644
--- a/docs/sdk/src/meta_contributing.rs
+++ b/docs/sdk/src/meta_contributing.rs
@@ -69,7 +69,8 @@
//! > what topics are already covered in this crate, and how you can build on top of the information
//! > that they already pose, rather than repeating yourself**.
//!
-//! For more details see the [latest documenting guidelines](https://github.com/paritytech/polkadot-sdk/blob/master/docs/contributor/DOCUMENTATION_GUIDELINES.md).
+//! For more details see the [latest documenting
+//! guidelines](https://github.com/paritytech/polkadot-sdk/blob/master/docs/contributor/DOCUMENTATION_GUIDELINES.md).
//!
//! #### Example: Explaining `#[pallet::call]`
//!
@@ -132,6 +133,13 @@
//! compromise, but in the long term, we should work towards finding a way to maintain different
//! revisions of this crate.
//!
+//! ## Versioning
+//!
+//! So long as not deployed in `crates.io`, please notice that all of the information in this crate,
+//! namely in [`crate::guides`] and such are compatible with the master branch of `polkadot-sdk`. A
+//! few solutions have been proposed to improve this, please see
+//! [here](https://github.com/paritytech/polkadot-sdk/issues/6191).
+//!
//! ## How to Develop Locally
//!
//! To view the docs specific [`crate`] locally for development, including the correct HTML headers
diff --git a/docs/sdk/src/polkadot_sdk/mod.rs b/docs/sdk/src/polkadot_sdk/mod.rs
index c089b6729ce5..bf7346b871a1 100644
--- a/docs/sdk/src/polkadot_sdk/mod.rs
+++ b/docs/sdk/src/polkadot_sdk/mod.rs
@@ -75,6 +75,26 @@
//! runtimes are located under the
//! [`polkadot-fellows/runtimes`](https://github.com/polkadot-fellows/runtimes) repository.
//!
+//! ### Binaries
+//!
+//! The main binaries that are part of the Polkadot SDK are:
+
+//! * [`polkadot`]: The Polkadot relay chain node binary, as noted above.
+//! * [`polkadot-omni-node`]: A white-labeled parachain collator node. See more in
+//! [`crate::reference_docs::omni_node`].
+//! * [`polkadot-parachain-bin`]: The collator node used to run collators for all Polkadot system
+//! parachains.
+//! * [`frame-omni-bencher`]: a benchmarking tool for FRAME-based runtimes. Nodes typically contain
+//! a
+//! `benchmark` subcommand that does the same.
+//! * [`chain_spec_builder`]: Utility to build chain-specs Nodes typically contain a `build-spec`
+//! subcommand that does the same.
+//! * [`subkey`]: Substrate's key management utility.
+//! * [`substrate-node`](node_cli) is an extensive substrate node that contains the superset of all
+//! runtime and node side features. The corresponding runtime, called [`kitchensink_runtime`]
+//! contains all of the modules that are provided with `FRAME`. This node and runtime is only used
+//! for testing and demonstration.
+//!
//! ### Summary
//!
//! The following diagram summarizes how some of the components of Polkadot SDK work together:
@@ -116,6 +136,9 @@
//! [`cumulus`]: crate::polkadot_sdk::cumulus
//! [`polkadot`]: crate::polkadot_sdk::polkadot
//! [`xcm`]: crate::polkadot_sdk::xcm
+//! [`frame-omni-bencher`]: https://crates.io/crates/frame-omni-bencher
+//! [`polkadot-parachain-bin`]: https://crates.io/crates/polkadot-parachain-bin
+//! [`polkadot-omni-node`]: https://crates.io/crates/polkadot-omni-node
/// Learn about Cumulus, the framework that transforms [`substrate`]-based chains into
/// [`polkadot`]-enabled parachains.
diff --git a/docs/sdk/src/polkadot_sdk/substrate.rs b/docs/sdk/src/polkadot_sdk/substrate.rs
index 56b89f8c9c2a..ed654c2842c4 100644
--- a/docs/sdk/src/polkadot_sdk/substrate.rs
+++ b/docs/sdk/src/polkadot_sdk/substrate.rs
@@ -90,22 +90,6 @@
//!
//! In order to ensure that the WASM build is **deterministic**, the [Substrate Runtime Toolbox (srtool)](https://github.com/paritytech/srtool) can be used.
//!
-//! ### Binaries
-//!
-//! Multiple binaries are shipped with substrate, the most important of which are located in the
-//! [`./bin`](https://github.com/paritytech/polkadot-sdk/tree/master/substrate/bin) folder.
-//!
-//! * [`node_cli`] is an extensive substrate node that contains the superset of all runtime and node
-//! side features. The corresponding runtime, called [`kitchensink_runtime`] contains all of the
-//! modules that are provided with `FRAME`. This node and runtime is only used for testing and
-//! demonstration.
-//! * [`chain_spec_builder`]: Utility to build more detailed chain-specs for the aforementioned
-//! node. Other projects typically contain a `build-spec` subcommand that does the same.
-//! * [`node_template`](https://github.com/paritytech/polkadot-sdk/tree/master/substrate/bin/node):
-//! a template node that contains a minimal set of features and can act as a starting point of a
-//! project.
-//! * [`subkey`]: Substrate's key management utility.
-//!
//! ### Anatomy of a Binary Crate
//!
//! From the above, [`node_cli`]/[`kitchensink_runtime`] and `node-template` are essentially
diff --git a/docs/sdk/src/reference_docs/chain_spec_genesis.rs b/docs/sdk/src/reference_docs/chain_spec_genesis.rs
index a2e22d1ed1eb..3326f433f288 100644
--- a/docs/sdk/src/reference_docs/chain_spec_genesis.rs
+++ b/docs/sdk/src/reference_docs/chain_spec_genesis.rs
@@ -152,10 +152,13 @@
//! presets and build the chain specification file. It is possible to use the tool with the
//! [_demonstration runtime_][`chain_spec_guide_runtime`]. To build the required packages, just run
//! the following command:
+//!
//! ```ignore
//! cargo build -p staging-chain-spec-builder -p chain-spec-guide-runtime --release
//! ```
+//!
//! The `chain-spec-builder` util can also be installed with `cargo install`:
+//!
//! ```ignore
//! cargo install staging-chain-spec-builder
//! cargo build -p chain-spec-guide-runtime --release
diff --git a/docs/sdk/src/reference_docs/frame_benchmarking_weight.rs b/docs/sdk/src/reference_docs/frame_benchmarking_weight.rs
index cf9e58791492..68d7d31f67f3 100644
--- a/docs/sdk/src/reference_docs/frame_benchmarking_weight.rs
+++ b/docs/sdk/src/reference_docs/frame_benchmarking_weight.rs
@@ -1,23 +1,212 @@
//! # FRAME Benchmarking and Weights.
//!
-//! Notes:
+//! This reference doc explores the concept of weights within Polkadot-SDK runtimes, and more
+//! specifically how FRAME-based runtimes handle it.
//!
-//! On Weight as a concept.
+//! ## Metering
//!
-//! - Why we need it. Super important. People hate this. We need to argue why it is worth it.
-//! - Axis of weight: PoV + Time.
-//! - pre dispatch weight vs. metering and post dispatch correction.
-//! - mention that we will do this for PoV
-//! - you can manually refund using `DispatchResultWithPostInfo`.
-//! - Technically you can have weights with any benchmarking framework. You just need one number to
-//! be computed pre-dispatch. But FRAME gives you a framework for this.
-//! - improve documentation of `#[weight = ..]` and `#[pallet::weight(..)]`. All syntax variation
-//! should be covered.
+//! The existence of "weight" as a concept in Polkadot-SDK is a direct consequence of the usage of
+//! WASM as a virtual machine. Unlike a metered virtual machine like EVM, where every instruction
+//! can have a (fairly) deterministic "cost" (also known as "gas price") associated with it, WASM is
+//! a stack machine with more complex instruction set, and more unpredictable execution times. This
+//! means that unlike EVM, it is not possible to implement a "metering" system in WASM. A metering
+//! system is one in which instructions are executed one by one, and the cost/gas is stored in an
+//! accumulator. The execution may then halt once a gas limit is reached.
//!
-//! On FRAME benchmarking machinery:
+//! In Polkadot-SDK, the WASM runtime is not assumed to be metered.
//!
-//! - Component analysis, why everything must be linear.
-//! - How to write benchmarks, how you must think of worst case.
-//! - How to run benchmarks.
+//! ## Trusted Code
//!
-//! -
+//! Another important difference is that EVM is mostly used to express smart contracts, which are
+//! foreign and untrusted codes from the perspective of the blockchain executing them. In such
+//! cases, metering is crucial, in order to ensure a malicious code cannot consume more gas than
+//! expected.
+//!
+//! This assumption does not hold about the runtime of Polkadot-SDK-based blockchains. The runtime
+//! is trusted code, and it is assumed to be written by the same team/developers who are running the
+//! blockchain itself. Therefore, this assumption of "untrusted foreign code" does not hold.
+//!
+//! This is why the runtime can opt for a more performant, more flexible virtual machine like WASM,
+//! and get away without having metering.
+//!
+//! ## Benchmarking
+//!
+//! With the matter of untrusted code execution out of the way, the need for strict metering goes
+//! out of the way. Yet, it would still be very beneficial for block producers to be able to know an
+//! upper bound on how much resources a operation is going to consume before actually executing that
+//! operation. This is why FRAME has a toolkit for benchmarking pallets: So that this upper bound
+//! can be empirically determined.
+//!
+//! > Note: Benchmarking is a static analysis: It is all about knowing the upper bound of how much
+//! > resources an operation takes statically, without actually executing it. In the context of
+//! > FRAME extrinsics, this static-ness is expressed by the keyword "pre-dispatch".
+//!
+//! To understand why this upper bound is needed, consider the following: A block producer knows
+//! they have 20ms left to finish producing their block, and wishes to include more transactions in
+//! the block. Yet, in a metered environment, it would not know which transaction is likely to fit
+//! the 20ms. In a benchmarked environment, it can examine the transactions for their upper bound,
+//! and include the ones that are known to fit based on the worst case.
+//!
+//! The benchmarking code can be written as a part of FRAME pallet, using the macros provided in
+//! [`frame_benchmarking`]. See any of the existing pallets in `polkadot-sdk`, or the pallets in our
+//! [`crate::polkadot_sdk::templates`] for examples.
+//!
+//! ## Weight
+//!
+//! Finally, [`sp_weights::Weight`] is the output of the benchmarking process. It is a
+//! two-dimensional data structure that demonstrates the resources consumed by a given block of
+//! code (for example, a transaction). The two dimensions are:
+//!
+//! * reference time: The time consumed in pico-seconds, on a reference hardware.
+//! * proof size: The amount of storage proof necessary to re-execute the block of code. This is
+//! mainly needed for parachain <> relay-chain verification.
+//!
+//! ## How To Write Benchmarks: Worst Case
+//!
+//! The most important detail about writing benchmarking code is that it must be written such that
+//! it captures the worst case execution of any block of code.
+//!
+//! Consider:
+#![doc = docify::embed!("./src/reference_docs/frame_benchmarking_weight.rs", simple_transfer)]
+//!
+//! If this block of code is to be benchmarked, then the benchmarking code must be written such that
+//! it captures the worst case.
+//!
+//! ## Gluing Pallet Benchmarking with Runtime
+//!
+//! FRAME pallets are mandated to provide their own benchmarking code. Runtimes contain the
+//! boilerplate needed to run these benchmarking (see [Running Benchmarks
+//! below](#running-benchmarks)). The outcome of running these benchmarks are meant to be fed back
+//! into the pallet via a conventional `trait WeightInfo` on `Config`:
+#![doc = docify::embed!("src/reference_docs/frame_benchmarking_weight.rs", WeightInfo)]
+//!
+//! Then, individual functions of this trait are the final values that we assigned to the
+//! [`frame::pallet_macros::weight`] attribute:
+#![doc = docify::embed!("./src/reference_docs/frame_benchmarking_weight.rs", simple_transfer_2)]
+//!
+//! ## Manual Refund
+//!
+//! Back to the assumption of writing benchmarks for worst case: Sometimes, the pre-dispatch weight
+//! significantly differ from the post-dispatch actual weight consumed. This can be expressed with
+//! the following FRAME syntax:
+#![doc = docify::embed!("./src/reference_docs/frame_benchmarking_weight.rs", simple_transfer_3)]
+//!
+//! ## Running Benchmarks
+//!
+//! Two ways exist to run the benchmarks of a runtime.
+//!
+//! 1. The old school way: Most Polkadot-SDK based nodes (such as the ones integrated in
+//! [`templates`]) have an a `benchmark` subcommand integrated into themselves.
+//! 2. The more [`crate::reference_docs::omni_node`] compatible way of running the benchmarks would
+//! be using [`frame-omni-bencher`] CLI, which only relies on a runtime.
+//!
+//! Note that by convention, the runtime and pallets always have their benchmarking code feature
+//! gated as behind `runtime-benchmarks`. So, the runtime should be compiled with `--features
+//! runtime-benchmarks`.
+//!
+//! ## Automatic Refund of `proof_size`.
+//!
+//! A new feature in FRAME allows the runtime to be configured for "automatic refund" of the proof
+//! size weight. This is very useful for maximizing the throughput of parachains. Please see:
+//! [`crate::guides::enable_pov_reclaim`].
+//!
+//! ## Summary
+//!
+//! Polkadot-SDK runtimes use a more performant VM, namely WASM, which does not have metering. In
+//! return they have to be benchmarked to provide an upper bound on the resources they consume. This
+//! upper bound is represented as [`sp_weights::Weight`].
+//!
+//! ## Future: PolkaVM
+//!
+//! With the transition of Polkadot relay chain to [JAM], a set of new features are being
+//! introduced, one of which being a new virtual machine named [PolkaVM] that is as flexible as
+//! WASM, but also capable of metering. This might alter the future of benchmarking in FRAME and
+//! Polkadot-SDK, rendering them not needed anymore once PolkaVM is fully integrated into
+//! Polkadot-sdk. For a basic explanation of JAM and PolkaVM, see [here](https://blog.kianenigma.com/posts/tech/demystifying-jam/#pvm).
+//!
+//!
+//! [`frame-omni-bencher`]: https://crates.io/crates/frame-omni-bencher
+//! [`templates`]: crate::polkadot_sdk::templates
+//! [PolkaVM]: https://github.com/koute/polkavm
+//! [JAM]: https://graypaper.com
+
+#[frame::pallet(dev_mode)]
+#[allow(unused_variables, unreachable_code, unused, clippy::diverging_sub_expression)]
+pub mod pallet {
+ use frame::prelude::*;
+
+ #[docify::export]
+ pub trait WeightInfo {
+ fn simple_transfer() -> Weight;
+ }
+
+ #[pallet::config]
+ pub trait Config: frame_system::Config {
+ type WeightInfo: WeightInfo;
+ }
+
+ #[pallet::pallet]
+ pub struct Pallet(_);
+
+ #[pallet::call]
+ impl Pallet {
+ #[docify::export]
+ #[pallet::weight(10_000)]
+ pub fn simple_transfer(
+ origin: OriginFor,
+ destination: T::AccountId,
+ amount: u32,
+ ) -> DispatchResult {
+ let destination_exists = todo!();
+ if destination_exists {
+ // simpler code path
+ } else {
+ // more complex code path
+ }
+ Ok(())
+ }
+
+ #[docify::export]
+ #[pallet::weight(T::WeightInfo::simple_transfer())]
+ pub fn simple_transfer_2(
+ origin: OriginFor,
+ destination: T::AccountId,
+ amount: u32,
+ ) -> DispatchResult {
+ let destination_exists = todo!();
+ if destination_exists {
+ // simpler code path
+ } else {
+ // more complex code path
+ }
+ Ok(())
+ }
+
+ #[docify::export]
+ // This is the worst-case, pre-dispatch weight.
+ #[pallet::weight(T::WeightInfo::simple_transfer())]
+ pub fn simple_transfer_3(
+ origin: OriginFor,
+ destination: T::AccountId,
+ amount: u32,
+ ) -> DispatchResultWithPostInfo {
+ // ^^ Notice the new return type
+ let destination_exists = todo!();
+ if destination_exists {
+ // simpler code path
+ // Note that need for .into(), to convert `()` to `PostDispatchInfo`
+ // See: https://paritytech.github.io/polkadot-sdk/master/frame_support/dispatch/struct.PostDispatchInfo.html#impl-From%3C()%3E-for-PostDispatchInfo
+ Ok(().into())
+ } else {
+ // more complex code path
+ let actual_weight =
+ todo!("this can likely come from another benchmark that is NOT the worst case");
+ let pays_fee = todo!("You can set this to `Pays::Yes` or `Pays::No` to change if this transaction should pay fees");
+ Ok(frame::deps::frame_support::dispatch::PostDispatchInfo {
+ actual_weight: Some(actual_weight),
+ pays_fee,
+ })
+ }
+ }
+ }
+}
diff --git a/docs/sdk/src/reference_docs/mod.rs b/docs/sdk/src/reference_docs/mod.rs
index 9cf5605a88ba..e47eece784c4 100644
--- a/docs/sdk/src/reference_docs/mod.rs
+++ b/docs/sdk/src/reference_docs/mod.rs
@@ -78,7 +78,6 @@ pub mod frame_system_accounts;
pub mod development_environment_advice;
/// Learn about benchmarking and weight.
-// TODO: @shawntabrizi @ggwpez https://github.com/paritytech/polkadot-sdk-docs/issues/50
pub mod frame_benchmarking_weight;
/// Learn about the token-related logic in FRAME and how to apply it to your use case.
@@ -109,3 +108,6 @@ pub mod umbrella_crate;
/// Learn about how to create custom RPC endpoints and runtime APIs.
pub mod custom_runtime_api_rpc;
+
+/// The [`polkadot-omni-node`](https://crates.io/crates/polkadot-omni-node) and its related binaries.
+pub mod omni_node;
diff --git a/docs/sdk/src/reference_docs/omni_node.rs b/docs/sdk/src/reference_docs/omni_node.rs
new file mode 100644
index 000000000000..44d63704a458
--- /dev/null
+++ b/docs/sdk/src/reference_docs/omni_node.rs
@@ -0,0 +1,185 @@
+//! # (Omni) Node
+//!
+//! This reference doc elaborates on what a Polkadot-SDK/Substrate node software is, and what
+//! various ways exist to run one.
+//!
+//! The node software, as denoted in [`crate::reference_docs::wasm_meta_protocol`], is everything in
+//! a blockchain other than the WASM runtime. It contains common components such as the database,
+//! networking, RPC server and consensus. Substrate-based nodes are native binaries that are
+//! compiled down from the Rust source code. The `node` folder in any of the [`templates`] are
+//! examples of this source.
+//!
+//! > Note: A typical node also contains a lot of other tools (exposed as subcommands) that are
+//! > useful for operating a blockchain, such as the ones noted in
+//! > [`polkadot_omni_node_lib::cli::Cli::subcommand`].
+//!
+//! ## Node <> Runtime Interdependence
+//!
+//! While in principle the node can be mostly independent of the runtime, for various reasons, such
+//! as the [native runtime](crate::reference_docs::wasm_meta_protocol#native-runtime), the node and
+//! runtime were historically tightly linked together. Another reason is that the node and the
+//! runtime need to be in agreement about which consensus algorithm they use, as described
+//! [below](#consensus-engine).
+//!
+//! Specifically, the node relied on the existence of a linked runtime, and *could only reliably run
+//! that runtime*. This is why if you look at any of the [`templates`], they are all composed of a
+//! node, and a runtime.
+//!
+//! Moreover, the code and API of each of these nodes was historically very advanced, and tailored
+//! towards those who wish to customize many of the node components at depth.
+//!
+//! > The notorious `service.rs` in any node template is a good example of this.
+//!
+//! A [trend](https://github.com/paritytech/polkadot-sdk/issues/62) has already been undergoing in
+//! order to de-couple the node and the runtime for a long time. The north star of this effort is
+//! twofold :
+//!
+//! 1. develop what can be described as an "omni-node": A node that can run most runtimes.
+//! 2. provide a cleaner abstraction for creating a custom node.
+//!
+//! While a single omni-node running *all possible runtimes* is not feasible, the
+//! [`polkadot-omni-node`] is an attempt at creating the former, and the [`polkadot_omni_node_lib`]
+//! is the latter.
+//!
+//! > Note: The OmniNodes are mainly focused on the development needs of **Polkadot
+//! > parachains ONLY**, not (Substrate) solo-chains. For the time being, solo-chains are not
+//! > supported by the OmniNodes. This might change in the future.
+//!
+//! ## Types of Nodes
+//!
+//! With the emergence of the OmniNodes, let's look at the various Node options available to a
+//! builder.
+//!
+//! ### [`polkadot-omni-node`]
+//!
+//! [`polkadot-omni-node`] is a white-labeled binary, released as a part of Polkadot SDK that is
+//! capable of meeting the needs of most Polkadot parachains.
+//!
+//! It can act as the collator of a parachain in production, with all the related auxillary
+//! functionalities that a normal collator node has: RPC server, archiving state, etc. Moreover, it
+//! can also run the wasm blob of the parachain locally for testing and development.
+//!
+//! ### [`polkadot_omni_node_lib`]
+//!
+//! [`polkadot_omni_node_lib`] is the library version of the above, which can be used to create a
+//! fresh parachain node, with a some limited configuration options using a lean API.
+//!
+//! ### Old School Nodes
+//!
+//! The existing node architecture, as seen in the [`templates`], is still available for those who
+//! want to have full control over the node software.
+//!
+//! ### Summary
+//!
+//! We can summarize the choices for the node software of any given user of Polkadot-SDK, wishing to
+//! deploy a parachain into 3 categories:
+//!
+//! 1. **Use the [`polkadot-omni-node`]**: This is the easiest way to get started, and is the most
+//! likely to be the best choice for most users.
+//! * can run almost any runtime with [`--dev-block-time`]
+//! 2. **Use the [`polkadot_omni_node_lib`]**: This is the best choice for those who want to have
+//! slightly more control over the node software, such as embedding a custom chain-spec.
+//! 3. **Use the old school nodes**: This is the best choice for those who want to have full control
+//! over the node software, such as changing the consensus engine, altering the transaction pool,
+//! and so on.
+//!
+//! ## _OmniTools_: User Journey
+//!
+//! All in all, the user journey of a team/builder, in the OmniNode world is as follows:
+//!
+//! * The [`templates`], most notably the [`parachain-template`] is the canonical starting point.
+//! That being said, the node code of the templates (which may be eventually
+//! removed/feature-gated) is no longer of relevance. The only focus is in the runtime, and
+//! obtaining a `.wasm` file. References:
+//! * [`crate::guides::your_first_pallet`]
+//! * [`crate::guides::your_first_runtime`]
+//! * If need be, the weights of the runtime need to be updated using `frame-omni-bencher`.
+//! References:
+//! * [`crate::reference_docs::frame_benchmarking_weight`]
+//! * Next, [`chain-spec-builder`] is used to generate a `chain_spec.json`, either for development,
+//! or for production. References:
+//! * [`crate::reference_docs::chain_spec_genesis`]
+//! * For local development, the following options are available:
+//! * `polkadot-omni-node` (notably, with [`--dev-block-time`]). References:
+//! * [`crate::guides::your_first_node`]
+//! * External tools such as `chopsticks`, `zombienet`.
+//! * See the `README.md` file of the `polkadot-sdk-parachain-template`.
+//! * For production `polkadot-omni-node` can be used out of the box.
+//! * For further customization [`polkadot_omni_node_lib`] can be used.
+//!
+//! ## Appendix
+//!
+//! This section describes how the interdependence between the node and the runtime is related to
+//! the consensus engine. This information is useful for those who want to understand the
+//! historical context of the node and the runtime.
+//!
+//! ### Consensus Engine
+//!
+//! In any given substrate-based chain, both the node and the runtime will have their own
+//! opinion/information about what consensus engine is going to be used.
+//!
+//! In practice, the majority of the implementation of any consensus engine is in the node side, but
+//! the runtime also typically needs to expose a custom runtime-api to enable the particular
+//! consensus engine to work, and that particular runtime-api is implemented by a pallet
+//! corresponding to that consensus engine.
+//!
+//! For example, taking a snippet from [`solochain_template_runtime`], the runtime has to provide
+//! this additional runtime-api (compared to [`minimal_template_runtime`]), if the node software is
+//! configured to use the Aura consensus engine:
+//!
+//! ```text
+//! impl sp_consensus_aura::AuraApi for Runtime {
+//! fn slot_duration() -> sp_consensus_aura::SlotDuration {
+//! ...
+//! }
+//! fn authorities() -> Vec {
+//! ...
+//! }
+//! }
+//! ```
+//!
+//! For simplicity, we can break down "consensus" into two main parts:
+//!
+//! * Block Authoring: Deciding who gets to produce the next block.
+//! * Finality: Deciding when a block is considered final.
+//!
+//! For block authoring, there are a number of options:
+//!
+//! * [`sc_consensus_manual_seal`]: Useful for testing, where any node can produce a block at any
+//! time. This is often combined with a fixed interval at which a block is produced.
+//! * [`sc_consensus_aura`]/[`pallet_aura`]: A simple round-robin block authoring mechanism.
+//! * [`sc_consensus_babe`]/[`pallet_babe`]: A more advanced block authoring mechanism, capable of
+//! anonymizing the next block author.
+//! * [`sc_consensus_pow`]: Proof of Work block authoring.
+//!
+//! For finality, there is one main option shipped with polkadot-sdk:
+//!
+//! * [`sc_consensus_grandpa`]/[`pallet_grandpa`]: A finality gadget that uses a voting mechanism to
+//! decide when a block
+//!
+//! **The most important lesson here is that the node and the runtime must have matching consensus
+//! components.**
+//!
+//! ### Consequences for OmniNode
+//!
+//!
+//! The consequence of the above is that anyone using the OmniNode must also be aware of the
+//! consensus system used in the runtime, and be aware if it is matching that of the OmniNode or
+//! not. For the time being, [`polkadot-omni-node`] only supports:
+//!
+//! * Parachain-based Aura consensus, with 6s async-backing block-time, and before full elastic
+//! scaling). [`polkadot_omni_node_lib::cli::Cli::experimental_use_slot_based`] for fixed factor
+//! scaling (a step
+//! * Ability to run any runtime with [`--dev-block-time`] flag. This uses
+//! [`sc_consensus_manual_seal`] under the hood, and has no restrictions on the runtime's
+//! consensus.
+//!
+//! [This](https://github.com/paritytech/polkadot-sdk/issues/5565) future improvement to OmniNode
+//! aims to make such checks automatic.
+//!
+//!
+//! [`templates`]: crate::polkadot_sdk::templates
+//! [`parachain-template`]: https://github.com/paritytech/polkadot-sdk-parachain-template
+//! [`--dev-block-time`]: polkadot_omni_node_lib::cli::Cli::dev_block_time
+//! [`polkadot-omni-node`]: https://crates.io/crates/polkadot-omni-node
+//! [`chain-spec-builder`]: https://crates.io/crates/staging-chain-spec-builder
diff --git a/docs/sdk/src/reference_docs/umbrella_crate.rs b/docs/sdk/src/reference_docs/umbrella_crate.rs
index 1074cde37693..8d9bcdfc2089 100644
--- a/docs/sdk/src/reference_docs/umbrella_crate.rs
+++ b/docs/sdk/src/reference_docs/umbrella_crate.rs
@@ -5,6 +5,7 @@
//! crate. This helps with selecting the right combination of crate versions, since otherwise 3rd
//! party tools are needed to select a compatible set of versions.
//!
+//!
//! ## Features
//!
//! The umbrella crate supports no-std builds and can therefore be used in the runtime and node.
diff --git a/prdoc/pr_6094.prdoc b/prdoc/pr_6094.prdoc
new file mode 100644
index 000000000000..23391c889155
--- /dev/null
+++ b/prdoc/pr_6094.prdoc
@@ -0,0 +1,21 @@
+# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
+# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json
+
+title: Polkadot OmniNode Docs
+
+doc:
+ - audience: ...
+ description: |
+ Adds documentation in https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/index.html and rust-docs for polkadot-omni-node project.
+
+crates:
+ - name: sp-genesis-builder
+ bump: patch
+ - name: pallet-aura
+ bump: patch
+ - name: polkadot-omni-node-lib
+ bump: patch
+ - name: polkadot-sdk-frame # since the crate is "experimental, we don't need to bump yet."
+ bump: major
+ - name: polkadot-omni-node
+ bump: patch
diff --git a/substrate/bin/node/cli/src/cli.rs b/substrate/bin/node/cli/src/cli.rs
index c0dcacb2e4b4..1d7001a5dccf 100644
--- a/substrate/bin/node/cli/src/cli.rs
+++ b/substrate/bin/node/cli/src/cli.rs
@@ -59,6 +59,7 @@ pub enum Subcommand {
Inspect(node_inspect::cli::InspectCmd),
/// Sub-commands concerned with benchmarking.
+ ///
/// The pallet benchmarking moved to the `pallet` sub-command.
#[command(subcommand)]
Benchmark(frame_benchmarking_cli::BenchmarkCmd),
diff --git a/substrate/frame/Cargo.toml b/substrate/frame/Cargo.toml
index 595fb5a19b04..2d0daf82997d 100644
--- a/substrate/frame/Cargo.toml
+++ b/substrate/frame/Cargo.toml
@@ -44,8 +44,10 @@ sp-offchain = { optional = true, workspace = true }
sp-session = { optional = true, workspace = true }
sp-consensus-aura = { optional = true, workspace = true }
sp-consensus-grandpa = { optional = true, workspace = true }
+sp-genesis-builder = { optional = true, workspace = true }
sp-inherents = { optional = true, workspace = true }
sp-storage = { optional = true, workspace = true }
+sp-keyring = { optional = true, workspace = true }
frame-executive = { optional = true, workspace = true }
frame-system-rpc-runtime-api = { optional = true, workspace = true }
@@ -73,7 +75,9 @@ runtime = [
"sp-block-builder",
"sp-consensus-aura",
"sp-consensus-grandpa",
+ "sp-genesis-builder",
"sp-inherents",
+ "sp-keyring",
"sp-offchain",
"sp-session",
"sp-storage",
@@ -97,8 +101,10 @@ std = [
"sp-consensus-aura?/std",
"sp-consensus-grandpa?/std",
"sp-core/std",
+ "sp-genesis-builder?/std",
"sp-inherents?/std",
"sp-io/std",
+ "sp-keyring?/std",
"sp-offchain?/std",
"sp-runtime/std",
"sp-session?/std",
diff --git a/substrate/frame/aura/src/lib.rs b/substrate/frame/aura/src/lib.rs
index f829578fb285..c74e864ea0d9 100644
--- a/substrate/frame/aura/src/lib.rs
+++ b/substrate/frame/aura/src/lib.rs
@@ -400,7 +400,9 @@ impl OnTimestampSet for Pallet {
assert_eq!(
CurrentSlot::::get(),
timestamp_slot,
- "Timestamp slot must match `CurrentSlot`"
+ "Timestamp slot must match `CurrentSlot`. This likely means that the configured block \
+ time in the node and/or rest of the runtime is not compatible with Aura's \
+ `SlotDuration`",
);
}
}
diff --git a/substrate/frame/src/lib.rs b/substrate/frame/src/lib.rs
index fcd96b40c3c4..ade1095cc504 100644
--- a/substrate/frame/src/lib.rs
+++ b/substrate/frame/src/lib.rs
@@ -222,7 +222,12 @@ pub mod runtime {
// Types often used in the runtime APIs.
pub use sp_core::OpaqueMetadata;
+ pub use sp_genesis_builder::{
+ PresetId, Result as GenesisBuilderResult, DEV_RUNTIME_PRESET,
+ LOCAL_TESTNET_RUNTIME_PRESET,
+ };
pub use sp_inherents::{CheckInherentsResult, InherentData};
+ pub use sp_keyring::AccountKeyring;
pub use sp_runtime::{ApplyExtrinsicResult, ExtrinsicInclusionMode};
}
@@ -246,6 +251,7 @@ pub mod runtime {
pub use sp_block_builder::*;
pub use sp_consensus_aura::*;
pub use sp_consensus_grandpa::*;
+ pub use sp_genesis_builder::*;
pub use sp_offchain::*;
pub use sp_session::runtime_api::*;
pub use sp_transaction_pool::runtime_api::*;
@@ -396,8 +402,12 @@ pub mod deps {
#[cfg(feature = "runtime")]
pub use sp_consensus_grandpa;
#[cfg(feature = "runtime")]
+ pub use sp_genesis_builder;
+ #[cfg(feature = "runtime")]
pub use sp_inherents;
#[cfg(feature = "runtime")]
+ pub use sp_keyring;
+ #[cfg(feature = "runtime")]
pub use sp_offchain;
#[cfg(feature = "runtime")]
pub use sp_storage;
diff --git a/substrate/primitives/genesis-builder/src/lib.rs b/substrate/primitives/genesis-builder/src/lib.rs
index 07317bc4cb52..4763aa06341e 100644
--- a/substrate/primitives/genesis-builder/src/lib.rs
+++ b/substrate/primitives/genesis-builder/src/lib.rs
@@ -17,17 +17,33 @@
#![cfg_attr(not(feature = "std"), no_std)]
-//! Substrate genesis config builder
+//! # Substrate genesis config builder.
//!
-//! For FRAME based runtimes, this runtime interface provides means to interact with
-//! `RuntimeGenesisConfig`. Runtime provides a default `RuntimeGenesisConfig` structure in a form of
-//! the JSON blob.
+//! This crate contains [`GenesisBuilder`], a runtime-api to be implemented by runtimes, in order to
+//! express their genesis state.
//!
-//! For non-FRAME runtimes this interface is intended to build genesis state of the runtime basing
-//! on some input arbitrary bytes array. This documentation uses term `RuntimeGenesisConfig`, which
-//! for non-FRAME runtimes may be understood as the runtime-side entity representing initial runtime
-//! configuration. The representation of the preset is an arbitrary `Vec` and does not
-//! necessarily have to represent a JSON blob.
+//! The overall flow of the methods in [`GenesisBuilder`] is as follows:
+//!
+//! 1. [`GenesisBuilder::preset_names`]: A runtime exposes a number of different
+//! `RuntimeGenesisConfig` variations, each of which is called a `preset`, and is identified by a
+//! [`PresetId`]. All runtimes are encouraged to expose at least [`DEV_RUNTIME_PRESET`] and
+//! [`LOCAL_TESTNET_RUNTIME_PRESET`] presets for consistency.
+//! 2. [`GenesisBuilder::get_preset`]: Given a `PresetId`, this the runtime returns the JSON blob
+//! representation of the `RuntimeGenesisConfig` for that preset. This JSON blob is often mixed
+//! into the broader `chain_spec`. If `None` is given, [`GenesisBuilder::get_preset`] provides a
+//! JSON represention of the default `RuntimeGenesisConfig` (by simply serializing the
+//! `RuntimeGenesisConfig::default()` value into JSON format). This is used as a base for
+//! applying patches / presets.
+
+//! 3. [`GenesisBuilder::build_state`]: Given a JSON blob, this method should deserialize it and
+//! enact it (using `frame_support::traits::BuildGenesisConfig` for Frame-based runtime),
+//! essentially writing it to the state.
+//!
+//! The first two flows are often done in between a runtime, and the `chain_spec_builder` binary.
+//! The latter is used when a new blockchain is launched to enact and store the genesis state. See
+//! the documentation of `chain_spec_builder` for more info.
+//!
+//! ## Patching
//!
//! The runtime may provide a number of partial predefined `RuntimeGenesisConfig` configurations in
//! the form of patches which shall be applied on top of the default `RuntimeGenesisConfig`. The
@@ -35,19 +51,22 @@
//! customized in the default runtime genesis config. These predefined configurations are referred
//! to as presets.
//!
-//! This allows the runtime to provide a number of predefined configs (e.g. for different
-//! testnets or development) without neccessity to leak the runtime types outside the itself (e.g.
-//! node or chain-spec related tools).
+//! This allows the runtime to provide a number of predefined configs (e.g. for different testnets
+//! or development) without necessarily to leak the runtime types outside itself (e.g. node or
+//! chain-spec related tools).
+//!
+//! ## FRAME vs. non-FRAME
+//!
+//! For FRAME based runtimes [`GenesisBuilder`] provides means to interact with
+//! `RuntimeGenesisConfig`.
+//!
+//! For non-FRAME runtimes this interface is intended to build genesis state of the runtime basing
+//! on some input arbitrary bytes array. This documentation uses term `RuntimeGenesisConfig`, which
+//! for non-FRAME runtimes may be understood as the "runtime-side entity representing initial
+//! runtime genesis configuration". The representation of the preset is an arbitrary `Vec` and
+//! does not necessarily have to represent a JSON blob.
//!
-//! This Runtime API allows to interact with `RuntimeGenesisConfig`, in particular:
-//! - provide the list of available preset names,
-//! - provide a number of named presets of `RuntimeGenesisConfig`,
-//! - provide a JSON represention of the default `RuntimeGenesisConfig` (by simply serializing the
-//! default `RuntimeGenesisConfig` struct into JSON format),
-//! - deserialize the full `RuntimeGenesisConfig` from given JSON blob and put the resulting
-//! `RuntimeGenesisConfig` structure into the state storage creating the initial runtime's state.
-//! Allows to build customized genesis. This operation internally calls `GenesisBuild::build`
-//! function for all runtime pallets.
+//! ## Genesis Block State
//!
//! Providing externalities with an empty storage and putting `RuntimeGenesisConfig` into storage
//! (by calling `build_state`) allows to construct the raw storage of `RuntimeGenesisConfig`
@@ -75,14 +94,15 @@ pub const DEV_RUNTIME_PRESET: &'static str = "development";
pub const LOCAL_TESTNET_RUNTIME_PRESET: &'static str = "local_testnet";
sp_api::decl_runtime_apis! {
- /// API to interact with RuntimeGenesisConfig for the runtime
+ /// API to interact with `RuntimeGenesisConfig` for the runtime
pub trait GenesisBuilder {
/// Build `RuntimeGenesisConfig` from a JSON blob not using any defaults and store it in the
/// storage.
///
- /// In the case of a FRAME-based runtime, this function deserializes the full `RuntimeGenesisConfig` from the given JSON blob and
- /// puts it into the storage. If the provided JSON blob is incorrect or incomplete or the
- /// deserialization fails, an error is returned.
+ /// In the case of a FRAME-based runtime, this function deserializes the full
+ /// `RuntimeGenesisConfig` from the given JSON blob and puts it into the storage. If the
+ /// provided JSON blob is incorrect or incomplete or the deserialization fails, an error
+ /// is returned.
///
/// Please note that provided JSON blob must contain all `RuntimeGenesisConfig` fields, no
/// defaults will be used.
@@ -91,7 +111,7 @@ sp_api::decl_runtime_apis! {
/// Returns a JSON blob representation of the built-in `RuntimeGenesisConfig` identified by
/// `id`.
///
- /// If `id` is `None` the function returns JSON blob representation of the default
+ /// If `id` is `None` the function should return JSON blob representation of the default
/// `RuntimeGenesisConfig` struct of the runtime. Implementation must provide default
/// `RuntimeGenesisConfig`.
///
diff --git a/templates/minimal/runtime/src/lib.rs b/templates/minimal/runtime/src/lib.rs
index 464cad4e3da0..4f914a823bf6 100644
--- a/templates/minimal/runtime/src/lib.rs
+++ b/templates/minimal/runtime/src/lib.rs
@@ -324,7 +324,7 @@ impl_runtime_apis! {
}
fn preset_names() -> Vec {
- self::genesis_config_presets::preset_names()
+ crate::genesis_config_presets::preset_names()
}
}
}
diff --git a/templates/parachain/runtime/src/genesis_config_presets.rs b/templates/parachain/runtime/src/genesis_config_presets.rs
index 322c91f4f136..394bde0be770 100644
--- a/templates/parachain/runtime/src/genesis_config_presets.rs
+++ b/templates/parachain/runtime/src/genesis_config_presets.rs
@@ -76,6 +76,8 @@ fn local_testnet_genesis() -> Value {
],
Sr25519Keyring::well_known().map(|k| k.to_account_id()).collect(),
Sr25519Keyring::Alice.to_account_id(),
+ // TODO: this is super opaque, how should one know they should configure this? add to
+ // README!
1000.into(),
)
}