This is a brief overview of runtime execution and versioning intended to inform the discussion about runtime upgrades. I’ll extend it over time with more info.
Substrate can execute blocks in two ways. It can execute the block with the runtime code stored as a Wasm blob on chain or with the native runtime code linked into the node binary.
The Wasm execution is considered the canonical one since it is the same for every node and only depends on the chain state and not on the node implementation. Running the native runtime is only a performance optimization.
Substrate has various strategies for deciding whether to execute native or wasm code. For all these strategies native execution is only tried if the
RuntimeVersion of the on-chain code is compatible with the runtime version of the native code. Two runtime versions are compatible if their
spec_version are equal. (The
impl_version may differ.)
Substrate uses different execution strategies for different execution context (sync, authoring, importing, etc.). This can be configured through the
execution_strategies field. By default Wasm is always used for authoring. Native code is used, when possible, for all other cases.