sc_cli/commands/
export_state_cmd.rs1use crate::{
20 error,
21 params::{BlockNumberOrHash, DatabaseParams, PruningParams, SharedParams},
22 CliConfiguration,
23};
24use clap::Parser;
25use log::info;
26use sc_client_api::{HeaderBackend, StorageProvider, UsageProvider};
27use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
28use std::{fmt::Debug, io::Write, str::FromStr, sync::Arc};
29
30#[derive(Debug, Clone, Parser)]
33pub struct ExportStateCmd {
34 #[arg(value_name = "HASH or NUMBER")]
36 pub input: Option<BlockNumberOrHash>,
37
38 #[allow(missing_docs)]
39 #[clap(flatten)]
40 pub shared_params: SharedParams,
41
42 #[allow(missing_docs)]
43 #[clap(flatten)]
44 pub pruning_params: PruningParams,
45
46 #[allow(missing_docs)]
47 #[clap(flatten)]
48 pub database_params: DatabaseParams,
49}
50
51impl ExportStateCmd {
52 pub async fn run<B, BA, C>(
54 &self,
55 client: Arc<C>,
56 mut input_spec: Box<dyn sc_service::ChainSpec>,
57 ) -> error::Result<()>
58 where
59 B: BlockT,
60 C: UsageProvider<B> + StorageProvider<B, BA> + HeaderBackend<B>,
61 BA: sc_client_api::backend::Backend<B>,
62 <B::Hash as FromStr>::Err: Debug,
63 <<B::Header as HeaderT>::Number as FromStr>::Err: Debug,
64 {
65 info!("Exporting raw state...");
66 let block_id = self.input.as_ref().map(|b| b.parse()).transpose()?;
67 let hash = match block_id {
68 Some(id) => client.expect_block_hash_from_id(&id)?,
69 None => client.usage_info().chain.best_hash,
70 };
71 let raw_state = sc_service::chain_ops::export_raw_state(client, hash)?;
72 input_spec.set_storage(raw_state);
73
74 info!("Generating new chain spec...");
75 let json = sc_service::chain_ops::build_spec(&*input_spec, true)?;
76 if std::io::stdout().write_all(json.as_bytes()).is_err() {
77 let _ = std::io::stderr().write_all(b"Error writing to stdout\n");
78 }
79 Ok(())
80 }
81}
82
83impl CliConfiguration for ExportStateCmd {
84 fn shared_params(&self) -> &SharedParams {
85 &self.shared_params
86 }
87
88 fn pruning_params(&self) -> Option<&PruningParams> {
89 Some(&self.pruning_params)
90 }
91
92 fn database_params(&self) -> Option<&DatabaseParams> {
93 Some(&self.database_params)
94 }
95}