referrerpolicy=no-referrer-when-downgrade

undying_collator/
main.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Polkadot.
3
4// Polkadot 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// Polkadot 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 Polkadot.  If not, see <http://www.gnu.org/licenses/>.
16
17//! Collator for the `Undying` test parachain.
18
19use polkadot_cli::{Error, Result};
20use polkadot_node_primitives::CollationGenerationConfig;
21use polkadot_node_subsystem::messages::{CollationGenerationMessage, CollatorProtocolMessage};
22use polkadot_primitives::Id as ParaId;
23use sc_cli::{Error as SubstrateCliError, SubstrateCli};
24use sp_core::hexdisplay::HexDisplay;
25use std::{
26	fs,
27	io::{self, Write},
28};
29use test_parachain_undying_collator::Collator;
30
31mod cli;
32use cli::{Cli, MalusType};
33
34fn main() -> Result<()> {
35	let cli = Cli::from_args();
36
37	match cli.subcommand {
38		Some(cli::Subcommand::ExportGenesisState(params)) => {
39			// `pov_size`, `pvf_complexity` need to match the
40			// ones that we start the collator with.
41			let collator = Collator::new(
42				params.pov_size,
43				params.pvf_complexity,
44				// The value of `experimental_send_approved_peer` doesn't matter because it's not
45				// part of the state.
46				false,
47			);
48
49			let output_buf =
50				format!("0x{:?}", HexDisplay::from(&collator.genesis_head())).into_bytes();
51
52			if let Some(output) = params.output {
53				std::fs::write(output, output_buf)?;
54			} else {
55				std::io::stdout().write_all(&output_buf)?;
56			}
57
58			Ok::<_, Error>(())
59		},
60		Some(cli::Subcommand::ExportGenesisWasm(params)) => {
61			// We pass some dummy values for `pov_size` and `pvf_complexity` as these don't
62			// matter for `wasm` export.
63			let collator = Collator::default();
64			let output_buf =
65				format!("0x{:?}", HexDisplay::from(&collator.validation_code())).into_bytes();
66
67			if let Some(output) = params.output {
68				fs::write(output, output_buf)?;
69			} else {
70				io::stdout().write_all(&output_buf)?;
71			}
72
73			Ok(())
74		},
75		None => {
76			let runner = cli.create_runner(&cli.run.base).map_err(|e| {
77				SubstrateCliError::Application(
78					Box::new(e) as Box<(dyn 'static + Send + Sync + std::error::Error)>
79				)
80			})?;
81
82			runner.run_node_until_exit(|config| async move {
83				let collator = Collator::new(
84					cli.run.pov_size,
85					cli.run.pvf_complexity,
86					cli.run.experimental_send_approved_peer,
87				);
88
89				let full_node = polkadot_service::build_full(
90					config,
91					polkadot_service::NewFullParams {
92						is_parachain_node: polkadot_service::IsParachainNode::Collator(
93							collator.collator_key(),
94						),
95						enable_beefy: false,
96						force_authoring_backoff: false,
97						telemetry_worker_handle: None,
98
99						// Collators don't spawn PVF workers, so we can disable version checks.
100						node_version: None,
101						secure_validator_mode: false,
102						workers_path: None,
103						workers_names: None,
104
105						overseer_gen: polkadot_service::CollatorOverseerGen,
106						overseer_message_channel_capacity_override: None,
107						malus_finality_delay: None,
108						hwbench: None,
109						execute_workers_max_num: None,
110						prepare_workers_hard_max_num: None,
111						prepare_workers_soft_max_num: None,
112						keep_finalized_for: None,
113					},
114				)
115				.map_err(|e| e.to_string())?;
116				let mut overseer_handle = full_node
117					.overseer_handle
118					.clone()
119					.expect("Overseer handle should be initialized for collators");
120
121				let genesis_head_hex =
122					format!("0x{:?}", HexDisplay::from(&collator.genesis_head()));
123				let validation_code_hex =
124					format!("0x{:?}", HexDisplay::from(&collator.validation_code()));
125
126				let para_id = ParaId::from(cli.run.parachain_id);
127
128				log::info!("Running `Undying` collator for parachain id: {}", para_id);
129				log::info!("Genesis state: {}", genesis_head_hex);
130				log::info!("Validation code: {}", validation_code_hex);
131
132				let config = CollationGenerationConfig {
133					key: collator.collator_key(),
134					// If the collator is malicious, disable the collation function
135					// (set to None) and manually handle collation submission later.
136					collator: if cli.run.malus_type == MalusType::None {
137						Some(
138							collator
139								.create_collation_function(full_node.task_manager.spawn_handle()),
140						)
141					} else {
142						None
143					},
144					para_id,
145				};
146				overseer_handle
147					.send_msg(CollationGenerationMessage::Initialize(config), "Collator")
148					.await;
149
150				overseer_handle
151					.send_msg(CollatorProtocolMessage::CollateOn(para_id), "Collator")
152					.await;
153
154				// If the collator is configured to behave maliciously, simulate the specified
155				// malicious behavior.
156				if cli.run.malus_type == MalusType::DuplicateCollations {
157					collator.send_same_collations_to_all_assigned_cores(
158						&full_node,
159						overseer_handle,
160						para_id,
161					);
162				}
163
164				Ok(full_node.task_manager)
165			})
166		},
167	}?;
168	Ok(())
169}