try_runtime_core/commands/
create_snapshot.rs

1// This file is part of try-runtime-cli.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18use std::{fmt::Debug, str::FromStr};
19
20use sc_executor::sp_wasm_interface::HostFunctions;
21use sp_runtime::traits::{Block as BlockT, NumberFor};
22use substrate_rpc_client::{ws_client, StateApi};
23
24use crate::{
25    common::{
26        shared_parameters,
27        state::{build_executor, LiveState, RuntimeChecks, State},
28    },
29    SharedParams, LOG_TARGET,
30};
31
32/// Configurations for [`run`].
33#[derive(Debug, Clone, clap::Parser)]
34pub struct Command {
35    /// The source of the snapshot. Must be a remote node.
36    #[clap(flatten)]
37    pub from: LiveState,
38
39    /// The snapshot path to write to.
40    ///
41    /// If not provided `<spec-name>-<spec-version>@<block-hash>.snap` will be used.
42    #[clap(index = 1)]
43    pub snapshot_path: Option<String>,
44}
45
46/// Runs the `create_snapshot` command.
47pub async fn run<Block, HostFns>(shared: SharedParams, command: Command) -> sc_cli::Result<()>
48where
49    Block: BlockT + serde::de::DeserializeOwned,
50    Block::Hash: serde::de::DeserializeOwned,
51    Block::Header: serde::de::DeserializeOwned,
52    <Block::Hash as FromStr>::Err: Debug,
53    NumberFor<Block>: FromStr,
54    <NumberFor<Block> as FromStr>::Err: Debug,
55    HostFns: HostFunctions,
56{
57    let snapshot_path = command.snapshot_path;
58    if !matches!(shared.runtime, shared_parameters::Runtime::Existing) {
59        return Err("creating a snapshot is only possible with --runtime existing.".into());
60    }
61
62    let path = match snapshot_path {
63        Some(path) => path,
64        None => {
65            let rpc = ws_client(&command.from.uri).await.unwrap();
66            let remote_spec = StateApi::<Block::Hash>::runtime_version(&rpc, None)
67                .await
68                .unwrap();
69            let path_str = format!(
70                "{}-{}@{}.snap",
71                remote_spec.spec_name.to_lowercase(),
72                remote_spec.spec_version,
73                command.from.at.clone().unwrap_or("latest".to_owned())
74            );
75            log::info!(target: LOG_TARGET, "snapshot path not provided (-s), using '{}'", path_str);
76            path_str
77        }
78    };
79
80    let executor = build_executor::<HostFns>(&shared);
81    let runtime_checks = RuntimeChecks {
82        name_matches: false,
83        version_increases: false,
84        try_runtime_feature_enabled: false,
85    };
86    let _ = State::Live(command.from)
87        .to_ext::<Block, HostFns>(&shared, &executor, Some(path.into()), runtime_checks)
88        .await?;
89
90    Ok(())
91}