command.rs 9.12 KB
Newer Older
Gavin Wood's avatar
Gavin Wood committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Copyright 2017-2020 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.

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

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

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

use log::info;
18
#[cfg(not(feature = "service-rewr"))]
Seun Lanlege's avatar
Seun Lanlege committed
19
use service::{IdentifyVariant, self};
20
21
#[cfg(feature = "service-rewr")]
use service_new::{IdentifyVariant, self as service};
Bastian Köcher's avatar
Bastian Köcher committed
22
use sc_cli::{SubstrateCli, Result, RuntimeVersion, Role};
Gavin Wood's avatar
Gavin Wood committed
23
use crate::cli::{Cli, Subcommand};
24
use std::sync::Arc;
25

Gavin Wood's avatar
Gavin Wood committed
26
27
28
29
30
31
32
fn get_exec_name() -> Option<String> {
	std::env::current_exe()
		.ok()
		.and_then(|pb| pb.file_name().map(|s| s.to_os_string()))
		.and_then(|s| s.into_string().ok())
}

33
impl SubstrateCli for Cli {
34
	fn impl_name() -> String { "Parity Polkadot".into() }
35

36
	fn impl_version() -> String { env!("SUBSTRATE_CLI_IMPL_VERSION").into() }
37

38
	fn description() -> String { env!("CARGO_PKG_DESCRIPTION").into() }
39

40
	fn author() -> String { env!("CARGO_PKG_AUTHORS").into() }
41

42
	fn support_url() -> String { "https://github.com/paritytech/polkadot/issues/new".into() }
43
44
45

	fn copyright_start_year() -> i32 { 2017 }

46
	fn executable_name() -> String { "polkadot".into() }
47
48

	fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
Gavin Wood's avatar
Gavin Wood committed
49
50
		let id = if id == "" {
			let n = get_exec_name().unwrap_or_default();
51
			["polkadot", "kusama", "westend"].iter()
Gavin Wood's avatar
Gavin Wood committed
52
53
54
55
				.cloned()
				.find(|&chain| n.starts_with(chain))
				.unwrap_or("polkadot")
		} else { id };
56
		Ok(match id {
Wei Tang's avatar
Wei Tang committed
57
58
59
60
61
62
			"polkadot-dev" | "dev" => Box::new(service::chain_spec::polkadot_development_config()?),
			"polkadot-local" => Box::new(service::chain_spec::polkadot_local_testnet_config()?),
			"polkadot-staging" => Box::new(service::chain_spec::polkadot_staging_testnet_config()?),
			"kusama-dev" => Box::new(service::chain_spec::kusama_development_config()?),
			"kusama-local" => Box::new(service::chain_spec::kusama_local_testnet_config()?),
			"kusama-staging" => Box::new(service::chain_spec::kusama_staging_testnet_config()?),
Gavin Wood's avatar
Gavin Wood committed
63
			"polkadot" => Box::new(service::chain_spec::polkadot_config()?),
64
			"westend" => Box::new(service::chain_spec::westend_config()?),
Gavin Wood's avatar
Gavin Wood committed
65
			"kusama" => Box::new(service::chain_spec::kusama_config()?),
Wei Tang's avatar
Wei Tang committed
66
67
68
			"westend-dev" => Box::new(service::chain_spec::westend_development_config()?),
			"westend-local" => Box::new(service::chain_spec::westend_local_testnet_config()?),
			"westend-staging" => Box::new(service::chain_spec::westend_staging_testnet_config()?),
69
70
71
72
73
74
75
76
77
			path => {
				let path = std::path::PathBuf::from(path);

				let starts_with = |prefix: &str| {
					path.file_name().map(|f| f.to_str().map(|s| s.starts_with(&prefix))).flatten().unwrap_or(false)
				};

				// When `force_*` is given or the file name starts with the name of one of the known chains,
				// we use the chain spec for the specific chain.
78
				if self.run.force_kusama || starts_with("kusama") {
79
80
81
82
83
84
					Box::new(service::KusamaChainSpec::from_json_file(path)?)
				} else if self.run.force_westend || starts_with("westend") {
					Box::new(service::WestendChainSpec::from_json_file(path)?)
				} else {
					Box::new(service::PolkadotChainSpec::from_json_file(path)?)
				}
85
86
87
			},
		})
	}
