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	/// Upper bound on collator reserved-peer mesh slots. `0` disables the mesh.
59	#[arg(long, value_name = "N", default_value_t = 32)]
60	pub collator_reserved_slots: usize,
61}
62
63/// Collator implementation to use.
64#[derive(PartialEq, Debug, ValueEnum, Clone, Copy)]
65pub enum AuthoringPolicy {
66	/// Use the lookahead collator. Builds blocks once per relay chain block,
67	/// builds on relay chain forks.
68	Lookahead,
69	/// Use the slot-based collator which can handle elastic-scaling. Builds blocks based on time
70	/// and can utilize multiple cores, always builds on the best relay chain block available.
71	SlotBased,
72}
73
74impl Display for AuthoringPolicy {
75	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
76		match self {
77			AuthoringPolicy::Lookahead => write!(f, "lookahead"),
78			AuthoringPolicy::SlotBased => write!(f, "slot-based"),
79		}
80	}
81}
82
83#[derive(Debug, clap::Subcommand)]
84pub enum Subcommand {
85	/// Build a chain specification.
86	/// DEPRECATED: `build-spec` command will be removed after 1/04/2026. Use `export-chain-spec`
87	/// command instead.
88	#[deprecated(
89		note = "build-spec command will be removed after 1/04/2026. Use export-chain-spec command instead"
90	)]
91	BuildSpec(sc_cli::BuildSpecCmd),
92
93	/// Export the chain specification.
94	ExportChainSpec(sc_cli::ExportChainSpecCmd),
95
96	/// Export the genesis state of the parachain.
97	#[command(alias = "export-genesis-state")]
98	ExportGenesisHead(ExportGenesisHeadCommand),
99
100	/// Export the genesis wasm of the parachain.
101	ExportGenesisWasm(ExportGenesisWasmCommand),
102}
103
104#[derive(Debug)]
105pub struct RelayChainCli {
106	/// The actual relay chain cli object.
107	pub base: polkadot_cli::RunCmd,
108
109	/// Optional chain id that should be passed to the relay chain.
110	pub chain_id: Option<String>,
111
112	/// The base path that should be used by the relay chain.
113	pub base_path: Option<PathBuf>,
114}
115
116impl RelayChainCli {
117	/// Parse the relay chain CLI parameters using the para chain `Configuration`.
118	pub fn new<'a>(
119		para_config: &sc_service::Configuration,
120		relay_chain_args: impl Iterator<Item = &'a String>,
121	) -> Self {
122		let base_path = para_config.base_path.path().join("polkadot");
123		Self {
124			base_path: Some(base_path),
125			chain_id: None,
126			base: clap::Parser::parse_from(relay_chain_args),
127		}
128	}
129}
130
131impl CliConfiguration<Self> for RelayChainCli {
132	fn shared_params(&self) -> &SharedParams {
133		self.base.base.shared_params()
134	}
135
136	fn import_params(&self) -> Option<&ImportParams> {
137		self.base.base.import_params()
138	}
139
140	fn network_params(&self) -> Option<&NetworkParams> {
141		self.base.base.network_params()
142	}
143
144	fn keystore_params(&self) -> Option<&KeystoreParams> {
145		self.base.base.keystore_params()
146	}
147
148	fn base_path(&self) -> CliResult<Option<BasePath>> {
149		Ok(self
150			.shared_params()
151			.base_path()?
152			.or_else(|| self.base_path.clone().map(Into::into)))
153	}
154
155	fn rpc_addr(&self, default_listen_port: u16) -> CliResult<Option<Vec<RpcEndpoint>>> {
156		self.base.base.rpc_addr(default_listen_port)
157	}
158
159	fn prometheus_config(
160		&self,
161		default_listen_port: u16,
162		chain_spec: &Box<dyn ChainSpec>,
163	) -> CliResult<Option<PrometheusConfig>> {
164		self.base.base.prometheus_config(default_listen_port, chain_spec)
165	}
166
167	fn init<F>(
168		&self,
169		_support_url: &String,
170		_impl_version: &String,
171		_logger_hook: F,
172	) -> CliResult<()>
173	where
174		F: FnOnce(&mut sc_cli::LoggerBuilder),
175	{
176		unreachable!("PolkadotCli is never initialized; qed");
177	}
178
179	fn chain_id(&self, is_dev: bool) -> CliResult<String> {
180		let chain_id = self.base.base.chain_id(is_dev)?;
181
182		Ok(if chain_id.is_empty() { self.chain_id.clone().unwrap_or_default() } else { chain_id })
183	}
184
185	fn role(&self, is_dev: bool) -> CliResult<sc_service::Role> {
186		self.base.base.role(is_dev)
187	}
188
189	fn transaction_pool(
190		&self,
191		is_dev: bool,
192	) -> CliResult<sc_service::config::TransactionPoolOptions> {
193		self.base.base.transaction_pool(is_dev)
194	}
195
196	fn trie_cache_maximum_size(&self) -> CliResult<Option<usize>> {
197		self.base.base.trie_cache_maximum_size()
198	}
199
200	fn rpc_methods(&self) -> CliResult<sc_service::config::RpcMethods> {
201		self.base.base.rpc_methods()
202	}
203
204	fn rpc_max_connections(&self) -> CliResult<u32> {
205		self.base.base.rpc_max_connections()
206	}
207
208	fn rpc_cors(&self, is_dev: bool) -> CliResult<Option<Vec<String>>> {
209		self.base.base.rpc_cors(is_dev)
210	}
211
212	fn default_heap_pages(&self) -> CliResult<Option<u64>> {
213		self.base.base.default_heap_pages()
214	}
215
216	fn force_authoring(&self) -> CliResult<bool> {
217		self.base.base.force_authoring()
218	}
219
220	fn disable_grandpa(&self) -> CliResult<bool> {
221		self.base.base.disable_grandpa()
222	}
223
224	fn max_runtime_instances(&self) -> CliResult<Option<usize>> {
225		self.base.base.max_runtime_instances()
226	}
227
228	fn announce_block(&self) -> CliResult<bool> {
229		self.base.base.announce_block()
230	}
231
232	fn telemetry_endpoints(
233		&self,
234		chain_spec: &Box<dyn ChainSpec>,
235	) -> CliResult<Option<sc_telemetry::TelemetryEndpoints>> {
236		self.base.base.telemetry_endpoints(chain_spec)
237	}
238
239	fn node_name(&self) -> CliResult<String> {
240		self.base.base.node_name()
241	}
242}
243
244impl DefaultConfigurationValues for RelayChainCli {
245	fn p2p_listen_port() -> u16 {
246		30334
247	}
248
249	fn rpc_listen_port() -> u16 {
250		9945
251	}
252
253	fn prometheus_listen_port() -> u16 {
254		9616
255	}
256}
257
258impl SubstrateCli for TestCollatorCli {
259	fn impl_name() -> String {
260		"Cumulus zombienet test parachain".into()
261	}
262
263	fn impl_version() -> String {
264		String::new()
265	}
266
267	fn description() -> String {
268		format!(
269			"Cumulus zombienet test parachain\n\nThe command-line arguments provided first will be \
270		passed to the parachain node, while the arguments provided after -- will be passed \
271		to the relaychain node.\n\n\
272		{} [parachain-args] -- [relaychain-args]",
273			Self::executable_name()
274		)
275	}
276
277	fn author() -> String {
278		env!("CARGO_PKG_AUTHORS").into()
279	}
280
281	fn support_url() -> String {
282		"https://github.com/paritytech/polkadot-sdk/issues/new".into()
283	}
284
285	fn copyright_start_year() -> i32 {
286		2017
287	}
288
289	fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
290		Ok(Box::new(match id {
291			"" => {
292				tracing::info!("Using default test service chain spec.");
293				cumulus_test_service::get_chain_spec(
294					cumulus_test_runtime::WASM_BINARY,
295					Some(ParaId::from(2000)),
296				)
297			},
298			"elastic-scaling-mvp" => {
299				tracing::info!("Using elastic-scaling mvp chain spec.");
300				cumulus_test_service::get_chain_spec(
301					cumulus_test_runtime::elastic_scaling::WASM_BINARY,
302					Some(ParaId::from(2100)),
303				)
304			},
305			"elastic-scaling" => {
306				tracing::info!("Using elastic-scaling chain spec.");
307				cumulus_test_service::get_chain_spec(
308					cumulus_test_runtime::elastic_scaling::WASM_BINARY,
309					Some(ParaId::from(2200)),
310				)
311			},
312			"elastic-scaling-500ms" => {
313				tracing::info!("Using elastic-scaling 500ms chain spec.");
314				cumulus_test_service::get_chain_spec(
315					cumulus_test_runtime::elastic_scaling_500ms::WASM_BINARY,
316					Some(ParaId::from(2300)),
317				)
318			},
319			"block-bundling" => {
320				tracing::info!("Using block-bundling chain spec.");
321				cumulus_test_service::get_chain_spec(
322					cumulus_test_runtime::block_bundling::WASM_BINARY,
323					Some(ParaId::from(2400)),
324				)
325			},
326			"sync-backing" => {
327				tracing::info!("Using sync backing chain spec.");
328				cumulus_test_service::get_chain_spec(
329					cumulus_test_runtime::sync_backing::WASM_BINARY,
330					Some(ParaId::from(2500)),
331				)
332			},
333			"async-backing" => {
334				tracing::info!("Using async backing chain spec.");
335				cumulus_test_service::get_chain_spec(
336					cumulus_test_runtime::WASM_BINARY,
337					Some(ParaId::from(2500)),
338				)
339			},
340			"relay-parent-offset" => cumulus_test_service::get_chain_spec(
341				cumulus_test_runtime::relay_parent_offset::WASM_BINARY,
342				Some(ParaId::from(2600)),
343			),
344			"with-authority-discovery" => {
345				tracing::info!("Using with-authority-discovery chain spec.");
346				cumulus_test_service::get_chain_spec(
347					cumulus_test_runtime::with_authority_discovery::WASM_BINARY,
348					Some(ParaId::from(1000)),
349				)
350			},
351			"v3" => {
352				tracing::info!("Using async backing V3 chain spec.");
353				cumulus_test_service::get_chain_spec(
354					cumulus_test_runtime::v3::WASM_BINARY,
355					Some(ParaId::from(2700)),
356				)
357			},
358			"v3-rpo-2" => {
359				tracing::info!("Using async backing V3 with relay parent offset 2 chain spec.");
360				cumulus_test_service::get_chain_spec(
361					cumulus_test_runtime::v3_rpo_2::WASM_BINARY,
362					Some(ParaId::from(2700)),
363				)
364			},
365			"v3-rpo-4" => {
366				tracing::info!("Using async backing V3 with relay parent offset 4 chain spec.");
367				cumulus_test_service::get_chain_spec(
368					cumulus_test_runtime::v3_rpo_4::WASM_BINARY,
369					Some(ParaId::from(2700)),
370				)
371			},
372			"v3-rpo-6" => {
373				tracing::info!("Using async backing V3 with relay parent offset 6 chain spec.");
374				cumulus_test_service::get_chain_spec(
375					cumulus_test_runtime::v3_rpo_6::WASM_BINARY,
376					Some(ParaId::from(2700)),
377				)
378			},
379			"v3-rpo-15" => {
380				tracing::info!("Using async backing V3 with relay parent offset 15 chain spec.");
381				cumulus_test_service::get_chain_spec(
382					cumulus_test_runtime::v3_rpo_15::WASM_BINARY,
383					Some(ParaId::from(2700)),
384				)
385			},
386			"elastic-scaling-v3" => {
387				tracing::info!("Using elastic scaling V3 chain spec.");
388				cumulus_test_service::get_chain_spec(
389					cumulus_test_runtime::elastic_scaling_v3::WASM_BINARY,
390					Some(ParaId::from(2800)),
391				)
392			},
393			path => {
394				let chain_spec: sc_chain_spec::GenericChainSpec =
395					sc_chain_spec::GenericChainSpec::from_json_file(path.into())?;
396				chain_spec
397			},
398		}))
399	}
400}
401
402impl SubstrateCli for RelayChainCli {
403	fn impl_name() -> String {
404		"Polkadot collator".into()
405	}
406
407	fn impl_version() -> String {
408		String::new()
409	}
410
411	fn description() -> String {
412		format!(
413			"Polkadot collator\n\nThe command-line arguments provided first will be \
414		passed to the parachain node, while the arguments provided after -- will be passed \
415		to the relay chain node.\n\n\
416		{} [parachain-args] -- [relay_chain-args]",
417			Self::executable_name()
418		)
419	}
420
421	fn author() -> String {
422		env!("CARGO_PKG_AUTHORS").into()
423	}
424
425	fn support_url() -> String {
426		"https://github.com/paritytech/polkadot-sdk/issues/new".into()
427	}
428
429	fn copyright_start_year() -> i32 {
430		2017
431	}
432
433	fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
434		<polkadot_cli::Cli as SubstrateCli>::from_iter([RelayChainCli::executable_name()].iter())
435			.load_spec(id)
436	}
437}