Skip to content

Commit 9b03db1

Browse files
authored
Impl DHT bootnodes support for all nodes (#1344)
Latest polkadot-sdk release includes a new feature that allows parachain nodes to advertise their IP address in the relay chain DHT (kademlia). This allows other nodes to discover peers without a centralized peer list. In this PR we implement it for all nodes, including collators and data preservers. Container chain collators do not advertise their IP address, but they do discover bootnodes for the chain they are assigned to. The reason for not advertising is that collators may rotate frequently, and also that they don't have the full block history. So collators can only be valid targets for warp sync, not for full sync.
1 parent 79f0c93 commit 9b03db1

16 files changed

Lines changed: 1010 additions & 29 deletions

File tree

.github/workflows/run-zombienet-tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ jobs:
6868
6969
if [ -z "$test_name" ]; then
7070
if [ "$test_bundle" == "weekly_bundle" ]; then
71-
tests='["zombie_tanssi_warp_sync", "zombie_tanssi_parathreads", "zombie_tanssi_metrics", "zombie_tanssi_relay_finalization_recovery"]'
71+
tests='["zombie_tanssi_warp_sync", "zombie_tanssi_parathreads", "zombie_tanssi_metrics", "zombie_tanssi_relay_finalization_recovery", "zombie_tanssi_relay_dht_bootnodes"]'
7272
elif [ "$test_bundle" == "manual_bundle" ]; then
7373
tests='["zombie_tanssi_relay_finalization_recovery", "zombie_simple_template_offchain", "zombie_tanssi_keep_db", "zombie_tanssi_one_node", "zombie_tanssi_relay_starlight", "zombie_tanssi_relay_unneeded_para", "zombie_tanssi_relay_keystore", "zombie_tanssi_relay_foreign_tokens"]'
7474
else
@@ -201,4 +201,4 @@ jobs:
201201
--body "Tests ${{ matrix.test_name }} failed in [${{ github.workflow }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}).\n\n@moondance-labs/coredev please investigate." \
202202
--repo "${{ github.repository }}"
203203
env:
204-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
204+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

chains/container-chains/nodes/frontier/src/service.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ where
204204
let (_, import_queue) = import_queue(&parachain_config, &node_builder);
205205

206206
// Relay chain interface
207-
let (relay_chain_interface, _collator_key) = node_builder
207+
let (relay_chain_interface, _collator_key, start_bootnode_params) = node_builder
208208
.build_relay_chain_interface(&parachain_config, polkadot_config, collator_options.clone())
209209
.await?;
210210

@@ -295,6 +295,7 @@ where
295295
para_id,
296296
relay_chain_interface.clone(),
297297
relay_chain_slot_duration,
298+
start_bootnode_params,
298299
)?;
299300

300301
Ok((node_builder.task_manager, node_builder.client))

chains/container-chains/nodes/simple/src/service.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ where
133133
let (_, import_queue) = import_queue(&parachain_config, &node_builder);
134134

135135
// Relay chain interface
136-
let (relay_chain_interface, _collator_key) = node_builder
136+
let (relay_chain_interface, _collator_key, start_bootnode_params) = node_builder
137137
.build_relay_chain_interface(&parachain_config, polkadot_config, collator_options.clone())
138138
.await?;
139139

@@ -170,6 +170,7 @@ where
170170
para_id,
171171
relay_chain_interface.clone(),
172172
relay_chain_slot_duration,
173+
start_bootnode_params,
173174
)?;
174175

175176
Ok((node_builder.task_manager, node_builder.client))

client/node-common/src/service/node_builder.rs

Lines changed: 85 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515
// along with Tanssi. If not, see <http://www.gnu.org/licenses/>.
1616

