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 sc_network_types::{build_multiaddr, ed25519};
39use sc_network_types::{
40 multiaddr::{self, Multiaddr},
41 PeerId,
42};
43
44use crate::service::{ensure_addresses_consistent_with_transport, traits::NetworkBackend};
45use codec::Encode;
46use prometheus_endpoint::Registry;
47use zeroize::Zeroize;
48
49pub use sc_network_common::{
50 role::{Role, Roles},
51 sync::SyncMode,
52 ExHashT,
53};
54
55use sp_runtime::traits::Block as BlockT;
56
57use std::{
58 error::Error,
59 fmt, fs,
60 future::Future,
61 io::{self, Write},
62 iter,
63 net::Ipv4Addr,
64 num::NonZeroUsize,
65 path::{Path, PathBuf},
66 pin::Pin,
67 str::{self, FromStr},
68 sync::Arc,
69 time::Duration,
70};
71
72pub const DEFAULT_IDLE_CONNECTION_TIMEOUT: Duration = Duration::from_secs(10);
76
77pub const KADEMLIA_MAX_PROVIDER_KEYS: usize = 10000;
81
82pub const KADEMLIA_PROVIDER_RECORD_TTL: Duration = Duration::from_secs(10 * 3600);
86
87pub const KADEMLIA_PROVIDER_REPUBLISH_INTERVAL: Duration = Duration::from_secs(12600);
91
92#[derive(Clone, PartialEq, Eq, Hash)]
96pub struct ProtocolId(smallvec::SmallVec<[u8; 6]>);
97
98impl<'a> From<&'a str> for ProtocolId {
99 fn from(bytes: &'a str) -> ProtocolId {
100 Self(bytes.as_bytes().into())
101 }
102}
103
104impl AsRef<str> for ProtocolId {
105 fn as_ref(&self) -> &str {
106 str::from_utf8(&self.0[..])
107 .expect("the only way to build a ProtocolId is through a UTF-8 String; qed")
108 }
109}
110
111impl fmt::Debug for ProtocolId {
112 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
113 fmt::Debug::fmt(self.as_ref(), f)
114 }
115}
116
117pub fn parse_str_addr(addr_str: &str) -> Result<(PeerId, Multiaddr), ParseErr> {
132 let addr: Multiaddr = addr_str.parse()?;
133 parse_addr(addr)
134}
135
136pub fn parse_addr(mut addr: Multiaddr) -> Result<(PeerId, Multiaddr), ParseErr> {
138 let multihash = match addr.pop() {
139 Some(multiaddr::Protocol::P2p(multihash)) => multihash,
140 _ => return Err(ParseErr::PeerIdMissing),
141 };
142 let peer_id = PeerId::from_multihash(multihash).map_err(|_| ParseErr::InvalidPeerId)?;
143
144 Ok((peer_id, addr))
145}
146
147#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
162#[serde(try_from = "String", into = "String")]
163pub struct MultiaddrWithPeerId {
164 pub multiaddr: Multiaddr,
166 pub peer_id: PeerId,
168}
169
170impl MultiaddrWithPeerId {
171 pub fn concat(&self) -> Multiaddr {
173 let proto = multiaddr::Protocol::P2p(From::from(self.peer_id));
174 self.multiaddr.clone().with(proto)
175 }
176}
177
178impl fmt::Display for MultiaddrWithPeerId {
179 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
180 fmt::Display::fmt(&self.concat(), f)
181 }
182}
183
184impl FromStr for MultiaddrWithPeerId {
185 type Err = ParseErr;
186
187 fn from_str(s: &str) -> Result<Self, Self::Err> {
188 let (peer_id, multiaddr) = parse_str_addr(s)?;
189 Ok(Self { peer_id, multiaddr })
190 }
191}
192
193impl From<MultiaddrWithPeerId> for String {
194 fn from(ma: MultiaddrWithPeerId) -> String {
195 format!("{}", ma)
196 }
197}
198
199impl TryFrom<String> for MultiaddrWithPeerId {
200 type Error = ParseErr;
201 fn try_from(string: String) -> Result<Self, Self::Error> {
202 string.parse()
203 }
204}
205
206#[derive(Debug)]
208pub enum ParseErr {
209 MultiaddrParse(multiaddr::ParseError),
211 InvalidPeerId,
213 PeerIdMissing,
215}
216
217impl fmt::Display for ParseErr {
218 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
219 match self {
220 Self::MultiaddrParse(err) => write!(f, "{}", err),
221 Self::InvalidPeerId => write!(f, "Peer id at the end of the address is invalid"),
222 Self::PeerIdMissing => write!(f, "Peer id is missing from the address"),
223 }
224 }
225}
226
227impl std::error::Error for ParseErr {
228 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
229 match self {
230 Self::MultiaddrParse(err) => Some(err),
231 Self::InvalidPeerId => None,
232 Self::PeerIdMissing => None,
233 }
234 }
235}
236
237impl From<multiaddr::ParseError> for ParseErr {
238 fn from(err: multiaddr::ParseError) -> ParseErr {
239 Self::MultiaddrParse(err)
240 }
241}
242
243#[derive(Debug, Clone)]
245pub struct NotificationHandshake(Vec<u8>);
246
247impl NotificationHandshake {
248 pub fn new<H: Encode>(handshake: H) -> Self {
250 Self(handshake.encode())
251 }
252
253 pub fn from_bytes(bytes: Vec<u8>) -> Self {
255 Self(bytes)
256 }
257}
258
259impl std::ops::Deref for NotificationHandshake {
260 type Target = Vec<u8>;
261
262 fn deref(&self) -> &Self::Target {
263 &self.0
264 }
265}
266
267#[derive(Clone, Debug)]
269pub enum TransportConfig {
270 Normal {
272 enable_mdns: bool,
275
276 allow_private_ip: bool,
280 },
281
282 MemoryOnly,
285}
286
287#[derive(Clone, Debug, PartialEq, Eq)]
289pub enum NonReservedPeerMode {
290 Accept,
292 Deny,
294}
295
296impl NonReservedPeerMode {
297 pub fn parse(s: &str) -> Option<Self> {
299 match s {
300 "accept" => Some(Self::Accept),
301 "deny" => Some(Self::Deny),
302 _ => None,
303 }
304 }
305
306 pub fn is_reserved_only(&self) -> bool {
308 matches!(self, NonReservedPeerMode::Deny)
309 }
310}
311
312#[derive(Clone, Debug)]
316pub enum NodeKeyConfig {
317 Ed25519(Secret<ed25519::SecretKey>),
319}
320
321impl Default for NodeKeyConfig {
322 fn default() -> NodeKeyConfig {
323 Self::Ed25519(Secret::New)
324 }
325}
326
327pub type Ed25519Secret = Secret<ed25519::SecretKey>;
329
330#[derive(Clone)]
332pub enum Secret<K> {
333 Input(K),
335 File(PathBuf),
341 New,
343}
344
345impl<K> fmt::Debug for Secret<K> {
346 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
347 match self {
348 Self::Input(_) => f.debug_tuple("Secret::Input").finish(),
349 Self::File(path) => f.debug_tuple("Secret::File").field(path).finish(),
350 Self::New => f.debug_tuple("Secret::New").finish(),
351 }
352 }
353}
354
355impl NodeKeyConfig {
356 pub fn into_keypair(self) -> io::Result<ed25519::Keypair> {
367 use NodeKeyConfig::*;
368 match self {
369 Ed25519(Secret::New) => Ok(ed25519::Keypair::generate()),
370
371 Ed25519(Secret::Input(k)) => Ok(ed25519::Keypair::from(k).into()),
372
373 Ed25519(Secret::File(f)) => get_secret(
374 f,
375 |mut b| match String::from_utf8(b.to_vec()).ok().and_then(|s| {
376 if s.len() == 64 {
377 array_bytes::hex2bytes(&s).ok()
378 } else {
379 None
380 }
381 }) {
382 Some(s) => ed25519::SecretKey::try_from_bytes(s),
383 _ => ed25519::SecretKey::try_from_bytes(&mut b),
384 },
385 ed25519::SecretKey::generate,
386 |b| b.as_ref().to_vec(),
387 )
388 .map(ed25519::Keypair::from),
389 }
390 }
391}
392
393fn get_secret<P, F, G, E, W, K>(file: P, parse: F, generate: G, serialize: W) -> io::Result<K>
397where
398 P: AsRef<Path>,
399 F: for<'r> FnOnce(&'r mut [u8]) -> Result<K, E>,
400 G: FnOnce() -> K,
401 E: Error + Send + Sync + 'static,
402 W: Fn(&K) -> Vec<u8>,
403{
404 std::fs::read(&file)
405 .and_then(|mut sk_bytes| {
406 parse(&mut sk_bytes).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
407 })
408 .or_else(|e| {
409 if e.kind() == io::ErrorKind::NotFound {
410 file.as_ref().parent().map_or(Ok(()), fs::create_dir_all)?;
411 let sk = generate();
412 let mut sk_vec = serialize(&sk);
413 write_secret_file(file, &sk_vec)?;
414 sk_vec.zeroize();
415 Ok(sk)
416 } else {
417 Err(e)
418 }
419 })
420}
421
422fn write_secret_file<P>(path: P, sk_bytes: &[u8]) -> io::Result<()>
424where
425 P: AsRef<Path>,
426{
427 let mut file = open_secret_file(&path)?;
428 file.write_all(sk_bytes)
429}
430
431#[cfg(unix)]
433fn open_secret_file<P>(path: P) -> io::Result<fs::File>
434where
435 P: AsRef<Path>,
436{
437 use std::os::unix::fs::OpenOptionsExt;
438 fs::OpenOptions::new().write(true).create_new(true).mode(0o600).open(path)
439}
440
441#[cfg(not(unix))]
443fn open_secret_file<P>(path: P) -> Result<fs::File, io::Error>
444where
445 P: AsRef<Path>,
446{
447 fs::OpenOptions::new().write(true).create_new(true).open(path)
448}
449
450#[derive(Clone, Debug)]
452pub struct SetConfig {
453 pub in_peers: u32,
455
456 pub out_peers: u32,
458
459 pub reserved_nodes: Vec<MultiaddrWithPeerId>,
461
462 pub non_reserved_mode: NonReservedPeerMode,
465}
466
467impl Default for SetConfig {
468 fn default() -> Self {
469 Self {
470 in_peers: 25,
471 out_peers: 75,
472 reserved_nodes: Vec::new(),
473 non_reserved_mode: NonReservedPeerMode::Accept,
474 }
475 }
476}
477
478#[derive(Debug)]
483pub struct NonDefaultSetConfig {
484 protocol_name: ProtocolName,
490
491 fallback_names: Vec<ProtocolName>,
498
499 handshake: Option<NotificationHandshake>,
505
506 max_notification_size: u64,
508
509 set_config: SetConfig,
511
512 protocol_handle_pair: ProtocolHandlePair,
520}
521
522impl NonDefaultSetConfig {
523 pub fn new(
526 protocol_name: ProtocolName,
527 fallback_names: Vec<ProtocolName>,
528 max_notification_size: u64,
529 handshake: Option<NotificationHandshake>,
530 set_config: SetConfig,
531 ) -> (Self, Box<dyn NotificationService>) {
532 let (protocol_handle_pair, notification_service) =
533 notification_service(protocol_name.clone());
534 (
535 Self {
536 protocol_name,
537 max_notification_size,
538 fallback_names,
539 handshake,
540 set_config,
541 protocol_handle_pair,
542 },
543 notification_service,
544 )
545 }
546
547 pub fn protocol_name(&self) -> &ProtocolName {
549 &self.protocol_name
550 }
551
552 pub fn fallback_names(&self) -> impl Iterator<Item = &ProtocolName> {
554 self.fallback_names.iter()
555 }
556
557 pub fn handshake(&self) -> &Option<NotificationHandshake> {
559 &self.handshake
560 }
561
562 pub fn max_notification_size(&self) -> u64 {
564 self.max_notification_size
565 }
566
567 pub fn set_config(&self) -> &SetConfig {
569 &self.set_config
570 }
571
572 pub fn take_protocol_handle(self) -> ProtocolHandlePair {
574 self.protocol_handle_pair
575 }
576
577 pub fn allow_non_reserved(&mut self, in_peers: u32, out_peers: u32) {
579 self.set_config.in_peers = in_peers;
580 self.set_config.out_peers = out_peers;
581 self.set_config.non_reserved_mode = NonReservedPeerMode::Accept;
582 }
583
584 pub fn add_reserved(&mut self, peer: MultiaddrWithPeerId) {
586 self.set_config.reserved_nodes.push(peer);
587 }
588
589 pub fn add_fallback_names(&mut self, fallback_names: Vec<ProtocolName>) {
593 self.fallback_names.extend(fallback_names);
594 }
595}
596
597impl NotificationConfig for NonDefaultSetConfig {
598 fn set_config(&self) -> &SetConfig {
599 &self.set_config
600 }
601
602 fn protocol_name(&self) -> &ProtocolName {
604 &self.protocol_name
605 }
606}
607
608#[derive(Clone, Debug)]
610pub struct NetworkConfiguration {
611 pub net_config_path: Option<PathBuf>,
613
614 pub listen_addresses: Vec<Multiaddr>,
616
617 pub public_addresses: Vec<Multiaddr>,
619
620 pub boot_nodes: Vec<MultiaddrWithPeerId>,
622
623 pub node_key: NodeKeyConfig,
625
626 pub default_peers_set: SetConfig,
628
629 pub default_peers_set_num_full: u32,
634
635 pub client_version: String,
637
638 pub node_name: String,
640
641 pub transport: TransportConfig,
643
644 pub idle_connection_timeout: Duration,
648
649 pub max_parallel_downloads: u32,
651
652 pub max_blocks_per_request: u32,
654
655 pub min_peers_to_start_warp_sync: Option<usize>,
657
658 pub sync_mode: SyncMode,
660
661 pub enable_dht_random_walk: bool,
665
666 pub allow_non_globals_in_dht: bool,
668
669 pub kademlia_disjoint_query_paths: bool,
672
673 pub kademlia_replication_factor: NonZeroUsize,
678
679 pub ipfs_server: bool,
681
682 pub network_backend: NetworkBackendType,
684}
685
686impl NetworkConfiguration {
687 pub fn new<SN: Into<String>, SV: Into<String>>(
689 node_name: SN,
690 client_version: SV,
691 node_key: NodeKeyConfig,
692 net_config_path: Option<PathBuf>,
693 ) -> Self {
694 let default_peers_set = SetConfig::default();
695 Self {
696 net_config_path,
697 listen_addresses: Vec::new(),
698 public_addresses: Vec::new(),
699 boot_nodes: Vec::new(),
700 node_key,
701 default_peers_set_num_full: default_peers_set.in_peers + default_peers_set.out_peers,
702 default_peers_set,
703 client_version: client_version.into(),
704 node_name: node_name.into(),
705 transport: TransportConfig::Normal { enable_mdns: false, allow_private_ip: true },
706 idle_connection_timeout: DEFAULT_IDLE_CONNECTION_TIMEOUT,
707 max_parallel_downloads: 5,
708 max_blocks_per_request: 64,
709 min_peers_to_start_warp_sync: None,
710 sync_mode: SyncMode::Full,
711 enable_dht_random_walk: true,
712 allow_non_globals_in_dht: false,
713 kademlia_disjoint_query_paths: false,
714 kademlia_replication_factor: NonZeroUsize::new(DEFAULT_KADEMLIA_REPLICATION_FACTOR)
715 .expect("value is a constant; constant is non-zero; qed."),
716 ipfs_server: false,
717 network_backend: NetworkBackendType::Litep2p,
718 }
719 }
720
721 pub fn new_local() -> NetworkConfiguration {
724 let mut config =
725 NetworkConfiguration::new("test-node", "test-client", Default::default(), None);
726
727 config.listen_addresses =
728 vec![iter::once(multiaddr::Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1)))
729 .chain(iter::once(multiaddr::Protocol::Tcp(0)))
730 .collect()];
731
732 config.allow_non_globals_in_dht = true;
733 config
734 }
735
736 pub fn new_memory() -> NetworkConfiguration {
739 let mut config =
740 NetworkConfiguration::new("test-node", "test-client", Default::default(), None);
741
742 config.listen_addresses =
743 vec![iter::once(multiaddr::Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1)))
744 .chain(iter::once(multiaddr::Protocol::Tcp(0)))
745 .collect()];
746
747 config.allow_non_globals_in_dht = true;
748 config
749 }
750}
751
752pub struct Params<Block: BlockT, H: ExHashT, N: NetworkBackend<Block, H>> {
754 pub role: Role,
756
757 pub executor: Box<dyn Fn(Pin<Box<dyn Future<Output = ()> + Send>>) + Send + Sync>,
759
760 pub network_config: FullNetworkConfiguration<Block, H, N>,
762
763 pub protocol_id: ProtocolId,
765
766 pub genesis_hash: Block::Hash,
768
769 pub fork_id: Option<String>,
772
773 pub metrics_registry: Option<Registry>,
775
776 pub block_announce_config: N::NotificationProtocolConfig,
778
779 pub bitswap_config: Option<N::BitswapConfig>,
781
782 pub notification_metrics: NotificationMetrics,
784}
785
786pub struct FullNetworkConfiguration<B: BlockT + 'static, H: ExHashT, N: NetworkBackend<B, H>> {
788 pub(crate) notification_protocols: Vec<N::NotificationProtocolConfig>,
790
791 pub(crate) request_response_protocols: Vec<N::RequestResponseProtocolConfig>,
793
794 pub network_config: NetworkConfiguration,
796
797 peer_store: Option<N::PeerStore>,
799
800 peer_store_handle: Arc<dyn PeerStoreProvider>,
802
803 pub metrics_registry: Option<Registry>,
805}
806
807impl<B: BlockT + 'static, H: ExHashT, N: NetworkBackend<B, H>> FullNetworkConfiguration<B, H, N> {
808 pub fn new(network_config: &NetworkConfiguration, metrics_registry: Option<Registry>) -> Self {
810 let bootnodes = network_config.boot_nodes.iter().map(|bootnode| bootnode.peer_id).collect();
811 let peer_store = N::peer_store(bootnodes, metrics_registry.clone());
812 let peer_store_handle = peer_store.handle();
813
814 Self {
815 peer_store: Some(peer_store),
816 peer_store_handle,
817 notification_protocols: Vec::new(),
818 request_response_protocols: Vec::new(),
819 network_config: network_config.clone(),
820 metrics_registry,
821 }
822 }
823
824 pub fn add_notification_protocol(&mut self, config: N::NotificationProtocolConfig) {
826 self.notification_protocols.push(config);
827 }
828
829 pub fn notification_protocols(&self) -> &Vec<N::NotificationProtocolConfig> {
831 &self.notification_protocols
832 }
833
834 pub fn add_request_response_protocol(&mut self, config: N::RequestResponseProtocolConfig) {
836 self.request_response_protocols.push(config);
837 }
838
839 pub fn peer_store_handle(&self) -> Arc<dyn PeerStoreProvider> {
841 Arc::clone(&self.peer_store_handle)
842 }
843
844 pub fn take_peer_store(&mut self) -> N::PeerStore {
852 self.peer_store
853 .take()
854 .expect("`PeerStore` can only be taken once when it's started; qed")
855 }
856
857 pub fn sanity_check_addresses(&self) -> Result<(), crate::error::Error> {
859 ensure_addresses_consistent_with_transport(
860 self.network_config.listen_addresses.iter(),
861 &self.network_config.transport,
862 )?;
863 ensure_addresses_consistent_with_transport(
864 self.network_config.boot_nodes.iter().map(|x| &x.multiaddr),
865 &self.network_config.transport,
866 )?;
867 ensure_addresses_consistent_with_transport(
868 self.network_config
869 .default_peers_set
870 .reserved_nodes
871 .iter()
872 .map(|x| &x.multiaddr),
873 &self.network_config.transport,
874 )?;
875
876 for notification_protocol in &self.notification_protocols {
877 ensure_addresses_consistent_with_transport(
878 notification_protocol.set_config().reserved_nodes.iter().map(|x| &x.multiaddr),
879 &self.network_config.transport,
880 )?;
881 }
882 ensure_addresses_consistent_with_transport(
883 self.network_config.public_addresses.iter(),
884 &self.network_config.transport,
885 )?;
886
887 Ok(())
888 }
889
890 pub fn sanity_check_bootnodes(&self) -> Result<(), crate::error::Error> {
892 self.network_config.boot_nodes.iter().try_for_each(|bootnode| {
893 if let Some(other) = self
894 .network_config
895 .boot_nodes
896 .iter()
897 .filter(|o| o.multiaddr == bootnode.multiaddr)
898 .find(|o| o.peer_id != bootnode.peer_id)
899 {
900 Err(crate::error::Error::DuplicateBootnode {
901 address: bootnode.multiaddr.clone().into(),
902 first_id: bootnode.peer_id.into(),
903 second_id: other.peer_id.into(),
904 })
905 } else {
906 Ok(())
907 }
908 })
909 }
910
911 pub fn known_addresses(&self) -> Vec<(PeerId, Multiaddr)> {
913 let mut addresses: Vec<_> = self
914 .network_config
915 .default_peers_set
916 .reserved_nodes
917 .iter()
918 .map(|reserved| (reserved.peer_id, reserved.multiaddr.clone()))
919 .chain(self.notification_protocols.iter().flat_map(|protocol| {
920 protocol
921 .set_config()
922 .reserved_nodes
923 .iter()
924 .map(|reserved| (reserved.peer_id, reserved.multiaddr.clone()))
925 }))
926 .chain(
927 self.network_config
928 .boot_nodes
929 .iter()
930 .map(|bootnode| (bootnode.peer_id, bootnode.multiaddr.clone())),
931 )
932 .collect();
933
934 addresses.sort();
936 addresses.dedup();
937
938 addresses
939 }
940}
941
942#[derive(Debug, Clone, Default, Copy)]
944pub enum NetworkBackendType {
945 #[default]
949 Litep2p,
950
951 Libp2p,
958}
959
960#[cfg(test)]
961mod tests {
962 use super::*;
963 use tempfile::TempDir;
964
965 fn tempdir_with_prefix(prefix: &str) -> TempDir {
966 tempfile::Builder::new().prefix(prefix).tempdir().unwrap()
967 }
968
969 fn secret_bytes(kp: ed25519::Keypair) -> Vec<u8> {
970 kp.secret().to_bytes().into()
971 }
972
973 #[test]
974 fn test_secret_file() {
975 let tmp = tempdir_with_prefix("x");
976 std::fs::remove_dir(tmp.path()).unwrap(); let file = tmp.path().join("x").to_path_buf();
978 let kp1 = NodeKeyConfig::Ed25519(Secret::File(file.clone())).into_keypair().unwrap();
979 let kp2 = NodeKeyConfig::Ed25519(Secret::File(file.clone())).into_keypair().unwrap();
980 assert!(file.is_file() && secret_bytes(kp1) == secret_bytes(kp2))
981 }
982
983 #[test]
984 fn test_secret_input() {
985 let sk = ed25519::SecretKey::generate();
986 let kp1 = NodeKeyConfig::Ed25519(Secret::Input(sk.clone())).into_keypair().unwrap();
987 let kp2 = NodeKeyConfig::Ed25519(Secret::Input(sk)).into_keypair().unwrap();
988 assert!(secret_bytes(kp1) == secret_bytes(kp2));
989 }
990
991 #[test]
992 fn test_secret_new() {
993 let kp1 = NodeKeyConfig::Ed25519(Secret::New).into_keypair().unwrap();
994 let kp2 = NodeKeyConfig::Ed25519(Secret::New).into_keypair().unwrap();
995 assert!(secret_bytes(kp1) != secret_bytes(kp2));
996 }
997}