command.rs 9.45 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_enabled = cli.run.authority_discovery_enabled;
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
						None,
152
						authority_discovery_enabled,
153
						grandpa_pause,
154
					).map(|full| full.task_manager),
155
156
				}
			})
Gavin Wood's avatar
Gavin Wood committed
157
		},
158
159
160
161
		Some(Subcommand::BuildSpec(cmd)) => {
			let runner = cli.create_runner(cmd)?;
			runner.sync_run(|config| cmd.run(config.chain_spec, config.network))
		},
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
		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();
186
187
188
189
190
191
192
193
				let service::NewFull {
					task_manager,
					client,
					network_status_sinks,
					..
				} = service::build_full(
					config, None, authority_discovery_enabled, grandpa_pause,
				)?;
194
195
196
197
198
				let client = Arc::new(client);

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

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

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

			set_default_ss58_version(chain_spec);
274

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