Substrate is a Rust framework for building blockchains in a modular and extensible way. While in itself un-opinionated, it is the main engine behind the Polkadot ecosystem.
This crate in itself does not contain any code and is just meant ot be a documentation hub for substrate-based crates.
Substrate approaches blockchain development with an acknowledgement of a few self-evident truths:
- Society and technology evolves.
- Humans are fallible.
This, specifically, makes the task of designing a correct, safe and long-lasting blockchain system hard.
Nonetheless, in order to achieve this goal, substrate embraces the following:
- Use of Rust as a modern, and safe programming language, which limits human error through various means, most notably memory safety.
- Substrate is written from the ground-up with a generic, modular and extensible design. This ensures that software components can be easily swapped and upgraded. Examples of this is multiple consensus mechanisms provided by Substrate, as listed below.
- Lastly, the final blockchain system created with the above properties needs to be upgradeable. In order to achieve this, Substrate is designed as a meta-protocol, whereby the application logic of the blockchain (called “Runtime”) is encoded as a Wasm blob, and is stored onchain. The rest of the system (called “Client”) acts as the executor of the Wasm blob.
In essence, the meta-protocol of all Substrate based chains is the “Runtime as Wasm blob” accord. This enables the Runtime to become inherently upgradeable (without forks). The upgrade is merely a matter of the Wasm blob being changed in the chain state, which is, in principle, same as updating an account’s balance.
To learn more about the substrate architecture using some visuals, see
FRAME, Substrate’s default runtime development library takes the above even further by
embracing a declarative programming model whereby correctness is enhanced and the system is
highly configurable through parameterization.
All in all, this design enables all substrate-based chains to achieve forkless, self-enacting
upgrades out of the box. Combined with governance abilities that are shipped with
enables a chain to survive the test of time.
Most developers want to leave the client side code as-is, and focus on the runtime. To do so,
look into the
frame_support crate, which is the entry point crate into runtime development
Side note, it is entirely possible to craft a substrate-based runtime without FRAME, an example of which can be found here.
In more broad terms, the following avenues exist into developing with substrate:
- Templates: A number of substrate-based templates exist and they can be used for various purposes, with zero to little additional code needed. All of these templates contain runtimes that are highly configurable and are likely suitable for basic needs.
FRAME: If need, one can customize that runtime even further, by using
FRAMEand developing custom modules.
- Core: To the contrary, some developers may want to customize the client side software to achieve novel goals such as a new consensus engine, or a new database backend. While Substrate’s main configurability is in the runtime, the client is also highly generic and can be customized to a great extent.
Substrate is a massive cargo workspace with hundreds of crates, therefore it is useful to know how to navigate its crates.
In broad terms, it is divided into three categories:
sc-*(short for substrate-client) crates, located under
./clientfolder. These are all the client crates. Notable examples are crates such as
sc-network, various consensus crates,
sc-client-db, all of which are expected to reside in the client side.
sp-*(short for substrate-primitives) crates, located under
./primitivesfolder. These are the traits that glue the client and runtime together, but are not opinionated about what framework is using for building the runtime. Notable examples are
sp-io, which form the communication bridge between the client and runtime, as explained in
frame-*crates, located under
./framefolder. These are the crates related to FRAME. See
frame_supportfor more information.
Many of the Substrate crates, such as entire
sp-*, need to compile to both Wasm (when a Wasm
runtime is being generated) and native (for example, when testing). To achieve this, Substrate
follows the convention of the Rust community, and uses a
feature = "std" to signify that a
crate is being built with the standard library, and is built for native. Otherwise, it is built
This can be summarized in
#![cfg_attr(not(feature = "std"), no_std)], which you can often find
in any Substrate-based runtime.
Substrate-based runtimes use
substrate-wasm-builder in their
build.rs to automatically
build their Wasm files as a part of normal build commandsOnce built, the wasm file is placed in
Multiple binaries are shipped with substrate, the most important of which are located in the
nodeis an extensive substrate node that contains the superset of all runtime and client side features. The corresponding runtime, called
kitchensink_runtimecontains 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-specsubcommand that does the same.
node-template: 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.
./runtime/src/lib.rswhich is the top level runtime amalgamator file. This file typically contains the
frame_support::construct_runtimemacro, which is the final definition of a runtime.
main.rs, which is the point, and a
./service.rs, which contains all the client side components. Skimming this file yields an overview of the networking, database, consensus and similar client side components.
The above two are conventions, not rules.
As noted above, Substrate is the main engine behind the Polkadot ecosystem. One of the ways through which Polkadot can be utilized is by building “parachains”, blockchains that are connected to Polkadot’s shared security.
To build a parachain, one could use
library on top of Substrate, empowering any substrate-based chain to be a Polkadot parachain.
Additional noteworthy crates within substrate:
- RPC APIs of a Substrate node:
- CLI Options of a Substrate node:
- All of the consensus related crates provided by Substrate:
Additional noteworthy external resources:
- Substrate Developer Hub
- Parity Tech’s Documentation Hub
- Frontier: Substrate’s Ethereum Compatibility Library
- Polkadot Wiki
Notable upstream crates:
- In this module, we explore substrate at a more depth. First, let’s establish substrate being divided into a client and runtime.