diff --git a/Cargo.lock b/Cargo.lock index b2aca09fe2564..f82343e442a89 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10646,6 +10646,7 @@ dependencies = [ "sc-executor", "sc-service", "serde", + "serde_json", "sp-api", "sp-core", "sp-debug-derive", diff --git a/utils/frame/try-runtime/cli/Cargo.toml b/utils/frame/try-runtime/cli/Cargo.toml index c4cc2e757d90f..ed0f25cae7a36 100644 --- a/utils/frame/try-runtime/cli/Cargo.toml +++ b/utils/frame/try-runtime/cli/Cargo.toml @@ -30,11 +30,12 @@ sp-weights = { version = "4.0.0", path = "../../../../primitives/weights" } frame-try-runtime = { optional = true, path = "../../../../frame/try-runtime" } substrate-rpc-client = { path = "../../rpc/client" } -parity-scale-codec = "3.0.0" -hex = "0.4.3" clap = { version = "4.0.9", features = ["derive"] } +hex = { version = "0.4.3", default-features = false } log = "0.4.17" +parity-scale-codec = "3.0.0" serde = "1.0.136" +serde_json = "1.0.85" zstd = { version = "0.11.2", default-features = false } [dev-dependencies] diff --git a/utils/frame/try-runtime/cli/src/commands/execute_block.rs b/utils/frame/try-runtime/cli/src/commands/execute_block.rs index 80d34002fa771..ee5e21af5d3ba 100644 --- a/utils/frame/try-runtime/cli/src/commands/execute_block.rs +++ b/utils/frame/try-runtime/cli/src/commands/execute_block.rs @@ -134,6 +134,7 @@ where "TryRuntime_execute_block", &payload, full_extensions(), + shared.export_proof, )?; Ok(()) diff --git a/utils/frame/try-runtime/cli/src/commands/follow_chain.rs b/utils/frame/try-runtime/cli/src/commands/follow_chain.rs index 4eb3b3a8f35a9..e4f166fe7ada7 100644 --- a/utils/frame/try-runtime/cli/src/commands/follow_chain.rs +++ b/utils/frame/try-runtime/cli/src/commands/follow_chain.rs @@ -150,6 +150,10 @@ where "TryRuntime_execute_block", (block, command.state_root_check, command.try_state.clone()).encode().as_ref(), full_extensions(), + shared + .export_proof + .as_ref() + .map(|path| path.as_path().join(&format!("{}.json", number))), ); if let Err(why) = result { diff --git a/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs b/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs index 80fb5d31f71a9..2b2800d505864 100644 --- a/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs +++ b/utils/frame/try-runtime/cli/src/commands/on_runtime_upgrade.rs @@ -59,6 +59,7 @@ where "TryRuntime_on_runtime_upgrade", command.checks.encode().as_ref(), Default::default(), // we don't really need any extensions here. + shared.export_proof, )?; let (weight, total_weight) = <(Weight, Weight) as Decode>::decode(&mut &*encoded_result) diff --git a/utils/frame/try-runtime/cli/src/lib.rs b/utils/frame/try-runtime/cli/src/lib.rs index 47a9dfa3f6544..aac2ad4238431 100644 --- a/utils/frame/try-runtime/cli/src/lib.rs +++ b/utils/frame/try-runtime/cli/src/lib.rs @@ -523,6 +523,12 @@ pub struct SharedParams { #[arg(long)] pub heap_pages: Option, + /// Path to a file to export the storage proof into (as a JSON). + /// If several blocks are executed, the path is interpreted as a folder + /// where one file per block will be written (named `{block_number}-{block_hash}`). + #[clap(long)] + pub export_proof: Option, + /// Overwrite the `state_version`. /// /// Otherwise `remote-externalities` will automatically set the correct state version. @@ -863,6 +869,7 @@ pub(crate) fn state_machine_call_with_proof, ) -> sc_cli::Result<(OverlayedChanges, Vec)> { use parity_scale_codec::Encode; @@ -891,6 +898,32 @@ pub(crate) fn state_machine_call_with_proof &'static str { log::error!(target: LOG_TARGET, "rpc error: {:?}", error); "rpc error." } + +/// Converts a [`sp_state_machine::StorageProof`] into a JSON string. +fn storage_proof_to_raw_json(storage_proof: &sp_state_machine::StorageProof) -> String { + serde_json::Value::Object( + storage_proof + .to_memory_db::() + .drain() + .iter() + .map(|(key, (value, _n))| { + ( + format!("0x{}", hex::encode(key.as_bytes())), + serde_json::Value::String(format!("0x{}", hex::encode(value))), + ) + }) + .collect(), + ) + .to_string() +}