Runtime

The runtime of a blockchain is the business logic that defines its behavior. In Substrate-based chains, the runtime is referred to as the "state transition function"; it is where Substrate developers define the storage items that are used to represent the blockchain's state as well as the functions that allow blockchain users to make changes to this state.

substrate-runtime-client

Each Substrate node contains a runtime. The runtime contains the business logic of the chain. It defines what transactions are valid and invalid and determines how the chain's state changes in response to transactions. The "outer node", everything other than the runtime, does not compile to Wasm, only to native. The outer node is responsible for handling peer discovery, transaction pooling, block and transaction gossiping, consensus, and answering RPC calls from the outside world. While performing these tasks, the outer node sometimes needs to query the runtime for information, or provide information to the runtime. A Runtime API facilitates this kind of communication between the outer node and the runtime.

Runtime APIs

In Substrate, the sp_api crate provides an interface to implement a runtime API. It is designed to give developers the ability to define their own custom runtime APIs using the impl_runtime_apis macro. However, every runtime must implement the Core and Metadata runtime APIs. In addition to these, a basic Substrate Node has the following runtime APIs implemented:

In order to provide its defining forkless runtime upgrade capabilities, Substrate runtimes are built as WebAssembly (Wasm) bytecode. Substrate also defines the core primitives that the runtime must implement.

Core primitives

The Substrate framework makes minimal assumptions about what your runtime must provide to the other layers of Substrate. But there are a few data types need to be defined and must fulfill a particular interface in order to work within the Substrate framework.

They are:

  • Hash: A type which encodes a cryptographic digest of some data. Typically just a 256-bit quantity.

  • DigestItem: A type which must be able to encode one of a number of "hard-wired" alternatives relevant to consensus and change-tracking as well as any number of "soft-coded" variants, relevant to specific modules within the runtime.

  • Digest: A series of DigestItems. This encodes all information that is relevant for a light-client to have on hand within the block.

  • Extrinsic: A type to represent a single piece of data external to the blockchain that is recognized by the blockchain. This typically involves one or more signatures, and some sort of encoded instructions (e.g. for transferring ownership of funds or calling into a smart contract).

  • Header: A type which is representative (cryptographically or otherwise) of all information relevant to a block. It includes the parent hash, the storage root and the extrinsics trie root, the digest and a block number.

  • Block: Essentially just a combination of Header and a series of Extrinsics, together with a specification of the hashing algorithm to be used.

  • BlockNumber: A type which encodes the total number of ancestors any valid block has. Typically a 32-bit quantity.

FRAME primitives

The core Substrate codebase ships with FRAME, Parity's system for Substrate runtime development that is used for chains like Kusama and Polkadot. FRAME defines additional runtime primitives and provides a framework that makes it easy to construct a runtime by composing modules, called pallets. Each pallet encapsulates domain-specific logic that is expressed as a set of a storage items, events, errors, and dispatchable functions. FRAME developers can create their own pallets and reuse existing pallets, including over 50 of those shipped with Substrate.

Runtime Composition

There are an additional set of primitives that are assumed about a runtime built with the Substrate FRAME. These are:

  • Call: The dispatch type that can be called via an extrinsic.

  • Origin: Represents where a call came from. For example, a signed message (a transaction), an unsigned message (an inherent extrinsic), or a call from the runtime itself (a root call).

  • Index: An account index (aka nonce) type. This stores the number of previous transactions associated with a sender account.

  • Hashing: The hashing algorithm being used in the runtime (e.g. Blake2).

  • AccountId: The type used to identify user accounts in the runtime.

  • Event: The type used for events emitted by the runtime.

  • Version: A type which represents the version of the runtime.

Although a lot of core runtime development can be enabled with FRAME and its related primitives, FRAME is not the only system for developing Substrate based blockchains.

Next steps

Learn more

References

Last edit: on

Was This Page Helpful?
Help us improve