command.rs 9.43 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;
Seun Lanlege's avatar
Seun Lanlege committed
18
use service::{IdentifyVariant, self};
Bastian Köcher's avatar
Bastian Köcher committed
19
use sc_cli::{SubstrateCli, Result, RuntimeVersion, Role};
Gavin Wood's avatar
Gavin Wood committed
20
use crate::cli::{Cli, Subcommand};
21
use std::sync::Arc;
22

Gavin Wood's avatar
Gavin Wood committed
23
24
25
26
27
28
29
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())
}

30
impl SubstrateCli for Cli {
31
	fn impl_name() -> String { "Parity Polkadot".into() }
32

33
	fn impl_version() -> String { env!("SUBSTRATE_CLI_IMPL_VERSION").into() }
34

35
	fn description() -> String { env!("CARGO_PKG_DESCRIPTION").into() }
36

37
	fn author() -> String { env!("CARGO_PKG_AUTHORS").into() }
38

39
	fn support_url() -> String { "https://github.com/paritytech/polkadot/issues/new".into() }
40
41
42

	fn copyright_start_year() -> i32 { 2017 }

43
	fn executable_name() -> String { "polkadot".into() }
44
45

	fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
Gavin Wood's avatar
Gavin Wood committed
46
47
		let id = if id == "" {
			let n = get_exec_name().unwrap_or_default();
48
			["polkadot", "kusama", "westend", "rococo"].iter()
Gavin Wood's avatar
Gavin Wood committed
49
50
51
52
				.cloned()
				.find(|&chain| n.starts_with(chain))
				.unwrap_or("polkadot")
		} else { id };
53
		Ok(match id {
Wei Tang's avatar
Wei Tang committed
54
55
56
57
58
59
			"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
60
			"polkadot" => Box::new(service::chain_spec::polkadot_config()?),
61
			"westend" => Box::new(service::chain_spec::westend_config()?),
Gavin Wood's avatar
Gavin Wood committed
62
			"kusama" => Box::new(service::chain_spec::kusama_config()?),
Wei Tang's avatar
Wei Tang committed
63
64
65
			"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()?),
66
67
68
			"rococo-staging" => Box::new(service::chain_spec::rococo_staging_testnet_config()?),
			"rococo-local" => Box::new(service::chain_spec::rococo_local_testnet_config()?),
			"rococo" => Box::new(service::chain_spec::rococo_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
79
80
				if self.run.force_rococo || starts_with("rococo") {
					Box::new(service::RococoChainSpec::from_json_file(path)?)
				} else if self.run.force_kusama || starts_with("kusama") {
81
82
83
84
85
86
					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)?)
				}
87
88
89
			},
		})
	}
90
91
92
93
94
95

	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
96
97
		} else if spec.is_rococo() {
			&service::rococo_runtime::VERSION
98
99
100
101
		} else {
			&service::polkadot_runtime::VERSION
		}
	}
102
}
Gavin Wood's avatar
Gavin Wood committed
103

104
105
106
107
108
109
110
111
112
113
114
115
116
117
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
118
/// Parses polkadot specific CLI arguments and run the service.
119
120
121
122
pub fn run() -> Result<()> {
	let cli = Cli::from_args();

	match &cli.subcommand {
Gavin Wood's avatar
Gavin Wood committed
123
		None => {
124
125
			let runner = cli.create_runner(&cli.run.base)?;
			let chain_spec = &runner.config().chain_spec;
126
127
128

			set_default_ss58_version(chain_spec);

129
			let authority_discovery_disabled = cli.run.authority_discovery_disabled;
130
131
132
133
134
			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
135

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

144
145
146
147
			runner.run_node_until_exit(|config| {
				let role = config.role.clone();

				match role {
148
149
150
					Role::Light => service::build_light(config).map(|(task_manager, _)| task_manager),
					_ => service::build_full(
						config,
151
						authority_discovery_disabled,
152
						grandpa_pause,
153
					).map(|full| full.task_manager),
154
155
				}
			})
Gavin Wood's avatar
Gavin Wood committed
156
		},
157
158
159
160
		Some(Subcommand::BuildSpec(cmd)) => {
			let runner = cli.create_runner(cmd)?;
			runner.sync_run(|config| cmd.run(config.chain_spec, config.network))
		},
161
162
163
164
165
166
		Some(Subcommand::BuildSyncSpec(cmd)) => {
			let runner = cli.create_runner(cmd)?;
			let chain_spec = &runner.config().chain_spec;

			set_default_ss58_version(chain_spec);

167
			let authority_discovery_disabled = cli.run.authority_discovery_disabled;
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
			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();
185
186
187
188
189
190
				let service::NewFull {
					task_manager,
					client,
					network_status_sinks,
					..
				} = service::build_full(
191
					config, authority_discovery_disabled, grandpa_pause,
192
				)?;
193
194
195
196
197
				let client = Arc::new(client);

				Ok((cmd.run(chain_spec, network_config, client, network_status_sinks), task_manager))
			})
		},
198
199
200
201
202
203
204
205
206
207
208
209
210
		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)?;
211
			let chain_spec = &runner.config().chain_spec;
212
213

			set_default_ss58_version(chain_spec);
Gavin Wood's avatar
Gavin Wood committed
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
249
250
251
252
253
254
255
			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
256
		},
257
		Some(Subcommand::ValidationWorker(cmd)) => {
Benjamin Kampmann's avatar
Benjamin Kampmann committed
258
			let _ = sc_cli::init_logger("", sc_tracing::TracingReceiver::Log, None);
Gavin Wood's avatar
Gavin Wood committed
259
260

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

			set_default_ss58_version(chain_spec);
273

274
275
276
			runner.sync_run(|config| {
				cmd.run::<service::kusama_runtime::Block, service::KusamaExecutor>(config)
			})
277
		},
Gavin Wood's avatar
Gavin Wood committed
278
279
	}
}