1717
use {
18+
async_channel::Receiver,
1819
async_io::Timer,
1920
core::time::Duration,
2021
core_extensions::TypeIdentity,
22+
cumulus_client_bootnodes::{start_bootnode_tasks, StartBootnodeTasksParams},
2123
cumulus_client_cli::CollatorOptions,
2224
cumulus_client_consensus_common::ParachainConsensus,
2325
cumulus_client_service::{
@@ -39,26 +41,32 @@ use {
3941
sp_wasm_interface::HostFunctions, HeapAllocStrategy, RuntimeVersionOf, WasmExecutor,
4042
DEFAULT_HEAP_ALLOC_STRATEGY,
4143
},
42-
sc_network::{config::FullNetworkConfiguration, NetworkBlock},
44+
sc_network::{
45+
config::FullNetworkConfiguration, request_responses::IncomingRequest,
46+
service::traits::NetworkService, NetworkBlock,
47+
},
4348
sc_network_sync::SyncingService,
4449
sc_network_transactions::TransactionsHandlerController,
4550
sc_service::{
46-
Configuration, KeystoreContainer, SpawnTaskHandle, TFullBackend, TFullClient, TaskManager,
51+
config::Multiaddr, Configuration, KeystoreContainer, SpawnTaskHandle, TFullBackend,
52+
TFullClient, TaskManager,
4753
},
4854
sc_telemetry::{Telemetry, TelemetryWorker, TelemetryWorkerHandle},
49-
sc_transaction_pool_api::OffchainTransactionPoolFactory,
55+
sc_transaction_pool_api::{OffchainTransactionPoolFactory, TransactionPool},
5056
sc_utils::mpsc::TracingUnboundedSender,
51-
sp_api::ConstructRuntimeApi,
57+
sp_api::{ConstructRuntimeApi, StorageProof},
5258
sp_block_builder::BlockBuilder,
5359
sp_consensus::SelectChain,
54-
sp_core::traits::CodeExecutor,
60+
sp_core::{
61+
traits::{CodeExecutor, SpawnNamed},
62+
H256,
63+
},
5564
sp_inherents::CreateInherentDataProviders,
5665
sp_offchain::OffchainWorkerApi,
5766
sp_runtime::Percent,
5867
sp_transaction_pool::runtime_api::TaggedTransactionQueue,
5968
std::{str::FromStr, sync::Arc},
6069
};
61-
use {sc_transaction_pool_api::TransactionPool, sp_api::StorageProof, sp_core::traits::SpawnNamed};
6270

6371
tp_traits::alias!(
6472
pub trait MinimalRuntimeApi<
@@ -299,6 +307,18 @@ where
299307
}
300308
}
301309

