1
// Copyright 2019-2022 PureStake Inc.
2
// This file is part of Moonbeam.
3

            
4
// Moonbeam is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Moonbeam is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Moonbeam.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
//! Moonbeam CLI Library. Built with clap
18
//!
19
//! This module defines the Moonbeam node's Command Line Interface (CLI)
20
//! It is built using clap and inherits behavior from Substrate's sc_cli crate.
21

            
22
use clap::Parser;
23
use moonbeam_cli_opt::{account_key::GenerateAccountKey, EthApi, FrontierBackendType, Sealing};
24
use moonbeam_service::chain_spec;
25
use sc_cli::{Error as CliError, SubstrateCli};
26
use std::path::PathBuf;
27
use std::time::Duration;
28

            
29
#[cfg(feature = "lazy-loading")]
30
fn parse_block_hash(s: &str) -> Result<sp_core::H256, String> {
31
	use std::str::FromStr;
32
	sp_core::H256::from_str(s).map_err(|err| err.to_string())
33
}
34

            
35
/// Sub-commands supported by the collator.
36
#[derive(Debug, clap::Subcommand)]
37
pub enum Subcommand {
38
	/// Export the genesis state of the parachain.
39
	#[clap(name = "export-genesis-state")]
40
	ExportGenesisHead(ExportGenesisHeadCommand),
41

            
42
	/// Export the genesis wasm of the parachain.
43
	#[clap(name = "export-genesis-wasm")]
44
	ExportGenesisWasm(ExportGenesisWasmCommand),
45

            
46
	/// Build a chain specification.
47
	BuildSpec(BuildSpecCommand),
48

            
49
	/// Validate blocks.
50
	CheckBlock(sc_cli::CheckBlockCmd),
51

            
52
	/// Export blocks.
53
	ExportBlocks(sc_cli::ExportBlocksCmd),
54

            
55
	/// Export the state of a given block into a chain spec.
56
	ExportState(sc_cli::ExportStateCmd),
57

            
58
	/// Import blocks.
59
	ImportBlocks(sc_cli::ImportBlocksCmd),
60

            
61
	/// Remove the whole chain.
62
	PurgeChain(cumulus_client_cli::PurgeChainCmd),
63

            
64
	/// Revert the chain to a previous state.
65
	Revert(sc_cli::RevertCmd),
66

            
67
	/// Sub-commands concerned with benchmarking.
68
	/// The pallet benchmarking moved to the `pallet` sub-command.
69
	#[clap(subcommand)]
70
	Benchmark(frame_benchmarking_cli::BenchmarkCmd),
71

            
72
	/// Try some command against runtime state.
73
	TryRuntime,
74

            
75
	/// Key management cli utilities
76
	#[clap(subcommand)]
77
	Key(KeyCmd),
78

            
79
	/// Precompile the WASM runtime into native code
80
	PrecompileWasm(sc_cli::PrecompileWasmCmd),
81
}
82

            
83
#[derive(Debug, Parser)]
84
pub struct BuildSpecCommand {
85
	#[clap(flatten)]
86
	pub base: sc_cli::BuildSpecCmd,
87

            
88
	/// Number of accounts to be funded in the genesis
89
	/// Warning: This flag implies a development spec and overrides any explicitly supplied spec
90
	#[clap(long, conflicts_with = "chain")]
91
	pub accounts: Option<u32>,
92

            
93
	/// Mnemonic from which we can derive funded accounts in the genesis
94
	/// Warning: This flag implies a development spec and overrides any explicitly supplied spec
95
	#[clap(long, conflicts_with = "chain")]
96
	pub mnemonic: Option<String>,
97
}
98

            
99
/// Command for exporting the genesis state of the parachain
100
#[derive(Debug, Parser)]
101
pub struct ExportGenesisHeadCommand {
102
	/// Output file name or stdout if unspecified.
103
	#[clap(value_parser)]
104
	pub output: Option<PathBuf>,
105

            
106
	/// Id of the parachain this state is for.
107
	#[clap(long)]
108
	pub parachain_id: Option<u32>,
109

            
110
	/// Write output in binary. Default is to write in hex.
111
	#[clap(short, long)]
112
	pub raw: bool,
113

            
114
	/// The name of the chain for that the genesis state should be exported.
115
	#[clap(long)]
116
	pub chain: Option<String>,
117
}
118

            
119
/// Command for exporting the genesis wasm file.
120
#[derive(Debug, Parser)]
121
pub struct ExportGenesisWasmCommand {
122
	/// Output file name or stdout if unspecified.
123
	#[clap(value_parser)]
124
	pub output: Option<PathBuf>,
125

            
126
	/// Write output in binary. Default is to write in hex.
127
	#[clap(short, long)]
128
	pub raw: bool,
129

            
130
	/// The name of the chain for that the genesis wasm file should be exported.
131
	#[clap(long)]
132
	pub chain: Option<String>,
133
}
134

            
135
#[derive(Debug, Parser)]
136
#[group(skip)]
137
pub struct RunCmd {
138
	#[clap(flatten)]
139
	pub base: cumulus_client_cli::RunCmd,
140

            
141
	/// Enable the development service to run without a backing relay chain
142
	#[clap(long)]
143
	pub dev_service: bool,
144

            
145
	#[cfg(feature = "lazy-loading")]
146
	#[clap(long)]
147
	pub fork_chain_from_rpc: Option<String>,
148

            
149
	#[cfg(feature = "lazy-loading")]
150
	#[arg(long, value_name = "BLOCK", value_parser = parse_block_hash)]
151
	pub block: Option<sp_core::H256>,
152

            
153
	#[cfg(feature = "lazy-loading")]
154
	#[clap(long, value_name = "PATH", value_parser)]
155
	pub fork_state_overrides: Option<PathBuf>,
156

            
157
	#[cfg(feature = "lazy-loading")]
158
	#[clap(long, value_name = "PATH", value_parser)]
159
	pub runtime_override: Option<PathBuf>,
160

            
161
	/// When blocks should be sealed in the dev service.
162
	///
163
	/// Options are "instant", "manual", or timer interval in milliseconds
164
	#[clap(long, default_value = "instant")]
165
	pub sealing: Sealing,
166

            
167
	/// Public authoring identity to be inserted in the author inherent
168
	/// This is not currently used, but we may want a way to use it in the dev service.
169
	// #[clap(long)]
170
	// pub author_id: Option<NimbusId>,
171

            
172
	/// Enable EVM tracing module on a non-authority node.
173
	#[clap(long, value_delimiter = ',')]
174
894
	pub ethapi: Vec<EthApi>,
175

            
176
	/// Number of concurrent tracing tasks. Meant to be shared by both "debug" and "trace" modules.
177
	#[clap(long, default_value = "10")]
178
	pub ethapi_max_permits: u32,
179

            
180
	/// Maximum number of trace entries a single request of `trace_filter` is allowed to return.
181
	/// A request asking for more or an unbounded one going over this limit will both return an
182
	/// error.
183
	#[clap(long, default_value = "500")]
184
	pub ethapi_trace_max_count: u32,
185

            
186
	/// Duration (in seconds) after which the cache of `trace_filter` for a given block will be
187
	/// discarded.
188
	#[clap(long, default_value = "300")]
189
	pub ethapi_trace_cache_duration: u64,
190

            
191
	/// Size in bytes of the LRU cache for block data.
192
	#[clap(long, default_value = "300000000")]
193
	pub eth_log_block_cache: usize,
194

            
195
	/// Size in bytes of the LRU cache for transactions statuses data.
196
	#[clap(long, default_value = "300000000")]
197
	pub eth_statuses_cache: usize,
198

            
199
	/// Sets the frontier backend type (KeyValue or Sql)
200
900
	#[arg(long, value_enum, ignore_case = true, default_value_t = FrontierBackendType::default())]
201
	pub frontier_backend_type: FrontierBackendType,
202

            
203
	// Sets the SQL backend's pool size.
204
	#[arg(long, default_value = "100")]
205
	pub frontier_sql_backend_pool_size: u32,
206

            
207
	/// Sets the SQL backend's query timeout in number of VM ops.
208
	#[arg(long, default_value = "10000000")]
209
	pub frontier_sql_backend_num_ops_timeout: u32,
210

            
211
	/// Sets the SQL backend's auxiliary thread limit.
212
	#[arg(long, default_value = "4")]
213
	pub frontier_sql_backend_thread_count: u32,
214

            
215
	/// Sets the SQL backend's query timeout in number of VM ops.
216
	/// Default value is 200MB.
217
	#[arg(long, default_value = "209715200")]
218
	pub frontier_sql_backend_cache_size: u64,
219

            
220
	/// Size in bytes of data a raw tracing request is allowed to use.
221
	/// Bound the size of memory, stack and storage data.
222
	#[clap(long, default_value = "20000000")]
223
	pub tracing_raw_max_memory_usage: usize,
224

            
225
	/// Maximum number of logs in a query.
226
	#[clap(long, default_value = "10000")]
227
	pub max_past_logs: u32,
228

            
229
	/// Force using Moonbase native runtime.
230
	#[clap(long = "force-moonbase")]
231
	pub force_moonbase: bool,
232

            
233
	/// Force using Moonriver native runtime.
234
	#[clap(long = "force-moonriver")]
235
	pub force_moonriver: bool,
236

            
237
	/// Id of the parachain this collator collates for.
238
	#[clap(long)]
239
	pub parachain_id: Option<u32>,
240

            
241
	/// Maximum fee history cache size.
242
	#[clap(long, default_value = "2048")]
243
	pub fee_history_limit: u64,
244

            
245
	/// Disable automatic hardware benchmarks.
246
	///
247
	/// By default these benchmarks are automatically ran at startup and measure
248
	/// the CPU speed, the memory bandwidth and the disk speed.
249
	///
250
	/// The results are then printed out in the logs, and also sent as part of
251
	/// telemetry, if telemetry is enabled.
252
	#[clap(long)]
253
	pub no_hardware_benchmarks: bool,
254

            
255
	/// Removes moonbeam prefix from Prometheus metrics
256
	#[clap(long)]
257
	pub no_prometheus_prefix: bool,
258

            
259
	/// Maximum duration in milliseconds to produce a block
260
	#[clap(long, default_value = "2000", value_parser=block_authoring_duration_parser)]
261
	pub block_authoring_duration: Duration,
262
}
263

            
264
900
fn block_authoring_duration_parser(s: &str) -> Result<Duration, String> {
265
900
	Ok(Duration::from_millis(clap_num::number_range(
266
900
		s, 250, 2_000,
267
900
	)?))
268
900
}
269

            
270
impl RunCmd {
271
896
	pub fn new_rpc_config(&self) -> moonbeam_cli_opt::RpcConfig {
272
896
		moonbeam_cli_opt::RpcConfig {
273
896
			ethapi: self.ethapi.clone(),
274
896
			ethapi_max_permits: self.ethapi_max_permits,
275
896
			ethapi_trace_max_count: self.ethapi_trace_max_count,
276
896
			ethapi_trace_cache_duration: self.ethapi_trace_cache_duration,
277
896
			eth_log_block_cache: self.eth_log_block_cache,
278
896
			eth_statuses_cache: self.eth_statuses_cache,
279
896
			fee_history_limit: self.fee_history_limit,
280
896
			max_past_logs: self.max_past_logs,
281
896
			relay_chain_rpc_urls: self.base.relay_chain_rpc_urls.clone(),
282
896
			tracing_raw_max_memory_usage: self.tracing_raw_max_memory_usage,
283
896
			frontier_backend_config: match self.frontier_backend_type {
284
896
				FrontierBackendType::KeyValue => moonbeam_cli_opt::FrontierBackendConfig::KeyValue,
285
				FrontierBackendType::Sql => moonbeam_cli_opt::FrontierBackendConfig::Sql {
286
					pool_size: self.frontier_sql_backend_pool_size,
287
					num_ops_timeout: self.frontier_sql_backend_num_ops_timeout,
288
					thread_count: self.frontier_sql_backend_thread_count,
289
					cache_size: self.frontier_sql_backend_cache_size,
290
				},
291
			},
292
896
			no_prometheus_prefix: self.no_prometheus_prefix,
293
896
		}
294
896
	}
295
}
296

            
297
impl std::ops::Deref for RunCmd {
298
	type Target = cumulus_client_cli::RunCmd;
299

            
300
1788
	fn deref(&self) -> &Self::Target {
301
1788
		&self.base
302
1788
	}
303
}
304

            
305
#[derive(Debug, clap::Subcommand)]
306
pub enum KeyCmd {
307
	#[clap(flatten)]
308
	BaseCli(sc_cli::KeySubcommand),
309
	/// Generate an Ethereum account.
310
	GenerateAccountKey(GenerateAccountKey),
311
}
312

            
313
impl KeyCmd {
314
	/// run the key subcommands
315
	pub fn run<C: SubstrateCli>(&self, cli: &C) -> Result<(), CliError> {
316
		match self {
317
			KeyCmd::BaseCli(cmd) => cmd.run(cli),
318
			KeyCmd::GenerateAccountKey(cmd) => {
319
				cmd.run();
320
				Ok(())
321
			}
322
		}
323
	}
324
}
325

            
326
#[derive(Debug, Parser)]
327
#[clap(
328
	propagate_version = true,
