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