#
pezkuwi_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 Bizinikiwi-based blockchains, state transition functions are referred to as
    9//! [runtimes](https://docs.pezkuwichain.io/sdk/master/pezkuwi_sdk_docs/reference_docs/blockchain_state_machines/index.html).
    10//!
    11//! Traditionally, before Bizinikiwi, 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//! Bizinikiwi-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 Bizinikiwi 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`](pezframe_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 [`pezpallet_scheduler`].
    31//!
    32//! Prior to building the new runtime, don't forget to update the
    33//! [`RuntimeVersion`](pezsp_version::RuntimeVersion).
    34//!
    35//! # Migrations
    36//!
    37//! It is often desirable to define logic to execute immediately after runtime upgrades (see
    38//! [this diagram](pezframe::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' pezpallet storage from one layout to
    43//! another, for example when the encoding of a storage item is changed. However, they can also
    44//! execute arbitrary logic such as:
    45//!
    46//! - Calling arbitrary pezpallet 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 pezpallet storage migrations, see the
    58//! [Single Block Migration Example Pezpallet](pezpallet_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 parameter to your
    63//! [`Config`](pezframe_system) pezpallet:
    64//!
    65//! ```ignore
    66//! /// Tuple of migrations (structs that implement `OnRuntimeUpgrade`)
    67//! type Migrations = (
    68//! 	pezpallet_example_storage_migration::migrations::v1::versioned::MigrateV0ToV1,
    69//! 	MyCustomMigration,
    70//! 	// ...more migrations here
    71//! );
    72//! impl pezframe_system::Config for Runtime {
    73//! 	type SingleBlockMigrations = Migrations;
    74//! }
    75//! ```
    76//!
    77//! ### Ensuring Single Block Migration Safety
    78//!
    79//! "My migration unit tests pass, so it should be safe to deploy right?"
    80//!
    81//! No! Unit tests execute the migration in a very simple test environment, and cannot account
    82//! for the complexities of a real runtime or real on-chain state.
    83//!
    84//! Prior to deploying migrations, it is critical to perform additional checks to ensure that when
    85//! run in our real runtime they will not brick the chain due to:
    86//! - Panicking.
    87//! - Touching too many storage keys and resulting in an excessively large PoV.
    88//! - Taking too long to execute.
    89//!
    90//! [`try-runtime-cli`](https://github.com/paritytech/try-runtime-cli) has a sub-command
    91//! [`on-runtime-upgrade`](https://paritytech.github.io/try-runtime-cli/try_runtime_core/commands/enum.Action.html#variant.OnRuntimeUpgrade)
    92//! which is designed to help with exactly this.
    93//!
    94//! Developers MUST run this command before deploying migrations to ensure they will not
    95//! inadvertently result in a bricked chain.
    96//!
    97//! It is recommended to run as part of your CI pipeline. See the
    98//! [pezkuwi-sdk check-runtime-migration job](https://github.com/pezkuwichain/pezkuwi-sdk/blob/4a293bc5a25be637c06ce950a34490706597615b/.gitlab/pipeline/check.yml#L103-L124)
    99//! for an example of how to configure this.
    100//!
    101//! ### Note on the Manipulability of PoV Size and Execution Time
    102//!
    103//! While [`try-runtime-cli`](https://github.com/paritytech/try-runtime-cli) can help ensure with
    104//! very high certainty that a migration will succeed given **existing** on-chain state, it cannot
    105//! prevent a malicious actor from manipulating state in a way that will cause the migration to take
    106//! longer or produce a PoV much larger than previously measured.
    107//!
    108//! Therefore, it is important to write migrations in such a way that the execution time or PoV size
    109//! it adds to the block cannot be easily manipulated. e.g., do not iterate over storage that can
    110//! quickly or cheaply be bloated.
    111//!
    112//! If writing your migration in such a way is not possible, a multi block migration should be used
    113//! instead.
    114//!
    115//! ### Other useful tools
    116//!
    117//! [`Chopsticks`](https://github.com/AcalaNetwork/chopsticks) is another tool in the Bizinikiwi
    118//! ecosystem which developers may find useful to use in addition to `try-runtime-cli` when testing
    119//! their single block migrations.
    120//!
    121//! ## Multi Block Migrations
    122//!
    123//! Safely and easily execute long-running migrations across multiple blocks.
    124//!
    125//! Suitable for migrations which could use arbitrary amounts of block weight.
    126//!
    127//! See the
    128//! [multi-block-migrations example](https://github.com/pezkuwichain/pezkuwi-sdk/tree/0d7d2177807ec6b3094f4491a45b0bc0d74d3c8b/bizinikiwi/pezframe/examples/multi-block-migrations)
    129//! for reference.
    130//!
    131//! [`OnRuntimeUpgrade`]: pezframe_support::traits::OnRuntimeUpgrade
    132//! [`StorageVersion`]: pezframe_support::traits::StorageVersion
    133//! [`set_code`]: pezframe_system::Call::set_code
    134//! [`set_code_without_checks`]: pezframe_system::Call::set_code_without_checks