referrerpolicy=no-referrer-when-downgrade

cumulus_client_collator/
lib.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Cumulus.
3// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
4
5// Cumulus is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9
10// Cumulus is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14
15// You should have received a copy of the GNU General Public License
16// along with Cumulus. If not, see <https://www.gnu.org/licenses/>.
17
18//! Cumulus Collator implementation for Substrate.
19
20use polkadot_node_primitives::CollationGenerationConfig;
21use polkadot_node_subsystem::messages::{CollationGenerationMessage, CollatorProtocolMessage};
22use polkadot_overseer::Handle as OverseerHandle;
23use polkadot_primitives::{CollatorPair, Id as ParaId};
24pub mod service;
25
26/// Relay-chain-driven collators are those whose block production is driven purely
27/// by new relay chain blocks and the most recently included parachain blocks
28/// within them.
29///
30/// This method of driving collators is not suited to anything but the most simple parachain
31/// consensus mechanisms, and this module may soon be deprecated.
32pub mod relay_chain_driven {
33	use futures::{
34		channel::{mpsc, oneshot},
35		prelude::*,
36	};
37	use polkadot_node_primitives::{CollationGenerationConfig, CollationResult};
38	use polkadot_node_subsystem::messages::{CollationGenerationMessage, CollatorProtocolMessage};
39	use polkadot_overseer::Handle as OverseerHandle;
40	use polkadot_primitives::{CollatorPair, Id as ParaId};
41
42	use cumulus_primitives_core::{relay_chain::Hash as PHash, PersistedValidationData};
43
44	/// A request to author a collation, based on the advancement of the relay chain.
45	///
46	/// See the module docs for more info on relay-chain-driven collators.
47	pub struct CollationRequest {
48		relay_parent: PHash,
49		pvd: PersistedValidationData,
50		sender: oneshot::Sender<Option<CollationResult>>,
51	}
52
53	impl CollationRequest {
54		/// Get the relay parent of the collation request.
55		pub fn relay_parent(&self) -> &PHash {
56			&self.relay_parent
57		}
58
59		/// Get the [`PersistedValidationData`] for the request.
60		pub fn persisted_validation_data(&self) -> &PersistedValidationData {
61			&self.pvd
62		}
63
64		/// Complete the request with a collation, if any.
65		pub fn complete(self, collation: Option<CollationResult>) {
66			let _ = self.sender.send(collation);
67		}
68	}
69
70	/// Initialize the collator with Polkadot's collation-generation
71	/// subsystem, returning a stream of collation requests to handle.
72	pub async fn init(
73		key: CollatorPair,
74		para_id: ParaId,
75		overseer_handle: OverseerHandle,
76	) -> mpsc::Receiver<CollationRequest> {
77		let mut overseer_handle = overseer_handle;
78
79		let (stream_tx, stream_rx) = mpsc::channel(0);
80		let config = CollationGenerationConfig {
81			key,
82			para_id,
83			collator: Some(Box::new(move |relay_parent, validation_data| {
84				// Cloning the channel on each usage effectively makes the channel
85				// unbounded. The channel is actually bounded by the block production
86				// and consensus systems of Polkadot, which limits the amount of possible
87				// blocks.
88				let mut stream_tx = stream_tx.clone();
89				let validation_data = validation_data.clone();
90				Box::pin(async move {
91					let (this_tx, this_rx) = oneshot::channel();
92					let request =
93						CollationRequest { relay_parent, pvd: validation_data, sender: this_tx };
94
95					if stream_tx.send(request).await.is_err() {
96						return None
97					}
98
99					this_rx.await.ok().flatten()
100				})
101			})),
102		};
103
104		overseer_handle
105			.send_msg(CollationGenerationMessage::Initialize(config), "StartCollator")
106			.await;
107
108		overseer_handle
109			.send_msg(CollatorProtocolMessage::CollateOn(para_id), "StartCollator")
110			.await;
111
112		stream_rx
113	}
114}
115
116/// Initialize the collation-related subsystems on the relay-chain side.
117///
118/// This must be done prior to collation, and does not set up any callback for collation.
119/// For callback-driven collators, use the [`relay_chain_driven`] module.
120pub async fn initialize_collator_subsystems(
121	overseer_handle: &mut OverseerHandle,
122	key: CollatorPair,
123	para_id: ParaId,
124	reinitialize: bool,
125) {
126	let config = CollationGenerationConfig { key, para_id, collator: None };
127
128	if reinitialize {
129		overseer_handle
130			.send_msg(CollationGenerationMessage::Reinitialize(config), "StartCollator")
131			.await;
132	} else {
133		overseer_handle
134			.send_msg(CollationGenerationMessage::Initialize(config), "StartCollator")
135			.await;
136	}
137
138	overseer_handle
139		.send_msg(CollatorProtocolMessage::CollateOn(para_id), "StartCollator")
140		.await;
141}