1pub use crate::{
25 discovery::DEFAULT_KADEMLIA_REPLICATION_FACTOR,
26 peer_store::PeerStoreProvider,
27 protocol::{notification_service, NotificationsSink, ProtocolHandlePair},
28 request_responses::{
29 IncomingRequest, OutgoingResponse, ProtocolConfig as RequestResponseConfig,
30 },
31 service::{
32 metrics::NotificationMetrics,
33 traits::{NotificationConfig, NotificationService, PeerStore},
34 },
35 types::ProtocolName,
36};
37
38pub use litep2p::protocol::libp2p::bitswap::BitswapHandle as Litep2pBitswapHandle;
39pub use sc_network_types::{build_multiaddr, ed25519};
40use sc_network_types::{
41 multiaddr::{self, Multiaddr},
42 multihash::Multihash,
43 PeerId,
44};
45
46use crate::{
47 service::{ensure_addresses_consistent_with_transport, traits::NetworkBackend},
48 webrtc,
49};
50use codec::Encode;
51use prometheus_endpoint::Registry;
52use zeroize::Zeroize;
53
54pub use sc_network_common::{
55 role::{Role, Roles},
56 sync::SyncMode,
57 ExHashT,
58};
59
60use sp_runtime::traits::Block as BlockT;
61
62use std::{
63 error::Error,
64 fmt, fs,
65 future::Future,
66 io::{self, Write},
67 iter,
68 net::Ipv4Addr,
69 num::NonZeroUsize,
70 path::{Path, PathBuf},
71 pin::Pin,
72 str::{self, FromStr},
73 sync::Arc,
74 time::Duration,
75};
76
77pub const DEFAULT_IDLE_CONNECTION_TIMEOUT: Duration = Duration::from_secs(10);
81
82pub const KADEMLIA_MAX_PROVIDER_KEYS: usize = 10000;
86
87pub const KADEMLIA_PROVIDER_RECORD_TTL: Duration = Duration::from_secs(10 * 3600);
91
92pub const KADEMLIA_PROVIDER_REPUBLISH_INTERVAL: Duration = Duration::from_secs(12600);
96
97pub const DEFAULT_LIGHT_REQUEST_EXECUTION_TIMEOUT: Duration = Duration::from_secs(3);
99
100#[derive(Clone, PartialEq, Eq, Hash)]
104pub struct ProtocolId(smallvec::SmallVec<[u8; 6]>);
105
106impl<'a> From<&'a str> for ProtocolId {
107 fn from(bytes: &'a str) -> ProtocolId {
108 Self(bytes.as_bytes().into())
109 }
110}
111
112impl AsRef<str> for ProtocolId {
113 fn as_ref(&self) -> &str {
114 str::from_utf8(&self.0[..])
115 .expect("the only way to build a ProtocolId is through a UTF-8 String; qed")
116 }
117}
118
119impl fmt::Debug for ProtocolId {
120 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
121 fmt::Debug::fmt(self.as_ref(), f)
122 }
123}
124
125pub fn parse_str_addr(addr_str: &str) -> Result<(PeerId, Multiaddr), ParseErr> {
140 let addr: Multiaddr = addr_str.parse()?;
141 parse_addr(addr)
142}
143
144pub fn parse_addr(mut addr: Multiaddr) -> Result<(PeerId, Multiaddr), ParseErr> {
146 let multihash = match addr.pop() {
147 Some(multiaddr::Protocol::P2p(multihash)) => multihash,
148 _ => return Err(ParseErr::PeerIdMissing),
149 };
150 let peer_id = PeerId::from_multihash(multihash).map_err(|_| ParseErr::InvalidPeerId)?;
151
152 Ok((peer_id, addr))
153}
154
155fn configured_identity(address: &Multiaddr) -> Option<multiaddr::Protocol<'_>> {
157 address.iter().find(|protocol| {
158 matches!(protocol, multiaddr::Protocol::P2p(_) | multiaddr::Protocol::Certhash(_))
159 })
160}
161
162fn check_and_strip_identity(
170 address: &mut Multiaddr,
171 local_peer_id: PeerId,
172 certhash: Option<Multihash>,
173 node_key_origin: &str,
174) -> Result<(), crate::error::Error> {
175 let configured_address = address.clone();
176
177 let configured_peer_id = match address.iter().last() {
179 Some(multiaddr::Protocol::P2p(peer_id)) => {
180 address.pop();
181 Some(peer_id)
182 },
183 _ => None,
185 };
186
187 let configured_certhash = match address.iter().last() {
188 Some(multiaddr::Protocol::Certhash(hash)) => {
189 address.pop();
190 Some(hash)
191 },
192 _ => None,
193 };
194
195 if let Some(identity) = configured_identity(address) {
197 return Err(crate::error::Error::MalformedAddressIdentity {
198 component: identity.to_string(),
199 address: configured_address,
200 });
201 }
202
203 if address.iter().next().is_none() {
205 if let Some(identity) = configured_identity(&configured_address) {
206 return Err(crate::error::Error::MalformedAddressIdentity {
207 component: identity.to_string(),
208 address: configured_address,
209 });
210 }
211 }
212
213 if let Some(configured) = configured_certhash {
215 let expected =
216 certhash.filter(|_| webrtc::is_webrtc_address(address)).ok_or_else(|| {
217 crate::error::Error::InvalidWebRtcAddress { address: configured_address.clone() }
218 })?;
219
220 if configured != expected {
221 return Err(crate::error::Error::MismatchedAddressIdentity {
222 address: configured_address,
223 configured: multiaddr::Protocol::Certhash(configured).to_string(),
224 expected: multiaddr::Protocol::Certhash(expected).to_string(),
225 node_key_origin: node_key_origin.to_string(),
226 });
227 }
228 }
229
230 if let Some(configured) = configured_peer_id {
231 let expected = local_peer_id.into();
232 if configured != expected {
233 return Err(crate::error::Error::MismatchedAddressIdentity {
234 address: configured_address,
235 configured: multiaddr::Protocol::P2p(configured).to_string(),
236 expected: multiaddr::Protocol::P2p(expected).to_string(),
237 node_key_origin: node_key_origin.to_string(),
238 });
239 }
240 }
241
242 Ok(())
243}
244
245#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
260#[serde(try_from = "String", into = "String")]
261pub struct MultiaddrWithPeerId {
262 pub multiaddr: Multiaddr,
264 pub peer_id: PeerId,
266}
267
268impl MultiaddrWithPeerId {
269 pub fn concat(&self) -> Multiaddr {
271 let mut addr = self.multiaddr.clone();
272 if matches!(addr.iter().last(), Some(multiaddr::Protocol::P2p(_))) {
274 addr.pop();
275 }
276 addr.with(multiaddr::Protocol::P2p(From::from(self.peer_id)))
277 }
278}
279
280impl fmt::Display for MultiaddrWithPeerId {
281 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
282 fmt::Display::fmt(&self.concat(), f)
283 }
284}
285
286impl FromStr for MultiaddrWithPeerId {
287 type Err = ParseErr;
288
289 fn from_str(s: &str) -> Result<Self, Self::Err> {
290 let (peer_id, multiaddr) = parse_str_addr(s)?;
291 Ok(Self { peer_id, multiaddr })
292 }
293}
294
295impl From<MultiaddrWithPeerId> for String {
296 fn from(ma: MultiaddrWithPeerId) -> String {
297 format!("{}", ma)
298 }
299}
300
301impl TryFrom<String> for MultiaddrWithPeerId {
302 type Error = ParseErr;
303 fn try_from(string: String) -> Result<Self, Self::Error> {
304 string.parse()
305 }
306}
307
308#[derive(Debug)]
310pub enum ParseErr {
311 MultiaddrParse(multiaddr::ParseError),
313 InvalidPeerId,
315 PeerIdMissing,
317}
318
319impl fmt::Display for ParseErr {
320 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
321 match self {
322 Self::MultiaddrParse(err) => write!(f, "{}", err),
323 Self::InvalidPeerId => write!(f, "Peer id at the end of the address is invalid"),
324 Self::PeerIdMissing => write!(f, "Peer id is missing from the address"),
325 }
326 }
327}
328
329impl std::error::Error for ParseErr {
330 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
331 match self {
332 Self::MultiaddrParse(err) => Some(err),
333 Self::InvalidPeerId => None,
334 Self::PeerIdMissing => None,
335 }
336 }
337}
338
339impl From<multiaddr::ParseError> for ParseErr {
340 fn from(err: multiaddr::ParseError) -> ParseErr {
341 Self::MultiaddrParse(err)
342 }
343}
344
345#[derive(Debug, Clone)]
347pub struct NotificationHandshake(Vec<u8>);
348
349impl NotificationHandshake {
350 pub fn new<H: Encode>(handshake: H) -> Self {
352 Self(handshake.encode())
353 }
354
355 pub fn from_bytes(bytes: Vec<u8>) -> Self {
357 Self(bytes)
358 }
359}
360
361impl std::ops::Deref for NotificationHandshake {
362 type Target = Vec<u8>;
363
364 fn deref(&self) -> &Self::Target {
365 &self.0
366 }
367}
368
369#[derive(Clone, Debug)]
371pub enum TransportConfig {
372 Normal {
374 enable_mdns: bool,
377
378 allow_private_ip: bool,
382 },
383
384 MemoryOnly,
387}
388
389#[derive(Clone, Debug, PartialEq, Eq)]
391pub enum NonReservedPeerMode {
392 Accept,
394 Deny,
396}
397
398impl NonReservedPeerMode {
399 pub fn parse(s: &str) -> Option<Self> {
401 match s {
402 "accept" => Some(Self::Accept),
403 "deny" => Some(Self::Deny),
404 _ => None,
405 }
406 }
407
408 pub fn is_reserved_only(&self) -> bool {
410 matches!(self, NonReservedPeerMode::Deny)
411 }
412}
413
414#[derive(Clone, Debug)]
418pub enum NodeKeyConfig {
419 Ed25519(Secret<ed25519::SecretKey>),
421}
422
423impl Default for NodeKeyConfig {
424 fn default() -> NodeKeyConfig {
425 Self::Ed25519(Secret::New)
426 }
427}
428
429pub type Ed25519Secret = Secret<ed25519::SecretKey>;
431
432#[derive(Clone)]
434pub enum Secret<K> {
435 Input(K),
437 File(PathBuf),
443 New,
445}
446
447impl<K> fmt::Debug for Secret<K> {
448 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
449 match self {
450 Self::Input(_) => f.debug_tuple("Secret::Input").finish(),
451 Self::File(path) => f.debug_tuple("Secret::File").field(path).finish(),
452 Self::New => f.debug_tuple("Secret::New").finish(),
453 }
454 }
455}
456
457impl NodeKeyConfig {
458 fn source(&self) -> String {
460 match self {
461 Self::Ed25519(Secret::Input(_)) => "the node key given with `--node-key`".into(),
462 Self::Ed25519(Secret::File(path)) => format!("the node key file `{}`", path.display()),
463 Self::Ed25519(Secret::New) => "the node key generated anew on each start".into(),
464 }
465 }
466
467 fn missing(&self) -> bool {
469 match self {
470 Self::Ed25519(Secret::Input(_)) => false,
471 Self::Ed25519(Secret::File(path)) => !path.exists(),
472 Self::Ed25519(Secret::New) => true,
473 }
474 }
475
476 pub fn into_keypair(self) -> io::Result<ed25519::Keypair> {
487 use NodeKeyConfig::*;
488 match self {
489 Ed25519(Secret::New) => Ok(ed25519::Keypair::generate()),
490
491 Ed25519(Secret::Input(k)) => Ok(ed25519::Keypair::from(k).into()),
492
493 Ed25519(Secret::File(f)) => get_secret(
494 f,
495 |mut b| match String::from_utf8(b.to_vec()).ok().and_then(|s| {
496 if s.len() == 64 {
497 array_bytes::hex2bytes(&s).ok()
498 } else {
499 None
500 }
501 }) {
502 Some(s) => ed25519::SecretKey::try_from_bytes(s),
503 _ => ed25519::SecretKey::try_from_bytes(&mut b),
504 },
505 ed25519::SecretKey::generate,
506 |b| b.as_ref().to_vec(),
507 )
508 .map(ed25519::Keypair::from),
509 }
510 }
511}
512
513fn get_secret<P, F, G, E, W, K>(file: P, parse: F, generate: G, serialize: W) -> io::Result<K>
517where
518 P: AsRef<Path>,
519 F: for<'r> FnOnce(&'r mut [u8]) -> Result<K, E>,
520 G: FnOnce() -> K,
521 E: Error + Send + Sync + 'static,
522 W: Fn(&K) -> Vec<u8>,
523{
524 std::fs::read(&file)
525 .and_then(|mut sk_bytes| {
526 parse(&mut sk_bytes).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
527 })
528 .or_else(|e| {
529 if e.kind() == io::ErrorKind::NotFound {
530 file.as_ref().parent().map_or(Ok(()), fs::create_dir_all)?;
531 let sk = generate();
532 let mut sk_vec = serialize(&sk);
533 write_secret_file(file, &sk_vec)?;
534 sk_vec.zeroize();
535 Ok(sk)
536 } else {
537 Err(e)
538 }
539 })
540}
541
542pub(super) fn write_secret_file<P>(path: P, sk_bytes: &[u8]) -> io::Result<()>
544where
545 P: AsRef<Path>,
546{
547 let mut file = open_secret_file(&path)?;
548 file.write_all(sk_bytes)
549}
550
551#[cfg(unix)]
553fn open_secret_file<P>(path: P) -> io::Result<fs::File>
554where
555 P: AsRef<Path>,
556{
557 use std::os::unix::fs::OpenOptionsExt;
558 fs::OpenOptions::new().write(true).create_new(true).mode(0o600).open(path)
559}
560
561#[cfg(not(unix))]
563fn open_secret_file<P>(path: P) -> Result<fs::File, io::Error>
564where
565 P: AsRef<Path>,
566{
567 fs::OpenOptions::new().write(true).create_new(true).open(path)
568}
569
570#[derive(Clone, Debug)]
572pub struct SetConfig {
573 pub in_peers: u32,
575
576 pub out_peers: u32,
578
579 pub reserved_nodes: Vec<MultiaddrWithPeerId>,
581
582 pub non_reserved_mode: NonReservedPeerMode,
585}
586
587impl Default for SetConfig {
588 fn default() -> Self {
589 Self {
590 in_peers: 25,
591 out_peers: 75,
592 reserved_nodes: Vec::new(),
593 non_reserved_mode: NonReservedPeerMode::Accept,
594 }
595 }
596}
597
598#[derive(Debug)]
603pub struct NonDefaultSetConfig {
604 protocol_name: ProtocolName,
610
611 fallback_names: Vec<ProtocolName>,
618
619 handshake: Option<NotificationHandshake>,
625
626 max_notification_size: u64,
628
629 set_config: SetConfig,
631
632 protocol_handle_pair: ProtocolHandlePair,
640}
641
642impl NonDefaultSetConfig {
643 pub fn new(
646 protocol_name: ProtocolName,
647 fallback_names: Vec<ProtocolName>,
648 max_notification_size: u64,
649 handshake: Option<NotificationHandshake>,
650 set_config: SetConfig,
651 ) -> (Self, Box<dyn NotificationService>) {
652 let (protocol_handle_pair, notification_service) =
653 notification_service(protocol_name.clone());
654 (
655 Self {
656 protocol_name,
657 max_notification_size,
658 fallback_names,
659 handshake,
660 set_config,
661 protocol_handle_pair,
662 },
663 notification_service,
664 )
665 }
666
667 pub fn protocol_name(&self) -> &ProtocolName {
669 &self.protocol_name
670 }
671
672 pub fn fallback_names(&self) -> impl Iterator<Item = &ProtocolName> {
674 self.fallback_names.iter()
675 }
676
677 pub fn handshake(&self) -> &Option<NotificationHandshake> {
679 &self.handshake
680 }
681
682 pub fn max_notification_size(&self) -> u64 {
684 self.max_notification_size
685 }
686
687 pub fn set_config(&self) -> &SetConfig {
689 &self.set_config
690 }
691
692 pub fn take_protocol_handle(self) -> ProtocolHandlePair {
694 self.protocol_handle_pair
695 }
696
697 pub fn allow_non_reserved(&mut self, in_peers: u32, out_peers: u32) {
699 self.set_config.in_peers = in_peers;
700 self.set_config.out_peers = out_peers;
701 self.set_config.non_reserved_mode = NonReservedPeerMode::Accept;
702 }
703
704 pub fn add_reserved(&mut self, peer: MultiaddrWithPeerId) {
706 self.set_config.reserved_nodes.push(peer);
707 }
708
709 pub fn add_fallback_names(&mut self, fallback_names: Vec<ProtocolName>) {
713 self.fallback_names.extend(fallback_names);
714 }
715}
716
717impl NotificationConfig for NonDefaultSetConfig {
718 fn set_config(&self) -> &SetConfig {
719 &self.set_config
720 }
721
722 fn protocol_name(&self) -> &ProtocolName {
724 &self.protocol_name
725 }
726}
727
728#[derive(Clone, Debug)]
730pub struct NetworkConfiguration {
731 pub net_config_path: Option<PathBuf>,
733
734 pub listen_addresses: Vec<Multiaddr>,
736
737 pub public_addresses: Vec<Multiaddr>,
739
740 pub boot_nodes: Vec<MultiaddrWithPeerId>,
742
743 pub node_key: NodeKeyConfig,
745
746 pub default_peers_set: SetConfig,
748
749 pub default_peers_set_num_full: u32,
754
755 pub client_version: String,
757
758 pub node_name: String,
760
761 pub transport: TransportConfig,
763
764 pub idle_connection_timeout: Duration,
768
769 pub max_parallel_downloads: u32,
771
772 pub max_blocks_per_request: u32,
774
775 pub min_peers_to_start_warp_sync: Option<usize>,
777
778 pub sync_mode: SyncMode,
780
781 pub enable_dht_random_walk: bool,
785
786 pub allow_non_globals_in_dht: bool,
788
789 pub kademlia_disjoint_query_paths: bool,
792
793 pub kademlia_replication_factor: NonZeroUsize,
798
799 pub ipfs_server: bool,
801
802 pub ipfs_bootnodes: Vec<MultiaddrWithPeerId>,
808
809 pub light_request_execution_timeout: Option<Duration>,
812
813 pub network_backend: NetworkBackendType,
815}
816
817impl NetworkConfiguration {
818 pub fn new<SN: Into<String>, SV: Into<String>>(
820 node_name: SN,
821 client_version: SV,
822 node_key: NodeKeyConfig,
823 net_config_path: Option<PathBuf>,
824 ) -> Self {
825 let default_peers_set = SetConfig::default();
826 Self {
827 net_config_path,
828 listen_addresses: Vec::new(),
829 public_addresses: Vec::new(),
830 boot_nodes: Vec::new(),
831 node_key,
832 default_peers_set_num_full: default_peers_set.in_peers + default_peers_set.out_peers,
833 default_peers_set,
834 client_version: client_version.into(),
835 node_name: node_name.into(),
836 transport: TransportConfig::Normal { enable_mdns: false, allow_private_ip: true },
837 idle_connection_timeout: DEFAULT_IDLE_CONNECTION_TIMEOUT,
838 max_parallel_downloads: 5,
839 max_blocks_per_request: 64,
840 min_peers_to_start_warp_sync: None,
841 sync_mode: SyncMode::Full,
842 enable_dht_random_walk: true,
843 allow_non_globals_in_dht: false,
844 kademlia_disjoint_query_paths: false,
845 kademlia_replication_factor: NonZeroUsize::new(DEFAULT_KADEMLIA_REPLICATION_FACTOR)
846 .expect("value is a constant; constant is non-zero; qed."),
847 ipfs_server: false,
848 ipfs_bootnodes: Vec::new(),
849 light_request_execution_timeout: Some(DEFAULT_LIGHT_REQUEST_EXECUTION_TIMEOUT),
850 network_backend: NetworkBackendType::Litep2p,
851 }
852 }
853
854 pub fn new_local() -> NetworkConfiguration {
857 let mut config =
858 NetworkConfiguration::new("test-node", "test-client", Default::default(), None);
859
860 config.listen_addresses =
861 vec![iter::once(multiaddr::Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1)))
862 .chain(iter::once(multiaddr::Protocol::Tcp(0)))
863 .collect()];
864
865 config.allow_non_globals_in_dht = true;
866 config
867 }
868
869 pub fn new_memory() -> NetworkConfiguration {
872 let mut config =
873 NetworkConfiguration::new("test-node", "test-client", Default::default(), None);
874
875 config.listen_addresses =
876 vec![iter::once(multiaddr::Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1)))
877 .chain(iter::once(multiaddr::Protocol::Tcp(0)))
878 .collect()];
879
880 config.allow_non_globals_in_dht = true;
881 config
882 }
883
884 pub fn validate_and_complete_addresses(&mut self) -> Result<(), crate::error::Error> {
890 let listen_webrtc = self.listen_addresses.iter().any(webrtc::is_webrtc_address);
891 let public_webrtc = self.public_addresses.iter().any(webrtc::is_webrtc_address);
892 let addresses = || self.listen_addresses.iter().chain(&self.public_addresses);
893
894 if matches!(self.network_backend, NetworkBackendType::Libp2p) &&
896 (listen_webrtc || public_webrtc)
897 {
898 return Err(crate::error::Error::WebRtcNotSupportedByBackend);
899 }
900
901 if !listen_webrtc && public_webrtc {
904 return Err(crate::error::Error::WebRtcTransportNotConfigured);
905 }
906
907 let has_identity = addresses().any(|address| configured_identity(address).is_some());
908
909 if !listen_webrtc && !has_identity {
912 return Ok(());
913 }
914
915 if has_identity && self.node_key.missing() {
917 return Err(crate::error::Error::AddressIdentityWithoutNodeKey);
918 }
919
920 let node_key_origin = self.node_key.source();
922 let keypair = self.node_key.clone().into_keypair()?;
923 let local_peer_id = keypair.public().to_peer_id();
924
925 let certhash = listen_webrtc
926 .then(|| webrtc::derive_certificate(keypair.secret().into()))
927 .transpose()
928 .map_err(crate::error::Error::Litep2p)?
929 .map(|certificate| certificate.certhash().into());
930
931 self.node_key = NodeKeyConfig::Ed25519(Secret::Input(keypair.secret()));
934
935 for address in self.listen_addresses.iter_mut() {
936 check_and_strip_identity(address, local_peer_id, certhash, &node_key_origin)?;
937 }
938
939 for address in self.public_addresses.iter_mut() {
941 check_and_strip_identity(address, local_peer_id, certhash, &node_key_origin)?;
942 }
943
944 if let Some(certhash) = certhash {
947 webrtc::validate_and_complete_addresses(
948 &self.listen_addresses,
949 &mut self.public_addresses,
950 certhash,
951 )?;
952 }
953
954 Ok(())
955 }
956
957 pub fn remove_webrtc_addresses(&mut self) {
963 self.listen_addresses.retain(|address| !webrtc::is_webrtc_address(address));
964 self.public_addresses.retain(|address| {
965 let keep = !webrtc::is_webrtc_address(address);
966 if !keep {
967 log::warn!(
968 target: crate::LOG_TARGET,
969 "removing public WebRTC address {address}: no WebRTC listener on this node",
970 );
971 }
972 keep
973 });
974 }
975}
976
977pub struct IpfsConfig {
979 pub litep2p_bitswap_config: litep2p::protocol::libp2p::bitswap::Config,
981 pub block_provider: Box<dyn crate::IpfsBlockProvider>,
983 pub bootnodes: Vec<MultiaddrWithPeerId>,
985}
986
987impl IpfsConfig {
988 pub fn new(
990 block_provider: Box<dyn crate::IpfsBlockProvider>,
991 bootnodes: Vec<MultiaddrWithPeerId>,
992 ) -> (Self, Litep2pBitswapHandle) {
993 let (litep2p_bitswap_config, litep2p_handle) =
994 litep2p::protocol::libp2p::bitswap::Config::new();
995 (Self { litep2p_bitswap_config, block_provider, bootnodes }, litep2p_handle)
996 }
997}
998
999pub struct Params<Block: BlockT, H: ExHashT, N: NetworkBackend<Block, H>> {
1001 pub role: Role,
1003
1004 pub executor: Box<dyn Fn(Pin<Box<dyn Future<Output = ()> + Send>>) + Send + Sync>,
1006
1007 pub network_config: FullNetworkConfiguration<Block, H, N>,
1009
1010 pub protocol_id: ProtocolId,
1012
1013 pub genesis_hash: Block::Hash,
1015
1016 pub fork_id: Option<String>,
1019
1020 pub metrics_registry: Option<Registry>,
1022
1023 pub block_announce_config: N::NotificationProtocolConfig,
1025
1026 pub ipfs_config: Option<IpfsConfig>,
1028
1029 pub notification_metrics: NotificationMetrics,
1031}
1032
1033pub struct FullNetworkConfiguration<B: BlockT + 'static, H: ExHashT, N: NetworkBackend<B, H>> {
1035 pub(crate) notification_protocols: Vec<N::NotificationProtocolConfig>,
1037
1038 pub(crate) request_response_protocols: Vec<N::RequestResponseProtocolConfig>,
1040
1041 pub network_config: NetworkConfiguration,
1043
1044 peer_store: Option<N::PeerStore>,
1046
1047 peer_store_handle: Arc<dyn PeerStoreProvider>,
1049
1050 pub metrics_registry: Option<Registry>,
1052}
1053
1054impl<B: BlockT + 'static, H: ExHashT, N: NetworkBackend<B, H>> FullNetworkConfiguration<B, H, N> {
1055 pub fn new(network_config: &NetworkConfiguration, metrics_registry: Option<Registry>) -> Self {
1057 let bootnodes = network_config.boot_nodes.iter().map(|bootnode| bootnode.peer_id).collect();
1058 let peer_store = N::peer_store(bootnodes, metrics_registry.clone());
1059 let peer_store_handle = peer_store.handle();
1060
1061 Self {
1062 peer_store: Some(peer_store),
1063 peer_store_handle,
1064 notification_protocols: Vec::new(),
1065 request_response_protocols: Vec::new(),
1066 network_config: network_config.clone(),
1067 metrics_registry,
1068 }
1069 }
1070
1071 pub fn add_notification_protocol(&mut self, config: N::NotificationProtocolConfig) {
1073 self.notification_protocols.push(config);
1074 }
1075
1076 pub fn notification_protocols(&self) -> &Vec<N::NotificationProtocolConfig> {
1078 &self.notification_protocols
1079 }
1080
1081 pub fn add_request_response_protocol(&mut self, config: N::RequestResponseProtocolConfig) {
1083 self.request_response_protocols.push(config);
1084 }
1085
1086 pub fn peer_store_handle(&self) -> Arc<dyn PeerStoreProvider> {
1088 Arc::clone(&self.peer_store_handle)
1089 }
1090
1091 pub fn take_peer_store(&mut self) -> N::PeerStore {
1099 self.peer_store
1100 .take()
1101 .expect("`PeerStore` can only be taken once when it's started; qed")
1102 }
1103
1104 pub fn sanity_check_addresses(&self) -> Result<(), crate::error::Error> {
1106 ensure_addresses_consistent_with_transport(
1107 self.network_config.listen_addresses.iter(),
1108 &self.network_config.transport,
1109 )?;
1110 ensure_addresses_consistent_with_transport(
1111 self.network_config.boot_nodes.iter().map(|x| &x.multiaddr),
1112 &self.network_config.transport,
1113 )?;
1114 ensure_addresses_consistent_with_transport(
1115 self.network_config
1116 .default_peers_set
1117 .reserved_nodes
1118 .iter()
1119 .map(|x| &x.multiaddr),
1120 &self.network_config.transport,
1121 )?;
1122
1123 for notification_protocol in &self.notification_protocols {
1124 ensure_addresses_consistent_with_transport(
1125 notification_protocol.set_config().reserved_nodes.iter().map(|x| &x.multiaddr),
1126 &self.network_config.transport,
1127 )?;
1128 }
1129 ensure_addresses_consistent_with_transport(
1130 self.network_config.public_addresses.iter(),
1131 &self.network_config.transport,
1132 )?;
1133
1134 Ok(())
1135 }
1136
1137 pub fn sanity_check_bootnodes(&self) -> Result<(), crate::error::Error> {
1139 self.network_config.boot_nodes.iter().try_for_each(|bootnode| {
1140 if let Some(other) = self
1141 .network_config
1142 .boot_nodes
1143 .iter()
1144 .filter(|o| o.multiaddr == bootnode.multiaddr)
1145 .find(|o| o.peer_id != bootnode.peer_id)
1146 {
1147 Err(crate::error::Error::DuplicateBootnode {
1148 address: bootnode.multiaddr.clone().into(),
1149 first_id: bootnode.peer_id.into(),
1150 second_id: other.peer_id.into(),
1151 })
1152 } else {
1153 Ok(())
1154 }
1155 })
1156 }
1157
1158 pub fn known_addresses(&self) -> Vec<(PeerId, Multiaddr)> {
1160 let mut addresses: Vec<_> = self
1161 .network_config
1162 .default_peers_set
1163 .reserved_nodes
1164 .iter()
1165 .map(|reserved| (reserved.peer_id, reserved.multiaddr.clone()))
1166 .chain(self.notification_protocols.iter().flat_map(|protocol| {
1167 protocol
1168 .set_config()
1169 .reserved_nodes
1170 .iter()
1171 .map(|reserved| (reserved.peer_id, reserved.multiaddr.clone()))
1172 }))
1173 .chain(
1174 self.network_config
1175 .boot_nodes
1176 .iter()
1177 .map(|bootnode| (bootnode.peer_id, bootnode.multiaddr.clone())),
1178 )
1179 .collect();
1180
1181 addresses.sort();
1183 addresses.dedup();
1184
1185 addresses
1186 }
1187}
1188
1189#[derive(Debug, Clone, Default, Copy)]
1191pub enum NetworkBackendType {
1192 #[default]
1196 Litep2p,
1197
1198 Libp2p,
1205}
1206
1207#[cfg(test)]
1208mod tests {
1209 use super::*;
1210 use tempfile::TempDir;
1211
1212 fn tempdir_with_prefix(prefix: &str) -> TempDir {
1213 tempfile::Builder::new().prefix(prefix).tempdir().unwrap()
1214 }
1215
1216 fn secret_bytes(kp: ed25519::Keypair) -> Vec<u8> {
1217 kp.secret().to_bytes().into()
1218 }
1219
1220 #[test]
1221 fn test_secret_file() {
1222 let tmp = tempdir_with_prefix("x");
1223 std::fs::remove_dir(tmp.path()).unwrap(); let file = tmp.path().join("x").to_path_buf();
1225 let kp1 = NodeKeyConfig::Ed25519(Secret::File(file.clone())).into_keypair().unwrap();
1226 let kp2 = NodeKeyConfig::Ed25519(Secret::File(file.clone())).into_keypair().unwrap();
1227 assert!(file.is_file() && secret_bytes(kp1) == secret_bytes(kp2))
1228 }
1229
1230 #[test]
1231 fn test_secret_input() {
1232 let sk = ed25519::SecretKey::generate();
1233 let kp1 = NodeKeyConfig::Ed25519(Secret::Input(sk.clone())).into_keypair().unwrap();
1234 let kp2 = NodeKeyConfig::Ed25519(Secret::Input(sk)).into_keypair().unwrap();
1235 assert!(secret_bytes(kp1) == secret_bytes(kp2));
1236 }
1237
1238 #[test]
1239 fn test_secret_new() {
1240 let kp1 = NodeKeyConfig::Ed25519(Secret::New).into_keypair().unwrap();
1241 let kp2 = NodeKeyConfig::Ed25519(Secret::New).into_keypair().unwrap();
1242 assert!(secret_bytes(kp1) != secret_bytes(kp2));
1243 }
1244}