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