88
89
90
91
92
93
94
95
96
97

	fn native_runtime_version(spec: &Box<dyn service::ChainSpec>) -> &'static RuntimeVersion {
		if spec.is_kusama() {
			&service::kusama_runtime::VERSION
		} else if spec.is_westend() {
			&service::westend_runtime::VERSION
		} else {
			&service::polkadot_runtime::VERSION
		}
	}
98
}
Gavin Wood's avatar
Gavin Wood committed
99

100
101
102
103
104
105
106
107
108
109
110
111
112
113
fn set_default_ss58_version(spec: &Box<dyn service::ChainSpec>) {
	use sp_core::crypto::Ss58AddressFormat;

	let ss58_version = if spec.is_kusama() {
		Ss58AddressFormat::KusamaAccount
	} else if spec.is_westend() {
		Ss58AddressFormat::SubstrateAccount
	} else {
		Ss58AddressFormat::PolkadotAccount
	};

	sp_core::crypto::set_default_ss58_version(ss58_version);
}

Gavin Wood's avatar
Gavin Wood committed
114
/// Parses polkadot specific CLI arguments and run the service.
115
116
117
118
pub fn run() -> Result<()> {
	let cli = Cli::from_args();

	match &cli.subcommand {
Gavin Wood's avatar
Gavin Wood committed
119
		None => {
120
121
			let runner = cli.create_runner(&cli.run.base)?;
			let chain_spec = &runner.config().chain_spec;
122
123
124

			set_default_ss58_version(chain_spec);

125
			let authority_discovery_enabled = cli.run.authority_discovery_enabled;
126
127
128
129
130
			let grandpa_pause = if cli.run.grandpa_pause.is_empty() {
				None
			} else {
				Some((cli.run.grandpa_pause[0], cli.run.grandpa_pause[1]))
			};
Gavin Wood's avatar
Gavin Wood committed
131

132
			if chain_spec.is_kusama() {
Gavin Wood's avatar
Gavin Wood committed
133
134
135
136
137
				info!("----------------------------");
				info!("This chain is not in any way");
				info!("      endorsed by the       ");
				info!("     KUSAMA FOUNDATION      ");
				info!("----------------------------");
138
			}
Gavin Wood's avatar
Gavin Wood committed
139

140
141
142
143
			runner.run_node_until_exit(|config| {
				let role = config.role.clone();

				match role {
144
145
146
					Role::Light => service::build_light(config).map(|(task_manager, _)| task_manager),
					_ => service::build_full(
						config,
147
						None,
148
						authority_discovery_enabled,
149
						grandpa_pause,
150
					).map(|r| r.0),
151
152
				}
			})
Gavin Wood's avatar
Gavin Wood committed
153
		},
154
155
156
157
		Some(Subcommand::BuildSpec(cmd)) => {
			let runner = cli.create_runner(cmd)?;
			runner.sync_run(|config| cmd.run(config.chain_spec, config.network))
		},
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
		Some(Subcommand::BuildSyncSpec(cmd)) => {
			let runner = cli.create_runner(cmd)?;
			let chain_spec = &runner.config().chain_spec;

			set_default_ss58_version(chain_spec);

			let authority_discovery_enabled = cli.run.authority_discovery_enabled;
			let grandpa_pause = if cli.run.grandpa_pause.is_empty() {
				None
			} else {
				Some((cli.run.grandpa_pause[0], cli.run.grandpa_pause[1]))
			};

			if chain_spec.is_kusama() {
				info!("----------------------------");
				info!("This chain is not in any way");
				info!("      endorsed by the       ");
				info!("     KUSAMA FOUNDATION      ");
				info!("----------------------------");
			}

			runner.async_run(|config| {
				let chain_spec = config.chain_spec.cloned_box();
				let network_config = config.network.clone();
182
183
184
185
				let service::NewFull { task_manager, client, network_status_sinks, .. }
					= service::new_full_nongeneric(
						config, None, authority_discovery_enabled, grandpa_pause, false,
					)?;
186
187
188
189
190
				let client = Arc::new(client);

				Ok((cmd.run(chain_spec, network_config, client, network_status_sinks), task_manager))
			})
		},
191
192
193
194
195
196
197
198
199
200
201
202
203
		Some(Subcommand::CheckBlock(cmd)) => {
			let runner = cli.create_runner(cmd)?;
			let chain_spec = &runner.config().chain_spec;

			set_default_ss58_version(chain_spec);

			runner.async_run(|mut config| {
				let (client, _, import_queue, task_manager) = service::new_chain_ops(&mut config)?;
				Ok((cmd.run(client, import_queue), task_manager))
			})
		},
		Some(Subcommand::ExportBlocks(cmd)) => {
			let runner = cli.create_runner(cmd)?;
204
			let chain_spec = &runner.config().chain_spec;
205
206

			set_default_ss58_version(chain_spec);
Gavin Wood's avatar
Gavin Wood committed
207

208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
			runner.async_run(|mut config| {
				let (client, _, _, task_manager) = service::new_chain_ops(&mut config)?;
				Ok((cmd.run(client, config.database), task_manager))
			})
		},
		Some(Subcommand::ExportState(cmd)) => {
			let runner = cli.create_runner(cmd)?;
			let chain_spec = &runner.config().chain_spec;

			set_default_ss58_version(chain_spec);

			runner.async_run(|mut config| {
				let (client, _, _, task_manager) = service::new_chain_ops(&mut config)?;
				Ok((cmd.run(client, config.chain_spec), task_manager))
			})
		},
		Some(Subcommand::ImportBlocks(cmd)) => {
			let runner = cli.create_runner(cmd)?;
			let chain_spec = &runner.config().chain_spec;

			set_default_ss58_version(chain_spec);

			runner.async_run(|mut config| {
				let (client, _, import_queue, task_manager) = service::new_chain_ops(&mut config)?;
				Ok((cmd.run(client, import_queue), task_manager))
			})
		},
		Some(Subcommand::PurgeChain(cmd)) => {
			let runner = cli.create_runner(cmd)?;
			runner.sync_run(|config| cmd.run(config.database))
		},
		Some(Subcommand::Revert(cmd)) => {
			let runner = cli.create_runner(cmd)?;
			let chain_spec = &runner.config().chain_spec;

			set_default_ss58_version(chain_spec);

			runner.async_run(|mut config| {
				let (client, backend, _, task_manager) = service::new_chain_ops(&mut config)?;
				Ok((cmd.run(client, backend), task_manager))
			})
Gavin Wood's avatar
Gavin Wood committed
249
		},
250
		Some(Subcommand::ValidationWorker(cmd)) => {
Benjamin Kampmann's avatar
Benjamin Kampmann committed
251
			let _ = sc_cli::init_logger("", sc_tracing::TracingReceiver::Log, None);
Gavin Wood's avatar
Gavin Wood committed
252
253

			if cfg!(feature = "browser") {
254
				Err(sc_cli::Error::Input("Cannot run validation worker in browser".into()))
Gavin Wood's avatar
Gavin Wood committed
255
			} else {
256
				#[cfg(all(not(feature = "browser"), not(feature = "service-rewr")))]
257
				service::run_validation_worker(&cmd.mem_id)?;
Gavin Wood's avatar
Gavin Wood committed
258
259
260
				Ok(())
			}
		},
261
		Some(Subcommand::Benchmark(cmd)) => {
262
263
			let runner = cli.create_runner(cmd)?;
			let chain_spec = &runner.config().chain_spec;
264
265

			set_default_ss58_version(chain_spec);
266

267
268
269
			runner.sync_run(|config| {
				cmd.run::<service::kusama_runtime::Block, service::KusamaExecutor>(config)
			})
270
		},
Gavin Wood's avatar
Gavin Wood committed
271
272
	}
}