310+
#[derive(Clone)]
311+
pub struct StartBootnodeParams {
312+
pub relay_chain_fork_id: Option<String>,
313+
pub parachain_fork_id: Option<String>,
314+
pub advertise_non_global_ips: bool,
315+
pub parachain_public_addresses: Vec<Multiaddr>,
316+
pub relay_chain_network: Arc<dyn NetworkService>,
317+
pub paranode_rx: Receiver<IncomingRequest>,
318+
pub embedded_dht_bootnode: bool,
319+
pub dht_bootnode_discovery: bool,
320+
}
321+
302322
impl<T: NodeBuilderConfig, SNetwork, STxHandler, SImportQueueService>
303323
NodeBuilder<T, SNetwork, STxHandler, SImportQueueService>
304324
where
@@ -314,9 +334,20 @@ where
314334
) -> sc_service::error::Result<(
315335
Arc<(dyn RelayChainInterface + 'static)>,
316336
Option<CollatorPair>,
337+
StartBootnodeParams,
317338
)> {
318-
// FIXME(MD-1374): support DHT bootnodes
319-
let (relay_chain_interface, collator_key, _relay_chain_network, _paranode_rx) =
339+
let relay_chain_fork_id = polkadot_config
340+
.chain_spec
341+
.fork_id()
342+
.map(ToString::to_string);
343+
let parachain_fork_id = parachain_config
344+
.chain_spec
345+
.fork_id()
346+
.map(ToString::to_string);
347+
let advertise_non_global_ips = parachain_config.network.allow_non_globals_in_dht;
348+
let parachain_public_addresses = parachain_config.network.public_addresses.clone();
349+
350+
let (relay_chain_interface, collator_key, relay_chain_network, paranode_rx) =
320351
build_relay_chain_interface(
321352
polkadot_config,
322353
parachain_config,
@@ -328,7 +359,18 @@ where
328359
.await
329360
.map_err(|e| sc_service::Error::Application(Box::new(e) as Box<_>))?;
330361

331-
Ok((relay_chain_interface, collator_key))
362+
let start_bootnode_params = StartBootnodeParams {
363+
relay_chain_fork_id,
364+
parachain_fork_id,
365+
advertise_non_global_ips,
366+
parachain_public_addresses,
367+
relay_chain_network,
368+
paranode_rx,
369+
embedded_dht_bootnode: collator_options.embedded_dht_bootnode,
370+
dht_bootnode_discovery: collator_options.dht_bootnode_discovery,
371+
};
372+
373+
Ok((relay_chain_interface, collator_key, start_bootnode_params))
332374
}
333375

334376
/// Given an import queue, calls [`cumulus_client_service::build_network`] and
@@ -716,11 +758,14 @@ where
716758
para_id: ParaId,
717759
relay_chain_interface: RCInterface,
718760
relay_chain_slot_duration: Duration,
761+
start_bootnode_params: StartBootnodeParams,
719762
) -> sc_service::error::Result<NodeBuilder<T, SNetwork, STxHandler, ()>>
720763
where
721764
SNetwork: TypeIdentity<Type = Network<BlockOf<T>>>,
722765
SImportQueueService: TypeIdentity<Type = ImportQueueServiceOf<T>>,
723766
RCInterface: RelayChainInterface + Clone + 'static,
767+
RCInterface: TypeIdentity<Type = Arc<dyn RelayChainInterface + 'static>>,
768+
BlockHashOf<T>: TypeIdentity<Type = H256>,
724769
{
725770
let NodeBuilder {
726771
client,
@@ -754,7 +799,7 @@ where
754799
announce_block,
755800
task_manager: &mut task_manager,
756801
para_id,
757-
relay_chain_interface,
802+
relay_chain_interface: relay_chain_interface.clone(),
758803
relay_chain_slot_duration,
759804
import_queue: import_queue_service,
760805
recovery_handle: Box::new(overseer_handle),
@@ -763,9 +808,39 @@ where
763808
};
764809

765810
// TODO: change for async backing
811+
// TODO: to fix deprecation warning, we only need to change
812+
// `start_full_node` to `start_relay_chain_tasks`
766813
#[allow(deprecated)]
767814
cumulus_client_service::start_full_node(params)?;
768815

816+
let StartBootnodeParams {
817+
relay_chain_fork_id,
818+
parachain_fork_id,
819+
advertise_non_global_ips,
820+
parachain_public_addresses,
821+
relay_chain_network,
822+
paranode_rx,
823+
embedded_dht_bootnode,
824+
dht_bootnode_discovery,
825+
} = start_bootnode_params;
826+
827+
// Advertise parachain bootnode address in relay chain DHT
828+
start_bootnode_tasks(StartBootnodeTasksParams {
829+
embedded_dht_bootnode,
830+
dht_bootnode_discovery,
831+
para_id,
832+
task_manager: &mut task_manager,
833+
relay_chain_interface: TypeIdentity::into_type(relay_chain_interface),
834+
relay_chain_fork_id,
835+
relay_chain_network,
836+
request_receiver: paranode_rx,
837+
parachain_network: network.network.clone(),
838+
advertise_non_global_ips,
839+
parachain_genesis_hash: TypeIdentity::into_type(client.chain_info().genesis_hash),
840+
parachain_fork_id,
841+
parachain_public_addresses,
842+
});
843+
769844
Ok(NodeBuilder {
770845
client,
771846
backend,

client/service-container-chain-data-preserver/src/lib.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ pub mod watch_assignment;
1919

2020
use {
2121
cumulus_client_cli::CollatorOptions,
22-
cumulus_client_service::build_relay_chain_interface,
2322
cumulus_primitives_core::ParaId,
2423
cumulus_relay_chain_interface::RelayChainInterface,
2524
dc_orchestrator_chain_interface::OrchestratorChainInterface,
@@ -33,7 +32,9 @@ use {
3332
service::MinimalContainerRuntimeApi,
3433
spawner::{ContainerChainSpawnParams, ContainerChainSpawner},
3534
},
36-
tc_service_orchestrator_chain::solochain::EnableContainerChainSpawner,
35+
tc_service_orchestrator_chain::solochain::{
36+
build_relay_chain_interface_solochain, EnableContainerChainSpawner,
37+
},
3738
url::Url,
3839
};
3940

@@ -131,6 +132,7 @@ where
131132
let orchestrator_chain_interface: Arc<dyn OrchestratorChainInterface>;
132133
let relay_chain_interface: Arc<dyn RelayChainInterface>;
133134
let keystore;
135+
let start_bootnode_params;
134136

135137
if self.orchestrator_endpoints.is_empty() {
136138
// Embeded node
@@ -197,6 +199,7 @@ where
197199
relay_chain_interface = started.relay_chain_interface;
198200
orchestrator_chain_interface = started.orchestrator_chain_interface;
199201
keystore = started.keystore;
202+
start_bootnode_params = started.start_bootnode_params;
200203
} else {
201204
log::info!("Starting embeded orchestrator solochain node ...");
202205

@@ -222,6 +225,7 @@ where
222225
relay_chain_interface = started.relay_chain_interface;
223226
orchestrator_chain_interface = started.orchestrator_chain_interface;
224227
keystore = started.keystore;
228+
start_bootnode_params = started.start_bootnode_params;
225229
}
226230
} else {
227231
log::info!("Connecting to remote orchestrator node(s) ...");
@@ -266,20 +270,22 @@ where
266270

267271
let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle());
268272

269-
relay_chain_interface = build_relay_chain_interface(
270-
polkadot_config,
273+
// This is not solochain mode but this function is just to return the start_bootnode_params
274+
let relay_chain_interface_parts = build_relay_chain_interface_solochain(
271275
&self.config,
276+
polkadot_config,
277+
collator_options,
272278
telemetry_worker_handle,
273279
&mut task_manager,
274-
collator_options,
275280
None,
276281
)
277282
.await
278-
.map_err(|e| sc_service::Error::Application(Box::new(e) as Box<_>))?
279-
.0;
283+
.map_err(|e| sc_service::Error::Application(Box::new(e) as Box<_>))?;
284+
relay_chain_interface = relay_chain_interface_parts.0;
280285

281286
let keystore_container = KeystoreContainer::new(&self.config.keystore)?;
282287
keystore = keystore_container.keystore();
288+
start_bootnode_params = relay_chain_interface_parts.2;
283289
}
284290

285291
log::info!("Starting container chain spawner and assignment watcher ...");
@@ -300,9 +306,10 @@ where
300306
sync_keystore: keystore,
301307
collation_params: None,
302308
spawn_handle: task_manager.spawn_handle().clone(),
303-
data_preserver: true,
304309
generate_rpc_builder: self.generate_rpc_builder,
305310
override_sync_mode: None,
311+
start_bootnode_params,
312+
data_preserver: true,
306313
phantom: PhantomData,
307314
},
308315
state: Default::default(),

client/service-container-chain-spawner/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ sp-timestamp = { workspace = true, features = [ "std" ] }
7272
polkadot-primitives = { workspace = true }
7373

7474
# Cumulus
75+
cumulus-client-bootnodes = { workspace = true }
7576
cumulus-client-cli = { workspace = true }
7677
cumulus-client-collator = { workspace = true }
7778
cumulus-client-consensus-aura = { workspace = true }

0 commit comments

Comments
 (0)