referrerpolicy=no-referrer-when-downgrade

test_parachain/
cli.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Cumulus.
3
4// Cumulus is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Cumulus is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Cumulus.  If not, see <http://www.gnu.org/licenses/>.
16
17use clap::ValueEnum;
18use cumulus_client_cli::{ExportGenesisHeadCommand, ExportGenesisWasmCommand};
19use polkadot_service::{ChainSpec, ParaId, PrometheusConfig};
20use sc_cli::{
21	CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, NetworkParams,
22	Result as CliResult, RpcEndpoint, SharedParams, SubstrateCli,
23};
24use sc_service::BasePath;
25use std::{
26	fmt::{Display, Formatter},
27	path::PathBuf,
28};
29
30#[derive(Debug, clap::Parser)]
31#[command(
32	version,
33	propagate_version = true,
34	args_conflicts_with_subcommands = true,
35	subcommand_negates_reqs = true
36)]
37pub struct TestCollatorCli {
38	#[command(subcommand)]
39	pub subcommand: Option<Subcommand>,
40
41	#[command(flatten)]
42	pub run: cumulus_client_cli::RunCmd,
43
44	/// Relay chain arguments
45	#[arg(raw = true)]
46	pub relaychain_args: Vec<String>,
47
48	#[arg(long)]
49	pub disable_block_announcements: bool,
50
51	#[arg(long)]
52	pub fail_pov_recovery: bool,
53
54	/// Authoring style to use.
55	#[arg(long, default_value_t = AuthoringPolicy::Lookahead)]
56	pub authoring: AuthoringPolicy,
57}
58
59/// Collator implementation to use.
60#[derive(PartialEq, Debug, ValueEnum, Clone, Copy)]
61pub enum AuthoringPolicy {
62	/// Use the lookahead collator. Builds blocks once per relay chain block,
63	/// builds on relay chain forks.
64	Lookahead,
65	/// Use the slot-based collator which can handle elastic-scaling. Builds blocks based on time
66	/// and can utilize multiple cores, always builds on the best relay chain block available.
67	SlotBased,
68}
69
70impl Display for AuthoringPolicy {
71	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
72		match self {
73			AuthoringPolicy::Lookahead => write!(f, "lookahead"),
74			AuthoringPolicy::SlotBased => write!(f, "slot-based"),
75		}
76	}
77}
78
79#[derive(Debug, clap::Subcommand)]
80pub enum Subcommand {
81	/// Build a chain specification.
82	/// DEPRECATED: `build-spec` command will be removed after 1/04/2026. Use `export-chain-spec`
83	/// command instead.
84	#[deprecated(
85		note = "build-spec command will be removed after 1/04/2026. Use export-chain-spec command instead"
86	)]
87	BuildSpec(sc_cli::BuildSpecCmd),
88
89	/// Export the chain specification.
90	ExportChainSpec(sc_cli::ExportChainSpecCmd),
91
92	/// Export the genesis state of the parachain.
93	#[command(alias = "export-genesis-state")]
94	ExportGenesisHead(ExportGenesisHeadCommand),
95
96	/// Export the genesis wasm of the parachain.
97	ExportGenesisWasm(ExportGenesisWasmCommand),
98}
99
100#[derive(Debug)]
101pub struct RelayChainCli {
102	/// The actual relay chain cli object.
103	pub base: polkadot_cli::RunCmd,
104
105	/// Optional chain id that should be passed to the relay chain.
106	pub chain_id: Option<String>,
107
108	/// The base path that should be used by the relay chain.
109	pub base_path: Option<PathBuf>,
110}
111
112impl RelayChainCli {
113	/// Parse the relay chain CLI parameters using the para chain `Configuration`.
114	pub fn new<'a>(
115		para_config: &sc_service::Configuration,
116		relay_chain_args: impl Iterator<Item = &'a String>,
117	) -> Self {
118		let base_path = para_config.base_path.path().join("polkadot");
119		Self {
120			base_path: Some(base_path),
121			chain_id: None,
122			base: clap::Parser::parse_from(relay_chain_args),
123		}
124	}
125}
126
127impl CliConfiguration<Self> for RelayChainCli {
128	fn shared_params(&self) -> &SharedParams {
129		self.base.base.shared_params()
130	}
131
132	fn import_params(&self) -> Option<&ImportParams> {
133		self.base.base.import_params()
134	}
135
136	fn network_params(&self) -> Option<&NetworkParams> {
137		self.base.base.network_params()
138	}
139
140	fn keystore_params(&self) -> Option<&KeystoreParams> {
141		self.base.base.keystore_params()
142	}
143
144	fn base_path(&self) -> CliResult<Option<BasePath>> {
145		Ok(self
146			.shared_params()
147			.base_path()?
148			.or_else(|| self.base_path.clone().map(Into::into)))
149	}
150
151	fn rpc_addr(&self, default_listen_port: u16) -> CliResult<Option<Vec<RpcEndpoint>>> {
152		self.base.base.rpc_addr(default_listen_port)
153	}
154
155	fn prometheus_config(
156		&self,
157		default_listen_port: u16,
158		chain_spec: &Box<dyn ChainSpec>,
159	) -> CliResult<Option<PrometheusConfig>> {
160		self.base.base.prometheus_config(default_listen_port, chain_spec)
161	}
162
163	fn init<F>(
164		&self,
165		_support_url: &String,
166		_impl_version: &String,
167		_logger_hook: F,
168	) -> CliResult<()>
169	where
170		F: FnOnce(&mut sc_cli::LoggerBuilder),
171	{
172		unreachable!("PolkadotCli is never initialized; qed");
173	}
174
175	fn chain_id(&self, is_dev: bool) -> CliResult<String> {
176		let chain_id = self.base.base.chain_id(is_dev)?;
177
178		Ok(if chain_id.is_empty() { self.chain_id.clone().unwrap_or_default() } else { chain_id })
179	}
180
181	fn role(&self, is_dev: bool) -> CliResult<sc_service::Role> {
182		self.base.base.role(is_dev)
183	}
184
185	fn transaction_pool(
186		&self,
187		is_dev: bool,
188	) -> CliResult<sc_service::config::TransactionPoolOptions> {
189		self.base.base.transaction_pool(is_dev)
190	}
191
192	fn trie_cache_maximum_size(&self) -> CliResult<Option<usize>> {
193		self.base.base.trie_cache_maximum_size()
194	}
195
196	fn rpc_methods(&self) -> CliResult<sc_service::config::RpcMethods> {
197		self.base.base.rpc_methods()
198	}
199
200	fn rpc_max_connections(&self) -> CliResult<u32> {
201		self.base.base.rpc_max_connections()
202	}
203
204	fn rpc_cors(&self, is_dev: bool) -> CliResult<Option<Vec<String>>> {
205		self.base.base.rpc_cors(is_dev)
206	}
207
208	fn default_heap_pages(&self) -> CliResult<Option<u64>> {
209		self.base.base.default_heap_pages()
210	}
211
212	fn force_authoring(&self) -> CliResult<bool> {
213		self.base.base.force_authoring()
214	}
215
216	fn disable_grandpa(&self) -> CliResult<bool> {
217		self.base.base.disable_grandpa()
218	}
219
220	fn max_runtime_instances(&self) -> CliResult<Option<usize>> {
221		self.base.base.max_runtime_instances()
222	}
223
224	fn announce_block(&self) -> CliResult<bool> {
225		self.base.base.announce_block()
226	}
227
228	fn telemetry_endpoints(
229		&self,
230		chain_spec: &Box<dyn ChainSpec>,
231	) -> CliResult<Option<sc_telemetry::TelemetryEndpoints>> {
232		self.base.base.telemetry_endpoints(chain_spec)
233	}
234
235	fn node_name(&self) -> CliResult<String> {
236		self.base.base.node_name()
237	}
238}
239
240impl DefaultConfigurationValues for RelayChainCli {
241	fn p2p_listen_port() -> u16 {
242		30334
243	}
244
245	fn rpc_listen_port() -> u16 {
246		9945
247	}
248
249	fn prometheus_listen_port() -> u16 {
250		9616
251	}
252}
253
254impl SubstrateCli for TestCollatorCli {
255	fn impl_name() -> String {
256		"Cumulus zombienet test parachain".into()
257	}
258
259	fn impl_version() -> String {
260		String::new()
261	}
262
263	fn description() -> String {
264		format!(
265			"Cumulus zombienet test parachain\n\nThe command-line arguments provided first will be \
266		passed to the parachain node, while the arguments provided after -- will be passed \
267		to the relaychain node.\n\n\
268		{} [parachain-args] -- [relaychain-args]",
269			Self::executable_name()
270		)
271	}
272
273	fn author() -> String {
274		env!("CARGO_PKG_AUTHORS").into()
275	}
276
277	fn support_url() -> String {
278		"https://github.com/paritytech/polkadot-sdk/issues/new".into()
279	}
280
281	fn copyright_start_year() -> i32 {
282		2017
283	}
284
285	fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
286		Ok(match id {
287			"" => {
288				tracing::info!("Using default test service chain spec.");
289				Box::new(cumulus_test_service::get_chain_spec(Some(ParaId::from(2000)))) as Box<_>
290			},
291			"elastic-scaling-mvp" => {
292				tracing::info!("Using elastic-scaling mvp chain spec.");
293				Box::new(cumulus_test_service::get_elastic_scaling_mvp_chain_spec(Some(
294					ParaId::from(2100),
295				))) as Box<_>
296			},
297			"elastic-scaling" => {
298				tracing::info!("Using elastic-scaling chain spec.");
299				Box::new(cumulus_test_service::get_elastic_scaling_chain_spec(Some(ParaId::from(
300					2200,
301				)))) as Box<_>
302			},
303			"elastic-scaling-500ms" => {
304				tracing::info!("Using elastic-scaling 500ms chain spec.");
305				Box::new(cumulus_test_service::get_elastic_scaling_500ms_chain_spec(Some(
306					ParaId::from(2300),
307				))) as Box<_>
308			},
309			"elastic-scaling-multi-block-slot" => {
310				tracing::info!("Using elastic-scaling multi-block-slot chain spec.");
311				Box::new(cumulus_test_service::get_elastic_scaling_multi_block_slot_chain_spec(
312					Some(ParaId::from(2400)),
313				)) as Box<_>
314			},
315			"sync-backing" => {
316				tracing::info!("Using sync backing chain spec.");
317				Box::new(cumulus_test_service::get_sync_backing_chain_spec(Some(ParaId::from(
318					2500,
319				)))) as Box<_>
320			},
321			"relay-parent-offset" => Box::new(
322				cumulus_test_service::get_relay_parent_offset_chain_spec(Some(ParaId::from(2600))),
323			) as Box<_>,
324			path => {
325				let chain_spec: sc_chain_spec::GenericChainSpec =
326					sc_chain_spec::GenericChainSpec::from_json_file(path.into())?;
327				Box::new(chain_spec)
328			},
329		})
330	}
331}
332
333impl SubstrateCli for RelayChainCli {
334	fn impl_name() -> String {
335		"Polkadot collator".into()
336	}
337
338	fn impl_version() -> String {
339		String::new()
340	}
341
342	fn description() -> String {
343		format!(
344			"Polkadot collator\n\nThe command-line arguments provided first will be \
345		passed to the parachain node, while the arguments provided after -- will be passed \
346		to the relay chain node.\n\n\
347		{} [parachain-args] -- [relay_chain-args]",
348			Self::executable_name()
349		)
350	}
351
352	fn author() -> String {
353		env!("CARGO_PKG_AUTHORS").into()
354	}
355
356	fn support_url() -> String {
357		"https://github.com/paritytech/polkadot-sdk/issues/new".into()
358	}
359
360	fn copyright_start_year() -> i32 {
361		2017
362	}
363
364	fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
365		<polkadot_cli::Cli as SubstrateCli>::from_iter([RelayChainCli::executable_name()].iter())
366			.load_spec(id)
367	}
368}