git.delta.rocks / unique-network / refs/commits / d832d2049e99

difftreelog

source

node/cli/src/command.rs16.7 KiBsourcehistory
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617// Original license18// This file is part of Substrate.1920// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd.21// SPDX-License-Identifier: Apache-2.02223// Licensed under the Apache License, Version 2.0 (the "License");24// you may not use this file except in compliance with the License.25// You may obtain a copy of the License at26//27// 	http://www.apache.org/licenses/LICENSE-2.028//29// Unless required by applicable law or agreed to in writing, software30// distributed under the License is distributed on an "AS IS" BASIS,31// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.32// See the License for the specific language governing permissions and33// limitations under the License.3435use crate::{36	chain_spec::{self, RuntimeIdentification},37	cli::{Cli, RelayChainCli, Subcommand},38	service::new_partial,39};4041#[cfg(feature = "unique-runtime")]42use crate::service::UniqueRuntimeExecutor;4344#[cfg(feature = "quartz-runtime")]45use crate::service::QuartzRuntimeExecutor;4647#[cfg(feature = "opal-runtime")]48use crate::service::OpalRuntimeExecutor;4950use codec::Encode;51use cumulus_primitives_core::ParaId;52use cumulus_client_service::genesis::generate_genesis_block;53use log::info;54use polkadot_parachain::primitives::AccountIdConversion;55use sc_cli::{56	ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams,57	NetworkParams, Result, RuntimeVersion, SharedParams, SubstrateCli,58};59use sc_service::{60	config::{BasePath, PrometheusConfig},61};62use sp_core::hexdisplay::HexDisplay;63use sp_runtime::traits::Block as BlockT;64use std::{io::Write, net::SocketAddr};6566use unique_runtime_common::types::Block;6768macro_rules! no_runtime_err {69	($chain_spec:expr) => {70		format!(71			"No runtime valid runtime was found, chain id: {}",72			$chain_spec.id()73		)74	};75}7677fn load_spec(id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {78	match id {79		"westend-local" => Ok(Box::new(chain_spec::local_testnet_westend_config())),80		"rococo-local" => Ok(Box::new(chain_spec::local_testnet_rococo_config())),81		"dev" => Ok(Box::new(chain_spec::development_config())),82		"" | "local" => Ok(Box::new(chain_spec::local_testnet_rococo_config())),83		path => {84			let path = std::path::PathBuf::from(path);85			let chain_spec = Box::new(chain_spec::UniqueChainSpec::from_json_file(path.clone())?)86				as Box<dyn sc_service::ChainSpec>;8788			#[cfg(feature = "unique-runtime")]89			if chain_spec.is_unique() {90				return Ok(chain_spec);91			}9293			#[cfg(feature = "quartz-runtime")]94			if chain_spec.is_quartz() {95				let chain_spec = chain_spec::QuartzChainSpec::from_json_file(path)?;96				return Ok(Box::new(chain_spec));97			}9899			#[cfg(feature = "opal-runtime")]100			if chain_spec.is_opal() {101				let chain_spec = chain_spec::OpalChainSpec::from_json_file(path)?;102				return Ok(Box::new(chain_spec));103			}104105			Err(no_runtime_err!(chain_spec))106		}107	}108}109110impl SubstrateCli for Cli {111	// TODO use args112	fn impl_name() -> String {113		"Unique Node".into()114	}115116	fn impl_version() -> String {117		env!("SUBSTRATE_CLI_IMPL_VERSION").into()118	}119	// TODO use args120	fn description() -> String {121		format!(122			"Unique Node\n\nThe command-line arguments provided first will be \123		passed to the parachain node, while the arguments provided after -- will be passed \124		to the relaychain node.\n\n\125		{} [parachain-args] -- [relaychain-args]",126			Self::executable_name()127		)128	}129130	fn author() -> String {131		env!("CARGO_PKG_AUTHORS").into()132	}133134	//TODO use args135	fn support_url() -> String {136		"support@unique.network".into()137	}138139	fn copyright_start_year() -> i32 {140		2019141	}142143	fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {144		load_spec(id)145	}146147	fn native_runtime_version(chain_spec: &Box<dyn ChainSpec>) -> &'static RuntimeVersion {148		#[cfg(feature = "unique-runtime")]149		if chain_spec.is_unique() {150			return &unique_runtime::VERSION;151		}152153		#[cfg(feature = "quartz-runtime")]154		if chain_spec.is_quartz() {155			return &quartz_runtime::VERSION;156		}157158		#[cfg(feature = "opal-runtime")]159		if chain_spec.is_opal() {160			return &opal_runtime::VERSION;161		}162163		panic!("{}", no_runtime_err!(chain_spec));164	}165}166167impl SubstrateCli for RelayChainCli {168	// TODO use args169	fn impl_name() -> String {170		"Unique Node".into()171	}172173	fn impl_version() -> String {174		env!("SUBSTRATE_CLI_IMPL_VERSION").into()175	}176	// TODO use args177	fn description() -> String {178		"Unique Node\n\nThe command-line arguments provided first will be \179		passed to the parachain node, while the arguments provided after -- will be passed \180		to the relaychain node.\n\n\181		parachain-collator [parachain-args] -- [relaychain-args]"182			.into()183	}184185	fn author() -> String {186		env!("CARGO_PKG_AUTHORS").into()187	}188	// TODO use args189	fn support_url() -> String {190		"support@unique.network".into()191	}192193	fn copyright_start_year() -> i32 {194		2019195	}196197	fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {198		polkadot_cli::Cli::from_iter([RelayChainCli::executable_name()].iter()).load_spec(id)199	}200201	fn native_runtime_version(chain_spec: &Box<dyn ChainSpec>) -> &'static RuntimeVersion {202		polkadot_cli::Cli::native_runtime_version(chain_spec)203	}204}205206#[allow(clippy::borrowed_box)]207fn extract_genesis_wasm(chain_spec: &Box<dyn sc_service::ChainSpec>) -> Result<Vec<u8>> {208	let mut storage = chain_spec.build_storage()?;209210	storage211		.top212		.remove(sp_core::storage::well_known_keys::CODE)213		.ok_or_else(|| "Could not find wasm file in genesis state!".into())214}215216macro_rules! construct_async_run {217	(|$components:ident, $cli:ident, $cmd:ident, $config:ident| $( $code:tt )* ) => {{218		let runner = $cli.create_runner($cmd)?;219220		#[cfg(feature = "unique-runtime")]221		if runner.config().chain_spec.is_unique() {222			return runner.async_run(|$config| {223				let $components = new_partial::<224					unique_runtime::RuntimeApi, UniqueRuntimeExecutor, _225				>(226					&$config,227					crate::service::parachain_build_import_queue,228				)?;229				let task_manager = $components.task_manager;230				{ $( $code )* }.map(|v| (v, task_manager))231			});232		}233234		#[cfg(feature = "quartz-runtime")]235		if runner.config().chain_spec.is_quartz() {236			return runner.async_run(|$config| {237				let $components = new_partial::<238					quartz_runtime::RuntimeApi, QuartzRuntimeExecutor, _239				>(240					&$config,241					crate::service::parachain_build_import_queue,242				)?;243				let task_manager = $components.task_manager;244				{ $( $code )* }.map(|v| (v, task_manager))245			});246		}247248		#[cfg(feature = "opal-runtime")]249		if runner.config().chain_spec.is_opal() {250			return runner.async_run(|$config| {251				let $components = new_partial::<252					opal_runtime::RuntimeApi, OpalRuntimeExecutor, _253				>(254					&$config,255					crate::service::parachain_build_import_queue,256				)?;257				let task_manager = $components.task_manager;258				{ $( $code )* }.map(|v| (v, task_manager))259			});260		}261262		Err(no_runtime_err!(runner.config().chain_spec).into())263	}}264}265266/// Parse command line arguments into service configuration.267pub fn run() -> Result<()> {268	let cli = Cli::from_args();269270	match &cli.subcommand {271		Some(Subcommand::BuildSpec(cmd)) => {272			let runner = cli.create_runner(cmd)?;273			runner.sync_run(|config| cmd.run(config.chain_spec, config.network))274		}275		Some(Subcommand::CheckBlock(cmd)) => {276			construct_async_run!(|components, cli, cmd, config| {277				Ok(cmd.run(components.client, components.import_queue))278			})279		}280		Some(Subcommand::ExportBlocks(cmd)) => {281			construct_async_run!(|components, cli, cmd, config| {282				Ok(cmd.run(components.client, config.database))283			})284		}285		Some(Subcommand::ExportState(cmd)) => {286			construct_async_run!(|components, cli, cmd, config| {287				Ok(cmd.run(components.client, config.chain_spec))288			})289		}290		Some(Subcommand::ImportBlocks(cmd)) => {291			construct_async_run!(|components, cli, cmd, config| {292				Ok(cmd.run(components.client, components.import_queue))293			})294		}295		Some(Subcommand::PurgeChain(cmd)) => {296			let runner = cli.create_runner(cmd)?;297298			runner.sync_run(|config| {299				let polkadot_cli = RelayChainCli::new(300					&config,301					[RelayChainCli::executable_name()]302						.iter()303						.chain(cli.relaychain_args.iter()),304				);305306				let polkadot_config = SubstrateCli::create_configuration(307					&polkadot_cli,308					&polkadot_cli,309					config.tokio_handle.clone(),310				)311				.map_err(|err| format!("Relay chain argument error: {}", err))?;312313				cmd.run(config, polkadot_config)314			})315		}316		Some(Subcommand::Revert(cmd)) => construct_async_run!(|components, cli, cmd, config| {317			Ok(cmd.run(components.client, components.backend))318		}),319		Some(Subcommand::ExportGenesisState(params)) => {320			let mut builder = sc_cli::LoggerBuilder::new("");321			builder.with_profiling(sc_tracing::TracingReceiver::Log, "");322			let _ = builder.init();323324			let spec = load_spec(&params.chain.clone().unwrap_or_default())?;325			let state_version = Cli::native_runtime_version(&spec).state_version();326			let block: Block = generate_genesis_block(&spec, state_version)?;327			let raw_header = block.header().encode();328			let output_buf = if params.raw {329				raw_header330			} else {331				format!("0x{:?}", HexDisplay::from(&block.header().encode())).into_bytes()332			};333334			if let Some(output) = &params.output {335				std::fs::write(output, output_buf)?;336			} else {337				std::io::stdout().write_all(&output_buf)?;338			}339340			Ok(())341		}342		Some(Subcommand::ExportGenesisWasm(params)) => {343			let mut builder = sc_cli::LoggerBuilder::new("");344			builder.with_profiling(sc_tracing::TracingReceiver::Log, "");345			let _ = builder.init();346347			let raw_wasm_blob =348				extract_genesis_wasm(&cli.load_spec(&params.chain.clone().unwrap_or_default())?)?;349			let output_buf = if params.raw {350				raw_wasm_blob351			} else {352				format!("0x{:?}", HexDisplay::from(&raw_wasm_blob)).into_bytes()353			};354355			if let Some(output) = &params.output {356				std::fs::write(output, output_buf)?;357			} else {358				std::io::stdout().write_all(&output_buf)?;359			}360361			Ok(())362		}363		Some(Subcommand::Benchmark(cmd)) => {364			if cfg!(feature = "runtime-benchmarks") {365				let runner = cli.create_runner(cmd)?;366				runner.sync_run(|config| {367					#[cfg(feature = "unique-runtime")]368					if config.chain_spec.is_unique() {369						return cmd.run::<Block, UniqueRuntimeExecutor>(config);370					}371372					#[cfg(feature = "quartz-runtime")]373					if config.chain_spec.is_quartz() {374						return cmd.run::<Block, QuartzRuntimeExecutor>(config);375					}376377					#[cfg(feature = "opal-runtime")]378					if config.chain_spec.is_opal() {379						return cmd.run::<Block, OpalRuntimeExecutor>(config);380					}381382					Err(no_runtime_err!(config.chain_spec).into())383				})384			} else {385				Err("Benchmarking wasn't enabled when building the node. \386				You can enable it with `--features runtime-benchmarks`."387					.into())388			}389		}390		None => {391			let runner = cli.create_runner(&cli.run.normalize())?;392393			runner.run_node_until_exit(|config| async move {394				let para_id = chain_spec::Extensions::try_get(&*config.chain_spec)395					.map(|e| e.para_id)396					.ok_or("Could not find parachain ID in chain-spec.")?;397398				let polkadot_cli = RelayChainCli::new(399					&config,400					[RelayChainCli::executable_name()]401						.iter()402						.chain(cli.relaychain_args.iter()),403				);404405				let id = ParaId::from(para_id);406407				let parachain_account =408					AccountIdConversion::<polkadot_primitives::v0::AccountId>::into_account(&id);409410				let state_version =411					RelayChainCli::native_runtime_version(&config.chain_spec).state_version();412				let block: Block = generate_genesis_block(&config.chain_spec, state_version)413					.map_err(|e| format!("{:?}", e))?;414				let genesis_state = format!("0x{:?}", HexDisplay::from(&block.header().encode()));415				let genesis_hash = format!("0x{:?}", HexDisplay::from(&block.header().hash().0));416417				let polkadot_config = SubstrateCli::create_configuration(418					&polkadot_cli,419					&polkadot_cli,420					config.tokio_handle.clone(),421				)422				.map_err(|err| format!("Relay chain argument error: {}", err))?;423424				info!("Parachain id: {:?}", id);425				info!("Parachain Account: {}", parachain_account);426				info!("Parachain genesis state: {}", genesis_state);427				info!("Parachain genesis hash: {}", genesis_hash);428				info!(429					"Is collating: {}",430					if config.role.is_authority() {431						"yes"432					} else {433						"no"434					}435				);436437				#[cfg(feature = "unique-runtime")]438				if config.chain_spec.is_unique() {439					return crate::service::start_node::<440						unique_runtime::Runtime,441						unique_runtime::RuntimeApi,442						UniqueRuntimeExecutor,443					>(config, polkadot_config, id)444					.await445					.map(|r| r.0)446					.map_err(Into::into);447				}448449				#[cfg(feature = "quartz-runtime")]450				if config.chain_spec.is_quartz() {451					return crate::service::start_node::<452						quartz_runtime::Runtime,453						quartz_runtime::RuntimeApi,454						QuartzRuntimeExecutor,455					>(config, polkadot_config, id)456					.await457					.map(|r| r.0)458					.map_err(Into::into);459				}460461				#[cfg(feature = "opal-runtime")]462				if config.chain_spec.is_opal() {463					return crate::service::start_node::<464						opal_runtime::Runtime,465						opal_runtime::RuntimeApi,466						OpalRuntimeExecutor,467					>(config, polkadot_config, id)468					.await469					.map(|r| r.0)470					.map_err(Into::into);471				}472473				Err(no_runtime_err!(config.chain_spec).into())474			})475		}476	}477}478479impl DefaultConfigurationValues for RelayChainCli {480	fn p2p_listen_port() -> u16 {481		30334482	}483484	fn rpc_ws_listen_port() -> u16 {485		9945486	}487488	fn rpc_http_listen_port() -> u16 {489		9934490	}491492	fn prometheus_listen_port() -> u16 {493		9616494	}495}496497impl CliConfiguration<Self> for RelayChainCli {498	fn shared_params(&self) -> &SharedParams {499		self.base.base.shared_params()500	}501502	fn import_params(&self) -> Option<&ImportParams> {503		self.base.base.import_params()504	}505506	fn network_params(&self) -> Option<&NetworkParams> {507		self.base.base.network_params()508	}509510	fn keystore_params(&self) -> Option<&KeystoreParams> {511		self.base.base.keystore_params()512	}513514	fn base_path(&self) -> Result<Option<BasePath>> {515		Ok(self516			.shared_params()517			.base_path()518			.or_else(|| self.base_path.clone().map(Into::into)))519	}520521	fn rpc_http(&self, default_listen_port: u16) -> Result<Option<SocketAddr>> {522		self.base.base.rpc_http(default_listen_port)523	}524525	fn rpc_ipc(&self) -> Result<Option<String>> {526		self.base.base.rpc_ipc()527	}528529	fn rpc_ws(&self, default_listen_port: u16) -> Result<Option<SocketAddr>> {530		self.base.base.rpc_ws(default_listen_port)531	}532533	fn prometheus_config(534		&self,535		default_listen_port: u16,536		chain_spec: &Box<dyn ChainSpec>,537	) -> Result<Option<PrometheusConfig>> {538		self.base539			.base540			.prometheus_config(default_listen_port, chain_spec)541	}542543	fn init<F>(544		&self,545		_support_url: &String,546		_impl_version: &String,547		_logger_hook: F,548		_config: &sc_service::Configuration,549	) -> Result<()> {550		unreachable!("PolkadotCli is never initialized; qed");551	}552553	fn chain_id(&self, is_dev: bool) -> Result<String> {554		let chain_id = self.base.base.chain_id(is_dev)?;555556		Ok(if chain_id.is_empty() {557			self.chain_id.clone().unwrap_or_default()558		} else {559			chain_id560		})561	}562563	fn role(&self, is_dev: bool) -> Result<sc_service::Role> {564		self.base.base.role(is_dev)565	}566567	fn transaction_pool(&self) -> Result<sc_service::config::TransactionPoolOptions> {568		self.base.base.transaction_pool()569	}570571	fn state_cache_child_ratio(&self) -> Result<Option<usize>> {572		self.base.base.state_cache_child_ratio()573	}574575	fn rpc_methods(&self) -> Result<sc_service::config::RpcMethods> {576		self.base.base.rpc_methods()577	}578579	fn rpc_ws_max_connections(&self) -> Result<Option<usize>> {580		self.base.base.rpc_ws_max_connections()581	}582583	fn rpc_cors(&self, is_dev: bool) -> Result<Option<Vec<String>>> {584		self.base.base.rpc_cors(is_dev)585	}586587	fn default_heap_pages(&self) -> Result<Option<u64>> {588		self.base.base.default_heap_pages()589	}590591	fn force_authoring(&self) -> Result<bool> {592		self.base.base.force_authoring()593	}594595	fn disable_grandpa(&self) -> Result<bool> {596		self.base.base.disable_grandpa()597	}598599	fn max_runtime_instances(&self) -> Result<Option<usize>> {600		self.base.base.max_runtime_instances()601	}602603	fn announce_block(&self) -> Result<bool> {604		self.base.base.announce_block()605	}606607	fn telemetry_endpoints(608		&self,609		chain_spec: &Box<dyn ChainSpec>,610	) -> Result<Option<sc_telemetry::TelemetryEndpoints>> {611		self.base.base.telemetry_endpoints(chain_spec)612	}613}