Use try-runtime
The try-runtime tool enables you to run tests and verify operations in a simulated environment before launching a runtime to production.
This guide demonstrates the basic steps for integrating the try-runtime tool into a runtime so you can use it to test a storage migration.
In general, adding the try-runtime tool to your runtime is similar to importing pallets.
It involves adding the appropriate dependencies in the correct places and updating the runtime logic to include the try-runtime features.
As with pallets, be sure that you are using the appropriate tag or branch for the try-runtime tool when adding dependencies to the runtime.
Add runtime dependencies
- Open a terminal shell and change to the root directory for the node template.
- Open the
runtime/Cargo.tomlconfiguration file in a text editor. - Locate the [dependencies] section and note how other pallets are imported.
-
Add the
frame-try-runtimedependency:[dependencies] frame-try-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "polkadot-v1.0.0", optional = true }Note that you should use the same branch and version information for all of the pallets to ensure that the imported pallets are compatible with each other. Using pallets from different branches can result in compiler errors. This example illustrates adding the
frame-try-runtimepallet to theCargo.tomlfile if the other pallets usebranch = "polkadot-v1.0.0". -
Add the
try-runtime-clidependency:try-runtime-cli = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "polkadot-v1.0.0", optional = true } -
Add
frame-try-runtimeto the list of standard features:[features] default = ["std"] std = [ "codec/std", "scale-info/std", "frame-try-runtime/std", ... ] ``` -
Add or update
try-runtimein the[features]section in include every pallet in your runtime.try-runtime = [ "frame-executive/try-runtime", "frame-try-runtime", "frame-system/try-runtime", "pallet-aura/try-runtime", "pallet-balances/try-runtime", "pallet-nicks/try-runtime", "pallet-grandpa/try-runtime", "pallet-randomness-collective-flip/try-runtime", "pallet-sudo/try-runtime", "pallet-template/try-runtime", "pallet-timestamp/try-runtime", "pallet-transaction-payment/try-runtime", ]
Implement try-runtime in the runtime api
-
Add a configuration block for the try-runtime feature.
// Implementation of runtime's apis impl_runtime_apis! { ... /* --snip-- */ #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime<Block> for Runtime { fn on_runtime_upgrade() -> (frame_support::weights::Weight, frame_support::weights::Weight) { log::info!("try-runtime::on_runtime_upgrade."); // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to // have a backtrace here. If any of the pre/post migration checks fail, we shall stop // right here and right now. let weight = Executive::try_runtime_upgrade().map_err(|err|{ log::info!("try-runtime::on_runtime_upgrade failed with: {:?}", err); err }).unwrap(); (weight, RuntimeBlockWeights::get().max_block) } fn execute_block_no_check(block: Block) -> frame_support::weights::Weight { Executive::execute_block_no_check(block) } } ```
Add node dependencies
- Open the
node/Cargo.tomlconfiguration file in a text editor. - Locate the [dependencies] section and note how other pallets are imported.
-
Add the
frame-try-runtimedependency:frame-try-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "polkadot-v1.0.0", optional = true } -
Add the
try-runtime-clidependency:try-runtime-cli = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "polkadot-v1.0.0", optional = true } -
Add or update
cliandtry-runtimein the[features]section.[features] ... cli = [ "try-runtime-cli" ] try-runtime = [ "node-template-runtime/try-runtime", "try-runtime-cli" ] ...
Add command-line subcommands
- Open the
node/src/cli.rsfile in a text editor.
/* --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-- */Add commands
- Open the
node/src/commands.rsfile in a text editor. -
Add commands
/* --snip-- */ #[cfg(feature = "try-runtime")] Some(Subcommand::TryRuntime(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { // only need 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.tokio_handle.clone(), registry, ).map_err(|e| sc_cli::Error::Service(sc_service::Error::Prometheus(e)))?; Ok((cmd.run::<Block, service::ExecutorDispatch>(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-- */
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.
Use the try-runtime
Using the try-runtime tool is similar to writing unit tests.
To use try-runtime:
- Create an externalities instance.
- Call
execute_withon instance.
