1use crate::{
44 log, metrics,
45 platform::{self, PlatformRef, address_parse},
46};
47
48use alloc::{
49 borrow::ToOwned as _,
50 boxed::Box,
51 collections::{BTreeMap, VecDeque},
52 format,
53 string::{String, ToString as _},
54 sync::Arc,
55 vec::{self, Vec},
56};
57use core::{cmp, mem, num::NonZero, pin::Pin, time::Duration};
58use futures_channel::oneshot;
59use futures_lite::FutureExt as _;
60use futures_util::{StreamExt as _, future, stream};
61use hashbrown::{HashMap, HashSet};
62use rand::seq::IteratorRandom as _;
63use rand_chacha::rand_core::SeedableRng as _;
64use smoldot::{
65 header,
66 informant::{BytesDisplay, HashDisplay},
67 libp2p::{
68 connection,
69 multiaddr::{self, Multiaddr},
70 peer_id,
71 },
72 network::{basic_peering_strategy, bitswap_peering_strategy, codec, service},
73};
74
75pub use codec::{AffinityFilter, CallProofRequestConfig, Role};
76use service::SendTopicAffinityError;
77pub use service::{
78 ChainId, EncodedMerkleProof, PeerId, QueueNotificationError, SendBitswapMessageError,
79};
80
81mod tasks;
82
83const SECONDARY_SUBSTREAM_RETRY_DELAY: Duration = Duration::from_millis(200);
87
88pub struct Config<TPlat> {
90 pub platform: TPlat,
92
93 pub identify_agent_version: String,
95
96 pub chains_capacity: usize,
98
99 pub connections_open_pool_size: u32,
103
104 pub connections_open_pool_restore_delay: Duration,
109}
110
111pub struct ConfigChain {
117 pub log_name: String,
119
120 pub num_out_slots: usize,
123
124 pub genesis_block_hash: [u8; 32],
130
131 pub best_block: (u64, [u8; 32]),
134
135 pub fork_id: Option<String>,
138
139 pub block_number_bytes: usize,
141
142 pub grandpa_protocol_finalized_block_height: Option<u64>,
145
146 pub enable_statement_protocol: bool,
148
149 pub metrics: Arc<metrics::ChainMetrics>,
151}
152
153pub struct NetworkService<TPlat: PlatformRef> {
154 messages_tx: async_channel::Sender<ToBackground<TPlat>>,
156
157 platform: TPlat,
159
160 metrics: Arc<metrics::NetworkMetrics>,
162}
163
164impl<TPlat: PlatformRef> NetworkService<TPlat> {
165 pub fn new(config: Config<TPlat>) -> Arc<Self> {
167 let (main_messages_tx, main_messages_rx) = async_channel::bounded(4);
168
169 let metrics = Arc::new(metrics::NetworkMetrics::default());
170
171 let network = service::ChainNetwork::new(service::Config {
172 chains_capacity: config.chains_capacity,
173 connections_capacity: 32,
174 handshake_timeout: Duration::from_secs(4),
176 randomness_seed: {
177 let mut seed = [0; 32];
178 config.platform.fill_random_bytes(&mut seed);
179 seed
180 },
181 });
182
183 let (tasks_messages_tx, tasks_messages_rx) = async_channel::bounded(32);
185 let task = Box::pin(background_task(BackgroundTask {
186 randomness: rand_chacha::ChaCha20Rng::from_seed({
187 let mut seed = [0; 32];
188 config.platform.fill_random_bytes(&mut seed);
189 seed
190 }),
191 identify_agent_version: config.identify_agent_version,
192 tasks_messages_tx,
193 tasks_messages_rx: Box::pin(tasks_messages_rx),
194 peering_strategy: basic_peering_strategy::BasicPeeringStrategy::new(
195 basic_peering_strategy::Config {
196 randomness_seed: {
197 let mut seed = [0; 32];
198 config.platform.fill_random_bytes(&mut seed);
199 seed
200 },
201 peers_capacity: 50, chains_capacity: config.chains_capacity,
203 },
204 ),
205 bitswap_peering_strategy: bitswap_peering_strategy::BitswapPeeringStrategy::new(
206 bitswap_peering_strategy::Config {
207 randomness_seed: {
208 let mut seed = [0; 32];
209 config.platform.fill_random_bytes(&mut seed);
210 seed
211 },
212 peers_capacity: 50, },
214 ),
215 network,
216 connections_open_pool_size: config.connections_open_pool_size,
217 connections_open_pool_restore_delay: config.connections_open_pool_restore_delay,
218 num_recent_connection_opening: 0,
219 next_recent_connection_restore: None,
220 platform: config.platform.clone(),
221 metrics: metrics.clone(),
222 open_gossip_links: BTreeMap::new(),
223 chains_ever_gossip_connected: HashSet::with_capacity_and_hasher(4, Default::default()),
224 v2_statement_peers: HashMap::with_capacity_and_hasher(4, Default::default()),
225 current_affinity_filter: HashMap::with_capacity_and_hasher(4, Default::default()),
226 events_pending_send: VecDeque::with_capacity(4),
227 event_senders: either::Left(Vec::new()),
228 pending_new_subscriptions: Vec::new(),
229 bitswap_event_pending_send: None,
230 bitswap_connected_peers: 0,
231 bitswap_event_senders: either::Left(Vec::new()),
232 pending_new_bitswap_subscriptions: Vec::new(),
233 statement_event_pending_send: None,
234 statement_event_senders: either::Left(Vec::new()),
235 pending_new_statement_subscriptions: Vec::new(),
236 important_nodes: HashMap::with_capacity_and_hasher(16, Default::default()),
237 main_messages_rx: Box::pin(main_messages_rx),
238 messages_rx: stream::SelectAll::new(),
239 blocks_requests: HashMap::with_capacity_and_hasher(8, Default::default()),
240 grandpa_warp_sync_requests: HashMap::with_capacity_and_hasher(8, Default::default()),
241 storage_proof_requests: HashMap::with_capacity_and_hasher(8, Default::default()),
242 call_proof_requests: HashMap::with_capacity_and_hasher(8, Default::default()),
243 child_storage_proof_requests: HashMap::with_capacity_and_hasher(8, Default::default()),
244 chains_by_next_discovery: BTreeMap::new(),
245 secondary_reopens: BTreeMap::new(),
246 }));
247
248 config.platform.spawn_task("network-service".into(), {
249 let platform = config.platform.clone();
250 async move {
251 task.await;
252 log!(&platform, Debug, "network", "shutdown");
253 }
254 });
255
256 Arc::new(NetworkService {
257 messages_tx: main_messages_tx,
258 platform: config.platform,
259 metrics,
260 })
261 }
262
263 pub fn metrics(&self) -> Arc<metrics::NetworkMetrics> {
265 self.metrics.clone()
266 }
267
268 pub fn add_chain(&self, config: ConfigChain) -> Arc<NetworkServiceChain<TPlat>> {
274 let (messages_tx, messages_rx) = async_channel::bounded(32);
275 let chain_metrics = config.metrics.clone();
276
277 self.platform.spawn_task("add-chain-message-send".into(), {
279 let config = service::ChainConfig {
280 grandpa_protocol_config: config.grandpa_protocol_finalized_block_height.map(
281 |commit_finalized_height| service::GrandpaState {
282 commit_finalized_height,
283 round_number: 1,
284 set_id: 0,
285 },
286 ),
287 enable_statement_protocol: config.enable_statement_protocol,
288 fork_id: config.fork_id.clone(),
289 block_number_bytes: config.block_number_bytes,
290 best_hash: config.best_block.1,
291 best_number: config.best_block.0,
292 genesis_hash: config.genesis_block_hash,
293 role: Role::Light,
294 allow_inbound_block_requests: false,
295 user_data: Chain {
296 log_name: config.log_name,
297 block_number_bytes: config.block_number_bytes,
298 num_out_slots: config.num_out_slots,
299 num_references: NonZero::<usize>::new(1).unwrap(),
300 next_discovery_period: Duration::from_secs(2),
301 next_discovery_when: self.platform.now(),
302 metrics: config.metrics,
303 },
304 };
305
306 let messages_tx = self.messages_tx.clone();
307 async move {
308 let _ = messages_tx
309 .send(ToBackground::AddChain {
310 messages_rx,
311 config,
312 })
313 .await;
314 }
315 });
316
317 Arc::new(NetworkServiceChain {
318 _keep_alive_messages_tx: self.messages_tx.clone(),
319 messages_tx,
320 metrics: chain_metrics,
321 platform: self.platform.clone(),
322 })
323 }
324}
325
326pub struct NetworkServiceChain<TPlat: PlatformRef> {
327 _keep_alive_messages_tx: async_channel::Sender<ToBackground<TPlat>>,
330
331 messages_tx: async_channel::Sender<ToBackgroundChain>,
333
334 metrics: Arc<metrics::ChainMetrics>,
336
337 platform: TPlat,
339}
340
341#[derive(Debug, Copy, Clone, PartialEq, Eq)]
343pub enum BanSeverity {
344 Low,
345 High,
346}
347
348#[derive(
353 Debug, Copy, Clone, PartialEq, Eq, strum::Display, strum::EnumIter, strum::IntoStaticStr,
354)]
355#[strum(serialize_all = "kebab-case")]
356pub enum BanReason {
357 BadBlockAnnounce,
358 BadChildTrieRoot,
359 BadGrandpaCommit,
360 BadJustification,
361 BadMerkleProof,
362 BadWarpSyncFragment,
363 InvalidCallProof,
364 BlocksRequestFailed,
365 CallProofRequestFailed,
366 ChildStorageRequestFailed,
367 StorageRequestFailed,
368 WarpSyncRequestFailed,
369}
370
371impl<TPlat: PlatformRef> NetworkServiceChain<TPlat> {
372 pub async fn subscribe(&self) -> async_channel::Receiver<Event> {
389 let (tx, rx) = async_channel::bounded(128);
390
391 self.messages_tx
392 .send(ToBackgroundChain::Subscribe { sender: tx })
393 .await
394 .unwrap();
395
396 rx
397 }
398
399 pub async fn subscribe_bitswap(&self) -> async_channel::Receiver<BitswapEvent> {
414 let (tx, rx) = async_channel::bounded(128);
415
416 self.messages_tx
417 .send(ToBackgroundChain::SubscribeBitswap { sender: tx })
418 .await
419 .unwrap();
420
421 rx
422 }
423
424 pub async fn subscribe_statements(&self) -> async_channel::Receiver<StatementEvent> {
435 let (tx, rx) = async_channel::bounded(128);
436
437 self.messages_tx
438 .send(ToBackgroundChain::SubscribeStatements { sender: tx })
439 .await
440 .unwrap();
441
442 rx
443 }
444
445 pub async fn ban_and_disconnect(
457 &self,
458 peer_id: PeerId,
459 severity: BanSeverity,
460 reason: BanReason,
461 ) {
462 self.metrics.peer_bans.inc(reason);
463
464 let _ = self
465 .messages_tx
466 .send(ToBackgroundChain::DisconnectAndBan {
467 peer_id,
468 severity,
469 reason,
470 })
471 .await;
472 }
473
474 pub async fn blocks_request(
477 self: Arc<Self>,
478 target: PeerId,
479 config: codec::BlocksRequestConfig,
480 timeout: Duration,
481 ) -> Result<Vec<codec::BlockData>, BlocksRequestError> {
482 let when_started = self.platform.now();
483 let (tx, rx) = oneshot::channel();
484
485 self.messages_tx
486 .send(ToBackgroundChain::StartBlocksRequest {
487 target: target.clone(),
488 config,
489 timeout,
490 result: tx,
491 })
492 .await
493 .unwrap();
494
495 let result = rx.await.unwrap();
496 self.metrics
497 .blocks_requests
498 .observe(result.is_ok(), self.platform.now() - when_started);
499 result
500 }
501
502 pub async fn grandpa_warp_sync_request(
505 self: Arc<Self>,
506 target: PeerId,
507 begin_hash: [u8; 32],
508 timeout: Duration,
509 ) -> Result<service::EncodedGrandpaWarpSyncResponse, WarpSyncRequestError> {
510 let when_started = self.platform.now();
511 let (tx, rx) = oneshot::channel();
512
513 self.messages_tx
514 .send(ToBackgroundChain::StartWarpSyncRequest {
515 target: target.clone(),
516 begin_hash,
517 timeout,
518 result: tx,
519 })
520 .await
521 .unwrap();
522
523 let result = rx.await.unwrap();
524 self.metrics
525 .warp_sync_requests
526 .observe(result.is_ok(), self.platform.now() - when_started);
527 result
528 }
529
530 pub async fn set_local_best_block(&self, best_hash: [u8; 32], best_number: u64) {
531 self.messages_tx
532 .send(ToBackgroundChain::SetLocalBestBlock {
533 best_hash,
534 best_number,
535 })
536 .await
537 .unwrap();
538 }
539
540 pub async fn set_local_grandpa_state(&self, grandpa_state: service::GrandpaState) {
541 self.messages_tx
542 .send(ToBackgroundChain::SetLocalGrandpaState { grandpa_state })
543 .await
544 .unwrap();
545 }
546
547 pub async fn storage_proof_request(
550 self: Arc<Self>,
551 target: PeerId, config: codec::StorageProofRequestConfig<impl Iterator<Item = impl AsRef<[u8]> + Clone>>,
553 timeout: Duration,
554 ) -> Result<service::EncodedMerkleProof, StorageProofRequestError> {
555 let when_started = self.platform.now();
556 let (tx, rx) = oneshot::channel();
557
558 self.messages_tx
559 .send(ToBackgroundChain::StartStorageProofRequest {
560 target: target.clone(),
561 config: codec::StorageProofRequestConfig {
562 block_hash: config.block_hash,
563 keys: config
564 .keys
565 .map(|key| key.as_ref().to_vec()) .collect::<Vec<_>>()
567 .into_iter(),
568 },
569 timeout,
570 result: tx,
571 })
572 .await
573 .unwrap();
574
575 let result = rx.await.unwrap();
576 self.metrics
577 .storage_proof_requests
578 .observe(result.is_ok(), self.platform.now() - when_started);
579 result
580 }
581
582 pub async fn call_proof_request(
587 self: Arc<Self>,
588 target: PeerId, config: codec::CallProofRequestConfig<'_, impl Iterator<Item = impl AsRef<[u8]>>>,
590 timeout: Duration,
591 ) -> Result<EncodedMerkleProof, CallProofRequestError> {
592 let when_started = self.platform.now();
593 let (tx, rx) = oneshot::channel();
594
595 self.messages_tx
596 .send(ToBackgroundChain::StartCallProofRequest {
597 target: target.clone(),
598 config: codec::CallProofRequestConfig {
599 block_hash: config.block_hash,
600 method: config.method.into_owned().into(),
601 parameter_vectored: config
602 .parameter_vectored
603 .map(|v| v.as_ref().to_vec()) .collect::<Vec<_>>()
605 .into_iter(),
606 },
607 timeout,
608 result: tx,
609 })
610 .await
611 .unwrap();
612
613 let result = rx.await.unwrap();
614 self.metrics
615 .call_proof_requests
616 .observe(result.is_ok(), self.platform.now() - when_started);
617 result
618 }
619
620 pub async fn child_storage_proof_request(
622 self: Arc<Self>,
623 target: PeerId,
624 config: codec::ChildStorageProofRequestConfig<
625 impl AsRef<[u8]> + Clone,
626 impl Iterator<Item = impl AsRef<[u8]> + Clone>,
627 >,
628 timeout: Duration,
629 ) -> Result<service::EncodedMerkleProof, ChildStorageProofRequestError> {
630 let when_started = self.platform.now();
631 let (tx, rx) = oneshot::channel();
632
633 self.messages_tx
634 .send(ToBackgroundChain::StartChildStorageProofRequest {
635 target: target.clone(),
636 config: ChildStorageProofRequestConfigOwned {
637 block_hash: config.block_hash,
638 child_trie: config.child_trie.as_ref().to_vec(),
639 keys: config
640 .keys
641 .map(|key| key.as_ref().to_vec())
642 .collect::<Vec<_>>(),
643 },
644 timeout,
645 result: tx,
646 })
647 .await
648 .unwrap();
649
650 let result = rx.await.unwrap();
651 self.metrics
652 .child_storage_proof_requests
653 .observe(result.is_ok(), self.platform.now() - when_started);
654 result
655 }
656
657 pub async fn announce_transaction(self: Arc<Self>, transaction: &[u8]) -> Vec<PeerId> {
667 let (tx, rx) = oneshot::channel();
668
669 self.messages_tx
670 .send(ToBackgroundChain::AnnounceTransaction {
671 transaction: transaction.to_vec(), result: tx,
673 })
674 .await
675 .unwrap();
676
677 rx.await.unwrap()
678 }
679
680 pub async fn send_block_announce(
682 self: Arc<Self>,
683 target: &PeerId,
684 scale_encoded_header: &[u8],
685 is_best: bool,
686 ) -> Result<(), QueueNotificationError> {
687 let (tx, rx) = oneshot::channel();
688
689 self.messages_tx
690 .send(ToBackgroundChain::SendBlockAnnounce {
691 target: target.clone(), scale_encoded_header: scale_encoded_header.to_vec(), is_best,
694 result: tx,
695 })
696 .await
697 .unwrap();
698
699 rx.await.unwrap()
700 }
701
702 pub async fn send_bitswap_message(
704 &self,
705 target: PeerId,
706 message: Vec<u8>,
707 ) -> Result<(), SendBitswapMessageError> {
708 let (tx, rx) = oneshot::channel();
709
710 self.messages_tx
711 .send(ToBackgroundChain::SendBitswapMessage {
712 target,
713 message,
714 result: tx,
715 })
716 .await
717 .unwrap();
718
719 rx.await.unwrap()
720 }
721
722 pub async fn broadcast_bitswap_message(
730 &self,
731 message: Vec<u8>,
732 ) -> Result<Vec<PeerId>, SendBitswapMessageError> {
733 let (tx, rx) = oneshot::channel();
734
735 self.messages_tx
736 .send(ToBackgroundChain::BroadcastBitswapMessage {
737 message,
738 result: tx,
739 })
740 .await
741 .unwrap();
742
743 rx.await.unwrap()
744 }
745
746 pub async fn broadcast_statement(
748 self: Arc<Self>,
749 statement: Vec<u8>,
750 ) -> BroadcastStatementResult {
751 let (tx, rx) = oneshot::channel();
752
753 self.messages_tx
754 .send(ToBackgroundChain::BroadcastStatement {
755 statement,
756 result: tx,
757 })
758 .await
759 .unwrap();
760
761 rx.await.unwrap()
762 }
763
764 pub async fn update_topic_affinity(&self, filter: AffinityFilter) {
765 self.messages_tx
766 .send(ToBackgroundChain::UpdateTopicAffinity { filter })
767 .await
768 .unwrap();
769 }
770
771 pub async fn discover(
777 &self,
778 list: impl IntoIterator<Item = (PeerId, impl IntoIterator<Item = Multiaddr>)>,
779 important_nodes: bool,
780 ) {
781 self.messages_tx
782 .send(ToBackgroundChain::Discover {
783 list: list
785 .into_iter()
786 .map(|(peer_id, addrs)| {
787 (peer_id, addrs.into_iter().collect::<Vec<_>>().into_iter())
788 })
789 .collect::<Vec<_>>()
790 .into_iter(),
791 important_nodes,
792 })
793 .await
794 .unwrap();
795 }
796
797 pub async fn discovered_nodes(
804 &self,
805 ) -> impl Iterator<Item = (PeerId, impl Iterator<Item = Multiaddr>)> {
806 let (tx, rx) = oneshot::channel();
807
808 self.messages_tx
809 .send(ToBackgroundChain::DiscoveredNodes { result: tx })
810 .await
811 .unwrap();
812
813 rx.await
814 .unwrap()
815 .into_iter()
816 .map(|(peer_id, addrs)| (peer_id, addrs.into_iter()))
817 }
818
819 pub async fn peers_list(&self) -> impl Iterator<Item = PeerId> {
822 let (tx, rx) = oneshot::channel();
823 self.messages_tx
824 .send(ToBackgroundChain::PeersList { result: tx })
825 .await
826 .unwrap();
827 rx.await.unwrap().into_iter()
828 }
829}
830
831#[derive(Debug, Clone)]
832pub struct BroadcastStatementResult {
833 pub sent: usize,
834 pub total: usize,
835}
836
837#[derive(Debug, Clone)]
839pub enum Event {
840 Connected {
841 peer_id: PeerId,
842 role: Role,
843 best_block_number: u64,
844 best_block_hash: [u8; 32],
845 },
846 Disconnected {
847 peer_id: PeerId,
848 },
849 BlockAnnounce {
850 peer_id: PeerId,
851 announce: service::EncodedBlockAnnounce,
852 },
853 GrandpaNeighborPacket {
854 peer_id: PeerId,
855 finalized_block_height: u64,
856 },
857 GrandpaCommitMessage {
859 peer_id: PeerId,
860 message: service::EncodedGrandpaCommitMessage,
861 },
862}
863
864#[derive(Debug, Clone)]
868pub enum BitswapEvent {
869 BitswapMessage {
870 peer_id: PeerId,
871 message: service::EncodedBitswapMessage,
872 },
873}
874
875#[derive(Debug, Clone)]
877pub enum StatementEvent {
878 StatementsNotification {
880 peer_id: PeerId,
881 statements: Vec<([u8; 32], codec::Statement)>,
882 },
883}
884
885#[derive(Debug, derive_more::Display, derive_more::Error)]
887pub enum BlocksRequestError {
888 NoConnection,
890 #[display("{_0}")]
892 Request(service::BlocksRequestError),
893}
894
895#[derive(Debug, derive_more::Display, derive_more::Error)]
897pub enum WarpSyncRequestError {
898 NoConnection,
900 #[display("{_0}")]
902 Request(service::GrandpaWarpSyncRequestError),
903}
904
905#[derive(Debug, derive_more::Display, derive_more::Error, Clone)]
907pub enum StorageProofRequestError {
908 NoConnection,
910 RequestTooLarge,
912 #[display("{_0}")]
914 Request(service::StorageProofRequestError),
915}
916
917#[derive(Debug, derive_more::Display, derive_more::Error, Clone)]
919pub enum CallProofRequestError {
920 NoConnection,
922 RequestTooLarge,
924 #[display("{_0}")]
926 Request(service::CallProofRequestError),
927}
928
929impl CallProofRequestError {
930 pub fn is_network_problem(&self) -> bool {
933 match self {
934 CallProofRequestError::Request(err) => err.is_network_problem(),
935 CallProofRequestError::RequestTooLarge => false,
936 CallProofRequestError::NoConnection => true,
937 }
938 }
939}
940
941#[derive(Debug, derive_more::Display, derive_more::Error, Clone)]
943pub enum ChildStorageProofRequestError {
944 NoConnection,
946 RequestTooLarge,
948 #[display("{_0}")]
950 Request(service::StorageProofRequestError),
951}
952
953impl ChildStorageProofRequestError {
954 pub fn is_network_problem(&self) -> bool {
957 match self {
958 ChildStorageProofRequestError::Request(err) => err.is_network_problem(),
959 ChildStorageProofRequestError::RequestTooLarge => false,
960 ChildStorageProofRequestError::NoConnection => true,
961 }
962 }
963}
964
965#[derive(
970 Debug, Clone, Copy, PartialEq, Eq, strum::Display, strum::EnumIter, strum::IntoStaticStr,
971)]
972#[strum(serialize_all = "kebab-case")]
973pub(crate) enum DiscoveredAddressDropReason {
974 PeerIdMismatch,
976 NotSupported,
978 Invalid,
980}
981
982struct ChildStorageProofRequestConfigOwned {
984 block_hash: [u8; 32],
985 child_trie: Vec<u8>,
986 keys: Vec<Vec<u8>>,
987}
988
989enum ToBackground<TPlat: PlatformRef> {
990 AddChain {
991 messages_rx: async_channel::Receiver<ToBackgroundChain>,
992 config: service::ChainConfig<Chain<TPlat>>,
993 },
994}
995
996enum ToBackgroundChain {
997 RemoveChain,
998 Subscribe {
999 sender: async_channel::Sender<Event>,
1000 },
1001 SubscribeBitswap {
1002 sender: async_channel::Sender<BitswapEvent>,
1003 },
1004 SubscribeStatements {
1005 sender: async_channel::Sender<StatementEvent>,
1006 },
1007 DisconnectAndBan {
1008 peer_id: PeerId,
1009 severity: BanSeverity,
1010 reason: BanReason,
1011 },
1012 StartBlocksRequest {
1014 target: PeerId, config: codec::BlocksRequestConfig,
1016 timeout: Duration,
1017 result: oneshot::Sender<Result<Vec<codec::BlockData>, BlocksRequestError>>,
1018 },
1019 StartWarpSyncRequest {
1021 target: PeerId,
1022 begin_hash: [u8; 32],
1023 timeout: Duration,
1024 result:
1025 oneshot::Sender<Result<service::EncodedGrandpaWarpSyncResponse, WarpSyncRequestError>>,
1026 },
1027 StartStorageProofRequest {
1029 target: PeerId,
1030 config: codec::StorageProofRequestConfig<vec::IntoIter<Vec<u8>>>,
1031 timeout: Duration,
1032 result: oneshot::Sender<Result<service::EncodedMerkleProof, StorageProofRequestError>>,
1033 },
1034 StartCallProofRequest {
1036 target: PeerId, config: codec::CallProofRequestConfig<'static, vec::IntoIter<Vec<u8>>>,
1038 timeout: Duration,
1039 result: oneshot::Sender<Result<service::EncodedMerkleProof, CallProofRequestError>>,
1040 },
1041 StartChildStorageProofRequest {
1043 target: PeerId,
1044 config: ChildStorageProofRequestConfigOwned,
1045 timeout: Duration,
1046 result: oneshot::Sender<Result<service::EncodedMerkleProof, ChildStorageProofRequestError>>,
1047 },
1048 SetLocalBestBlock {
1049 best_hash: [u8; 32],
1050 best_number: u64,
1051 },
1052 SetLocalGrandpaState {
1053 grandpa_state: service::GrandpaState,
1054 },
1055 AnnounceTransaction {
1056 transaction: Vec<u8>,
1057 result: oneshot::Sender<Vec<PeerId>>,
1058 },
1059 SendBlockAnnounce {
1060 target: PeerId,
1061 scale_encoded_header: Vec<u8>,
1062 is_best: bool,
1063 result: oneshot::Sender<Result<(), QueueNotificationError>>,
1064 },
1065 SendBitswapMessage {
1066 target: PeerId,
1067 message: Vec<u8>,
1068 result: oneshot::Sender<Result<(), SendBitswapMessageError>>,
1069 },
1070 BroadcastBitswapMessage {
1071 message: Vec<u8>,
1072 result: oneshot::Sender<Result<Vec<PeerId>, SendBitswapMessageError>>,
1073 },
1074 BroadcastStatement {
1075 statement: Vec<u8>,
1076 result: oneshot::Sender<BroadcastStatementResult>,
1077 },
1078 UpdateTopicAffinity {
1079 filter: AffinityFilter,
1080 },
1081 Discover {
1082 list: vec::IntoIter<(PeerId, vec::IntoIter<Multiaddr>)>,
1083 important_nodes: bool,
1084 },
1085 DiscoveredNodes {
1086 result: oneshot::Sender<Vec<(PeerId, Vec<Multiaddr>)>>,
1087 },
1088 PeersList {
1089 result: oneshot::Sender<Vec<PeerId>>,
1090 },
1091}
1092
1093struct BackgroundTask<TPlat: PlatformRef> {
1094 platform: TPlat,
1096
1097 metrics: Arc<metrics::NetworkMetrics>,
1099
1100 randomness: rand_chacha::ChaCha20Rng,
1102
1103 identify_agent_version: String,
1105
1106 tasks_messages_tx:
1108 async_channel::Sender<(service::ConnectionId, service::ConnectionToCoordinator)>,
1109
1110 tasks_messages_rx: Pin<
1112 Box<async_channel::Receiver<(service::ConnectionId, service::ConnectionToCoordinator)>>,
1113 >,
1114
1115 network: service::ChainNetwork<
1117 Chain<TPlat>,
1118 async_channel::Sender<service::CoordinatorToConnection>,
1119 TPlat::Instant,
1120 >,
1121
1122 peering_strategy: basic_peering_strategy::BasicPeeringStrategy<ChainId, TPlat::Instant>,
1124
1125 bitswap_peering_strategy: bitswap_peering_strategy::BitswapPeeringStrategy<TPlat::Instant>,
1127
1128 connections_open_pool_size: u32,
1130
1131 connections_open_pool_restore_delay: Duration,
1133
1134 num_recent_connection_opening: u32,
1138
1139 next_recent_connection_restore: Option<Pin<Box<TPlat::Delay>>>,
1141
1142 open_gossip_links: BTreeMap<(ChainId, PeerId), OpenGossipLinkState>,
1145
1146 chains_ever_gossip_connected: HashSet<ChainId, fnv::FnvBuildHasher>,
1149
1150 v2_statement_peers: HashMap<ChainId, HashSet<PeerId, fnv::FnvBuildHasher>, fnv::FnvBuildHasher>,
1152
1153 current_affinity_filter: HashMap<ChainId, AffinityFilter, fnv::FnvBuildHasher>,
1155
1156 important_nodes: HashMap<ChainId, HashSet<PeerId, fnv::FnvBuildHasher>, fnv::FnvBuildHasher>,
1160
1161 events_pending_send: VecDeque<(ChainId, Event)>,
1167
1168 bitswap_event_pending_send: Option<BitswapEvent>,
1170
1171 bitswap_connected_peers: usize,
1176
1177 event_senders: either::Either<
1183 Vec<(ChainId, async_channel::Sender<Event>)>,
1184 Pin<Box<dyn Future<Output = Vec<(ChainId, async_channel::Sender<Event>)>> + Send>>,
1185 >,
1186
1187 pending_new_subscriptions: Vec<(ChainId, async_channel::Sender<Event>)>,
1190
1191 bitswap_event_senders: either::Either<
1201 Vec<async_channel::Sender<BitswapEvent>>,
1202 Pin<Box<dyn Future<Output = Vec<async_channel::Sender<BitswapEvent>>> + Send>>,
1203 >,
1204
1205 pending_new_bitswap_subscriptions: Vec<async_channel::Sender<BitswapEvent>>,
1209
1210 statement_event_pending_send: Option<(ChainId, StatementEvent)>,
1213
1214 statement_event_senders: either::Either<
1219 Vec<(ChainId, async_channel::Sender<StatementEvent>)>,
1220 Pin<Box<dyn Future<Output = Vec<(ChainId, async_channel::Sender<StatementEvent>)>> + Send>>,
1221 >,
1222
1223 pending_new_statement_subscriptions: Vec<(ChainId, async_channel::Sender<StatementEvent>)>,
1227
1228 main_messages_rx: Pin<Box<async_channel::Receiver<ToBackground<TPlat>>>>,
1229
1230 messages_rx:
1231 stream::SelectAll<Pin<Box<dyn stream::Stream<Item = (ChainId, ToBackgroundChain)> + Send>>>,
1232
1233 blocks_requests: HashMap<
1234 service::SubstreamId,
1235 oneshot::Sender<Result<Vec<codec::BlockData>, BlocksRequestError>>,
1236 fnv::FnvBuildHasher,
1237 >,
1238
1239 grandpa_warp_sync_requests: HashMap<
1240 service::SubstreamId,
1241 oneshot::Sender<Result<service::EncodedGrandpaWarpSyncResponse, WarpSyncRequestError>>,
1242 fnv::FnvBuildHasher,
1243 >,
1244
1245 storage_proof_requests: HashMap<
1246 service::SubstreamId,
1247 oneshot::Sender<Result<service::EncodedMerkleProof, StorageProofRequestError>>,
1248 fnv::FnvBuildHasher,
1249 >,
1250
1251 call_proof_requests: HashMap<
1252 service::SubstreamId,
1253 oneshot::Sender<Result<service::EncodedMerkleProof, CallProofRequestError>>,
1254 fnv::FnvBuildHasher,
1255 >,
1256
1257 child_storage_proof_requests: HashMap<
1258 service::SubstreamId,
1259 oneshot::Sender<Result<service::EncodedMerkleProof, ChildStorageProofRequestError>>,
1260 fnv::FnvBuildHasher,
1261 >,
1262
1263 chains_by_next_discovery: BTreeMap<(TPlat::Instant, ChainId), Pin<Box<TPlat::Delay>>>,
1265
1266 secondary_reopens: BTreeMap<(TPlat::Instant, ChainId, PeerId), Pin<Box<TPlat::Delay>>>,
1270}
1271
1272struct Chain<TPlat: PlatformRef> {
1273 log_name: String,
1274
1275 num_references: NonZero<usize>,
1277
1278 block_number_bytes: usize,
1281
1282 num_out_slots: usize,
1284
1285 metrics: Arc<metrics::ChainMetrics>,
1287
1288 next_discovery_when: TPlat::Instant,
1290
1291 next_discovery_period: Duration,
1294}
1295
1296#[derive(Clone)]
1297struct OpenGossipLinkState {
1298 role: Role,
1299 best_block_number: u64,
1300 best_block_hash: [u8; 32],
1301 finalized_block_height: Option<u64>,
1303 secondary_reopened_at_once: bool,
1305}
1306
1307async fn background_task<TPlat: PlatformRef>(mut task: BackgroundTask<TPlat>) {
1308 loop {
1309 futures_lite::future::yield_now().await;
1311
1312 enum WakeUpReason<TPlat: PlatformRef> {
1313 ForegroundClosed,
1314 Message(ToBackground<TPlat>),
1315 MessageForChain(ChainId, ToBackgroundChain),
1316 NetworkEvent(service::Event<async_channel::Sender<service::CoordinatorToConnection>>),
1317 CanAssignSlot(PeerId, ChainId),
1318 CanAssignBitswapSlot(PeerId),
1319 NextRecentConnectionRestore,
1320 CanStartConnect(PeerId),
1321 CanOpenGossip(PeerId, ChainId, service::GossipKind),
1322 CanOpenBitswap(PeerId),
1323 MessageFromConnection {
1324 connection_id: service::ConnectionId,
1325 message: service::ConnectionToCoordinator,
1326 },
1327 MessageToConnection {
1328 connection_id: service::ConnectionId,
1329 message: service::CoordinatorToConnection,
1330 },
1331 EventSendersReady,
1332 BitswapEventSendersReady,
1333 StatementEventSendersReady,
1334 StartDiscovery(ChainId),
1335 ReopenSecondaries {
1336 chain_id: ChainId,
1337 peer_id: PeerId,
1338 },
1339 }
1340
1341 let wake_up_reason = {
1342 let message_received = async {
1343 task.main_messages_rx
1344 .next()
1345 .await
1346 .map_or(WakeUpReason::ForegroundClosed, WakeUpReason::Message)
1347 };
1348 let message_for_chain_received = async {
1349 let Some((chain_id, message)) = task.messages_rx.next().await else {
1354 future::pending().await
1355 };
1356 WakeUpReason::MessageForChain(chain_id, message)
1357 };
1358 let message_from_task_received = async {
1359 let (connection_id, message) = task.tasks_messages_rx.next().await.unwrap();
1360 WakeUpReason::MessageFromConnection {
1361 connection_id,
1362 message,
1363 }
1364 };
1365 let service_event = async {
1366 if let Some(event) = (task.events_pending_send.is_empty()
1367 && task.bitswap_event_pending_send.is_none()
1368 && task.statement_event_pending_send.is_none()
1369 && task.pending_new_subscriptions.is_empty()
1370 && task.pending_new_bitswap_subscriptions.is_empty()
1371 && task.pending_new_statement_subscriptions.is_empty())
1372 .then(|| task.network.next_event())
1373 .flatten()
1374 {
1375 WakeUpReason::NetworkEvent(event)
1376 } else if let Some(start_connect) = {
1377 let x = (task.num_recent_connection_opening < task.connections_open_pool_size)
1378 .then(|| {
1379 task.network
1380 .unconnected_desired()
1381 .choose(&mut task.randomness)
1382 .cloned()
1383 })
1384 .flatten();
1385 x
1386 } {
1387 WakeUpReason::CanStartConnect(start_connect)
1388 } else if let Some((peer_id, chain_id, kind)) = {
1389 let x = task
1390 .network
1391 .connected_unopened_gossip_desired()
1392 .choose(&mut task.randomness)
1393 .map(|(peer_id, chain_id, kind)| (peer_id.clone(), chain_id, kind));
1394 x
1395 } {
1396 WakeUpReason::CanOpenGossip(peer_id, chain_id, kind)
1397 } else if let Some(peer_id) = {
1398 let x = task
1399 .network
1400 .connected_unopened_bitswap_desired()
1401 .choose(&mut task.randomness)
1402 .cloned();
1403 x
1404 } {
1405 WakeUpReason::CanOpenBitswap(peer_id)
1406 } else if let Some((connection_id, message)) =
1407 task.network.pull_message_to_connection()
1408 {
1409 WakeUpReason::MessageToConnection {
1410 connection_id,
1411 message,
1412 }
1413 } else {
1414 'search: loop {
1415 let mut earlier_unban = None;
1416
1417 for chain_id in task.network.chains().collect::<Vec<_>>() {
1418 if task.network.gossip_desired_num(
1419 chain_id,
1420 service::GossipKind::ConsensusTransactions,
1421 ) >= task.network[chain_id].num_out_slots
1422 {
1423 continue;
1424 }
1425
1426 let now = task.platform.now();
1427
1428 if !task.chains_ever_gossip_connected.contains(&chain_id) {
1431 if let basic_peering_strategy::AssignablePeer::Assignable(peer_id) =
1432 task.peering_strategy.pick_assignable_peer_filtered(
1433 &chain_id,
1434 &now,
1435 |peer_id| {
1436 task.important_nodes
1437 .get(&chain_id)
1438 .map_or(false, |nodes| nodes.contains(peer_id))
1439 },
1440 )
1441 {
1442 break 'search WakeUpReason::CanAssignSlot(
1443 peer_id.clone(),
1444 chain_id,
1445 );
1446 }
1447 }
1448
1449 match task.peering_strategy.pick_assignable_peer(&chain_id, &now) {
1450 basic_peering_strategy::AssignablePeer::Assignable(peer_id) => {
1451 break 'search WakeUpReason::CanAssignSlot(
1452 peer_id.clone(),
1453 chain_id,
1454 );
1455 }
1456 basic_peering_strategy::AssignablePeer::AllPeersBanned {
1457 next_unban,
1458 } => {
1459 if earlier_unban.as_ref().map_or(true, |b| b > next_unban) {
1460 earlier_unban = Some(next_unban.clone());
1461 }
1462 }
1463 basic_peering_strategy::AssignablePeer::NoPeer => continue,
1464 }
1465 }
1466
1467 match task
1468 .bitswap_peering_strategy
1469 .pick_assignable_peer(&task.platform.now())
1470 {
1471 bitswap_peering_strategy::AssignablePeer::Assignable(peer_id) => {
1472 break 'search WakeUpReason::CanAssignBitswapSlot(peer_id.clone());
1473 }
1474 bitswap_peering_strategy::AssignablePeer::AllPeersBanned {
1475 next_unban,
1476 } => {
1477 if earlier_unban.as_ref().map_or(true, |b| b > next_unban) {
1478 earlier_unban = Some(next_unban.clone());
1479 }
1480 }
1481 bitswap_peering_strategy::AssignablePeer::NoPeer => {}
1482 }
1483
1484 if let Some(earlier_unban) = earlier_unban {
1485 task.platform.sleep_until(earlier_unban).await;
1486 } else {
1487 future::pending::<()>().await;
1488 }
1489 }
1490 }
1491 };
1492 let next_recent_connection_restore = async {
1493 if task.num_recent_connection_opening != 0
1494 && task.next_recent_connection_restore.is_none()
1495 {
1496 task.next_recent_connection_restore = Some(Box::pin(
1497 task.platform
1498 .sleep(task.connections_open_pool_restore_delay),
1499 ));
1500 }
1501 if let Some(delay) = task.next_recent_connection_restore.as_mut() {
1502 delay.await;
1503 task.next_recent_connection_restore = None;
1504 WakeUpReason::NextRecentConnectionRestore
1505 } else {
1506 future::pending().await
1507 }
1508 };
1509 let finished_sending_event = async {
1510 if let either::Right(event_sending_future) = &mut task.event_senders {
1511 let event_senders = event_sending_future.await;
1512 task.event_senders = either::Left(event_senders);
1513 WakeUpReason::EventSendersReady
1514 } else if !task.events_pending_send.is_empty()
1515 || !task.pending_new_subscriptions.is_empty()
1516 {
1517 WakeUpReason::EventSendersReady
1518 } else {
1519 future::pending().await
1520 }
1521 };
1522 let finished_sending_bitswap_event = async {
1523 if let either::Right(bitswap_event_sending_future) = &mut task.bitswap_event_senders
1524 {
1525 let bitswap_event_senders = bitswap_event_sending_future.await;
1526 task.bitswap_event_senders = either::Left(bitswap_event_senders);
1527 WakeUpReason::BitswapEventSendersReady
1528 } else if task.bitswap_event_pending_send.is_some()
1529 || !task.pending_new_bitswap_subscriptions.is_empty()
1530 {
1531 WakeUpReason::BitswapEventSendersReady
1532 } else {
1533 future::pending().await
1534 }
1535 };
1536 let finished_sending_statement_event = async {
1537 if let either::Right(statement_event_sending_future) =
1538 &mut task.statement_event_senders
1539 {
1540 let statement_event_senders = statement_event_sending_future.await;
1541 task.statement_event_senders = either::Left(statement_event_senders);
1542 WakeUpReason::StatementEventSendersReady
1543 } else if task.statement_event_pending_send.is_some()
1544 || !task.pending_new_statement_subscriptions.is_empty()
1545 {
1546 WakeUpReason::StatementEventSendersReady
1547 } else {
1548 future::pending().await
1549 }
1550 };
1551 let start_discovery = async {
1552 let Some(mut next_discovery) = task.chains_by_next_discovery.first_entry() else {
1553 future::pending().await
1554 };
1555 next_discovery.get_mut().await;
1556 let ((_, chain_id), _) = next_discovery.remove_entry();
1557 WakeUpReason::StartDiscovery(chain_id)
1558 };
1559 let reopen_secondaries = async {
1560 let Some(mut next_reopen) = task.secondary_reopens.first_entry() else {
1561 future::pending().await
1562 };
1563 next_reopen.get_mut().await;
1564 let ((_, chain_id, peer_id), _) = next_reopen.remove_entry();
1565 WakeUpReason::ReopenSecondaries { chain_id, peer_id }
1566 };
1567
1568 message_for_chain_received
1569 .or(message_received)
1570 .or(message_from_task_received)
1571 .or(service_event)
1572 .or(next_recent_connection_restore)
1573 .or(finished_sending_event)
1574 .or(finished_sending_bitswap_event)
1575 .or(finished_sending_statement_event)
1576 .or(start_discovery)
1577 .or(reopen_secondaries)
1578 .await
1579 };
1580
1581 match wake_up_reason {
1582 WakeUpReason::ForegroundClosed => {
1583 return;
1585 }
1586 WakeUpReason::Message(ToBackground::AddChain {
1587 messages_rx,
1588 config,
1589 }) => {
1590 let chain_id = match task.network.add_chain(config) {
1592 Ok(id) => id,
1593 Err(service::AddChainError::Duplicate { existing_identical }) => {
1594 task.network[existing_identical].num_references = task.network
1595 [existing_identical]
1596 .num_references
1597 .checked_add(1)
1598 .unwrap();
1599 existing_identical
1600 }
1601 };
1602
1603 task.chains_by_next_discovery.insert(
1604 (task.network[chain_id].next_discovery_when.clone(), chain_id),
1605 Box::pin(
1606 task.platform
1607 .sleep_until(task.network[chain_id].next_discovery_when.clone()),
1608 ),
1609 );
1610
1611 task.messages_rx
1612 .push(Box::pin(
1613 messages_rx
1614 .map(move |msg| (chain_id, msg))
1615 .chain(stream::once(future::ready((
1616 chain_id,
1617 ToBackgroundChain::RemoveChain,
1618 )))),
1619 ) as Pin<Box<_>>);
1620
1621 log!(
1622 &task.platform,
1623 Debug,
1624 "network",
1625 "chain-added",
1626 id = task.network[chain_id].log_name
1627 );
1628 }
1629 WakeUpReason::EventSendersReady => {
1630 let either::Left(event_senders) = &mut task.event_senders else {
1634 unreachable!()
1635 };
1636
1637 if let Some((event_to_dispatch_chain_id, event_to_dispatch)) =
1638 task.events_pending_send.pop_front()
1639 {
1640 let mut event_senders = mem::take(event_senders);
1641 task.event_senders = either::Right(Box::pin(async move {
1642 for index in (0..event_senders.len()).rev() {
1645 let (event_sender_chain_id, event_sender) =
1646 event_senders.swap_remove(index);
1647 if event_sender_chain_id == event_to_dispatch_chain_id {
1648 if event_sender.send(event_to_dispatch.clone()).await.is_err() {
1649 continue;
1650 }
1651 }
1652 event_senders.push((event_sender_chain_id, event_sender));
1653 }
1654 event_senders
1655 }));
1656 } else if !task.pending_new_subscriptions.is_empty() {
1657 let pending_new_subscriptions = mem::take(&mut task.pending_new_subscriptions);
1658 let mut event_senders = mem::take(event_senders);
1659 let open_gossip_links = task.open_gossip_links.clone();
1661 task.event_senders = either::Right(Box::pin(async move {
1662 for (chain_id, new_subscription) in pending_new_subscriptions {
1663 for ((link_chain_id, peer_id), state) in &open_gossip_links {
1664 if *link_chain_id != chain_id {
1666 continue;
1667 }
1668
1669 let _ = new_subscription
1670 .send(Event::Connected {
1671 peer_id: peer_id.clone(),
1672 role: state.role,
1673 best_block_number: state.best_block_number,
1674 best_block_hash: state.best_block_hash,
1675 })
1676 .await;
1677
1678 if let Some(finalized_block_height) = state.finalized_block_height {
1679 let _ = new_subscription
1680 .send(Event::GrandpaNeighborPacket {
1681 peer_id: peer_id.clone(),
1682 finalized_block_height,
1683 })
1684 .await;
1685 }
1686 }
1687
1688 event_senders.push((chain_id, new_subscription));
1689 }
1690
1691 event_senders
1692 }));
1693 }
1694 }
1695 WakeUpReason::BitswapEventSendersReady => {
1696 let either::Left(bitswap_event_senders) = &mut task.bitswap_event_senders else {
1698 unreachable!()
1699 };
1700
1701 if let Some(event_to_dispatch) = task.bitswap_event_pending_send.take() {
1702 let mut bitswap_event_senders = mem::take(bitswap_event_senders);
1703 task.bitswap_event_senders = either::Right(Box::pin(async move {
1704 for index in (0..bitswap_event_senders.len()).rev() {
1707 let event_sender = bitswap_event_senders.swap_remove(index);
1708 if event_sender.send(event_to_dispatch.clone()).await.is_err() {
1709 continue;
1710 }
1711 bitswap_event_senders.push(event_sender);
1712 }
1713 bitswap_event_senders
1714 }));
1715 } else if !task.pending_new_bitswap_subscriptions.is_empty() {
1716 bitswap_event_senders.append(&mut task.pending_new_bitswap_subscriptions);
1717 }
1718 }
1719 WakeUpReason::StatementEventSendersReady => {
1720 let either::Left(statement_event_senders) = &mut task.statement_event_senders
1722 else {
1723 unreachable!()
1724 };
1725
1726 if let Some((event_to_dispatch_chain_id, event_to_dispatch)) =
1727 task.statement_event_pending_send.take()
1728 {
1729 let mut statement_event_senders = mem::take(statement_event_senders);
1730 task.statement_event_senders = either::Right(Box::pin(async move {
1731 for index in (0..statement_event_senders.len()).rev() {
1734 let (event_sender_chain_id, event_sender) =
1735 statement_event_senders.swap_remove(index);
1736 if event_sender_chain_id == event_to_dispatch_chain_id {
1737 if event_sender.send(event_to_dispatch.clone()).await.is_err() {
1738 continue;
1739 }
1740 }
1741 statement_event_senders.push((event_sender_chain_id, event_sender));
1742 }
1743 statement_event_senders
1744 }));
1745 } else if !task.pending_new_statement_subscriptions.is_empty() {
1746 statement_event_senders.append(&mut task.pending_new_statement_subscriptions);
1747 }
1748 }
1749 WakeUpReason::MessageFromConnection {
1750 connection_id,
1751 message,
1752 } => {
1753 task.network
1754 .inject_connection_message(connection_id, message);
1755 }
1756 WakeUpReason::MessageForChain(chain_id, ToBackgroundChain::RemoveChain) => {
1757 if let Some(new_ref) =
1758 NonZero::<usize>::new(task.network[chain_id].num_references.get() - 1)
1759 {
1760 task.network[chain_id].num_references = new_ref;
1761 continue;
1762 }
1763
1764 for peer_id in task
1765 .network
1766 .gossip_connected_peers(chain_id, service::GossipKind::ConsensusTransactions)
1767 .cloned()
1768 .collect::<Vec<_>>()
1769 {
1770 task.network
1771 .gossip_close(
1772 chain_id,
1773 &peer_id,
1774 service::GossipKind::ConsensusTransactions,
1775 )
1776 .unwrap();
1777
1778 let _was_in = task.open_gossip_links.remove(&(chain_id, peer_id));
1779 debug_assert!(_was_in.is_some());
1780 }
1781
1782 for peer_id in task
1783 .network
1784 .gossip_connected_peers(chain_id, service::GossipKind::Statement)
1785 .cloned()
1786 .collect::<Vec<_>>()
1787 {
1788 task.network
1789 .gossip_close(chain_id, &peer_id, service::GossipKind::Statement)
1790 .unwrap();
1791 }
1792
1793 let _was_in = task
1794 .chains_by_next_discovery
1795 .remove(&(task.network[chain_id].next_discovery_when.clone(), chain_id));
1796 debug_assert!(_was_in.is_some());
1797 task.secondary_reopens.retain(|(_, c, _), _| *c != chain_id);
1798
1799 log!(
1800 &task.platform,
1801 Debug,
1802 "network",
1803 "chain-removed",
1804 id = task.network[chain_id].log_name
1805 );
1806 task.v2_statement_peers.remove(&chain_id);
1807 task.current_affinity_filter.remove(&chain_id);
1808 task.important_nodes.remove(&chain_id);
1809 task.chains_ever_gossip_connected.remove(&chain_id);
1810 task.network.remove_chain(chain_id).unwrap();
1811 task.peering_strategy.remove_chain_peers(&chain_id);
1812 }
1813 WakeUpReason::MessageForChain(chain_id, ToBackgroundChain::Subscribe { sender }) => {
1814 task.pending_new_subscriptions.push((chain_id, sender));
1815 }
1816 WakeUpReason::MessageForChain(
1817 _chain_id,
1818 ToBackgroundChain::SubscribeBitswap { sender },
1819 ) => {
1820 task.pending_new_bitswap_subscriptions.push(sender);
1821 }
1822 WakeUpReason::MessageForChain(
1823 chain_id,
1824 ToBackgroundChain::SubscribeStatements { sender },
1825 ) => {
1826 task.pending_new_statement_subscriptions
1827 .push((chain_id, sender));
1828 }
1829 WakeUpReason::MessageForChain(
1830 chain_id,
1831 ToBackgroundChain::DisconnectAndBan {
1832 peer_id,
1833 severity,
1834 reason,
1835 },
1836 ) => {
1837 let ban_duration = Duration::from_secs(match severity {
1838 BanSeverity::Low => 10,
1839 BanSeverity::High => 40,
1840 });
1841
1842 let had_slot = matches!(
1843 task.peering_strategy.unassign_slot_and_ban(
1844 &chain_id,
1845 &peer_id,
1846 task.platform.now() + ban_duration,
1847 ),
1848 basic_peering_strategy::UnassignSlotAndBan::Banned { had_slot: true }
1849 );
1850
1851 if had_slot {
1852 log!(
1853 &task.platform,
1854 Debug,
1855 "network",
1856 "slot-unassigned",
1857 chain = &task.network[chain_id].log_name,
1858 peer_id,
1859 ?ban_duration,
1860 reason = "user-ban",
1861 user_reason = reason
1862 );
1863 task.network.gossip_remove_desired(
1864 chain_id,
1865 &peer_id,
1866 service::GossipKind::ConsensusTransactions,
1867 );
1868 }
1869
1870 if task.network.gossip_is_connected(
1871 chain_id,
1872 &peer_id,
1873 service::GossipKind::ConsensusTransactions,
1874 ) {
1875 let _closed_result = task.network.gossip_close(
1876 chain_id,
1877 &peer_id,
1878 service::GossipKind::ConsensusTransactions,
1879 );
1880 debug_assert!(_closed_result.is_ok());
1881
1882 log!(
1883 &task.platform,
1884 Debug,
1885 "network",
1886 "gossip-closed",
1887 chain = &task.network[chain_id].log_name,
1888 peer_id,
1889 );
1890
1891 let _was_in = task.open_gossip_links.remove(&(chain_id, peer_id.clone()));
1892 debug_assert!(_was_in.is_some());
1893 task.network[chain_id].metrics.gossip_peers_connected.dec();
1894
1895 task.events_pending_send.push_back((
1898 chain_id,
1899 Event::Disconnected {
1900 peer_id: peer_id.clone(),
1901 },
1902 ));
1903 }
1904
1905 task.network.gossip_remove_desired(
1908 chain_id,
1909 &peer_id,
1910 service::GossipKind::Statement,
1911 );
1912 if task
1913 .network
1914 .gossip_close(chain_id, &peer_id, service::GossipKind::Statement)
1915 .is_ok()
1916 {
1917 log!(
1918 &task.platform,
1919 Debug,
1920 "network",
1921 "statement-protocol-closed",
1922 chain = &task.network[chain_id].log_name,
1923 peer_id,
1924 reason = "user-ban",
1925 );
1926 }
1927 if let Some(peers) = task.v2_statement_peers.get_mut(&chain_id) {
1928 peers.remove(&peer_id);
1929 }
1930 }
1931 WakeUpReason::MessageForChain(
1932 chain_id,
1933 ToBackgroundChain::StartBlocksRequest {
1934 target,
1935 config,
1936 timeout,
1937 result,
1938 },
1939 ) => {
1940 match &config.start {
1941 codec::BlocksRequestConfigStart::Hash(hash) => {
1942 log!(
1943 &task.platform,
1944 Debug,
1945 "network",
1946 "blocks-request-started",
1947 chain = task.network[chain_id].log_name, target,
1948 start = HashDisplay(hash),
1949 num = config.desired_count.get(),
1950 descending = ?matches!(config.direction, codec::BlocksRequestDirection::Descending),
1951 header = ?config.fields.header, body = ?config.fields.body,
1952 justifications = ?config.fields.justifications
1953 );
1954 }
1955 codec::BlocksRequestConfigStart::Number(number) => {
1956 log!(
1957 &task.platform,
1958 Debug,
1959 "network",
1960 "blocks-request-started",
1961 chain = task.network[chain_id].log_name, target, start = number,
1962 num = config.desired_count.get(),
1963 descending = ?matches!(config.direction, codec::BlocksRequestDirection::Descending),
1964 header = ?config.fields.header, body = ?config.fields.body, justifications = ?config.fields.justifications
1965 );
1966 }
1967 }
1968
1969 match task
1970 .network
1971 .start_blocks_request(&target, chain_id, config.clone(), timeout)
1972 {
1973 Ok(substream_id) => {
1974 task.blocks_requests.insert(substream_id, result);
1975 }
1976 Err(service::StartRequestError::NoConnection) => {
1977 log!(
1978 &task.platform,
1979 Debug,
1980 "network",
1981 "blocks-request-error",
1982 chain = task.network[chain_id].log_name,
1983 target,
1984 error = "NoConnection"
1985 );
1986 let _ = result.send(Err(BlocksRequestError::NoConnection));
1987 }
1988 }
1989 }
1990 WakeUpReason::MessageForChain(
1991 chain_id,
1992 ToBackgroundChain::StartWarpSyncRequest {
1993 target,
1994 begin_hash,
1995 timeout,
1996 result,
1997 },
1998 ) => {
1999 log!(
2000 &task.platform,
2001 Debug,
2002 "network",
2003 "warp-sync-request-started",
2004 chain = task.network[chain_id].log_name,
2005 target,
2006 start = HashDisplay(&begin_hash)
2007 );
2008
2009 match task
2010 .network
2011 .start_grandpa_warp_sync_request(&target, chain_id, begin_hash, timeout)
2012 {
2013 Ok(substream_id) => {
2014 task.grandpa_warp_sync_requests.insert(substream_id, result);
2015 }
2016 Err(service::StartRequestError::NoConnection) => {
2017 log!(
2018 &task.platform,
2019 Debug,
2020 "network",
2021 "warp-sync-request-error",
2022 chain = task.network[chain_id].log_name,
2023 target,
2024 error = "NoConnection"
2025 );
2026 let _ = result.send(Err(WarpSyncRequestError::NoConnection));
2027 }
2028 }
2029 }
2030 WakeUpReason::MessageForChain(
2031 chain_id,
2032 ToBackgroundChain::StartStorageProofRequest {
2033 target,
2034 config,
2035 timeout,
2036 result,
2037 },
2038 ) => {
2039 log!(
2040 &task.platform,
2041 Debug,
2042 "network",
2043 "storage-proof-request-started",
2044 chain = task.network[chain_id].log_name,
2045 target,
2046 block_hash = HashDisplay(&config.block_hash)
2047 );
2048
2049 match task.network.start_storage_proof_request(
2050 &target,
2051 chain_id,
2052 config.clone(),
2053 timeout,
2054 ) {
2055 Ok(substream_id) => {
2056 task.storage_proof_requests.insert(substream_id, result);
2057 }
2058 Err(service::StartRequestMaybeTooLargeError::NoConnection) => {
2059 log!(
2060 &task.platform,
2061 Debug,
2062 "network",
2063 "storage-proof-request-error",
2064 chain = task.network[chain_id].log_name,
2065 target,
2066 error = "NoConnection"
2067 );
2068 let _ = result.send(Err(StorageProofRequestError::NoConnection));
2069 }
2070 Err(service::StartRequestMaybeTooLargeError::RequestTooLarge) => {
2071 log!(
2072 &task.platform,
2073 Debug,
2074 "network",
2075 "storage-proof-request-error",
2076 chain = task.network[chain_id].log_name,
2077 target,
2078 error = "RequestTooLarge"
2079 );
2080 let _ = result.send(Err(StorageProofRequestError::RequestTooLarge));
2081 }
2082 };
2083 }
2084 WakeUpReason::MessageForChain(
2085 chain_id,
2086 ToBackgroundChain::StartCallProofRequest {
2087 target,
2088 config,
2089 timeout,
2090 result,
2091 },
2092 ) => {
2093 log!(
2094 &task.platform,
2095 Debug,
2096 "network",
2097 "call-proof-request-started",
2098 chain = task.network[chain_id].log_name,
2099 target,
2100 block_hash = HashDisplay(&config.block_hash),
2101 function = config.method
2102 );
2103 match task.network.start_call_proof_request(
2106 &target,
2107 chain_id,
2108 config.clone(),
2109 timeout,
2110 ) {
2111 Ok(substream_id) => {
2112 task.call_proof_requests.insert(substream_id, result);
2113 }
2114 Err(service::StartRequestMaybeTooLargeError::NoConnection) => {
2115 log!(
2116 &task.platform,
2117 Debug,
2118 "network",
2119 "call-proof-request-error",
2120 chain = task.network[chain_id].log_name,
2121 target,
2122 error = "NoConnection"
2123 );
2124 let _ = result.send(Err(CallProofRequestError::NoConnection));
2125 }
2126 Err(service::StartRequestMaybeTooLargeError::RequestTooLarge) => {
2127 log!(
2128 &task.platform,
2129 Debug,
2130 "network",
2131 "call-proof-request-error",
2132 chain = task.network[chain_id].log_name,
2133 target,
2134 error = "RequestTooLarge"
2135 );
2136 let _ = result.send(Err(CallProofRequestError::RequestTooLarge));
2137 }
2138 };
2139 }
2140 WakeUpReason::MessageForChain(
2141 chain_id,
2142 ToBackgroundChain::StartChildStorageProofRequest {
2143 target,
2144 config,
2145 timeout,
2146 result,
2147 },
2148 ) => {
2149 log!(
2150 &task.platform,
2151 Debug,
2152 "network",
2153 "child-storage-proof-request-started",
2154 chain = task.network[chain_id].log_name,
2155 target,
2156 block_hash = HashDisplay(&config.block_hash)
2157 );
2158
2159 match task.network.start_child_storage_proof_request(
2160 &target,
2161 chain_id,
2162 codec::ChildStorageProofRequestConfig {
2163 block_hash: config.block_hash,
2164 child_trie: &config.child_trie,
2165 keys: config.keys.iter().map(|k| k.as_slice()),
2166 },
2167 timeout,
2168 ) {
2169 Ok(substream_id) => {
2170 task.child_storage_proof_requests
2171 .insert(substream_id, result);
2172 }
2173 Err(service::StartRequestMaybeTooLargeError::NoConnection) => {
2174 log!(
2175 &task.platform,
2176 Debug,
2177 "network",
2178 "child-storage-proof-request-error",
2179 chain = task.network[chain_id].log_name,
2180 target,
2181 error = "NoConnection"
2182 );
2183 let _ = result.send(Err(ChildStorageProofRequestError::NoConnection));
2184 }
2185 Err(service::StartRequestMaybeTooLargeError::RequestTooLarge) => {
2186 log!(
2187 &task.platform,
2188 Debug,
2189 "network",
2190 "child-storage-proof-request-error",
2191 chain = task.network[chain_id].log_name,
2192 target,
2193 error = "RequestTooLarge"
2194 );
2195 let _ = result.send(Err(ChildStorageProofRequestError::RequestTooLarge));
2196 }
2197 };
2198 }
2199 WakeUpReason::MessageForChain(
2200 chain_id,
2201 ToBackgroundChain::SetLocalBestBlock {
2202 best_hash,
2203 best_number,
2204 },
2205 ) => {
2206 task.network
2207 .set_chain_local_best_block(chain_id, best_hash, best_number);
2208 }
2209 WakeUpReason::MessageForChain(
2210 chain_id,
2211 ToBackgroundChain::SetLocalGrandpaState { grandpa_state },
2212 ) => {
2213 log!(
2214 &task.platform,
2215 Debug,
2216 "network",
2217 "local-grandpa-state-announced",
2218 chain = task.network[chain_id].log_name,
2219 set_id = grandpa_state.set_id,
2220 commit_finalized_height = grandpa_state.commit_finalized_height,
2221 );
2222
2223 task.network
2226 .gossip_broadcast_grandpa_state_and_update(chain_id, grandpa_state);
2227 }
2228 WakeUpReason::MessageForChain(
2229 chain_id,
2230 ToBackgroundChain::AnnounceTransaction {
2231 transaction,
2232 result,
2233 },
2234 ) => {
2235 let peers_to_send = task
2238 .network
2239 .gossip_connected_peers(chain_id, service::GossipKind::ConsensusTransactions)
2240 .cloned()
2241 .collect::<Vec<_>>();
2242
2243 let mut peers_sent = Vec::with_capacity(peers_to_send.len());
2244 let mut peers_queue_full = Vec::with_capacity(peers_to_send.len());
2245 for peer in &peers_to_send {
2246 match task
2247 .network
2248 .gossip_send_transaction(peer, chain_id, &transaction)
2249 {
2250 Ok(()) => peers_sent.push(peer.to_base58()),
2251 Err(QueueNotificationError::QueueFull) => {
2252 peers_queue_full.push(peer.to_base58())
2253 }
2254 Err(QueueNotificationError::NoConnection) => unreachable!(),
2255 }
2256 }
2257
2258 log!(
2259 &task.platform,
2260 Debug,
2261 "network",
2262 "transaction-announced",
2263 chain = task.network[chain_id].log_name,
2264 transaction =
2265 hex::encode(blake2_rfc::blake2b::blake2b(32, &[], &transaction).as_bytes()),
2266 size = transaction.len(),
2267 peers_sent = peers_sent.join(", "),
2268 peers_queue_full = peers_queue_full.join(", "),
2269 );
2270
2271 let _ = result.send(peers_to_send);
2272 }
2273 WakeUpReason::MessageForChain(
2274 chain_id,
2275 ToBackgroundChain::SendBlockAnnounce {
2276 target,
2277 scale_encoded_header,
2278 is_best,
2279 result,
2280 },
2281 ) => {
2282 let _ = result.send(task.network.gossip_send_block_announce(
2284 &target,
2285 chain_id,
2286 &scale_encoded_header,
2287 is_best,
2288 ));
2289 }
2290 WakeUpReason::MessageForChain(
2291 _chain_id,
2292 ToBackgroundChain::SendBitswapMessage {
2293 target,
2294 message,
2295 result,
2296 },
2297 ) => {
2298 let _ = result.send(task.network.bitswap_send_message(&target, message));
2299 }
2300 WakeUpReason::MessageForChain(
2301 _chain_id,
2302 ToBackgroundChain::BroadcastBitswapMessage { message, result },
2303 ) => {
2304 let peers = task
2305 .network
2306 .established_bitswap_desired()
2307 .cloned()
2308 .collect::<Vec<_>>();
2309 let results = peers
2310 .iter()
2311 .map(|peer| {
2312 (
2313 peer,
2314 task.network.bitswap_send_message(peer, message.clone()),
2315 )
2316 })
2317 .collect::<Vec<_>>(); let succeeded_peers = results
2320 .iter()
2321 .filter_map(|(peer, r)| r.is_ok().then(|| (*peer).clone()))
2322 .collect::<Vec<_>>();
2323
2324 let r = if !succeeded_peers.is_empty() {
2326 Ok(succeeded_peers)
2327 } else if results
2328 .iter()
2329 .any(|(_peer, r)| matches!(r, Err(SendBitswapMessageError::QueueFull)))
2330 {
2331 Err(SendBitswapMessageError::QueueFull)
2334 } else {
2335 Err(SendBitswapMessageError::NoConnection)
2338 };
2339
2340 let _ = result.send(r);
2341 }
2342 WakeUpReason::MessageForChain(
2343 chain_id,
2344 ToBackgroundChain::BroadcastStatement { statement, result },
2345 ) => {
2346 let peers_to_send = task
2347 .network
2348 .gossip_connected_peers(chain_id, service::GossipKind::Statement)
2349 .cloned()
2350 .collect::<Vec<_>>();
2351
2352 let total = peers_to_send.len();
2353 let mut sent = 0;
2354 for peer in &peers_to_send {
2355 if task
2356 .network
2357 .gossip_send_statement(peer, chain_id, statement.clone())
2358 .is_ok()
2359 {
2360 sent += 1;
2361 }
2362 }
2363
2364 log!(
2365 &task.platform,
2366 Debug,
2367 "network",
2368 "statement-broadcast",
2369 chain = task.network[chain_id].log_name,
2370 sent,
2371 total,
2372 );
2373
2374 let _ = result.send(BroadcastStatementResult { sent, total });
2375 }
2376 WakeUpReason::MessageForChain(
2377 chain_id,
2378 ToBackgroundChain::UpdateTopicAffinity { filter },
2379 ) => {
2380 task.current_affinity_filter
2381 .insert(chain_id, filter.clone());
2382 if let Some(peers) = task.v2_statement_peers.get_mut(&chain_id) {
2383 let mut to_remove = Vec::new();
2384 for peer_id in peers.iter() {
2385 if let Err(
2386 SendTopicAffinityError::NoConnection
2387 | SendTopicAffinityError::ProtocolV1,
2388 ) = task.network.send_topic_affinity(peer_id, chain_id, &filter)
2389 {
2390 to_remove.push(peer_id.clone());
2391 }
2392 }
2393 for peer_id in &to_remove {
2394 peers.remove(peer_id);
2395 }
2396 }
2397 }
2398 WakeUpReason::MessageForChain(
2399 chain_id,
2400 ToBackgroundChain::Discover {
2401 list,
2402 important_nodes,
2403 },
2404 ) => {
2405 for (peer_id, addrs) in list {
2406 if important_nodes {
2407 task.important_nodes
2408 .entry(chain_id)
2409 .or_default()
2410 .insert(peer_id.clone());
2411 }
2412
2413 task.peering_strategy
2416 .insert_chain_peer(chain_id, peer_id.clone(), 30); for addr in addrs {
2419 let _ =
2420 task.peering_strategy
2421 .insert_address(&peer_id, addr.into_bytes(), 10);
2422 }
2424 }
2425 }
2426 WakeUpReason::MessageForChain(
2427 chain_id,
2428 ToBackgroundChain::DiscoveredNodes { result },
2429 ) => {
2430 let _ = result.send(
2432 task.peering_strategy
2433 .chain_peers_unordered(&chain_id)
2434 .map(|peer_id| {
2435 let addrs = task
2436 .peering_strategy
2437 .peer_addresses(peer_id)
2438 .map(|a| Multiaddr::from_bytes(a.to_owned()).unwrap())
2439 .collect::<Vec<_>>();
2440 (peer_id.clone(), addrs)
2441 })
2442 .collect::<Vec<_>>(),
2443 );
2444 }
2445 WakeUpReason::MessageForChain(chain_id, ToBackgroundChain::PeersList { result }) => {
2446 let _ = result.send(
2447 task.network
2448 .gossip_connected_peers(
2449 chain_id,
2450 service::GossipKind::ConsensusTransactions,
2451 )
2452 .cloned()
2453 .collect(),
2454 );
2455 }
2456 WakeUpReason::ReopenSecondaries { chain_id, peer_id } => {
2457 let outcome = task.network.gossip_reopen_secondaries(chain_id, &peer_id);
2459 log!(
2460 &task.platform,
2461 Debug,
2462 "network",
2463 "gossip-secondaries-reopen",
2464 chain = &task.network[chain_id].log_name,
2465 peer_id,
2466 ?outcome,
2467 );
2468 }
2469 WakeUpReason::StartDiscovery(chain_id) => {
2470 let chain = &mut task.network[chain_id];
2472 chain.next_discovery_when = task.platform.now() + chain.next_discovery_period;
2473 chain.next_discovery_period =
2474 cmp::min(chain.next_discovery_period * 2, Duration::from_secs(120));
2475 task.chains_by_next_discovery.insert(
2476 (chain.next_discovery_when.clone(), chain_id),
2477 Box::pin(
2478 task.platform
2479 .sleep(task.network[chain_id].next_discovery_period),
2480 ),
2481 );
2482
2483 const PARALLEL_FIND_NODE_PER_ROUND: usize = 3;
2495
2496 let mut candidates: Vec<PeerId> = task
2497 .network
2498 .kademlia_capable_peers(chain_id)
2499 .cloned()
2500 .collect();
2501 for p in task
2502 .network
2503 .gossip_connected_peers(chain_id, service::GossipKind::ConsensusTransactions)
2504 .cloned()
2505 {
2506 if !candidates.contains(&p) {
2507 candidates.push(p);
2508 }
2509 }
2510
2511 let started = dispatch_find_node_requests(
2512 &mut task.network,
2513 &mut task.randomness,
2514 chain_id,
2515 &candidates,
2516 PARALLEL_FIND_NODE_PER_ROUND,
2517 );
2518
2519 let chain_log_name = &task.network[chain_id].log_name;
2520 for (request_target, requested_peer_id) in &started {
2521 log!(
2522 &task.platform,
2523 Debug,
2524 "network",
2525 "discovery-find-node-started",
2526 chain = chain_log_name,
2527 request_target,
2528 requested_peer_id
2529 );
2530 }
2531 if started.is_empty() {
2532 log!(
2533 &task.platform,
2534 Debug,
2535 "network",
2536 "discovery-skipped-no-peer",
2537 chain = chain_log_name
2538 );
2539 }
2540 }
2541 WakeUpReason::NetworkEvent(service::Event::HandshakeFinished {
2542 peer_id,
2543 expected_peer_id,
2544 id,
2545 }) => {
2546 let remote_addr =
2547 Multiaddr::from_bytes(task.network.connection_remote_addr(id)).unwrap(); if let Some(expected_peer_id) = expected_peer_id.as_ref().filter(|p| **p != peer_id)
2549 {
2550 log!(
2551 &task.platform,
2552 Debug,
2553 "network",
2554 "handshake-finished-peer-id-mismatch",
2555 remote_addr,
2556 expected_peer_id,
2557 actual_peer_id = peer_id
2558 );
2559
2560 let _was_in = task
2561 .peering_strategy
2562 .decrease_address_connections_and_remove_if_zero(
2563 expected_peer_id,
2564 remote_addr.as_ref(),
2565 );
2566 debug_assert!(_was_in.is_ok());
2567 let _ = task.peering_strategy.increase_address_connections(
2568 &peer_id,
2569 remote_addr.into_bytes().to_vec(),
2570 10,
2571 );
2572 } else {
2573 log!(
2574 &task.platform,
2575 Debug,
2576 "network",
2577 "handshake-finished",
2578 remote_addr,
2579 peer_id
2580 );
2581 }
2582
2583 task.metrics.connections_handshakes_finished.inc();
2584 task.bitswap_peering_strategy
2585 .increase_peer_connections(&peer_id);
2586 }
2587 WakeUpReason::NetworkEvent(service::Event::PreHandshakeDisconnected {
2588 expected_peer_id: Some(_),
2589 ..
2590 })
2591 | WakeUpReason::NetworkEvent(service::Event::Disconnected { .. }) => {
2592 let (address, peer_id, handshake_finished) = match wake_up_reason {
2593 WakeUpReason::NetworkEvent(service::Event::PreHandshakeDisconnected {
2594 address,
2595 expected_peer_id: Some(peer_id),
2596 ..
2597 }) => (address, peer_id, false),
2598 WakeUpReason::NetworkEvent(service::Event::Disconnected {
2599 address,
2600 peer_id,
2601 ..
2602 }) => (address, peer_id, true),
2603 _ => unreachable!(),
2604 };
2605
2606 task.peering_strategy
2607 .decrease_address_connections(&peer_id, &address)
2608 .unwrap();
2609 let address = Multiaddr::from_bytes(address).unwrap();
2610 log!(
2611 &task.platform,
2612 Debug,
2613 "network",
2614 "connection-shutdown",
2615 peer_id,
2616 address,
2617 ?handshake_finished
2618 );
2619 task.metrics.connections_shutdowns.inc();
2620
2621 let ban_duration = if handshake_finished {
2632 Duration::from_secs(5)
2633 } else {
2634 Duration::from_secs(2)
2635 };
2636 task.network.gossip_remove_desired_all(
2637 &peer_id,
2638 service::GossipKind::ConsensusTransactions,
2639 );
2640 task.network
2641 .gossip_remove_desired_all(&peer_id, service::GossipKind::Statement);
2642 for (&chain_id, what_happened) in task
2643 .peering_strategy
2644 .unassign_slots_and_ban(&peer_id, task.platform.now() + ban_duration)
2645 {
2646 if matches!(
2647 what_happened,
2648 basic_peering_strategy::UnassignSlotsAndBan::Banned { had_slot: true }
2649 ) {
2650 log!(
2651 &task.platform,
2652 Debug,
2653 "network",
2654 "slot-unassigned",
2655 chain = &task.network[chain_id].log_name,
2656 peer_id,
2657 ?ban_duration,
2658 reason = "pre-handshake-disconnect"
2660 );
2661 }
2662 }
2663
2664 if handshake_finished {
2665 task.network.bitswap_remove_desired(&peer_id);
2666 let what_happened = task
2667 .bitswap_peering_strategy
2668 .unassign_slot_and_ban(&peer_id, task.platform.now() + ban_duration);
2669 if matches!(
2670 what_happened,
2671 bitswap_peering_strategy::UnassignSlotAndBan::Banned { had_slot: true },
2672 ) {
2673 log!(
2674 &task.platform,
2675 Debug,
2676 "network",
2677 "bitswap-slot-unassigned",
2678 peer_id,
2679 ?ban_duration,
2680 reason = "disconnect",
2681 );
2682 }
2683 let _ = task
2684 .bitswap_peering_strategy
2685 .decrease_peer_connections(&peer_id);
2686 }
2687 }
2688 WakeUpReason::NetworkEvent(service::Event::PreHandshakeDisconnected {
2689 expected_peer_id: None,
2690 ..
2691 }) => {
2692 debug_assert!(false);
2695 }
2696 WakeUpReason::NetworkEvent(service::Event::PingOutSuccess {
2697 id,
2698 peer_id,
2699 ping_time,
2700 }) => {
2701 let remote_addr =
2702 Multiaddr::from_bytes(task.network.connection_remote_addr(id)).unwrap(); log!(
2704 &task.platform,
2705 Debug,
2706 "network",
2707 "pong",
2708 peer_id,
2709 remote_addr,
2710 ?ping_time
2711 );
2712 }
2713 WakeUpReason::NetworkEvent(service::Event::BlockAnnounce {
2714 chain_id,
2715 peer_id,
2716 announce,
2717 }) => {
2718 log!(
2719 &task.platform,
2720 Debug,
2721 "network",
2722 "block-announce-received",
2723 chain = &task.network[chain_id].log_name,
2724 peer_id,
2725 block_hash = HashDisplay(&header::hash_from_scale_encoded_header(
2726 announce.decode().scale_encoded_header
2727 )),
2728 is_best = announce.decode().is_best
2729 );
2730
2731 let decoded_announce = announce.decode();
2732 if decoded_announce.is_best {
2733 let link = task
2734 .open_gossip_links
2735 .get_mut(&(chain_id, peer_id.clone()))
2736 .unwrap();
2737 if let Ok(decoded) = header::decode(
2738 decoded_announce.scale_encoded_header,
2739 task.network[chain_id].block_number_bytes,
2740 ) {
2741 link.best_block_hash = header::hash_from_scale_encoded_header(
2742 decoded_announce.scale_encoded_header,
2743 );
2744 link.best_block_number = decoded.number;
2745 }
2746 }
2747
2748 debug_assert!(task.events_pending_send.is_empty());
2749 task.events_pending_send
2750 .push_back((chain_id, Event::BlockAnnounce { peer_id, announce }));
2751 }
2752 WakeUpReason::NetworkEvent(service::Event::GossipConnected {
2753 peer_id,
2754 chain_id,
2755 role,
2756 best_number,
2757 best_hash,
2758 kind: service::GossipKind::ConsensusTransactions,
2759 }) => {
2760 log!(
2761 &task.platform,
2762 Debug,
2763 "network",
2764 "gossip-open-success",
2765 chain = &task.network[chain_id].log_name,
2766 peer_id,
2767 best_number,
2768 best_hash = HashDisplay(&best_hash)
2769 );
2770
2771 let _prev_value = task.open_gossip_links.insert(
2772 (chain_id, peer_id.clone()),
2773 OpenGossipLinkState {
2774 best_block_number: best_number,
2775 best_block_hash: best_hash,
2776 role,
2777 finalized_block_height: None,
2778 secondary_reopened_at_once: false,
2779 },
2780 );
2781 debug_assert!(_prev_value.is_none());
2782 task.network[chain_id].metrics.gossip_peers_connected.inc();
2783
2784 task.chains_ever_gossip_connected.insert(chain_id);
2785
2786 debug_assert!(task.events_pending_send.is_empty());
2787 task.events_pending_send.push_back((
2788 chain_id,
2789 Event::Connected {
2790 peer_id,
2791 role,
2792 best_block_number: best_number,
2793 best_block_hash: best_hash,
2794 },
2795 ));
2796 }
2797 WakeUpReason::NetworkEvent(service::Event::GossipOpenFailed {
2798 peer_id,
2799 chain_id,
2800 error,
2801 kind: service::GossipKind::ConsensusTransactions,
2802 }) => {
2803 log!(
2804 &task.platform,
2805 Debug,
2806 "network",
2807 "gossip-open-error",
2808 chain = &task.network[chain_id].log_name,
2809 peer_id,
2810 ?error,
2811 );
2812 let ban_duration = Duration::from_millis(5500);
2816
2817 let had_slot = if let service::GossipConnectError::GenesisMismatch { .. } = error {
2820 matches!(
2821 task.peering_strategy
2822 .unassign_slot_and_remove_chain_peer(&chain_id, &peer_id),
2823 basic_peering_strategy::UnassignSlotAndRemoveChainPeer::HadSlot
2824 )
2825 } else {
2826 matches!(
2827 task.peering_strategy.unassign_slot_and_ban(
2828 &chain_id,
2829 &peer_id,
2830 task.platform.now() + ban_duration,
2831 ),
2832 basic_peering_strategy::UnassignSlotAndBan::Banned { had_slot: true }
2833 )
2834 };
2835
2836 if had_slot {
2837 log!(
2838 &task.platform,
2839 Debug,
2840 "network",
2841 "slot-unassigned",
2842 chain = &task.network[chain_id].log_name,
2843 peer_id,
2844 ?ban_duration,
2845 reason = "gossip-open-failed"
2846 );
2847 task.network.gossip_remove_desired(
2848 chain_id,
2849 &peer_id,
2850 service::GossipKind::ConsensusTransactions,
2851 );
2852 }
2853 }
2854 WakeUpReason::NetworkEvent(service::Event::GossipDisconnected {
2855 peer_id,
2856 chain_id,
2857 kind: service::GossipKind::ConsensusTransactions,
2858 }) => {
2859 log!(
2860 &task.platform,
2861 Debug,
2862 "network",
2863 "gossip-closed",
2864 chain = &task.network[chain_id].log_name,
2865 peer_id,
2866 );
2867 let ban_duration = Duration::from_secs(10);
2868
2869 task.secondary_reopens
2871 .retain(|(_, c, p), _| *c != chain_id || *p != peer_id);
2872
2873 let _was_in = task.open_gossip_links.remove(&(chain_id, peer_id.clone()));
2874 debug_assert!(_was_in.is_some());
2875 task.network[chain_id].metrics.gossip_peers_connected.dec();
2876
2877 if matches!(
2880 task.peering_strategy.unassign_slot_and_ban(
2881 &chain_id,
2882 &peer_id,
2883 task.platform.now() + ban_duration,
2884 ),
2885 basic_peering_strategy::UnassignSlotAndBan::Banned { had_slot: true }
2886 ) {
2887 log!(
2888 &task.platform,
2889 Debug,
2890 "network",
2891 "slot-unassigned",
2892 chain = &task.network[chain_id].log_name,
2893 peer_id,
2894 ?ban_duration,
2895 reason = "gossip-closed"
2896 );
2897 task.network.gossip_remove_desired(
2898 chain_id,
2899 &peer_id,
2900 service::GossipKind::ConsensusTransactions,
2901 );
2902 }
2903
2904 if !task.network.gossip_is_connected(
2907 chain_id,
2908 &peer_id,
2909 service::GossipKind::Statement,
2910 ) && let Some(peers) = task.v2_statement_peers.get_mut(&chain_id)
2911 {
2912 peers.remove(&peer_id);
2913 }
2914
2915 debug_assert!(task.events_pending_send.is_empty());
2916 task.events_pending_send
2917 .push_back((chain_id, Event::Disconnected { peer_id }));
2918 }
2919 WakeUpReason::NetworkEvent(service::Event::GossipSecondaryClosed {
2920 peer_id,
2921 chain_id,
2922 error,
2923 }) => {
2924 log!(
2925 &task.platform,
2926 Debug,
2927 "network",
2928 "gossip-secondary-closed",
2929 chain = &task.network[chain_id].log_name,
2930 peer_id,
2931 ?error,
2932 );
2933
2934 let link = task.open_gossip_links.get_mut(&(chain_id, peer_id.clone()));
2938 let Some(link) = link else {
2939 log!(
2941 &task.platform,
2942 Warn,
2943 "network",
2944 "gossip-secondary-closed-unknown-link",
2945 chain = &task.network[chain_id].log_name,
2946 peer_id,
2947 );
2948 continue;
2949 };
2950 if !link.secondary_reopened_at_once {
2951 link.secondary_reopened_at_once = true;
2952 let outcome = task.network.gossip_reopen_secondaries(chain_id, &peer_id);
2953 log!(
2954 &task.platform,
2955 Debug,
2956 "network",
2957 "gossip-secondaries-reopen",
2958 chain = &task.network[chain_id].log_name,
2959 peer_id,
2960 ?outcome,
2961 );
2962 } else if !task
2963 .secondary_reopens
2964 .keys()
2965 .any(|(_, c, p)| *c == chain_id && *p == peer_id)
2966 {
2967 task.secondary_reopens.insert(
2968 (
2969 task.platform.now() + SECONDARY_SUBSTREAM_RETRY_DELAY,
2970 chain_id,
2971 peer_id,
2972 ),
2973 Box::pin(task.platform.sleep(SECONDARY_SUBSTREAM_RETRY_DELAY)),
2974 );
2975 }
2976 }
2977 WakeUpReason::NetworkEvent(service::Event::BitswapConnected { peer_id }) => {
2978 task.bitswap_connected_peers = task.bitswap_connected_peers.saturating_add(1);
2979 log!(
2980 &task.platform,
2981 Debug,
2982 "network",
2983 "bitswap-open-success",
2984 peer_id,
2985 total = task.bitswap_connected_peers
2986 );
2987 }
2988 WakeUpReason::NetworkEvent(service::Event::BitswapOpenFailed { peer_id, error }) => {
2989 log!(
2990 &task.platform,
2991 Debug,
2992 "network",
2993 "bitswap-open-error",
2994 peer_id,
2995 ?error
2996 );
2997 let ban_duration = if error.is_protocol_not_available() {
2998 Duration::from_secs(600)
2999 } else {
3000 Duration::from_secs(15)
3001 };
3002 if matches!(
3003 task.bitswap_peering_strategy
3004 .unassign_slot_and_ban(&peer_id, task.platform.now() + ban_duration,),
3005 bitswap_peering_strategy::UnassignSlotAndBan::Banned { had_slot: true }
3006 ) {
3007 log!(
3008 &task.platform,
3009 Debug,
3010 "network",
3011 "bitswap-slot-unassigned",
3012 peer_id,
3013 ?ban_duration,
3014 reason = "bitswap-open-failed"
3015 );
3016 task.network.bitswap_remove_desired(&peer_id);
3017 }
3018 }
3019 WakeUpReason::NetworkEvent(service::Event::BitswapMessage { peer_id, message }) => {
3020 log!(
3021 &task.platform,
3022 Debug,
3023 "network",
3024 "bitswap-message-received",
3025 peer_id
3026 );
3027 debug_assert!(task.bitswap_event_pending_send.is_none());
3028 task.bitswap_event_pending_send =
3029 Some(BitswapEvent::BitswapMessage { peer_id, message });
3030 }
3031 WakeUpReason::NetworkEvent(service::Event::BitswapDisconnected { peer_id }) => {
3032 debug_assert!(task.bitswap_connected_peers > 0);
3033 task.bitswap_connected_peers = task.bitswap_connected_peers.saturating_sub(1);
3034 log!(
3035 &task.platform,
3036 Debug,
3037 "network",
3038 "bitswap-closed",
3039 peer_id,
3040 total = task.bitswap_connected_peers
3041 );
3042 let ban_duration = Duration::from_secs(10);
3043 if matches!(
3044 task.bitswap_peering_strategy
3045 .unassign_slot_and_ban(&peer_id, task.platform.now() + ban_duration,),
3046 bitswap_peering_strategy::UnassignSlotAndBan::Banned { had_slot: true }
3047 ) {
3048 log!(
3049 &task.platform,
3050 Debug,
3051 "network",
3052 "bitswap-slot-unassigned",
3053 peer_id,
3054 ?ban_duration,
3055 reason = "bitswap-closed"
3056 );
3057 task.network.bitswap_remove_desired(&peer_id);
3058 }
3059 }
3060 WakeUpReason::NetworkEvent(service::Event::RequestResult {
3061 substream_id,
3062 peer_id,
3063 chain_id,
3064 response: service::RequestResult::Blocks(response),
3065 }) => {
3066 match &response {
3067 Ok(blocks) => {
3068 log!(
3069 &task.platform,
3070 Debug,
3071 "network",
3072 "blocks-request-success",
3073 chain = task.network[chain_id].log_name,
3074 target = peer_id,
3075 num_blocks = blocks.len(),
3076 block_data_total_size =
3077 BytesDisplay(blocks.iter().fold(0, |sum, block| {
3078 let block_size = block.header.as_ref().map_or(0, |h| h.len())
3079 + block
3080 .body
3081 .as_ref()
3082 .map_or(0, |b| b.iter().fold(0, |s, e| s + e.len()))
3083 + block
3084 .justifications
3085 .as_ref()
3086 .into_iter()
3087 .flat_map(|l| l.iter())
3088 .fold(0, |s, j| s + j.justification.len());
3089 sum + u64::try_from(block_size).unwrap()
3090 }))
3091 );
3092 }
3093 Err(error) => {
3094 log!(
3095 &task.platform,
3096 Debug,
3097 "network",
3098 "blocks-request-error",
3099 chain = task.network[chain_id].log_name,
3100 target = peer_id,
3101 ?error
3102 );
3103 }
3104 }
3105
3106 match &response {
3107 Ok(_) => {}
3108 Err(service::BlocksRequestError::Request(err)) if !err.is_protocol_error() => {}
3109 Err(err) => {
3110 log!(
3111 &task.platform,
3112 Debug,
3113 "network",
3114 format!(
3115 "Error in block request with {}. This might indicate an \
3116 incompatibility. Error: {}",
3117 peer_id, err
3118 )
3119 );
3120 }
3121 }
3122
3123 let _ = task
3124 .blocks_requests
3125 .remove(&substream_id)
3126 .unwrap()
3127 .send(response.map_err(BlocksRequestError::Request));
3128 }
3129 WakeUpReason::NetworkEvent(service::Event::RequestResult {
3130 substream_id,
3131 peer_id,
3132 chain_id,
3133 response: service::RequestResult::GrandpaWarpSync(response),
3134 }) => {
3135 match &response {
3136 Ok(response) => {
3137 let decoded = response.decode();
3139 log!(
3140 &task.platform,
3141 Debug,
3142 "network",
3143 "warp-sync-request-success",
3144 chain = task.network[chain_id].log_name,
3145 target = peer_id,
3146 num_fragments = decoded.fragments.len(),
3147 is_finished = ?decoded.is_finished,
3148 );
3149 }
3150 Err(error) => {
3151 log!(
3152 &task.platform,
3153 Debug,
3154 "network",
3155 "warp-sync-request-error",
3156 chain = task.network[chain_id].log_name,
3157 target = peer_id,
3158 ?error,
3159 );
3160 }
3161 }
3162
3163 let _ = task
3164 .grandpa_warp_sync_requests
3165 .remove(&substream_id)
3166 .unwrap()
3167 .send(response.map_err(WarpSyncRequestError::Request));
3168 }
3169 WakeUpReason::NetworkEvent(service::Event::RequestResult {
3170 substream_id,
3171 peer_id,
3172 chain_id,
3173 response: service::RequestResult::StorageProof(response),
3174 }) => {
3175 match &response {
3176 Ok(items) => {
3177 let decoded = items.decode();
3178 log!(
3179 &task.platform,
3180 Debug,
3181 "network",
3182 "storage-proof-request-success",
3183 chain = task.network[chain_id].log_name,
3184 target = peer_id,
3185 total_size = BytesDisplay(u64::try_from(decoded.len()).unwrap()),
3186 );
3187 }
3188 Err(error) => {
3189 log!(
3190 &task.platform,
3191 Debug,
3192 "network",
3193 "storage-proof-request-error",
3194 chain = task.network[chain_id].log_name,
3195 target = peer_id,
3196 ?error
3197 );
3198 }
3199 }
3200
3201 if let Some(sender) = task.storage_proof_requests.remove(&substream_id) {
3204 let _ = sender.send(response.map_err(StorageProofRequestError::Request));
3205 } else if let Some(sender) = task.child_storage_proof_requests.remove(&substream_id)
3206 {
3207 let _ = sender.send(response.map_err(ChildStorageProofRequestError::Request));
3208 } else {
3209 unreachable!()
3210 }
3211 }
3212 WakeUpReason::NetworkEvent(service::Event::RequestResult {
3213 substream_id,
3214 peer_id,
3215 chain_id,
3216 response: service::RequestResult::CallProof(response),
3217 }) => {
3218 match &response {
3219 Ok(items) => {
3220 let decoded = items.decode();
3221 log!(
3222 &task.platform,
3223 Debug,
3224 "network",
3225 "call-proof-request-success",
3226 chain = task.network[chain_id].log_name,
3227 target = peer_id,
3228 total_size = BytesDisplay(u64::try_from(decoded.len()).unwrap())
3229 );
3230 }
3231 Err(error) => {
3232 log!(
3233 &task.platform,
3234 Debug,
3235 "network",
3236 "call-proof-request-error",
3237 chain = task.network[chain_id].log_name,
3238 target = peer_id,
3239 ?error
3240 );
3241 }
3242 }
3243
3244 let _ = task
3245 .call_proof_requests
3246 .remove(&substream_id)
3247 .unwrap()
3248 .send(response.map_err(CallProofRequestError::Request));
3249 }
3250 WakeUpReason::NetworkEvent(service::Event::RequestResult {
3251 peer_id: requestee_peer_id,
3252 chain_id,
3253 response: service::RequestResult::KademliaFindNode(Ok(nodes)),
3254 ..
3255 }) => {
3256 let mut any_new_peer = false;
3261 for (peer_id, mut addrs) in nodes {
3262 if addrs.len() >= 10 {
3265 addrs.truncate(10);
3266 }
3267
3268 let mut valid_addrs = Vec::with_capacity(addrs.len());
3269 for addr in addrs {
3270 match Multiaddr::from_bytes(addr) {
3271 Ok(mut a) => {
3272 if !pop_p2p_if_matches(&mut a, &peer_id) {
3273 let reason = DiscoveredAddressDropReason::PeerIdMismatch;
3274 log!(
3275 &task.platform,
3276 Debug,
3277 "network",
3278 "discovered-address-dropped",
3279 chain = &task.network[chain_id].log_name,
3280 reason,
3281 announced_peer_id = peer_id,
3282 addr = &a,
3283 obtained_from = requestee_peer_id
3284 );
3285 task.metrics.discovery_addresses_dropped.inc(reason);
3286 continue;
3287 }
3288 if platform::address_parse::multiaddr_to_address(&a)
3289 .ok()
3290 .map_or(false, |addr| {
3291 task.platform.supports_connection_type((&addr).into())
3292 })
3293 {
3294 valid_addrs.push(a)
3295 } else {
3296 let reason = DiscoveredAddressDropReason::NotSupported;
3297 log!(
3298 &task.platform,
3299 Debug,
3300 "network",
3301 "discovered-address-dropped",
3302 chain = &task.network[chain_id].log_name,
3303 reason,
3304 peer_id,
3305 addr = &a,
3306 obtained_from = requestee_peer_id
3307 );
3308 task.metrics.discovery_addresses_dropped.inc(reason);
3309 }
3310 }
3311 Err((error, addr)) => {
3312 let reason = DiscoveredAddressDropReason::Invalid;
3313 log!(
3314 &task.platform,
3315 Debug,
3316 "network",
3317 "discovered-address-dropped",
3318 chain = &task.network[chain_id].log_name,
3319 reason,
3320 peer_id,
3321 error,
3322 addr = hex::encode(&addr),
3323 obtained_from = requestee_peer_id
3324 );
3325 task.metrics.discovery_addresses_dropped.inc(reason);
3326 }
3327 }
3328 }
3329
3330 if !valid_addrs.is_empty() {
3331 let insert_outcome =
3334 task.peering_strategy
3335 .insert_chain_peer(chain_id, peer_id.clone(), 30); if let basic_peering_strategy::InsertChainPeerResult::Inserted {
3338 peer_removed,
3339 } = insert_outcome
3340 {
3341 any_new_peer = true;
3342 if let Some(peer_removed) = peer_removed {
3343 log!(
3344 &task.platform,
3345 Debug,
3346 "network",
3347 "peer-purged-from-address-book",
3348 chain = &task.network[chain_id].log_name,
3349 peer_id = peer_removed,
3350 );
3351 }
3352
3353 log!(
3354 &task.platform,
3355 Debug,
3356 "network",
3357 "peer-discovered",
3358 chain = &task.network[chain_id].log_name,
3359 peer_id,
3360 addrs = ?valid_addrs.iter().map(|a| a.to_string()).collect::<Vec<_>>(), obtained_from = requestee_peer_id
3362 );
3363 }
3364 }
3365
3366 for addr in valid_addrs {
3367 let _insert_result =
3368 task.peering_strategy
3369 .insert_address(&peer_id, addr.into_bytes(), 10); debug_assert!(!matches!(
3371 _insert_result,
3372 basic_peering_strategy::InsertAddressResult::UnknownPeer
3373 ));
3374 }
3375 }
3376
3377 if any_new_peer {
3378 task.network[chain_id].next_discovery_period = Duration::from_secs(2);
3379 }
3380 }
3381 WakeUpReason::NetworkEvent(service::Event::RequestResult {
3382 peer_id,
3383 chain_id,
3384 response: service::RequestResult::KademliaFindNode(Err(error)),
3385 ..
3386 }) => {
3387 log!(
3388 &task.platform,
3389 Debug,
3390 "network",
3391 "discovery-find-node-error",
3392 chain = &task.network[chain_id].log_name,
3393 ?error,
3394 find_node_target = peer_id,
3395 );
3396
3397 match error {
3400 service::KademliaFindNodeError::RequestFailed(err)
3401 if !err.is_protocol_error() => {}
3402
3403 service::KademliaFindNodeError::RequestFailed(
3404 service::RequestError::Substream(
3405 connection::established::RequestError::ProtocolNotAvailable,
3406 ),
3407 ) => {
3408 log!(
3410 &task.platform,
3411 Warn,
3412 "network",
3413 format!(
3414 "Problem during discovery on {}: protocol not available. \
3415 This might indicate that the version of Substrate used by \
3416 the chain doesn't include \
3417 <https://github.com/paritytech/substrate/pull/12545>.",
3418 &task.network[chain_id].log_name
3419 )
3420 );
3421 }
3422 _ => {
3423 log!(
3424 &task.platform,
3425 Debug,
3426 "network",
3427 format!(
3428 "Problem during discovery on {}: {}",
3429 &task.network[chain_id].log_name, error
3430 )
3431 );
3432 }
3433 }
3434 }
3435 WakeUpReason::NetworkEvent(service::Event::RequestResult { .. }) => {
3436 unreachable!()
3438 }
3439 WakeUpReason::NetworkEvent(service::Event::GossipInDesired {
3440 peer_id,
3441 chain_id,
3442 kind: service::GossipKind::ConsensusTransactions,
3443 }) => {
3444 if task
3452 .network
3453 .opened_gossip_undesired_by_chain(chain_id)
3454 .filter(|(_, kind)| *kind == service::GossipKind::ConsensusTransactions)
3455 .count()
3456 < 4
3457 {
3458 log!(
3459 &task.platform,
3460 Debug,
3461 "network",
3462 "gossip-in-request",
3463 chain = &task.network[chain_id].log_name,
3464 peer_id,
3465 outcome = "accepted"
3466 );
3467 task.network
3468 .gossip_open(
3469 chain_id,
3470 &peer_id,
3471 service::GossipKind::ConsensusTransactions,
3472 )
3473 .unwrap();
3474 } else {
3475 log!(
3476 &task.platform,
3477 Debug,
3478 "network",
3479 "gossip-in-request",
3480 chain = &task.network[chain_id].log_name,
3481 peer_id,
3482 outcome = "rejected",
3483 );
3484 task.network
3485 .gossip_close(
3486 chain_id,
3487 &peer_id,
3488 service::GossipKind::ConsensusTransactions,
3489 )
3490 .unwrap();
3491 }
3492 }
3493 WakeUpReason::NetworkEvent(service::Event::GossipInDesiredCancel { .. }) => {
3494 unreachable!()
3496 }
3497 WakeUpReason::NetworkEvent(
3498 service::Event::GossipConnected {
3499 kind: service::GossipKind::Statement,
3500 ..
3501 }
3502 | service::Event::GossipOpenFailed {
3503 kind: service::GossipKind::Statement,
3504 ..
3505 }
3506 | service::Event::GossipDisconnected {
3507 kind: service::GossipKind::Statement,
3508 ..
3509 }
3510 | service::Event::GossipInDesired {
3511 kind: service::GossipKind::Statement,
3512 ..
3513 },
3514 ) => {
3515 unreachable!()
3519 }
3520 WakeUpReason::NetworkEvent(service::Event::IdentifyRequestIn {
3521 peer_id,
3522 substream_id,
3523 }) => {
3524 log!(
3525 &task.platform,
3526 Debug,
3527 "network",
3528 "identify-request-received",
3529 peer_id,
3530 );
3531 task.network
3532 .respond_identify(substream_id, &task.identify_agent_version);
3533 }
3534 WakeUpReason::NetworkEvent(service::Event::BlocksRequestIn { .. }) => unreachable!(),
3535 WakeUpReason::NetworkEvent(service::Event::RequestInCancel { .. }) => {
3536 unreachable!()
3538 }
3539 WakeUpReason::NetworkEvent(service::Event::GrandpaNeighborPacket {
3540 chain_id,
3541 peer_id,
3542 state,
3543 }) => {
3544 log!(
3545 &task.platform,
3546 Debug,
3547 "network",
3548 "grandpa-neighbor-packet-received",
3549 chain = &task.network[chain_id].log_name,
3550 peer_id,
3551 round_number = state.round_number,
3552 set_id = state.set_id,
3553 commit_finalized_height = state.commit_finalized_height,
3554 );
3555
3556 task.open_gossip_links
3557 .get_mut(&(chain_id, peer_id.clone()))
3558 .unwrap()
3559 .finalized_block_height = Some(state.commit_finalized_height);
3560
3561 debug_assert!(task.events_pending_send.is_empty());
3562 task.events_pending_send.push_back((
3563 chain_id,
3564 Event::GrandpaNeighborPacket {
3565 peer_id,
3566 finalized_block_height: state.commit_finalized_height,
3567 },
3568 ));
3569 }
3570 WakeUpReason::NetworkEvent(service::Event::GrandpaCommitMessage {
3571 chain_id,
3572 peer_id,
3573 message,
3574 }) => {
3575 log!(
3576 &task.platform,
3577 Debug,
3578 "network",
3579 "grandpa-commit-message-received",
3580 chain = &task.network[chain_id].log_name,
3581 peer_id,
3582 target_block_hash = HashDisplay(message.decode().target_hash),
3583 );
3584
3585 debug_assert!(task.events_pending_send.is_empty());
3586 task.events_pending_send
3587 .push_back((chain_id, Event::GrandpaCommitMessage { peer_id, message }));
3588 }
3589 WakeUpReason::NetworkEvent(service::Event::StatementsNotification {
3590 chain_id,
3591 peer_id,
3592 statements,
3593 }) => {
3594 debug_assert!(task.statement_event_pending_send.is_none());
3595
3596 if statements.is_empty() {
3597 continue;
3598 }
3599
3600 task.statement_event_pending_send = Some((
3601 chain_id,
3602 StatementEvent::StatementsNotification {
3603 peer_id,
3604 statements,
3605 },
3606 ));
3607 }
3608 WakeUpReason::NetworkEvent(service::Event::StatementProtocolConnected {
3609 peer_id,
3610 chain_id,
3611 version,
3612 }) => {
3613 log!(
3614 &task.platform,
3615 Trace,
3616 "network",
3617 "statement-protocol-open-success",
3618 chain = &task.network[chain_id].log_name,
3619 peer_id,
3620 ?version,
3621 );
3622
3623 if matches!(version, codec::StatementProtocolVersion::V2) {
3624 task.v2_statement_peers
3625 .entry(chain_id)
3626 .or_insert_with(|| {
3627 HashSet::with_capacity_and_hasher(16, Default::default())
3628 })
3629 .insert(peer_id.clone());
3630 if let Some(filter) = task.current_affinity_filter.get(&chain_id) {
3631 if let Err(
3632 SendTopicAffinityError::NoConnection
3633 | SendTopicAffinityError::ProtocolV1,
3634 ) = task.network.send_topic_affinity(&peer_id, chain_id, filter)
3635 {
3636 task.v2_statement_peers
3637 .get_mut(&chain_id)
3638 .unwrap()
3639 .remove(&peer_id);
3640 }
3641 }
3642 }
3643 }
3644 WakeUpReason::NetworkEvent(service::Event::StatementProtocolOpenFailed {
3645 peer_id,
3646 chain_id,
3647 error,
3648 }) => {
3649 log!(
3650 &task.platform,
3651 Debug,
3652 "network",
3653 "statement-protocol-open-error",
3654 chain = &task.network[chain_id].log_name,
3655 peer_id,
3656 ?error,
3657 );
3658
3659 task.network.gossip_remove_desired(
3663 chain_id,
3664 &peer_id,
3665 service::GossipKind::Statement,
3666 );
3667 }
3668 WakeUpReason::NetworkEvent(service::Event::StatementProtocolDisconnected {
3669 peer_id,
3670 chain_id,
3671 }) => {
3672 log!(
3673 &task.platform,
3674 Debug,
3675 "network",
3676 "statement-protocol-closed",
3677 chain = &task.network[chain_id].log_name,
3678 peer_id,
3679 );
3680
3681 task.network.gossip_remove_desired(
3684 chain_id,
3685 &peer_id,
3686 service::GossipKind::Statement,
3687 );
3688
3689 if let Some(peers) = task.v2_statement_peers.get_mut(&chain_id) {
3690 peers.remove(&peer_id);
3691 }
3692 }
3693 WakeUpReason::NetworkEvent(service::Event::StatementTopicAffinityReceived {
3695 ..
3696 }) => {}
3697 WakeUpReason::NetworkEvent(service::Event::ProtocolError { peer_id, error }) => {
3698 log!(
3700 &task.platform,
3701 Warn,
3702 "network",
3703 "protocol-error",
3704 peer_id,
3705 ?error
3706 );
3707
3708 }
3710 WakeUpReason::CanAssignSlot(peer_id, chain_id) => {
3711 task.peering_strategy.assign_slot(&chain_id, &peer_id);
3712
3713 log!(
3714 &task.platform,
3715 Debug,
3716 "network",
3717 "slot-assigned",
3718 chain = &task.network[chain_id].log_name,
3719 peer_id
3720 );
3721
3722 task.network.gossip_insert_desired(
3723 chain_id,
3724 peer_id,
3725 service::GossipKind::ConsensusTransactions,
3726 );
3727 }
3728 WakeUpReason::CanAssignBitswapSlot(peer_id) => {
3729 task.bitswap_peering_strategy.assign_slot(&peer_id).unwrap();
3730
3731 log!(
3732 &task.platform,
3733 Debug,
3734 "network",
3735 "bitswap-slot-assigned",
3736 peer_id
3737 );
3738
3739 task.network.bitswap_insert_desired(peer_id);
3740 }
3741 WakeUpReason::NextRecentConnectionRestore => {
3742 task.num_recent_connection_opening =
3743 task.num_recent_connection_opening.saturating_sub(1);
3744 }
3745 WakeUpReason::CanStartConnect(expected_peer_id) => {
3746 let Some(multiaddr) = task
3747 .peering_strategy
3748 .pick_address_and_add_connection(&expected_peer_id)
3749 else {
3750 task.network.gossip_remove_desired_all(
3752 &expected_peer_id,
3753 service::GossipKind::ConsensusTransactions,
3754 );
3755 task.network.gossip_remove_desired_all(
3756 &expected_peer_id,
3757 service::GossipKind::Statement,
3758 );
3759 let ban_duration = Duration::from_secs(10);
3760 for (&chain_id, what_happened) in task.peering_strategy.unassign_slots_and_ban(
3761 &expected_peer_id,
3762 task.platform.now() + ban_duration,
3763 ) {
3764 if matches!(
3765 what_happened,
3766 basic_peering_strategy::UnassignSlotsAndBan::Banned { had_slot: true }
3767 ) {
3768 log!(
3769 &task.platform,
3770 Debug,
3771 "network",
3772 "slot-unassigned",
3773 chain = &task.network[chain_id].log_name,
3774 peer_id = expected_peer_id,
3775 ?ban_duration,
3776 reason = "no-address"
3777 );
3778 }
3779 }
3780 continue;
3781 };
3782
3783 let multiaddr = match multiaddr::Multiaddr::from_bytes(multiaddr.to_owned()) {
3784 Ok(a) => a,
3785 Err((multiaddr::FromBytesError, addr)) => {
3786 let _was_in = task
3788 .peering_strategy
3789 .decrease_address_connections_and_remove_if_zero(
3790 &expected_peer_id,
3791 &addr,
3792 );
3793 debug_assert!(_was_in.is_ok());
3794 continue;
3795 }
3796 };
3797
3798 let address = address_parse::multiaddr_to_address(&multiaddr)
3799 .ok()
3800 .filter(|addr| {
3801 task.platform.supports_connection_type(match &addr {
3802 address_parse::AddressOrMultiStreamAddress::Address(addr) => {
3803 From::from(addr)
3804 }
3805 address_parse::AddressOrMultiStreamAddress::MultiStreamAddress(
3806 addr,
3807 ) => From::from(addr),
3808 })
3809 });
3810
3811 let Some(address) = address else {
3812 let _was_in = task
3814 .peering_strategy
3815 .decrease_address_connections_and_remove_if_zero(
3816 &expected_peer_id,
3817 multiaddr.as_ref(),
3818 );
3819 debug_assert!(_was_in.is_ok());
3820 continue;
3821 };
3822
3823 let noise_key = {
3825 let mut noise_static_key = zeroize::Zeroizing::new([0u8; 32]);
3826 task.platform.fill_random_bytes(&mut *noise_static_key);
3827 let mut libp2p_key = zeroize::Zeroizing::new([0u8; 32]);
3828 task.platform.fill_random_bytes(&mut *libp2p_key);
3829 connection::NoiseKey::new(&libp2p_key, &noise_static_key)
3830 };
3831
3832 log!(
3833 &task.platform,
3834 Debug,
3835 "network",
3836 "connection-started",
3837 expected_peer_id,
3838 remote_addr = multiaddr,
3839 local_peer_id =
3840 peer_id::PublicKey::Ed25519(*noise_key.libp2p_public_ed25519_key())
3841 .into_peer_id(),
3842 );
3843
3844 task.num_recent_connection_opening += 1;
3845 task.metrics.connections_dialed.inc();
3846
3847 let (coordinator_to_connection_tx, coordinator_to_connection_rx) =
3848 async_channel::bounded(8);
3849 let task_name = format!("connection-{}", multiaddr);
3850
3851 match address {
3852 address_parse::AddressOrMultiStreamAddress::Address(address) => {
3853 let connection = task.platform.connect_stream(address).await;
3856
3857 let (connection_id, connection_task) =
3858 task.network.add_single_stream_connection(
3859 task.platform.now(),
3860 service::SingleStreamHandshakeKind::MultistreamSelectNoiseYamux {
3861 is_initiator: true,
3862 noise_key: &noise_key,
3863 },
3864 multiaddr.clone().into_bytes(),
3865 Some(expected_peer_id.clone()),
3866 coordinator_to_connection_tx,
3867 );
3868
3869 task.platform.spawn_task(
3870 task_name.into(),
3871 tasks::single_stream_connection_task::<TPlat>(
3872 connection,
3873 multiaddr.to_string(),
3874 task.platform.clone(),
3875 connection_id,
3876 connection_task,
3877 coordinator_to_connection_rx,
3878 task.tasks_messages_tx.clone(),
3879 ),
3880 );
3881 }
3882 address_parse::AddressOrMultiStreamAddress::MultiStreamAddress(address) => {
3883 let remote_certificate_sha256 = match &address {
3884 platform::MultiStreamAddress::WebRtc {
3885 remote_certificate_sha256,
3886 ..
3887 }
3888 | platform::MultiStreamAddress::WebRtcDns {
3889 remote_certificate_sha256,
3890 ..
3891 } => *remote_certificate_sha256,
3892 };
3893
3894 let connection = task.platform.connect_multistream(address).await;
3899
3900 let local_tls_certificate_multihash = [18u8, 32]
3902 .into_iter()
3903 .chain(connection.local_tls_certificate_sha256.into_iter())
3904 .collect();
3905 let remote_tls_certificate_multihash = [18u8, 32]
3906 .into_iter()
3907 .chain(remote_certificate_sha256.iter().copied())
3908 .collect();
3909
3910 let (connection_id, connection_task) =
3911 task.network.add_multi_stream_connection(
3912 task.platform.now(),
3913 service::MultiStreamHandshakeKind::WebRtc {
3914 is_initiator: true,
3915 local_tls_certificate_multihash,
3916 remote_tls_certificate_multihash,
3917 noise_key: &noise_key,
3918 },
3919 multiaddr.clone().into_bytes(),
3920 Some(expected_peer_id.clone()),
3921 coordinator_to_connection_tx,
3922 );
3923
3924 task.platform.spawn_task(
3925 task_name.into(),
3926 tasks::webrtc_multi_stream_connection_task::<TPlat>(
3927 connection.connection,
3928 multiaddr.to_string(),
3929 task.platform.clone(),
3930 connection_id,
3931 connection_task,
3932 coordinator_to_connection_rx,
3933 task.tasks_messages_tx.clone(),
3934 ),
3935 );
3936 }
3937 }
3938 }
3939 WakeUpReason::CanOpenGossip(peer_id, chain_id, kind) => {
3940 task.network.gossip_open(chain_id, &peer_id, kind).unwrap();
3941
3942 log!(
3943 &task.platform,
3944 Debug,
3945 "network",
3946 "gossip-open-start",
3947 chain = &task.network[chain_id].log_name,
3948 peer_id,
3949 ?kind,
3950 );
3951 }
3952 WakeUpReason::CanOpenBitswap(peer_id) => {
3953 task.network.bitswap_open(&peer_id).unwrap();
3954
3955 log!(
3956 &task.platform,
3957 Debug,
3958 "network",
3959 "bitswap-open-start",
3960 peer_id
3961 );
3962 }
3963 WakeUpReason::MessageToConnection {
3964 connection_id,
3965 message,
3966 } => {
3967 let _send_result = task.network[connection_id].send(message).await;
3975 debug_assert!(_send_result.is_ok());
3976 }
3977 }
3978 }
3979}
3980
3981fn dispatch_find_node_requests<TChain, TConn, TNow>(
3988 network: &mut service::ChainNetwork<TChain, TConn, TNow>,
3989 randomness: &mut impl rand_chacha::rand_core::RngCore,
3990 chain_id: service::ChainId,
3991 candidates: &[PeerId],
3992 max: usize,
3993) -> Vec<(PeerId, PeerId)>
3994where
3995 TNow: Clone
3996 + core::ops::Add<Duration, Output = TNow>
3997 + core::ops::Sub<TNow, Output = Duration>
3998 + Ord,
3999{
4000 let mut started = Vec::with_capacity(max);
4001
4002 for target in candidates {
4003 if started.len() >= max {
4004 break;
4005 }
4006
4007 let random_peer_id = {
4008 let mut pub_key = [0; 32];
4009 randomness.fill_bytes(&mut pub_key);
4010 PeerId::from_public_key(&peer_id::PublicKey::Ed25519(pub_key))
4011 };
4012
4013 match network.start_kademlia_find_node_request(
4014 target,
4015 chain_id,
4016 &random_peer_id,
4017 Duration::from_secs(20),
4018 ) {
4019 Ok(_) => started.push((target.clone(), random_peer_id)),
4020 Err(service::StartRequestError::NoConnection) => {}
4021 }
4022 }
4023
4024 started
4025}
4026
4027fn pop_p2p_if_matches(
4030 addr: &mut smoldot::libp2p::multiaddr::Multiaddr,
4031 expected_peer: &smoldot::libp2p::peer_id::PeerId,
4032) -> bool {
4033 use smoldot::libp2p::multiaddr::Protocol;
4034 match addr.iter().last() {
4035 Some(Protocol::P2p(mh)) => {
4036 if mh.into_bytes() == expected_peer.as_bytes() {
4037 addr.pop();
4038 true
4039 } else {
4040 false
4041 }
4042 }
4043 _ => true,
4044 }
4045}
4046
4047#[cfg(test)]
4048mod tests {
4049 use super::{Role, dispatch_find_node_requests, pop_p2p_if_matches, service};
4050 use core::time::Duration;
4051 use rand_chacha::rand_core::SeedableRng as _;
4052 use smoldot::libp2p::{multiaddr::Multiaddr, peer_id::PeerId};
4053
4054 const PEER_A: &str = "12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN";
4058 const PEER_B: &str = "12D3KooWQk1yQtG1YugyKjiQf6KNk8VjGGAT5xy1FWcnRKN4yXYJ";
4059
4060 fn peer(s: &str) -> PeerId {
4061 PeerId::from_bytes(bs58::decode(s).into_vec().unwrap()).unwrap()
4062 }
4063
4064 #[test]
4065 fn no_suffix_passes_through_unchanged() {
4066 let mut addr: Multiaddr = "/ip4/127.0.0.1/tcp/30333/ws".parse().unwrap();
4067 let before = addr.clone();
4068 assert!(pop_p2p_if_matches(&mut addr, &peer(PEER_A)));
4069 assert_eq!(addr, before);
4070 }
4071
4072 #[test]
4073 fn matching_suffix_is_stripped() {
4074 let mut addr: Multiaddr = format!("/ip4/127.0.0.1/tcp/30333/ws/p2p/{PEER_A}")
4075 .parse()
4076 .unwrap();
4077 assert!(pop_p2p_if_matches(&mut addr, &peer(PEER_A)));
4078 let expected: Multiaddr = "/ip4/127.0.0.1/tcp/30333/ws".parse().unwrap();
4079 assert_eq!(addr, expected);
4080 }
4081
4082 #[test]
4083 fn mismatched_suffix_rejects_and_keeps_addr() {
4084 let original: Multiaddr = format!("/ip4/127.0.0.1/tcp/30333/ws/p2p/{PEER_A}")
4085 .parse()
4086 .unwrap();
4087 let mut addr = original.clone();
4088 assert!(!pop_p2p_if_matches(&mut addr, &peer(PEER_B)));
4089 assert_eq!(addr, original);
4090 }
4091
4092 fn empty_network() -> (service::ChainNetwork<(), (), Duration>, service::ChainId) {
4093 let mut network = service::ChainNetwork::new(service::Config {
4094 connections_capacity: 8,
4095 chains_capacity: 1,
4096 randomness_seed: [0; 32],
4097 handshake_timeout: Duration::from_secs(10),
4098 });
4099 let chain_id = network
4100 .add_chain(service::ChainConfig {
4101 user_data: (),
4102 genesis_hash: [0; 32],
4103 fork_id: None,
4104 block_number_bytes: 4,
4105 grandpa_protocol_config: None,
4106 allow_inbound_block_requests: false,
4107 best_hash: [0; 32],
4108 best_number: 0,
4109 role: Role::Light,
4110 enable_statement_protocol: false,
4111 })
4112 .unwrap();
4113 (network, chain_id)
4114 }
4115
4116 #[test]
4119 fn dispatch_skips_unreachable_candidates() {
4120 let (mut network, chain_id) = empty_network();
4121 let mut randomness = rand_chacha::ChaCha20Rng::from_seed([7; 32]);
4122
4123 let candidates = [peer(PEER_A), peer(PEER_B)];
4124 let started =
4125 dispatch_find_node_requests(&mut network, &mut randomness, chain_id, &candidates, 3);
4126
4127 assert!(started.is_empty());
4128 }
4129}