referrerpolicy=no-referrer-when-downgrade

cumulus_client_bootnodes/
task.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 <http://www.gnu.org/licenses/>.
17
18//! Parachain bootnodes advertisement and discovery service.
19
20use crate::{
21	advertisement::{BootnodeAdvertisement, BootnodeAdvertisementParams},
22	config::paranode_protocol_name,
23	discovery::{BootnodeDiscovery, BootnodeDiscoveryParams},
24};
25use cumulus_primitives_core::{relay_chain::BlockId, ParaId};
26use cumulus_relay_chain_interface::RelayChainInterface;
27use log::{debug, error};
28use num_traits::Zero;
29use parachains_common::Hash as ParaHash;
30use sc_network::{request_responses::IncomingRequest, service::traits::NetworkService, Multiaddr};
31use sc_service::TaskManager;
32use std::sync::Arc;
33
34/// Log target for this crate.
35const LOG_TARGET: &str = "bootnodes";
36
37/// Bootnode advertisement task params.
38pub struct StartBootnodeTasksParams<'a> {
39	/// Enable embedded DHT bootnode.
40	pub embedded_dht_bootnode: bool,
41	/// Enable DHT bootnode discovery.
42	pub dht_bootnode_discovery: bool,
43	/// Parachain ID.
44	pub para_id: ParaId,
45	/// Task manager.
46	pub task_manager: &'a mut TaskManager,
47	/// Relay chain interface.
48	pub relay_chain_interface: Arc<dyn RelayChainInterface>,
49	/// Relay chain fork ID.
50	pub relay_chain_fork_id: Option<String>,
51	/// Relay chain network service.
52	pub relay_chain_network: Arc<dyn NetworkService>,
53	/// `/paranode` protocol request receiver.
54	pub request_receiver: async_channel::Receiver<IncomingRequest>,
55	/// Parachain node network service.
56	pub parachain_network: Arc<dyn NetworkService>,
57	/// Whether to advertise non-global IP addresses.
58	pub advertise_non_global_ips: bool,
59	/// Parachain genesis hash.
60	pub parachain_genesis_hash: ParaHash,
61	/// Parachain fork ID.
62	pub parachain_fork_id: Option<String>,
63	/// Parachain public addresses provided by the operator.
64	pub parachain_public_addresses: Vec<Multiaddr>,
65}
66
67async fn bootnode_advertisement(
68	para_id: ParaId,
69	relay_chain_interface: Arc<dyn RelayChainInterface>,
70	relay_chain_network: Arc<dyn NetworkService>,
71	request_receiver: async_channel::Receiver<IncomingRequest>,
72	parachain_network: Arc<dyn NetworkService>,
73	advertise_non_global_ips: bool,
74	parachain_genesis_hash: ParaHash,
75	parachain_fork_id: Option<String>,
76	public_addresses: Vec<Multiaddr>,
77) {
78	let bootnode_advertisement = BootnodeAdvertisement::new(BootnodeAdvertisementParams {
79		para_id,
80		relay_chain_interface,
81		relay_chain_network,
82		request_receiver,
83		parachain_network,
84		advertise_non_global_ips,
85		parachain_genesis_hash,
86		parachain_fork_id,
87		public_addresses,
88	});
89
90	if let Err(e) = bootnode_advertisement.run().await {
91		error!(target: LOG_TARGET, "Bootnode advertisement terminated with error: {e}");
92	}
93}
94
95async fn bootnode_discovery(
96	para_id: ParaId,
97	parachain_network: Arc<dyn NetworkService>,
98	parachain_genesis_hash: ParaHash,
99	parachain_fork_id: Option<String>,
100	relay_chain_interface: Arc<dyn RelayChainInterface>,
101	relay_chain_fork_id: Option<String>,
102	relay_chain_network: Arc<dyn NetworkService>,
103) {
104	let relay_chain_genesis_hash =
105		match relay_chain_interface.header(BlockId::Number(Zero::zero())).await {
106			Ok(Some(header)) => header.hash().as_bytes().to_vec(),
107			Ok(None) => {
108				error!(
109					target: LOG_TARGET,
110					"Bootnode discovery: relay chain genesis hash does not exist",
111				);
112				// Make essential task fail.
113				return;
114			},
115			Err(e) => {
116				error!(
117					target: LOG_TARGET,
118					"Bootnode discovery: failed to obtain relay chain genesis hash: {e}",
119				);
120				// Make essential task fail.
121				return;
122			},
123		};
124
125	let paranode_protocol_name =
126		paranode_protocol_name(relay_chain_genesis_hash, relay_chain_fork_id.as_deref());
127
128	let bootnode_discovery = BootnodeDiscovery::new(BootnodeDiscoveryParams {
129		para_id,
130		parachain_network,
131		parachain_genesis_hash,
132		parachain_fork_id,
133		relay_chain_interface,
134		relay_chain_network,
135		paranode_protocol_name,
136	});
137
138	match bootnode_discovery.run().await {
139		// Do not terminate the essentil task if bootnode discovery succeeded.
140		Ok(()) => std::future::pending().await,
141		Err(e) => error!(target: LOG_TARGET, "Bootnode discovery terminated with error: {e}"),
142	}
143}
144
145/// Start parachain bootnode advertisement and discovery tasks.
146pub fn start_bootnode_tasks(
147	StartBootnodeTasksParams {
148		embedded_dht_bootnode,
149		dht_bootnode_discovery,
150		para_id,
151		task_manager,
152		relay_chain_interface,
153		relay_chain_fork_id,
154		relay_chain_network,
155		request_receiver,
156		parachain_network,
157		advertise_non_global_ips,
158		parachain_genesis_hash,
159		parachain_fork_id,
160		parachain_public_addresses,
161	}: StartBootnodeTasksParams,
162) {
163	debug!(
164		target: LOG_TARGET,
165		"Embedded DHT bootnode enabled: {embedded_dht_bootnode}; \
166		 DHT bootnode discovery enabled: {dht_bootnode_discovery}",
167	);
168
169	if embedded_dht_bootnode {
170		task_manager.spawn_essential_handle().spawn(
171			"cumulus-dht-bootnode-advertisement",
172			None,
173			bootnode_advertisement(
174				para_id,
175				relay_chain_interface.clone(),
176				relay_chain_network.clone(),
177				request_receiver,
178				parachain_network.clone(),
179				advertise_non_global_ips,
180				parachain_genesis_hash,
181				parachain_fork_id.clone(),
182				parachain_public_addresses,
183			),
184		);
185	}
186
187	if dht_bootnode_discovery {
188		task_manager.spawn_essential_handle().spawn(
189			"cumulus-dht-bootnode-discovery",
190			None,
191			bootnode_discovery(
192				para_id,
193				parachain_network,
194				parachain_genesis_hash,
195				parachain_fork_id,
196				relay_chain_interface,
197				relay_chain_fork_id,
198				relay_chain_network,
199			),
200		);
201	}
202}