Use try-runtime
Please read Substrate to Polkadot SDK page first.
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.toml
configuration file in a text editor. - Locate the [dependencies] section and note how other pallets are imported.
-
Add the
frame-try-runtime
dependency:[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-runtime
pallet to theCargo.toml
file if the other pallets usebranch = "polkadot-v1.0.0"
. -
Add the
try-runtime-cli
dependency:try-runtime-cli = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "polkadot-v1.0.0", optional = true }
-
Add
frame-try-runtime
to the list of standard features:[features] default = ["std"] std = [ "codec/std", "scale-info/std", "frame-try-runtime/std", ... ] ```
-
Add or update
try-runtime
in 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.toml
configuration file in a text editor. - Locate the [dependencies] section and note how other pallets are imported.
-
Add the
frame-try-runtime
dependency:frame-try-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "polkadot-v1.0.0", optional = true }
-
Add the
try-runtime-cli
dependency:try-runtime-cli = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "polkadot-v1.0.0", optional = true }
-
Add or update
cli
andtry-runtime
in 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.rs
file 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.rs
file 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_with
on instance.