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(match id {
291			"" => {
292				tracing::info!("Using default test service chain spec.");
293				Box::new(cumulus_test_service::get_chain_spec(Some(ParaId::from(2000)))) as Box<_>
294			},
295			"elastic-scaling-mvp" => {
296				tracing::info!("Using elastic-scaling mvp chain spec.");
297				Box::new(cumulus_test_service::get_elastic_scaling_chain_spec(Some(ParaId::from(
298					2100,
299				)))) as Box<_>
300			},
301			"elastic-scaling" => {
302				tracing::info!("Using elastic-scaling chain spec.");
303				Box::new(cumulus_test_service::get_elastic_scaling_chain_spec(Some(ParaId::from(
304					2200,
305				)))) as Box<_>
306			},
307			"elastic-scaling-500ms" => {
308				tracing::info!("Using elastic-scaling 500ms chain spec.");
309				Box::new(cumulus_test_service::get_elastic_scaling_500ms_chain_spec(Some(
310					ParaId::from(2300),
311				))) as Box<_>
312			},
313			"block-bundling" => {
314				tracing::info!("Using block-bundling chain spec.");
315				Box::new(cumulus_test_service::get_block_bundling_chain_spec(Some(ParaId::from(
316					2400,
317				)))) as Box<_>
318			},
319			"sync-backing" => {
320				tracing::info!("Using sync backing chain spec.");
321				Box::new(cumulus_test_service::get_sync_backing_chain_spec(Some(ParaId::from(
322					2500,
323				)))) as Box<_>
324			},
325			"async-backing" => {
326				tracing::info!("Using async backing chain spec.");
327				Box::new(cumulus_test_service::get_async_backing_chain_spec(Some(ParaId::from(
328					2500,
329				)))) as Box<_>
330			},
331			"relay-parent-offset" => Box::new(
332				cumulus_test_service::get_relay_parent_offset_chain_spec(Some(ParaId::from(2600))),
333			) as Box<_>,
334			"default-test" => {
335				tracing::info!("Using default test chain spec (no authority-discovery).");
336				Box::new(cumulus_test_service::get_chain_spec(Some(ParaId::from(1000)))) as Box<_>
337			},
338			"with-authority-discovery" => {
339				tracing::info!("Using with-authority-discovery chain spec.");
340				Box::new(cumulus_test_service::get_with_authority_discovery_chain_spec(Some(
341					ParaId::from(1000),
342				))) as Box<_>
343			},
344			"async-backing-v3" => {
345				tracing::info!("Using async backing V3 chain spec.");
346				Box::new(cumulus_test_service::get_async_backing_v3_chain_spec(Some(ParaId::from(
347					2700,
348				)))) as Box<_>
349			},
350			"async-backing-v3-rpo" => {
351				tracing::info!("Using async backing V3 with relay parent offset chain spec.");
352				Box::new(cumulus_test_service::get_async_backing_v3_rpo_chain_spec(Some(
353					ParaId::from(2700),
354				))) as Box<_>
355			},
356			"elastic-scaling-v3" => {
357				tracing::info!("Using elastic scaling V3 chain spec.");
358				Box::new(cumulus_test_service::get_elastic_scaling_v3_chain_spec(Some(
359					ParaId::from(2900),
360				))) as Box<_>
361			},
362			path => {
363				let chain_spec: sc_chain_spec::GenericChainSpec =
364					sc_chain_spec::GenericChainSpec::from_json_file(path.into())?;
365				Box::new(chain_spec)
366			},
367		})
368	}
369}
370
371impl SubstrateCli for RelayChainCli {
372	fn impl_name() -> String {
373		"Polkadot collator".into()
374	}
375
376	fn impl_version() -> String {
377		String::new()
378	}
379
380	fn description() -> String {
381		format!(
382			"Polkadot collator\n\nThe command-line arguments provided first will be \
383		passed to the parachain node, while the arguments provided after -- will be passed \
384		to the relay chain node.\n\n\
385		{} [parachain-args] -- [relay_chain-args]",
386			Self::executable_name()
387		)
388	}
389
390	fn author() -> String {
391		env!("CARGO_PKG_AUTHORS").into()
392	}
393
394	fn support_url() -> String {
395		"https://github.com/paritytech/polkadot-sdk/issues/new".into()
396	}
397
398	fn copyright_start_year() -> i32 {
399		2017
400	}
401
402	fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
403		<polkadot_cli::Cli as SubstrateCli>::from_iter([RelayChainCli::executable_name()].iter())
404			.load_spec(id)
405	}
406}