1use polkadot_sdk::*;
20
21use super::benchmarking::{inherent_benchmark_data, RemarkBuilder, TransferKeepAliveBuilder};
22use crate::{
23 chain_spec, service,
24 service::{new_partial, FullClient},
25 Cli, Subcommand,
26};
27use frame_benchmarking_cli::*;
28use kitchensink_runtime::{ExistentialDeposit, RuntimeApi};
29use node_primitives::Block;
30use sc_cli::{Result, SubstrateCli};
31use sc_service::PartialComponents;
32use sp_keyring::Sr25519Keyring;
33use sp_runtime::traits::HashingFor;
34
35use std::sync::Arc;
36
37impl SubstrateCli for Cli {
38 fn impl_name() -> String {
39 "Substrate Node".into()
40 }
41
42 fn impl_version() -> String {
43 env!("SUBSTRATE_CLI_IMPL_VERSION").into()
44 }
45
46 fn description() -> String {
47 env!("CARGO_PKG_DESCRIPTION").into()
48 }
49
50 fn author() -> String {
51 env!("CARGO_PKG_AUTHORS").into()
52 }
53
54 fn support_url() -> String {
55 "https://github.com/paritytech/polkadot-sdk/issues/new".into()
56 }
57
58 fn copyright_start_year() -> i32 {
59 2017
60 }
61
62 fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
63 let spec = match id {
64 "" =>
65 return Err(
66 "Please specify which chain you want to run, e.g. --dev or --chain=local"
67 .into(),
68 ),
69 "dev" => Box::new(chain_spec::development_config()),
70 "local" => Box::new(chain_spec::local_testnet_config()),
71 "fir" | "flaming-fir" => Box::new(chain_spec::flaming_fir_config()?),
72 "staging" => Box::new(chain_spec::staging_testnet_config()),
73 path =>
74 Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?),
75 };
76 Ok(spec)
77 }
78}
79
80pub fn run() -> Result<()> {
82 let cli = Cli::from_args();
83
84 match &cli.subcommand {
85 None => {
86 let runner = cli.create_runner(&cli.run)?;
87 runner.run_node_until_exit(|config| async move {
88 service::new_full(config, cli).map_err(sc_cli::Error::Service)
89 })
90 },
91 Some(Subcommand::Inspect(cmd)) => {
92 let runner = cli.create_runner(cmd)?;
93
94 runner.sync_run(|config| cmd.run::<Block, RuntimeApi>(config))
95 },
96 Some(Subcommand::ExportChainSpec(cmd)) => {
97 let chain_spec = cli.load_spec(&cmd.chain)?;
98 cmd.run(chain_spec)
99 },
100 Some(Subcommand::Benchmark(cmd)) => {
101 let runner = cli.create_runner(cmd)?;
102
103 runner.sync_run(|config| {
104 match cmd {
107 BenchmarkCmd::Pallet(cmd) => {
108 if !cfg!(feature = "runtime-benchmarks") {
109 return Err(
110 "Runtime benchmarking wasn't enabled when building the node. \
111 You can enable it with `--features runtime-benchmarks`."
112 .into(),
113 )
114 }
115
116 cmd.run_with_spec::<HashingFor<Block>, sp_statement_store::runtime_api::HostFunctions>(Some(config.chain_spec))
117 },
118 BenchmarkCmd::Block(cmd) => {
119 let partial = new_partial(&config, None)?;
121 cmd.run(partial.client)
122 },
123 #[cfg(not(feature = "runtime-benchmarks"))]
124 BenchmarkCmd::Storage(_) => Err(
125 "Storage benchmarking can be enabled with `--features runtime-benchmarks`."
126 .into(),
127 ),
128 #[cfg(feature = "runtime-benchmarks")]
129 BenchmarkCmd::Storage(cmd) => {
130 let partial = new_partial(&config, None)?;
132 let db = partial.backend.expose_db();
133 let storage = partial.backend.expose_storage();
134 let shared_trie_cache = partial.backend.expose_shared_trie_cache();
135
136 cmd.run(config, partial.client, db, storage, shared_trie_cache)
137 },
138 BenchmarkCmd::Overhead(cmd) => {
139 let partial = new_partial(&config, None)?;
141 let ext_builder = RemarkBuilder::new(partial.client.clone());
142
143 cmd.run(
144 config.chain_spec.name().into(),
145 partial.client,
146 inherent_benchmark_data()?,
147 Vec::new(),
148 &ext_builder,
149 false,
150 )
151 },
152 BenchmarkCmd::Extrinsic(cmd) => {
153 let partial = service::new_partial(&config, None)?;
155 let ext_factory = ExtrinsicFactory(vec![
157 Box::new(RemarkBuilder::new(partial.client.clone())),
158 Box::new(TransferKeepAliveBuilder::new(
159 partial.client.clone(),
160 Sr25519Keyring::Alice.to_account_id(),
161 ExistentialDeposit::get(),
162 )),
163 ]);
164
165 cmd.run(
166 partial.client,
167 inherent_benchmark_data()?,
168 Vec::new(),
169 &ext_factory,
170 )
171 },
172 BenchmarkCmd::Machine(cmd) =>
173 cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone()),
174 }
175 })
176 },
177 Some(Subcommand::Key(cmd)) => cmd.run(&cli),
178 Some(Subcommand::Sign(cmd)) => cmd.run(),
179 Some(Subcommand::Verify(cmd)) => cmd.run(),
180 Some(Subcommand::Vanity(cmd)) => cmd.run(),
181 #[allow(deprecated)]
182 Some(Subcommand::BuildSpec(cmd)) => {
183 let runner = cli.create_runner(cmd)?;
184 runner.sync_run(|config| cmd.run(config.chain_spec, config.network))
185 },
186 Some(Subcommand::CheckBlock(cmd)) => {
187 let runner = cli.create_runner(cmd)?;
188 runner.async_run(|config| {
189 let PartialComponents { client, task_manager, import_queue, .. } =
190 new_partial(&config, None)?;
191 Ok((cmd.run(client, import_queue), task_manager))
192 })
193 },
194 Some(Subcommand::ExportBlocks(cmd)) => {
195 let runner = cli.create_runner(cmd)?;
196 runner.async_run(|config| {
197 let PartialComponents { client, task_manager, .. } = new_partial(&config, None)?;
198 Ok((cmd.run(client, config.database), task_manager))
199 })
200 },
201 Some(Subcommand::ExportState(cmd)) => {
202 let runner = cli.create_runner(cmd)?;
203 runner.async_run(|config| {
204 let PartialComponents { client, task_manager, .. } = new_partial(&config, None)?;
205 Ok((cmd.run(client, config.chain_spec), task_manager))
206 })
207 },
208 Some(Subcommand::ImportBlocks(cmd)) => {
209 let runner = cli.create_runner(cmd)?;
210 runner.async_run(|config| {
211 let PartialComponents { client, task_manager, import_queue, .. } =
212 new_partial(&config, None)?;
213 Ok((cmd.run(client, import_queue), task_manager))
214 })
215 },
216 Some(Subcommand::PurgeChain(cmd)) => {
217 let runner = cli.create_runner(cmd)?;
218 runner.sync_run(|config| cmd.run(config.database))
219 },
220 Some(Subcommand::Revert(cmd)) => {
221 let runner = cli.create_runner(cmd)?;
222 runner.async_run(|config| {
223 let PartialComponents { client, task_manager, backend, .. } =
224 new_partial(&config, None)?;
225 let aux_revert = Box::new(|client: Arc<FullClient>, backend, blocks| {
226 sc_consensus_babe::revert(client.clone(), backend, blocks)?;
227 sc_consensus_grandpa::revert(client, blocks)?;
228 Ok(())
229 });
230 Ok((cmd.run(client, backend, Some(aux_revert)), task_manager))
231 })
232 },
233 Some(Subcommand::ChainInfo(cmd)) => {
234 let runner = cli.create_runner(cmd)?;
235 runner.sync_run(|config| cmd.run::<Block>(&config))
236 },
237 }
238}