Skip to main content

soil_cli/commands/
export_state_cmd.rs

1// This file is part of Soil.
2
3// Copyright (C) Soil contributors.
4// Copyright (C) Parity Technologies (UK) Ltd.
5// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
6
7use crate::{
8	error,
9	params::{BlockNumberOrHash, DatabaseParams, PruningParams, SharedParams},
10	CliConfiguration,
11};
12use clap::Parser;
13use log::info;
14use soil_client::client_api::{HeaderBackend, StorageProvider, UsageProvider};
15use std::{fmt::Debug, io::Write, str::FromStr, sync::Arc};
16use subsoil::runtime::traits::{Block as BlockT, Header as HeaderT};
17
18/// The `export-state` command used to export the state of a given block into
19/// a chain spec.
20#[derive(Debug, Clone, Parser)]
21pub struct ExportStateCmd {
22	/// Block hash or number.
23	#[arg(value_name = "HASH or NUMBER")]
24	pub input: Option<BlockNumberOrHash>,
25
26	#[allow(missing_docs)]
27	#[clap(flatten)]
28	pub shared_params: SharedParams,
29
30	#[allow(missing_docs)]
31	#[clap(flatten)]
32	pub pruning_params: PruningParams,
33
34	#[allow(missing_docs)]
35	#[clap(flatten)]
36	pub database_params: DatabaseParams,
37}
38
39impl ExportStateCmd {
40	/// Run the `export-state` command
41	pub async fn run<B, BA, C>(
42		&self,
43		client: Arc<C>,
44		mut input_spec: Box<dyn soil_service::ChainSpec>,
45	) -> error::Result<()>
46	where
47		B: BlockT,
48		C: UsageProvider<B> + StorageProvider<B, BA> + HeaderBackend<B>,
49		BA: soil_client::client_api::backend::Backend<B>,
50		<B::Hash as FromStr>::Err: Debug,
51		<<B::Header as HeaderT>::Number as FromStr>::Err: Debug,
52	{
53		info!("Exporting raw state...");
54		let block_id = self.input.as_ref().map(|b| b.parse()).transpose()?;
55		let hash = match block_id {
56			Some(id) => client.expect_block_hash_from_id(&id)?,
57			None => client.usage_info().chain.best_hash,
58		};
59		let raw_state = soil_service::chain_ops::export_raw_state(client, hash)?;
60		input_spec.set_storage(raw_state);
61
62		info!("Generating new chain spec...");
63		let json = soil_service::chain_ops::build_spec(&*input_spec, true)?;
64		if std::io::stdout().write_all(json.as_bytes()).is_err() {
65			let _ = std::io::stderr().write_all(b"Error writing to stdout\n");
66		}
67		Ok(())
68	}
69}
70
71impl CliConfiguration for ExportStateCmd {
72	fn shared_params(&self) -> &SharedParams {
73		&self.shared_params
74	}
75
76	fn pruning_params(&self) -> Option<&PruningParams> {
77		Some(&self.pruning_params)
78	}
79
80	fn database_params(&self) -> Option<&DatabaseParams> {
81		Some(&self.database_params)
82	}
83}