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