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