Developers Home»How-to Guide»Integrate Try Runtime

Integrate Try Runtime

Goal

Include try-runtime to use it in a Substrate node.

Use Cases

Use try-runtime to test a storage migration.

Overview

The try-runtime tool is useful for running tests before launching a runtime to production. This is a simple guide which steps through which dependencies to include and where to include them in order to use it inside a runtime.


Match versions!

Be sure to use the correct tag/branch when adding your dependencies!

Steps

1. Adding runtime dependencies

In runtime/Cargo.toml

Add the FRAME dependency:

[dependencies]
frame-try-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.17", optional = true }
try-runtime-cli = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.17", optional = true }

/* --snip-- */
    std = [
    /* --snip-- */
    "frame-try-runtime/std",
]

In runtime/Cargo.toml, for every pallet in your runtime:

try-runtime = [
    "frame-executive/try-runtime",
    "frame-try-runtime",
    "frame-system/try-runtime",
]

In runtime/src/lib.rs, implement it for your runtime:

#[cfg(feature = "try-runtime")]
impl frame_try_runtime::TryRuntime<Block> for Runtime {
    fn on_runtime_upgrade() -> Result<(Weight, Weight), sp_runtime::RuntimeString> {
        log::info!("try-runtime::on_runtime_upgrade.");
        let weight = Executive::try_runtime_upgrade()?;
        Ok((weight, BlockWeights::get().max_block))
    }
}

2. Adding node dependencies

In node/Cargo.toml (always check for the latest version):

[features]
/* --snip-- */
cli = [
    'try-runtime-cli',
]
try-runtime = [
    "node-template-runtime/try-runtime",
    "try-runtime-cli",
]

/* --snip-- */
frame-try-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.17", optional = true }
try-runtime-cli = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.17", optional = true }
/* --snip-- */

In node/src/cli.rs add the subcommands:

/* --snip-- */
/// Try some command against runtime state.
#[cfg(feature = "try-runtime")]
TryRuntime(try_runtime_cli::TryRuntimeCmd),

/// Try some command against runtime state. Note: `try-runtime` feature must be enabled.
#[cfg(not(feature = "try-runtime"))]
TryRuntime,
/* --snip-- */

In node/src/commands.rs, add:

/* --snip-- */
#[cfg(feature = "try-runtime")]
Some(Subcommand::TryRuntime(cmd)) => {
    let runner = cli.create_runner(cmd)?;
    runner.async_run(|config| {
        // we don't need any of the components of new_partial, just a runtime, or a task
        // manager to do `async_run`.
        let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry);
        let task_manager = sc_service::TaskManager::new(
            config.task_executor.clone(),
            registry,
        ).map_err(|e| sc_cli::Error::Service(sc_service::Error::Prometheus(e)))?;

        Ok((cmd.run::<Block, Executor>(config), task_manager))
    })
},

#[cfg(not(feature = "try-runtime"))]
Some(Subcommand::TryRuntime) => {
    Err("TryRuntime wasn't enabled when building the node. \
        You can enable it with `--features try-runtime`.".into())
},
/* --snip-- */

Note

If you're using custom pallets in your workspace, make sure you included try-runtime in the dependencies inside the pallets/pallet_name/Cargo.toml file of your workspace.

3. Using try-runtime

Just like writing unit tests, to use try-runtime create an externalities instance and call execute_with on it.

Examples

Resources

Docs

Try runtime

Other

Last edit: on

Run into problems?
Let us Know