1use crate::cli::{Cli, RelayChainCli, RunCmd, Subcommand};
20use cumulus_client_cli::extract_genesis_wasm;
21use cumulus_primitives_core::ParaId;
22use frame_benchmarking_cli::{BenchmarkCmd, SUBSTRATE_REFERENCE_HARDWARE};
23use log::{info, warn};
24use moonbeam_cli_opt::EthApi;
25
26#[cfg(feature = "moonbase-native")]
27use moonbeam_service::moonbase_runtime;
28#[cfg(feature = "moonbeam-native")]
29use moonbeam_service::moonbeam_runtime;
30#[cfg(feature = "moonriver-native")]
31use moonbeam_service::moonriver_runtime;
32
33use moonbeam_service::{
34 chain_spec, frontier_database_dir, lazy_loading, HostFunctions, IdentifyVariant,
35};
36use parity_scale_codec::Encode;
37use sc_cli::{
38 ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams,
39 NetworkParams, Result, RpcEndpoint, RuntimeVersion, SharedParams, SubstrateCli,
40};
41use sc_service::{
42 config::{BasePath, PrometheusConfig},
43 DatabaseSource, PartialComponents,
44};
45use sp_core::hexdisplay::HexDisplay;
46use sp_runtime::{
47 traits::{
48 AccountIdConversion, Block as BlockT, Hash as HashT, HashingFor, Header as HeaderT, Zero,
49 },
50 StateVersion,
51};
52use std::io::Write;
53
54fn load_spec(
55 id: &str,
56 para_id: ParaId,
57 run_cmd: &RunCmd,
58) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
59 Ok(match id {
60 "moonbase-alpha" | "alphanet" => Box::new(chain_spec::RawChainSpec::from_json_bytes(
62 &include_bytes!("../../../specs/alphanet/parachain-embedded-specs-v8.json")[..],
63 )?),
64 #[cfg(feature = "moonbase-native")]
65 "moonbase-local" => Box::new(chain_spec::moonbase::get_chain_spec(para_id)),
66 #[cfg(feature = "moonbase-native")]
67 "moonbase-dev" | "dev" | "development" => {
68 Box::new(chain_spec::moonbase::development_chain_spec(None, None))
69 }
70 #[cfg(feature = "moonbeam-native")]
71 "staking" => Box::new(chain_spec::moonbeam::get_chain_spec(para_id)),
72 "moonriver" => Box::new(chain_spec::RawChainSpec::from_json_bytes(
74 &include_bytes!("../../../specs/moonriver/parachain-embedded-specs.json")[..],
75 )?),
76 #[cfg(feature = "moonriver-native")]
77 "moonriver-dev" => Box::new(chain_spec::moonriver::development_chain_spec(None, None)),
78 #[cfg(feature = "moonriver-native")]
79 "moonriver-local" => Box::new(chain_spec::moonriver::get_chain_spec(para_id)),
80
81 "moonbeam" | "" => Box::new(chain_spec::RawChainSpec::from_json_bytes(
83 &include_bytes!("../../../specs/moonbeam/parachain-embedded-specs.json")[..],
84 )?),
85 #[cfg(feature = "moonbeam-native")]
86 "moonbeam-dev" => Box::new(chain_spec::moonbeam::development_chain_spec(None, None)),
87 #[cfg(feature = "moonbeam-native")]
88 "moonbeam-local" => Box::new(chain_spec::moonbeam::get_chain_spec(para_id)),
89
90 path => {
96 let path = std::path::PathBuf::from(path);
97
98 let starts_with = |prefix: &str| {
99 path.file_name()
100 .and_then(|f| f.to_str().map(|s| s.starts_with(&prefix)))
101 .unwrap_or(false)
102 };
103
104 if run_cmd.force_moonbase || starts_with("moonbase") {
105 Box::new(chain_spec::moonbase::ChainSpec::from_json_file(path)?)
106 } else if run_cmd.force_moonriver || starts_with("moonriver") {
107 Box::new(chain_spec::moonriver::ChainSpec::from_json_file(path)?)
108 } else {
109 Box::new(chain_spec::moonbeam::ChainSpec::from_json_file(path)?)
110 }
111 }
112 })
113}
114
115impl SubstrateCli for Cli {
116 fn impl_name() -> String {
117 "Moonbeam Parachain Collator".into()
118 }
119
120 fn impl_version() -> String {
121 env!("SUBSTRATE_CLI_IMPL_VERSION").into()
122 }
123
124 fn description() -> String {
125 format!(
126 "Moonbase Parachain Collator\n\nThe command-line arguments provided first will be \
127 passed to the parachain node, while the arguments provided after -- will be passed \
128 to the relaychain node.\n\n\
129 {} [parachain-args] -- [relaychain-args]",
130 Self::executable_name()
131 )
132 }
133
134 fn author() -> String {
135 env!("CARGO_PKG_AUTHORS").into()
136 }
137
138 fn support_url() -> String {
139 "https://github.com/moonbeam-foundation/moonbeam/issues/new".into()
140 }
141
142 fn copyright_start_year() -> i32 {
143 2019
144 }
145
146 fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
147 load_spec(id, self.run.parachain_id.unwrap_or(1000).into(), &self.run)
148 }
149}
150
151impl Cli {
152 fn runtime_version(spec: &Box<dyn sc_service::ChainSpec>) -> &'static RuntimeVersion {
153 match spec {
154 #[cfg(feature = "moonriver-native")]
155 spec if spec.is_moonriver() => return &moonbeam_service::moonriver_runtime::VERSION,
156 #[cfg(feature = "moonbeam-native")]
157 spec if spec.is_moonbeam() => return &moonbeam_service::moonbeam_runtime::VERSION,
158 #[cfg(feature = "moonbase-native")]
159 _ => return &moonbeam_service::moonbase_runtime::VERSION,
160 #[cfg(not(feature = "moonbase-native"))]
161 _ => panic!("invalid chain spec"),
162 }
163 }
164}
165
166impl SubstrateCli for RelayChainCli {
167 fn impl_name() -> String {
168 "Moonbeam Parachain Collator".into()
169 }
170
171 fn impl_version() -> String {
172 env!("SUBSTRATE_CLI_IMPL_VERSION").into()
173 }
174
175 fn description() -> String {
176 "Moonbeam Parachain Collator\n\nThe command-line arguments provided first will be \
177 passed to the parachain node, while the arguments provided after -- will be passed \
178 to the relaychain node.\n\n\
179 parachain-collator [parachain-args] -- [relaychain-args]"
180 .into()
181 }
182
183 fn author() -> String {
184 env!("CARGO_PKG_AUTHORS").into()
185 }
186
187 fn support_url() -> String {
188 "https://github.com/moonbeam-foundation/moonbeam/issues/new".into()
189 }
190
191 fn copyright_start_year() -> i32 {
192 2019
193 }
194
195 fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
196 match id {
197 "westend_moonbase_relay_testnet" => Ok(Box::new(
198 polkadot_service::WestendChainSpec::from_json_bytes(
199 &include_bytes!("../../../specs/alphanet/westend-embedded-specs-v8.json")[..],
200 )?,
201 )),
202 _ => polkadot_cli::Cli::from_iter([RelayChainCli::executable_name()].iter())
205 .load_spec(id),
206 }
207 }
208}
209
210fn validate_trace_environment(cli: &Cli) -> Result<()> {
211 if (cli.run.ethapi.contains(&EthApi::Debug) || cli.run.ethapi.contains(&EthApi::Trace))
212 && cli
213 .run
214 .base
215 .base
216 .import_params
217 .wasm_runtime_overrides
218 .is_none()
219 {
220 return Err(
221 "`debug` or `trace` namespaces requires `--wasm-runtime-overrides /path/to/overrides`."
222 .into(),
223 );
224 }
225 Ok(())
226}
227
228pub fn run() -> Result<()> {
230 let cli = Cli::from_args();
231 let _ = validate_trace_environment(&cli)?;
232
233 match &cli.subcommand {
234 Some(Subcommand::BuildSpec(params)) => {
235 let runner = cli.create_runner(¶ms.base)?;
236 runner.sync_run(|config| {
237 if params.mnemonic.is_some() || params.accounts.is_some() {
238 if config.chain_spec.is_moonbeam() {
239 params.base.run(
240 Box::new(chain_spec::moonbeam::development_chain_spec(
241 params.mnemonic.clone(),
242 params.accounts,
243 )),
244 config.network,
245 )
246 } else if config.chain_spec.is_moonriver() {
247 params.base.run(
248 Box::new(chain_spec::moonriver::development_chain_spec(
249 params.mnemonic.clone(),
250 params.accounts,
251 )),
252 config.network,
253 )
254 } else {
255 params.base.run(
256 Box::new(chain_spec::moonbase::development_chain_spec(
257 params.mnemonic.clone(),
258 params.accounts,
259 )),
260 config.network,
261 )
262 }
263 } else {
264 params.base.run(config.chain_spec, config.network)
265 }
266 })
267 }
268 Some(Subcommand::CheckBlock(cmd)) => {
269 let runner = cli.create_runner(cmd)?;
270 let rpc_config = cli.run.new_rpc_config();
271 runner.async_run(|mut config| {
272 let (client, _, import_queue, task_manager) = moonbeam_service::new_chain_ops(
273 &mut config,
274 &rpc_config,
275 cli.node_extra_args(),
276 )?;
277 Ok((cmd.run(client, import_queue), task_manager))
278 })
279 }
280 Some(Subcommand::ExportBlocks(cmd)) => {
281 let runner = cli.create_runner(cmd)?;
282 let rpc_config = cli.run.new_rpc_config();
283 runner.async_run(|mut config| {
284 let (client, _, _, task_manager) = moonbeam_service::new_chain_ops(
285 &mut config,
286 &rpc_config,
287 cli.node_extra_args(),
288 )?;
289 Ok((cmd.run(client, config.database), task_manager))
290 })
291 }
292 Some(Subcommand::ExportState(cmd)) => {
293 let runner = cli.create_runner(cmd)?;
294 let rpc_config = cli.run.new_rpc_config();
295 runner.async_run(|mut config| {
296 let (client, _, _, task_manager) = moonbeam_service::new_chain_ops(
297 &mut config,
298 &rpc_config,
299 cli.node_extra_args(),
300 )?;
301 Ok((cmd.run(client, config.chain_spec), task_manager))
302 })
303 }
304 Some(Subcommand::ImportBlocks(cmd)) => {
305 let runner = cli.create_runner(cmd)?;
306 let rpc_config = cli.run.new_rpc_config();
307 runner.async_run(|mut config| {
308 let (client, _, import_queue, task_manager) = moonbeam_service::new_chain_ops(
309 &mut config,
310 &rpc_config,
311 cli.node_extra_args(),
312 )?;
313 Ok((cmd.run(client, import_queue), task_manager))
314 })
315 }
316 Some(Subcommand::PurgeChain(cmd)) => {
317 let runner = cli.create_runner(cmd)?;
318 runner.sync_run(|config| {
319 let extension = chain_spec::Extensions::try_get(&*config.chain_spec);
322 let relay_chain_id = extension.map(|e| e.relay_chain.as_str());
323 let dev_service = cli.run.dev_service || relay_chain_id == Some("dev-service");
324
325 let frontier_database_config = match config.database {
327 DatabaseSource::RocksDb { .. } => DatabaseSource::RocksDb {
328 path: frontier_database_dir(&config, "db"),
329 cache_size: 0,
330 },
331 DatabaseSource::ParityDb { .. } => DatabaseSource::ParityDb {
332 path: frontier_database_dir(&config, "paritydb"),
333 },
334 _ => {
335 return Err(format!("Cannot purge `{:?}` database", config.database).into())
336 }
337 };
338 cmd.base.run(frontier_database_config)?;
339
340 if dev_service {
341 return cmd.base.run(config.database);
343 }
344
345 let polkadot_cli = RelayChainCli::new(
346 &config,
347 [RelayChainCli::executable_name().to_string()]
348 .iter()
349 .chain(cli.relaychain_args.iter()),
350 );
351
352 let polkadot_config = SubstrateCli::create_configuration(
353 &polkadot_cli,
354 &polkadot_cli,
355 config.tokio_handle.clone(),
356 )
357 .map_err(|err| format!("Relay chain argument error: {}", err))?;
358
359 cmd.run(config, polkadot_config)
360 })
361 }
362 Some(Subcommand::Revert(cmd)) => {
363 let runner = cli.create_runner(cmd)?;
364 let chain_spec = &runner.config().chain_spec;
365 let rpc_config = cli.run.new_rpc_config();
366 match chain_spec {
367 #[cfg(feature = "moonriver-native")]
368 spec if spec.is_moonriver() => runner.async_run(|mut config| {
369 let params = moonbeam_service::new_partial::<
370 moonbeam_service::moonriver_runtime::RuntimeApi,
371 moonbeam_service::MoonriverCustomizations,
372 >(&mut config, &rpc_config, cli.node_extra_args())?;
373
374 Ok((
375 cmd.run(params.client, params.backend, None),
376 params.task_manager,
377 ))
378 }),
379 #[cfg(feature = "moonbeam-native")]
380 spec if spec.is_moonbeam() => runner.async_run(|mut config| {
381 let params = moonbeam_service::new_partial::<
382 moonbeam_service::moonbeam_runtime::RuntimeApi,
383 moonbeam_service::MoonbeamCustomizations,
384 >(&mut config, &rpc_config, cli.node_extra_args())?;
385
386 Ok((
387 cmd.run(params.client, params.backend, None),
388 params.task_manager,
389 ))
390 }),
391 #[cfg(feature = "moonbase-native")]
392 _ => runner.async_run(|mut config| {
393 let params = moonbeam_service::new_partial::<
394 moonbeam_service::moonbase_runtime::RuntimeApi,
395 moonbeam_service::MoonbaseCustomizations,
396 >(&mut config, &rpc_config, cli.node_extra_args())?;
397
398 Ok((
399 cmd.run(params.client, params.backend, None),
400 params.task_manager,
401 ))
402 }),
403 #[cfg(not(feature = "moonbase-native"))]
404 _ => panic!("invalid chain spec"),
405 }
406 }
407 Some(Subcommand::ExportGenesisHead(params)) => {
408 let mut builder = sc_cli::LoggerBuilder::new("");
409 builder.with_profiling(sc_tracing::TracingReceiver::Log, "");
410 let _ = builder.init();
411
412 let chain_spec = load_spec(
414 params.chain.as_deref().unwrap_or_default(),
415 params.parachain_id.unwrap_or(1000).into(),
416 &cli.run,
417 )?;
418 let state_version = Cli::runtime_version(&chain_spec).state_version();
419
420 let output_buf = match chain_spec {
421 #[cfg(feature = "moonriver-native")]
422 chain_spec if chain_spec.is_moonriver() => {
423 let block: moonbeam_service::moonriver_runtime::Block =
424 generate_genesis_block(&*chain_spec, state_version)?;
425 let raw_header = block.header().encode();
426 let output_buf = if params.raw {
427 raw_header
428 } else {
429 format!("0x{:?}", HexDisplay::from(&block.header().encode())).into_bytes()
430 };
431 output_buf
432 }
433 #[cfg(feature = "moonbeam-native")]
434 chain_spec if chain_spec.is_moonbeam() => {
435 let block: moonbeam_service::moonbeam_runtime::Block =
436 generate_genesis_block(&*chain_spec, state_version)?;
437 let raw_header = block.header().encode();
438 let output_buf = if params.raw {
439 raw_header
440 } else {
441 format!("0x{:?}", HexDisplay::from(&block.header().encode())).into_bytes()
442 };
443 output_buf
444 }
445 #[cfg(feature = "moonbase-native")]
446 _ => {
447 let block: moonbeam_service::moonbase_runtime::Block =
448 generate_genesis_block(&*chain_spec, state_version)?;
449 let raw_header = block.header().encode();
450 let output_buf = if params.raw {
451 raw_header
452 } else {
453 format!("0x{:?}", HexDisplay::from(&block.header().encode())).into_bytes()
454 };
455 output_buf
456 }
457 #[cfg(not(feature = "moonbase-native"))]
458 _ => panic!("invalid chain spec"),
459 };
460
461 if let Some(output) = ¶ms.output {
462 std::fs::write(output, output_buf)?;
463 } else {
464 std::io::stdout().write_all(&output_buf)?;
465 }
466
467 Ok(())
468 }
469 Some(Subcommand::ExportGenesisWasm(params)) => {
470 let mut builder = sc_cli::LoggerBuilder::new("");
471 builder.with_profiling(sc_tracing::TracingReceiver::Log, "");
472 let _ = builder.init();
473
474 let raw_wasm_blob = extract_genesis_wasm(
475 &*cli.load_spec(params.chain.as_deref().unwrap_or_default())?,
476 )?;
477 let output_buf = if params.raw {
478 raw_wasm_blob
479 } else {
480 format!("0x{:?}", HexDisplay::from(&raw_wasm_blob)).into_bytes()
481 };
482
483 if let Some(output) = ¶ms.output {
484 std::fs::write(output, output_buf)?;
485 } else {
486 std::io::stdout().write_all(&output_buf)?;
487 }
488
489 Ok(())
490 }
491 Some(Subcommand::Benchmark(cmd)) => {
492 let runner = cli.create_runner(cmd)?;
493
494 match cmd {
496 BenchmarkCmd::Pallet(cmd) => {
497 if cfg!(feature = "runtime-benchmarks") {
498 let chain_spec = &runner.config().chain_spec;
499 match chain_spec {
500 #[cfg(feature = "moonriver-native")]
501 spec if spec.is_moonriver() => {
502 return runner.sync_run(|config| {
503 cmd.run_with_spec::<HashingFor<moonriver_runtime::Block>, HostFunctions>(
504 Some(config.chain_spec),
505 )
506 })
507 }
508 #[cfg(feature = "moonbeam-native")]
509 spec if spec.is_moonbeam() => {
510 return runner.sync_run(|config| {
511 cmd.run_with_spec::<HashingFor<moonbeam_runtime::Block>, HostFunctions>(
512 Some(config.chain_spec),
513 )
514 })
515 }
516 #[cfg(feature = "moonbase-native")]
517 _ => {
518 return runner.sync_run(|config| {
519 cmd.run_with_spec::<HashingFor<moonbase_runtime::Block>, HostFunctions>(
520 Some(config.chain_spec),
521 )
522 })
523 }
524 #[cfg(not(feature = "moonbase-native"))]
525 _ => panic!("invalid chain spec"),
526 }
527 } else {
528 Err("Benchmarking wasn't enabled when building the node. \
529 You can enable it with `--features runtime-benchmarks`."
530 .into())
531 }
532 }
533 BenchmarkCmd::Block(cmd) => {
534 let chain_spec = &runner.config().chain_spec;
535 let rpc_config = cli.run.new_rpc_config();
536 match chain_spec {
537 #[cfg(feature = "moonriver-native")]
538 spec if spec.is_moonriver() => {
539 return runner.sync_run(|mut config| {
540 let params =
541 moonbeam_service::new_partial::<
542 moonbeam_service::moonriver_runtime::RuntimeApi,
543 moonbeam_service::MoonriverCustomizations,
544 >(&mut config, &rpc_config, cli.node_extra_args())?;
545
546 cmd.run(params.client)
547 })
548 }
549 #[cfg(feature = "moonbeam-native")]
550 spec if spec.is_moonbeam() => {
551 return runner.sync_run(|mut config| {
552 let params =
553 moonbeam_service::new_partial::<
554 moonbeam_service::moonbeam_runtime::RuntimeApi,
555 moonbeam_service::MoonbeamCustomizations,
556 >(&mut config, &rpc_config, cli.node_extra_args())?;
557
558 cmd.run(params.client)
559 })
560 }
561 #[cfg(feature = "moonbase-native")]
562 _ => {
563 return runner.sync_run(|mut config| {
564 let params =
565 moonbeam_service::new_partial::<
566 moonbeam_service::moonbase_runtime::RuntimeApi,
567 moonbeam_service::MoonbaseCustomizations,
568 >(&mut config, &rpc_config, cli.node_extra_args())?;
569
570 cmd.run(params.client)
571 })
572 }
573 #[cfg(not(feature = "moonbase-native"))]
574 _ => panic!("invalid chain spec"),
575 }
576 }
577 #[cfg(not(feature = "runtime-benchmarks"))]
578 BenchmarkCmd::Storage(_) => Err(
579 "Storage benchmarking can be enabled with `--features runtime-benchmarks`."
580 .into(),
581 ),
582 #[cfg(feature = "runtime-benchmarks")]
583 BenchmarkCmd::Storage(cmd) => {
584 let chain_spec = &runner.config().chain_spec;
585 let rpc_config = cli.run.new_rpc_config();
586 match chain_spec {
587 #[cfg(feature = "moonriver-native")]
588 spec if spec.is_moonriver() => {
589 return runner.sync_run(|mut config| {
590 let params =
591 moonbeam_service::new_partial::<
592 moonbeam_service::moonriver_runtime::RuntimeApi,
593 moonbeam_service::MoonriverCustomizations,
594 >(&mut config, &rpc_config, cli.node_extra_args())?;
595
596 let db = params.backend.expose_db();
597 let storage = params.backend.expose_storage();
598
599 cmd.run(config, params.client, db, storage, None)
600 })
601 }
602 #[cfg(feature = "moonbeam-native")]
603 spec if spec.is_moonbeam() => {
604 return runner.sync_run(|mut config| {
605 let params =
606 moonbeam_service::new_partial::<
607 moonbeam_service::moonbeam_runtime::RuntimeApi,
608 moonbeam_service::MoonbeamCustomizations,
609 >(&mut config, &rpc_config, cli.node_extra_args())?;
610
611 let db = params.backend.expose_db();
612 let storage = params.backend.expose_storage();
613
614 cmd.run(config, params.client, db, storage, None)
615 })
616 }
617 #[cfg(feature = "moonbase-native")]
618 _ => {
619 return runner.sync_run(|mut config| {
620 let params =
621 moonbeam_service::new_partial::<
622 moonbeam_service::moonbase_runtime::RuntimeApi,
623 moonbeam_service::MoonbaseCustomizations,
624 >(&mut config, &rpc_config, cli.node_extra_args())?;
625
626 let db = params.backend.expose_db();
627 let storage = params.backend.expose_storage();
628
629 cmd.run(config, params.client, db, storage, None)
630 })
631 }
632 #[cfg(not(feature = "moonbase-native"))]
633 _ => panic!("invalid chain spec"),
634 }
635 }
636 BenchmarkCmd::Overhead(_) => Err("Unsupported benchmarking command".into()),
637 BenchmarkCmd::Extrinsic(_) => Err("Unsupported benchmarking command".into()),
638 BenchmarkCmd::Machine(cmd) => {
639 return runner.sync_run(|config| {
640 cmd.run(
641 &config,
642 frame_benchmarking_cli::SUBSTRATE_REFERENCE_HARDWARE.clone(),
643 )
644 });
645 }
646 }
647 }
648 Some(Subcommand::TryRuntime) => Err("The `try-runtime` subcommand has been migrated to a \
649 standalone CLI (https://github.com/paritytech/try-runtime-cli). It is no longer \
650 being maintained here and will be removed entirely some time after January 2024. \
651 Please remove this subcommand from your runtime and use the standalone CLI."
652 .into()),
653 Some(Subcommand::Key(cmd)) => Ok(cmd.run(&cli)?),
654 Some(Subcommand::PrecompileWasm(cmd)) => {
655 let runner = cli.create_runner(cmd)?;
656 let rpc_config = cli.run.new_rpc_config();
657 runner.async_run(|mut config| match &config.chain_spec {
658 #[cfg(feature = "moonriver-native")]
659 spec if spec.is_moonriver() => {
660 let PartialComponents {
661 task_manager,
662 backend,
663 ..
664 } = moonbeam_service::new_partial::<
665 moonbeam_service::moonriver_runtime::RuntimeApi,
666 moonbeam_service::MoonriverCustomizations,
667 >(&mut config, &rpc_config, cli.node_extra_args())?;
668
669 Ok((cmd.run(backend, config.chain_spec), task_manager))
670 }
671 #[cfg(feature = "moonbeam-native")]
672 spec if spec.is_moonbeam() => {
673 let PartialComponents {
674 task_manager,
675 backend,
676 ..
677 } = moonbeam_service::new_partial::<
678 moonbeam_service::moonbeam_runtime::RuntimeApi,
679 moonbeam_service::MoonbeamCustomizations,
680 >(&mut config, &rpc_config, cli.node_extra_args())?;
681
682 Ok((cmd.run(backend, config.chain_spec), task_manager))
683 }
684 #[cfg(feature = "moonbase-native")]
685 _ => {
686 let PartialComponents {
687 task_manager,
688 backend,
689 ..
690 } = moonbeam_service::new_partial::<
691 moonbeam_service::moonbase_runtime::RuntimeApi,
692 moonbeam_service::MoonbaseCustomizations,
693 >(&mut config, &rpc_config, cli.node_extra_args())?;
694
695 Ok((cmd.run(backend, config.chain_spec), task_manager))
696 }
697 #[cfg(not(feature = "moonbase-native"))]
698 _ => panic!("invalid chain spec"),
699 })
700 }
701 None => {
702 let runner = cli.create_runner(&(*cli.run).normalize())?;
703 let collator_options = cli.run.collator_options();
704
705 runner.run_node_until_exit(|mut config| async move {
706 let hwbench = if !cli.run.no_hardware_benchmarks {
707 config.database.path().map(|database_path| {
708 let _ = std::fs::create_dir_all(&database_path);
709 sc_sysinfo::gather_hwbench(
710 Some(database_path),
711 &SUBSTRATE_REFERENCE_HARDWARE,
712 )
713 })
714 } else {
715 None
716 };
717
718 let extension = chain_spec::Extensions::try_get(&*config.chain_spec);
719
720 let rpc_config = cli.run.new_rpc_config();
721
722 let relay_chain_id = extension.map(|e| e.relay_chain.as_str());
729 let para_id = extension.map(|e| e.para_id);
730
731 let dev_service = cli.run.dev_service
732 || config.chain_spec.is_dev()
733 || relay_chain_id == Some("dev-service");
734 if dev_service {
735 let author_id = Some(chain_spec::get_from_seed::<nimbus_primitives::NimbusId>(
739 "Alice",
740 ));
741
742 return match &config.chain_spec {
743 #[cfg(feature = "moonriver-native")]
744 spec if spec.is_moonriver() => moonbeam_service::new_dev::<
745 moonbeam_service::moonriver_runtime::RuntimeApi,
746 moonbeam_service::MoonriverCustomizations,
747 sc_network::NetworkWorker<_, _>,
748 >(
749 config,
750 para_id,
751 author_id,
752 cli.run.sealing,
753 rpc_config,
754 hwbench,
755 cli.node_extra_args(),
756 )
757 .await
758 .map_err(Into::into),
759 #[cfg(feature = "moonbeam-native")]
760 spec if spec.is_moonbeam() => moonbeam_service::new_dev::<
761 moonbeam_service::moonbeam_runtime::RuntimeApi,
762 moonbeam_service::MoonbeamCustomizations,
763 sc_network::NetworkWorker<_, _>,
764 >(
765 config,
766 para_id,
767 author_id,
768 cli.run.sealing,
769 rpc_config,
770 hwbench,
771 cli.node_extra_args(),
772 )
773 .await
774 .map_err(Into::into),
775 #[cfg(feature = "moonbase-native")]
776 _ => moonbeam_service::new_dev::<
777 moonbeam_service::moonbase_runtime::RuntimeApi,
778 moonbeam_service::MoonbaseCustomizations,
779 sc_network::NetworkWorker<_, _>,
780 >(
781 config,
782 para_id,
783 author_id,
784 cli.run.sealing,
785 rpc_config,
786 hwbench,
787 cli.node_extra_args(),
788 )
789 .await
790 .map_err(Into::into),
791 #[cfg(not(feature = "moonbase-native"))]
792 _ => panic!("invalid chain spec"),
793 };
794 }
795 #[cfg(feature = "lazy-loading")]
796 if let Some(lazy_loading_remote_rpc) = cli.run.lazy_loading_remote_rpc {
797 let author_id = Some(chain_spec::get_from_seed::<nimbus_primitives::NimbusId>(
798 "Alice",
799 ));
800
801 let lazy_loading_config = moonbeam_cli_opt::LazyLoadingConfig {
802 state_rpc: lazy_loading_remote_rpc,
803 from_block: cli.run.lazy_loading_block,
804 state_overrides_path: cli.run.lazy_loading_state_overrides,
805 runtime_override: cli.run.lazy_loading_runtime_override,
806 delay_between_requests: cli.run.lazy_loading_delay_between_requests,
807 max_retries_per_request: cli.run.lazy_loading_max_retries_per_request,
808 };
809
810 let spec_builder = lazy_loading::spec_builder();
811 config.chain_spec = Box::new(spec_builder.build());
812
813 config.offchain_worker.enabled = false;
816
817 return moonbeam_service::lazy_loading::new_lazy_loading_service::<
818 moonbeam_runtime::RuntimeApi,
819 moonbeam_service::MoonbeamCustomizations,
820 sc_network::NetworkWorker<_, _>,
821 >(
822 config,
823 author_id,
824 cli.run.sealing,
825 rpc_config,
826 lazy_loading_config,
827 hwbench,
828 )
829 .await
830 .map_err(Into::into);
831 }
832
833 let polkadot_cli = RelayChainCli::new(
834 &config,
835 [RelayChainCli::executable_name().to_string()]
836 .iter()
837 .chain(cli.relaychain_args.iter()),
838 );
839
840 let para_id = extension.map(|e| e.para_id);
841 let id = ParaId::from(cli.run.parachain_id.clone().or(para_id).unwrap_or(1000));
842
843 let parachain_account =
844 AccountIdConversion::<polkadot_primitives::v8::AccountId>::into_account_truncating(&id);
845
846 let tokio_handle = config.tokio_handle.clone();
847 let polkadot_config =
848 SubstrateCli::create_configuration(&polkadot_cli, &polkadot_cli, tokio_handle)
849 .map_err(|err| format!("Relay chain argument error: {}", err))?;
850
851 info!("Parachain Account: {}", parachain_account);
852 info!(
853 "Is collating: {}",
854 if config.role.is_authority() {
855 "yes"
856 } else {
857 "no"
858 }
859 );
860
861 if !rpc_config.relay_chain_rpc_urls.is_empty() && cli.relaychain_args.len() > 0 {
862 warn!(
863 "Detected relay chain node arguments together with \
864 --relay-chain-rpc-url. This command starts a minimal Polkadot node that only \
865 uses a network-related subset of all relay chain CLI options."
866 );
867 }
868
869 match &config.chain_spec {
870 #[cfg(feature = "moonriver-native")]
871 spec if spec.is_moonriver() => moonbeam_service::start_node::<
872 moonbeam_service::moonriver_runtime::RuntimeApi,
873 moonbeam_service::MoonriverCustomizations,
874 >(
875 config,
876 polkadot_config,
877 collator_options,
878 id,
879 rpc_config,
880 cli.run.block_authoring_duration,
881 hwbench,
882 cli.node_extra_args(),
883 )
884 .await
885 .map(|r| r.0)
886 .map_err(Into::into),
887 #[cfg(feature = "moonbeam-native")]
888 spec if spec.is_moonbeam() => moonbeam_service::start_node::<
889 moonbeam_service::moonbeam_runtime::RuntimeApi,
890 moonbeam_service::MoonbeamCustomizations,
891 >(
892 config,
893 polkadot_config,
894 collator_options,
895 id,
896 rpc_config,
897 cli.run.block_authoring_duration,
898 hwbench,
899 cli.node_extra_args(),
900 )
901 .await
902 .map(|r| r.0)
903 .map_err(Into::into),
904 #[cfg(feature = "moonbase-native")]
905 _ => moonbeam_service::start_node::<
906 moonbeam_service::moonbase_runtime::RuntimeApi,
907 moonbeam_service::MoonbaseCustomizations,
908 >(
909 config,
910 polkadot_config,
911 collator_options,
912 id,
913 rpc_config,
914 cli.run.block_authoring_duration,
915 hwbench,
916 cli.node_extra_args(),
917 )
918 .await
919 .map(|r| r.0)
920 .map_err(Into::into),
921 #[cfg(not(feature = "moonbase-native"))]
922 _ => panic!("invalid chain spec"),
923 }
924 })
925 }
926 }
927}
928
929impl DefaultConfigurationValues for RelayChainCli {
930 fn p2p_listen_port() -> u16 {
931 30334
932 }
933
934 fn rpc_listen_port() -> u16 {
935 9945
936 }
937
938 fn prometheus_listen_port() -> u16 {
939 9616
940 }
941}
942
943impl CliConfiguration<Self> for RelayChainCli {
944 fn shared_params(&self) -> &SharedParams {
945 self.base.base.shared_params()
946 }
947
948 fn import_params(&self) -> Option<&ImportParams> {
949 self.base.base.import_params()
950 }
951
952 fn network_params(&self) -> Option<&NetworkParams> {
953 self.base.base.network_params()
954 }
955
956 fn keystore_params(&self) -> Option<&KeystoreParams> {
957 self.base.base.keystore_params()
958 }
959
960 fn base_path(&self) -> Result<Option<BasePath>> {
961 Ok(self
962 .shared_params()
963 .base_path()?
964 .or_else(|| Some(self.base_path.clone().into())))
965 }
966
967 fn rpc_addr(&self, default_listen_port: u16) -> Result<Option<Vec<RpcEndpoint>>> {
968 self.base.base.rpc_addr(default_listen_port)
969 }
970
971 fn prometheus_config(
972 &self,
973 default_listen_port: u16,
974 chain_spec: &Box<dyn ChainSpec>,
975 ) -> Result<Option<PrometheusConfig>> {
976 self.base
977 .base
978 .prometheus_config(default_listen_port, chain_spec)
979 }
980
981 fn init<F>(&self, _support_url: &String, _impl_version: &String, _logger_hook: F) -> Result<()>
982 where
983 F: FnOnce(&mut sc_cli::LoggerBuilder),
984 {
985 unreachable!("PolkadotCli is never initialized; qed");
986 }
987
988 fn chain_id(&self, is_dev: bool) -> Result<String> {
989 let chain_id = self.base.base.chain_id(is_dev)?;
990
991 Ok(if chain_id.is_empty() {
992 self.chain_id.clone().unwrap_or_default()
993 } else {
994 chain_id
995 })
996 }
997
998 fn role(&self, is_dev: bool) -> Result<sc_service::Role> {
999 self.base.base.role(is_dev)
1000 }
1001
1002 fn transaction_pool(&self, is_dev: bool) -> Result<sc_service::config::TransactionPoolOptions> {
1003 self.base.base.transaction_pool(is_dev)
1004 }
1005
1006 fn rpc_methods(&self) -> Result<sc_service::config::RpcMethods> {
1007 self.base.base.rpc_methods()
1008 }
1009
1010 fn rpc_max_connections(&self) -> Result<u32> {
1011 self.base.base.rpc_max_connections()
1012 }
1013
1014 fn rpc_cors(&self, is_dev: bool) -> Result<Option<Vec<String>>> {
1015 self.base.base.rpc_cors(is_dev)
1016 }
1017
1018 fn default_heap_pages(&self) -> Result<Option<u64>> {
1023 self.base.base.default_heap_pages()
1024 }
1025
1026 fn force_authoring(&self) -> Result<bool> {
1027 self.base.base.force_authoring()
1028 }
1029
1030 fn disable_grandpa(&self) -> Result<bool> {
1031 self.base.base.disable_grandpa()
1032 }
1033
1034 fn max_runtime_instances(&self) -> Result<Option<usize>> {
1035 self.base.base.max_runtime_instances()
1036 }
1037
1038 fn announce_block(&self) -> Result<bool> {
1039 self.base.base.announce_block()
1040 }
1041}
1042
1043pub fn generate_genesis_block<Block: BlockT>(
1045 chain_spec: &dyn ChainSpec,
1046 genesis_state_version: StateVersion,
1047) -> std::result::Result<Block, String> {
1048 let storage = chain_spec.build_storage()?;
1049
1050 let child_roots = storage.children_default.iter().map(|(sk, child_content)| {
1051 let state_root = <<<Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
1052 child_content.data.clone().into_iter().collect(),
1053 genesis_state_version,
1054 );
1055 (sk.clone(), state_root.encode())
1056 });
1057 let state_root = <<<Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
1058 storage.top.clone().into_iter().chain(child_roots).collect(),
1059 genesis_state_version,
1060 );
1061
1062 let extrinsics_root = <<<Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
1063 Vec::new(),
1064 genesis_state_version,
1065 );
1066
1067 Ok(Block::new(
1068 <<Block as BlockT>::Header as HeaderT>::new(
1069 Zero::zero(),
1070 extrinsics_root,
1071 state_root,
1072 Default::default(),
1073 Default::default(),
1074 ),
1075 Default::default(),
1076 ))
1077}