referrerpolicy=no-referrer-when-downgrade

polkadot_sdk_docs/reference_docs/
frame_runtime_upgrades_and_migrations.rs

1//! # Runtime Upgrades
2//!
3//! At their core, blockchain logic consists of
4//!
5//! 1. on-chain state,
6//! 2. a state transition function.
7//!
8//! In Substrate-based blockchains, state transition functions are referred to as
9//! [runtimes](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/blockchain_state_machines/index.html).
10//!
11//! Traditionally, before Substrate, upgrading state transition functions required node
12//! operators to download new software and restart their nodes in a process called
13//! [forking](https://en.wikipedia.org/wiki/Fork_(blockchain)).
14//!
15//! Substrate-based blockchains do not require forking, and instead upgrade runtimes
16//! in a process called "Runtime Upgrades".
17//!
18//! Forkless runtime upgrades are a defining feature of the Substrate framework. Updating the
19//! runtime logic without forking the code base enables your blockchain to seamlessly evolve
20//! over time in a deterministic, rules-based manner. It also removes ambiguity for node operators
21//! and other participants in the network about what is the canonical runtime.
22//!
23//! This capability is possible due to the runtime of a blockchain existing in on-chain storage.
24//!
25//! ## Performing a Runtime Upgrade
26//!
27//! To upgrade a runtime, an [`Origin`](frame_system::RawOrigin) with the necessary permissions
28//! (usually via governance) changes the `:code` storage. Usually, this is performed via a call to
29//! [`set_code`] (or [`set_code_without_checks`]) with the desired new runtime blob, scheduled
30//! using [`pallet_scheduler`].
31//!
32//! Prior to building the new runtime, don't forget to update the
33//! [`RuntimeVersion`](sp_version::RuntimeVersion).
34//!
35//! # Migrations
36//!
37//! It is often desirable to define logic to execute immediately after runtime upgrades (see
38//! [this diagram](frame::traits::Hooks)).
39//!
40//! Self-contained pieces of logic that execute after a runtime upgrade are called "Migrations".
41//!
42//! The typical use case of a migration is to 'migrate' pallet storage from one layout to another,
43//! for example when the encoding of a storage item is changed. However, they can also execute
44//! arbitrary logic such as:
45//!
46//! - Calling arbitrary pallet methods.
47//! - Mutating arbitrary on-chain state.
48//! - Cleaning up some old storage items that are no longer needed.
49//!
50//! ## Single Block Migrations
51//!
52//! - Execute immediately and entirely at the beginning of the block following
53//! a runtime upgrade.
54//! - Are suitable for migrations which are guaranteed to not exceed the block weight.
55//! - Are simply implementations of [`OnRuntimeUpgrade`].
56//!
57//! To learn best practices for writing single block pallet storage migrations, see the
58//! [Single Block Migration Example Pallet](pallet_example_single_block_migrations).
59//!
60//! ### Scheduling the Single Block Migrations to Run Next Runtime Upgrade
61//!
62//! Schedule migrations to run next runtime upgrade passing them as a generic parameter to your
63//! [`Executive`](frame_executive) pallet:
64//!
65//! ```ignore
66//! /// Tuple of migrations (structs that implement `OnRuntimeUpgrade`)
67//! type Migrations = (
68//! 	pallet_example_storage_migration::migrations::v1::versioned::MigrateV0ToV1,
69//! 	MyCustomMigration,
70//! 	// ...more migrations here
71//! );
72//! pub type Executive = frame_executive::Executive<
73//! 	Runtime,
74//! 	Block,
75//! 	frame_system::ChainContext<Runtime>,
76//! 	Runtime,
77//! 	AllPalletsWithSystem,
78//! 	Migrations, // <-- pass your migrations to Executive here
79//! >;
80//! ```
81//!
82//! ### Ensuring Single Block Migration Safety
83//!
84//! "My migration unit tests pass, so it should be safe to deploy right?"
85//!
86//! No! Unit tests execute the migration in a very simple test environment, and cannot account
87//! for the complexities of a real runtime or real on-chain state.
88//!
89//! Prior to deploying migrations, it is critical to perform additional checks to ensure that when
90//! run in our real runtime they will not brick the chain due to:
91//! - Panicking.
92//! - Touching too many storage keys and resulting in an excessively large PoV.
93//! - Taking too long to execute.
94//!
95//! [`try-runtime-cli`](https://github.com/paritytech/try-runtime-cli) has a sub-command
96//! [`on-runtime-upgrade`](https://paritytech.github.io/try-runtime-cli/try_runtime_core/commands/enum.Action.html#variant.OnRuntimeUpgrade)
97//! which is designed to help with exactly this.
98//!
99//! Developers MUST run this command before deploying migrations to ensure they will not
100//! inadvertently result in a bricked chain.
101//!
102//! It is recommended to run as part of your CI pipeline. See the
103//! [polkadot-sdk check-runtime-migration job](https://github.com/paritytech/polkadot-sdk/blob/4a293bc5a25be637c06ce950a34490706597615b/.gitlab/pipeline/check.yml#L103-L124)
104//! for an example of how to configure this.
105//!
106//! ### Note on the Manipulability of PoV Size and Execution Time
107//!
108//! While [`try-runtime-cli`](https://github.com/paritytech/try-runtime-cli) can help ensure with
109//! very high certainty that a migration will succeed given **existing** on-chain state, it cannot
110//! prevent a malicious actor from manipulating state in a way that will cause the migration to take
111//! longer or produce a PoV much larger than previously measured.
112//!
113//! Therefore, it is important to write migrations in such a way that the execution time or PoV size
114//! it adds to the block cannot be easily manipulated. e.g., do not iterate over storage that can
115//! quickly or cheaply be bloated.
116//!
117//! If writing your migration in such a way is not possible, a multi block migration should be used
118//! instead.
119//!
120//! ### Other useful tools
121//!
122//! [`Chopsticks`](https://github.com/AcalaNetwork/chopsticks) is another tool in the Substrate
123//! ecosystem which developers may find useful to use in addition to `try-runtime-cli` when testing
124//! their single block migrations.
125//!
126//! ## Multi Block Migrations
127//!
128//! Safely and easily execute long-running migrations across multiple blocks.
129//!
130//! Suitable for migrations which could use arbitrary amounts of block weight.
131//!
132//! See the
133//! [multi-block-migrations example](https://github.com/paritytech/polkadot-sdk/tree/0d7d2177807ec6b3094f4491a45b0bc0d74d3c8b/substrate/frame/examples/multi-block-migrations)
134//! for reference.
135//!
136//! [`OnRuntimeUpgrade`]: frame_support::traits::OnRuntimeUpgrade
137//! [`StorageVersion`]: frame_support::traits::StorageVersion
138//! [`set_code`]: frame_system::Call::set_code
139//! [`set_code_without_checks`]: frame_system::Call::set_code_without_checks