1pub mod subcoin_params;
2
3use crate::commands::blockchain::{Blockchain, BlockchainCmd};
4use crate::commands::import_blocks::{ImportBlocks, ImportBlocksCmd};
5use crate::commands::run::{Run, RunCmd};
6use crate::commands::tools::Tools;
7use crate::substrate_cli::SubstrateCli;
8use clap::Parser;
9use sc_cli::SubstrateCli as SubstrateCliT;
12use sc_client_api::UsageProvider;
13use sc_consensus_nakamoto::ImportConfig;
14use sc_service::PartialComponents;
15use std::sync::Arc;
16use subcoin_primitives::CONFIRMATION_DEPTH;
17
18#[derive(Debug, clap::Subcommand)]
19pub enum Command {
20    Run(Box<Run>),
22
23    ImportBlocks(ImportBlocks),
25
26    #[command(subcommand)]
28    Tools(Tools),
29
30    #[command(subcommand)]
32    Blockchain(Blockchain),
33
34    BuildSpec(sc_cli::BuildSpecCmd),
36
37    CheckBlock(Box<sc_cli::CheckBlockCmd>),
39
40    ExportBlocks(sc_cli::ExportBlocksCmd),
42
43    ExportState(sc_cli::ExportStateCmd),
45
46    PurgeChain(sc_cli::PurgeChainCmd),
48
49    Revert(sc_cli::RevertCmd),
51
52    ChainInfo(sc_cli::ChainInfoCmd),
58}
59
60#[derive(Debug, Parser)]
62#[clap(version = env!("SUBSTRATE_CLI_IMPL_VERSION"))]
63pub struct Cli {
64    #[command(subcommand)]
65    pub command: Command,
66
67    #[allow(missing_docs)]
68    #[clap(flatten)]
69    pub storage_monitor: sc_storage_monitor::StorageMonitorParams,
70}
71
72pub fn run() -> sc_cli::Result<()> {
74    let Cli {
75        command,
76        storage_monitor,
77    } = Cli::parse();
78
79    match command {
80        Command::Run(run) => {
81            let run_cmd = RunCmd::new(*run);
82            let runner = SubstrateCli.create_runner(&run_cmd)?;
83            runner.run_node_until_exit(|config| async move {
84                run_cmd.start(config, storage_monitor).await
85            })
86        }
87        Command::ImportBlocks(cmd) => {
88            let bitcoin_network = cmd.common_params.bitcoin_network();
89            let import_config = ImportConfig {
90                execute_block: cmd.execute_transactions,
91                ..cmd.common_params.import_config(true)
92            };
93            let chain_spec_id = cmd.common_params.chain.chain_spec_id();
94            let maybe_prometheus_config = cmd
95                .prometheus_params
96                .prometheus_config(9615, chain_spec_id.to_string());
97            let import_blocks_cmd = ImportBlocksCmd::new(&cmd);
98            let runner = SubstrateCli.create_runner(&import_blocks_cmd)?;
99            let data_dir = cmd.data_dir;
100            runner.async_run(|config| {
101                let subcoin_service::NodeComponents {
102                    client,
103                    task_manager,
104                    ..
105                } = subcoin_service::new_node(subcoin_service::SubcoinConfiguration {
106                    network: bitcoin_network,
107                    config: &config,
108                    no_hardware_benchmarks: true,
109                    storage_monitor,
110                })?;
111                let spawn_handle = task_manager.spawn_handle();
112                spawn_handle.spawn("finalizer", None, {
113                    let client = client.clone();
114                    let spawn_handle = task_manager.spawn_handle();
115                    subcoin_service::SubcoinFinalizer::new(
116                        client,
117                        spawn_handle,
118                        CONFIRMATION_DEPTH,
119                        Arc::new(subcoin_network::OfflineSync),
120                        None,
121                    )
122                    .run()
123                });
124                Ok((
125                    import_blocks_cmd.run(
126                        client,
127                        data_dir,
128                        import_config,
129                        spawn_handle,
130                        maybe_prometheus_config,
131                    ),
132                    task_manager,
133                ))
134            })
135        }
136        Command::Tools(tools) => tools.run(),
137        Command::Blockchain(blockchain) => {
138            let cmd = BlockchainCmd::new(blockchain);
139            let runner = SubstrateCli.create_runner(&cmd)?;
140            runner.async_run(|config| {
141                let subcoin_service::NodeComponents {
142                    client,
143                    task_manager,
144                    ..
145                } = subcoin_service::new_node(subcoin_service::SubcoinConfiguration {
146                    network: bitcoin::Network::Bitcoin,
147                    config: &config,
148                    no_hardware_benchmarks: true,
149                    storage_monitor,
150                })?;
151                Ok((cmd.run(client), task_manager))
152            })
153        }
154        Command::BuildSpec(cmd) => {
155            let runner = SubstrateCli.create_runner(&cmd)?;
156            runner.sync_run(|config| cmd.run(config.chain_spec, config.network))
157        }
158        Command::CheckBlock(cmd) => {
159            let runner = SubstrateCli.create_runner(&*cmd)?;
160            runner.async_run(|config| {
161                let PartialComponents {
162                    client,
163                    task_manager,
164                    import_queue,
165                    ..
166                } = subcoin_service::new_partial(&config, bitcoin::Network::Bitcoin)?;
167                Ok((cmd.run(client, import_queue), task_manager))
168            })
169        }
170        Command::ExportBlocks(cmd) => {
171            let runner = SubstrateCli.create_runner(&cmd)?;
172            runner.async_run(|config| {
173                let PartialComponents {
174                    client,
175                    task_manager,
176                    ..
177                } = subcoin_service::new_partial(&config, bitcoin::Network::Bitcoin)?;
178                Ok((cmd.run(client, config.database), task_manager))
179            })
180        }
181        Command::ExportState(cmd) => {
182            let runner = SubstrateCli.create_runner(&cmd)?;
183            runner.async_run(|config| {
184                let PartialComponents {
185                    client,
186                    task_manager,
187                    ..
188                } = subcoin_service::new_partial(&config, bitcoin::Network::Bitcoin)?;
189
190                let run_cmd = async move {
191                    tracing::info!("Exporting raw state...");
192                    let hash = client.usage_info().chain.best_hash;
197                    let _raw_state = sc_service::chain_ops::export_raw_state(client, hash).unwrap();
199
200                    tracing::info!("Raw state exported successfully");
201
202                    Ok(())
203                };
204
205                Ok((run_cmd, task_manager))
206            })
207        }
208        Command::PurgeChain(cmd) => {
209            let runner = SubstrateCli.create_runner(&cmd)?;
210            runner.sync_run(|config| cmd.run(config.database))
211        }
212        Command::Revert(cmd) => {
213            let runner = SubstrateCli.create_runner(&cmd)?;
214            runner.async_run(|config| {
215                let PartialComponents {
216                    client,
217                    task_manager,
218                    backend,
219                    ..
220                } = subcoin_service::new_partial(&config, bitcoin::Network::Bitcoin)?;
221                Ok((cmd.run(client, backend, None), task_manager))
222            })
223        }
224        Command::ChainInfo(cmd) => {
268            let runner = SubstrateCli.create_runner(&cmd)?;
269            runner.sync_run(|config| cmd.run::<subcoin_runtime::interface::OpaqueBlock>(&config))
270        }
271    }
272}