329
	args_conflicts_with_subcommands = true,
330
	subcommand_negates_reqs = true
331
)]
332
pub struct Cli {
333
	#[clap(subcommand)]
334
	pub subcommand: Option<Subcommand>,
335

            
336
	#[clap(flatten)]
337
	pub run: RunCmd,
338

            
339
	/// Relaychain arguments
340
	#[clap(raw = true)]
341
	pub relaychain_args: Vec<String>,
342
}
343

            
344
#[derive(Debug)]
345
pub struct RelayChainCli {
346
	/// The actual relay chain cli object.
347
	pub base: polkadot_cli::RunCmd,
348

            
349
	/// Optional chain id that should be passed to the relay chain.
350
	pub chain_id: Option<String>,
351

            
352
	/// The base path that should be used by the relay chain.
353
	pub base_path: PathBuf,
354
}
355

            
356
impl RelayChainCli {
357
	/// Parse the relay chain CLI parameters using the para chain `Configuration`.
358
	pub fn new<'a>(
359
		para_config: &sc_service::Configuration,
360
		relay_chain_args: impl Iterator<Item = &'a String>,
361
	) -> Self {
362
		let extension = chain_spec::Extensions::try_get(&*para_config.chain_spec);
363
		let chain_id = extension.map(|e| e.relay_chain.clone());
364
		let base_path = para_config.base_path.path().join("polkadot");
365
		Self {
366
			base_path,
367
			chain_id,
368
			base: polkadot_cli::RunCmd::parse_from(relay_chain_args),
369
		}
370
	}
371
}