subcoin_node/
cli.rs

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;
9// #[cfg(feature = "benchmark")]
10// use frame_benchmarking_cli::{BenchmarkCmd, SUBSTRATE_REFERENCE_HARDWARE};
11use 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 subcoin node.
21    Run(Box<Run>),
22
23    /// Import blocks from bitcoind database.
24    ImportBlocks(ImportBlocks),
25
26    /// Utility tools.
27    #[command(subcommand)]
28    Tools(Tools),
29
30    /// Blockchain.
31    #[command(subcommand)]
32    Blockchain(Blockchain),
33
34    /// Build a chain specification.
35    BuildSpec(sc_cli::BuildSpecCmd),
36
37    /// Validate blocks.
38    CheckBlock(Box<sc_cli::CheckBlockCmd>),
39
40    /// Export blocks.
41    ExportBlocks(sc_cli::ExportBlocksCmd),
42
43    /// Export the state of a given block into a chain spec.
44    ExportState(sc_cli::ExportStateCmd),
45
46    /// Remove the whole chain.
47    PurgeChain(sc_cli::PurgeChainCmd),
48
49    /// Revert the chain to a previous state.
50    Revert(sc_cli::RevertCmd),
51
52    // Sub-commands concerned with benchmarking.
53    // #[cfg(feature = "benchmark")]
54    // #[command(subcommand)]
55    // Benchmark(Box<frame_benchmarking_cli::BenchmarkCmd>),
56    /// Db meta columns information.
57    ChainInfo(sc_cli::ChainInfoCmd),
58}
59
60/// Subcoin Client Node
61#[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
72/// Parse and run command line arguments
73pub 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 block_id = cmd.input.as_ref().map(|b| b.parse()).transpose()?;
193                    // let hash = match block_id {
194                    // Some(id) => client.expect_block_hash_from_id(&id)?,
195                    // None => client.usage_info().chain.best_hash,
196                    let hash = client.usage_info().chain.best_hash;
197                    // };
198                    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        // #[cfg(feature = "benchmark")]
225        // Command::Benchmark(cmd) => {
226        // let runner = SubstrateCli.create_runner(&*cmd)?;
227
228        // runner.sync_run(|config| {
229        // // This switch needs to be in the client, since the client decides
230        // // which sub-commands it wants to support.
231        // match *cmd {
232        // BenchmarkCmd::Pallet(_cmd) => {
233        // unimplemented!("")
234        // }
235        // BenchmarkCmd::Block(cmd) => {
236        // let PartialComponents { client, .. } =
237        // subcoin_service::new_partial(&config, bitcoin::Network::Bitcoin)?;
238        // cmd.run(client)
239        // }
240        // #[cfg(not(feature = "runtime-benchmarks"))]
241        // BenchmarkCmd::Storage(_) => Err(
242        // "Storage benchmarking can be enabled with `--features runtime-benchmarks`."
243        // .into(),
244        // ),
245        // #[cfg(feature = "runtime-benchmarks")]
246        // BenchmarkCmd::Storage(cmd) => {
247        // let PartialComponents {
248        // client, backend, ..
249        // } = subcoin_service::new_partial(&config, bitcoin::Network::Bitcoin)?;
250        // let db = backend.expose_db();
251        // let storage = backend.expose_storage();
252
253        // cmd.run(config, client, db, storage)
254        // }
255        // BenchmarkCmd::Overhead(_cmd) => {
256        // unimplemented!("")
257        // }
258        // BenchmarkCmd::Extrinsic(_cmd) => {
259        // unimplemented!("")
260        // }
261        // BenchmarkCmd::Machine(cmd) => {
262        // cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone())
263        // }
264        // }
265        // })
266        // }
267        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}