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};
70
71#[derive(Clone, PartialEq, Eq, Hash)]
75pub struct ProtocolId(smallvec::SmallVec<[u8; 6]>);
76
77impl<'a> From<&'a str> for ProtocolId {
78 fn from(bytes: &'a str) -> ProtocolId {
79 Self(bytes.as_bytes().into())
80 }
81}
82
83impl AsRef<str> for ProtocolId {
84 fn as_ref(&self) -> &str {
85 str::from_utf8(&self.0[..])
86 .expect("the only way to build a ProtocolId is through a UTF-8 String; qed")
87 }
88}
89
90impl fmt::Debug for ProtocolId {
91 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
92 fmt::Debug::fmt(self.as_ref(), f)
93 }
94}
95
96pub fn parse_str_addr(addr_str: &str) -> Result<(PeerId, Multiaddr), ParseErr> {
111 let addr: Multiaddr = addr_str.parse()?;
112 parse_addr(addr)
113}
114
115pub fn parse_addr(mut addr: Multiaddr) -> Result<(PeerId, Multiaddr), ParseErr> {
117 let multihash = match addr.pop() {
118 Some(multiaddr::Protocol::P2p(multihash)) => multihash,
119 _ => return Err(ParseErr::PeerIdMissing),
120 };
121 let peer_id = PeerId::from_multihash(multihash).map_err(|_| ParseErr::InvalidPeerId)?;
122
123 Ok((peer_id, addr))
124}
125
126#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
141#[serde(try_from = "String", into = "String")]
142pub struct MultiaddrWithPeerId {
143 pub multiaddr: Multiaddr,
145 pub peer_id: PeerId,
147}
148
149impl MultiaddrWithPeerId {
150 pub fn concat(&self) -> Multiaddr {
152 let mut addr = self.multiaddr.clone();
153 if matches!(addr.iter().last(), Some(multiaddr::Protocol::P2p(_))) {
155 addr.pop();
156 }
157 addr.with(multiaddr::Protocol::P2p(From::from(self.peer_id)))
158 }
159}
160
161impl fmt::Display for MultiaddrWithPeerId {
162 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
163 fmt::Display::fmt(&self.concat(), f)
164 }
165}
166
167impl FromStr for MultiaddrWithPeerId {
168 type Err = ParseErr;
169
170 fn from_str(s: &str) -> Result<Self, Self::Err> {
171 let (peer_id, multiaddr) = parse_str_addr(s)?;
172 Ok(Self { peer_id, multiaddr })
173 }
174}
175
176impl From<MultiaddrWithPeerId> for String {
177 fn from(ma: MultiaddrWithPeerId) -> String {
178 format!("{}", ma)
179 }
180}
181
182impl TryFrom<String> for MultiaddrWithPeerId {
183 type Error = ParseErr;
184 fn try_from(string: String) -> Result<Self, Self::Error> {
185 string.parse()
186 }
187}
188
189#[derive(Debug)]
191pub enum ParseErr {
192 MultiaddrParse(multiaddr::ParseError),
194 InvalidPeerId,
196 PeerIdMissing,
198}
199
200impl fmt::Display for ParseErr {
201 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
202 match self {
203 Self::MultiaddrParse(err) => write!(f, "{}", err),
204 Self::InvalidPeerId => write!(f, "Peer id at the end of the address is invalid"),
205 Self::PeerIdMissing => write!(f, "Peer id is missing from the address"),
206 }
207 }
208}
209
210impl std::error::Error for ParseErr {
211 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
212 match self {
213 Self::MultiaddrParse(err) => Some(err),
214 Self::InvalidPeerId => None,
215 Self::PeerIdMissing => None,
216 }
217 }
218}
219
220impl From<multiaddr::ParseError> for ParseErr {
221 fn from(err: multiaddr::ParseError) -> ParseErr {
222 Self::MultiaddrParse(err)
223 }
224}
225
226#[derive(Debug, Clone)]
228pub struct NotificationHandshake(Vec<u8>);
229
230impl NotificationHandshake {
231 pub fn new<H: Encode>(handshake: H) -> Self {
233 Self(handshake.encode())
234 }
235
236 pub fn from_bytes(bytes: Vec<u8>) -> Self {
238 Self(bytes)
239 }
240}
241
242impl std::ops::Deref for NotificationHandshake {
243 type Target = Vec<u8>;
244
245 fn deref(&self) -> &Self::Target {
246 &self.0
247 }
248}
249
250#[derive(Clone, Debug)]
252pub enum TransportConfig {
253 Normal {
255 enable_mdns: bool,
258
259 allow_private_ip: bool,
263 },
264
265 MemoryOnly,
268}
269
270#[derive(Clone, Debug, PartialEq, Eq)]
272pub enum NonReservedPeerMode {
273 Accept,
275 Deny,
277}
278
279impl NonReservedPeerMode {
280 pub fn parse(s: &str) -> Option<Self> {
282 match s {
283 "accept" => Some(Self::Accept),
284 "deny" => Some(Self::Deny),
285 _ => None,
286 }
287 }
288
289 pub fn is_reserved_only(&self) -> bool {
291 matches!(self, NonReservedPeerMode::Deny)
292 }
293}
294
295#[derive(Clone, Debug)]
299pub enum NodeKeyConfig {
300 Ed25519(Secret<ed25519::SecretKey>),
302}
303
304impl Default for NodeKeyConfig {
305 fn default() -> NodeKeyConfig {
306 Self::Ed25519(Secret::New)
307 }
308}
309
310pub type Ed25519Secret = Secret<ed25519::SecretKey>;
312
313#[derive(Clone)]
315pub enum Secret<K> {
316 Input(K),
318 File(PathBuf),
324 New,
326}
327
328impl<K> fmt::Debug for Secret<K> {
329 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
330 match self {
331 Self::Input(_) => f.debug_tuple("Secret::Input").finish(),
332 Self::File(path) => f.debug_tuple("Secret::File").field(path).finish(),
333 Self::New => f.debug_tuple("Secret::New").finish(),
334 }
335 }
336}
337
338impl NodeKeyConfig {
339 pub fn into_keypair(self) -> io::Result<ed25519::Keypair> {
350 use NodeKeyConfig::*;
351 match self {
352 Ed25519(Secret::New) => Ok(ed25519::Keypair::generate()),
353
354 Ed25519(Secret::Input(k)) => Ok(ed25519::Keypair::from(k).into()),
355
356 Ed25519(Secret::File(f)) => get_secret(
357 f,
358 |mut b| match String::from_utf8(b.to_vec()).ok().and_then(|s| {
359 if s.len() == 64 {
360 array_bytes::hex2bytes(&s).ok()
361 } else {
362 None
363 }
364 }) {
365 Some(s) => ed25519::SecretKey::try_from_bytes(s),
366 _ => ed25519::SecretKey::try_from_bytes(&mut b),
367 },
368 ed25519::SecretKey::generate,
369 |b| b.as_ref().to_vec(),
370 )
371 .map(ed25519::Keypair::from),
372 }
373 }
374}
375
376fn get_secret<P, F, G, E, W, K>(file: P, parse: F, generate: G, serialize: W) -> io::Result<K>
380where
381 P: AsRef<Path>,
382 F: for<'r> FnOnce(&'r mut [u8]) -> Result<K, E>,
383 G: FnOnce() -> K,
384 E: Error + Send + Sync + 'static,
385 W: Fn(&K) -> Vec<u8>,
386{
387 std::fs::read(&file)
388 .and_then(|mut sk_bytes| {
389 parse(&mut sk_bytes).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
390 })
391 .or_else(|e| {
392 if e.kind() == io::ErrorKind::NotFound {
393 file.as_ref().parent().map_or(Ok(()), fs::create_dir_all)?;
394 let sk = generate();
395 let mut sk_vec = serialize(&sk);
396 write_secret_file(file, &sk_vec)?;
397 sk_vec.zeroize();
398 Ok(sk)
399 } else {
400 Err(e)
401 }
402 })
403}
404
405fn write_secret_file<P>(path: P, sk_bytes: &[u8]) -> io::Result<()>
407where
408 P: AsRef<Path>,
409{
410 let mut file = open_secret_file(&path)?;
411 file.write_all(sk_bytes)
412}
413
414#[cfg(unix)]
416fn open_secret_file<P>(path: P) -> io::Result<fs::File>
417where
418 P: AsRef<Path>,
419{
420 use std::os::unix::fs::OpenOptionsExt;
421 fs::OpenOptions::new().write(true).create_new(true).mode(0o600).open(path)
422}
423
424#[cfg(not(unix))]
426fn open_secret_file<P>(path: P) -> Result<fs::File, io::Error>
427where
428 P: AsRef<Path>,
429{
430 fs::OpenOptions::new().write(true).create_new(true).open(path)
431}
432
433#[derive(Clone, Debug)]
435pub struct SetConfig {
436 pub in_peers: u32,
438
439 pub out_peers: u32,
441
442 pub reserved_nodes: Vec<MultiaddrWithPeerId>,
444
445 pub non_reserved_mode: NonReservedPeerMode,
448}
449
450impl Default for SetConfig {
451 fn default() -> Self {
452 Self {
453 in_peers: 25,
454 out_peers: 75,
455 reserved_nodes: Vec::new(),
456 non_reserved_mode: NonReservedPeerMode::Accept,
457 }
458 }
459}
460
461#[derive(Debug)]
466pub struct NonDefaultSetConfig {
467 protocol_name: ProtocolName,
473
474 fallback_names: Vec<ProtocolName>,
481
482 handshake: Option<NotificationHandshake>,
488
489 max_notification_size: u64,
491
492 set_config: SetConfig,
494
495 protocol_handle_pair: ProtocolHandlePair,
503}
504
505impl NonDefaultSetConfig {
506 pub fn new(
509 protocol_name: ProtocolName,
510 fallback_names: Vec<ProtocolName>,
511 max_notification_size: u64,
512 handshake: Option<NotificationHandshake>,
513 set_config: SetConfig,
514 ) -> (Self, Box<dyn NotificationService>) {
515 let (protocol_handle_pair, notification_service) =
516 notification_service(protocol_name.clone());
517 (
518 Self {
519 protocol_name,
520 max_notification_size,
521 fallback_names,
522 handshake,
523 set_config,
524 protocol_handle_pair,
525 },
526 notification_service,
527 )
528 }
529
530 pub fn protocol_name(&self) -> &ProtocolName {
532 &self.protocol_name
533 }
534
535 pub fn fallback_names(&self) -> impl Iterator<Item = &ProtocolName> {
537 self.fallback_names.iter()
538 }
539
540 pub fn handshake(&self) -> &Option<NotificationHandshake> {
542 &self.handshake
543 }
544
545 pub fn max_notification_size(&self) -> u64 {
547 self.max_notification_size
548 }
549
550 pub fn set_config(&self) -> &SetConfig {
552 &self.set_config
553 }
554
555 pub fn take_protocol_handle(self) -> ProtocolHandlePair {
557 self.protocol_handle_pair
558 }
559
560 pub fn allow_non_reserved(&mut self, in_peers: u32, out_peers: u32) {
562 self.set_config.in_peers = in_peers;
563 self.set_config.out_peers = out_peers;
564 self.set_config.non_reserved_mode = NonReservedPeerMode::Accept;
565 }
566
567 pub fn add_reserved(&mut self, peer: MultiaddrWithPeerId) {
569 self.set_config.reserved_nodes.push(peer);
570 }
571
572 pub fn add_fallback_names(&mut self, fallback_names: Vec<ProtocolName>) {
576 self.fallback_names.extend(fallback_names);
577 }
578}
579
580impl NotificationConfig for NonDefaultSetConfig {
581 fn set_config(&self) -> &SetConfig {
582 &self.set_config
583 }
584
585 fn protocol_name(&self) -> &ProtocolName {
587 &self.protocol_name
588 }
589}
590
591#[derive(Clone, Debug)]
593pub struct NetworkConfiguration {
594 pub net_config_path: Option<PathBuf>,
596
597 pub listen_addresses: Vec<Multiaddr>,
599
600 pub public_addresses: Vec<Multiaddr>,
602
603 pub boot_nodes: Vec<MultiaddrWithPeerId>,
605
606 pub node_key: NodeKeyConfig,
608
609 pub default_peers_set: SetConfig,
611
612 pub default_peers_set_num_full: u32,
617
618 pub client_version: String,
620
621 pub node_name: String,
623
624 pub transport: TransportConfig,
626
627 pub max_parallel_downloads: u32,
629
630 pub max_blocks_per_request: u32,
632
633 pub min_peers_to_start_warp_sync: Option<usize>,
635
636 pub sync_mode: SyncMode,
638
639 pub enable_dht_random_walk: bool,
643
644 pub allow_non_globals_in_dht: bool,
646
647 pub kademlia_disjoint_query_paths: bool,
650
651 pub kademlia_replication_factor: NonZeroUsize,
656
657 pub ipfs_server: bool,
659
660 pub network_backend: NetworkBackendType,
662}
663
664impl NetworkConfiguration {
665 pub fn new<SN: Into<String>, SV: Into<String>>(
667 node_name: SN,
668 client_version: SV,
669 node_key: NodeKeyConfig,
670 net_config_path: Option<PathBuf>,
671 ) -> Self {
672 let default_peers_set = SetConfig::default();
673 Self {
674 net_config_path,
675 listen_addresses: Vec::new(),
676 public_addresses: Vec::new(),
677 boot_nodes: Vec::new(),
678 node_key,
679 default_peers_set_num_full: default_peers_set.in_peers + default_peers_set.out_peers,
680 default_peers_set,
681 client_version: client_version.into(),
682 node_name: node_name.into(),
683 transport: TransportConfig::Normal { enable_mdns: false, allow_private_ip: true },
684 max_parallel_downloads: 5,
685 max_blocks_per_request: 64,
686 min_peers_to_start_warp_sync: None,
687 sync_mode: SyncMode::Full,
688 enable_dht_random_walk: true,
689 allow_non_globals_in_dht: false,
690 kademlia_disjoint_query_paths: false,
691 kademlia_replication_factor: NonZeroUsize::new(DEFAULT_KADEMLIA_REPLICATION_FACTOR)
692 .expect("value is a constant; constant is non-zero; qed."),
693 ipfs_server: false,
694 network_backend: NetworkBackendType::Litep2p,
695 }
696 }
697
698 pub fn new_local() -> NetworkConfiguration {
701 let mut config =
702 NetworkConfiguration::new("test-node", "test-client", Default::default(), None);
703
704 config.listen_addresses =
705 vec![iter::once(multiaddr::Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1)))
706 .chain(iter::once(multiaddr::Protocol::Tcp(0)))
707 .collect()];
708
709 config.allow_non_globals_in_dht = true;
710 config
711 }
712
713 pub fn new_memory() -> NetworkConfiguration {
716 let mut config =
717 NetworkConfiguration::new("test-node", "test-client", Default::default(), None);
718
719 config.listen_addresses =
720 vec![iter::once(multiaddr::Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1)))
721 .chain(iter::once(multiaddr::Protocol::Tcp(0)))
722 .collect()];
723
724 config.allow_non_globals_in_dht = true;
725 config
726 }
727}
728
729pub struct Params<Block: BlockT, H: ExHashT, N: NetworkBackend<Block, H>> {
731 pub role: Role,
733
734 pub executor: Box<dyn Fn(Pin<Box<dyn Future<Output = ()> + Send>>) + Send + Sync>,
736
737 pub network_config: FullNetworkConfiguration<Block, H, N>,
739
740 pub protocol_id: ProtocolId,
742
743 pub genesis_hash: Block::Hash,
745
746 pub fork_id: Option<String>,
749
750 pub metrics_registry: Option<Registry>,
752
753 pub block_announce_config: N::NotificationProtocolConfig,
755
756 pub bitswap_config: Option<N::BitswapConfig>,
758
759 pub notification_metrics: NotificationMetrics,
761}
762
763pub struct FullNetworkConfiguration<B: BlockT + 'static, H: ExHashT, N: NetworkBackend<B, H>> {
765 pub(crate) notification_protocols: Vec<N::NotificationProtocolConfig>,
767
768 pub(crate) request_response_protocols: Vec<N::RequestResponseProtocolConfig>,
770
771 pub network_config: NetworkConfiguration,
773
774 peer_store: Option<N::PeerStore>,
776
777 peer_store_handle: Arc<dyn PeerStoreProvider>,
779
780 pub metrics_registry: Option<Registry>,
782}
783
784impl<B: BlockT + 'static, H: ExHashT, N: NetworkBackend<B, H>> FullNetworkConfiguration<B, H, N> {
785 pub fn new(network_config: &NetworkConfiguration, metrics_registry: Option<Registry>) -> Self {
787 let bootnodes = network_config.boot_nodes.iter().map(|bootnode| bootnode.peer_id).collect();
788 let peer_store = N::peer_store(bootnodes, metrics_registry.clone());
789 let peer_store_handle = peer_store.handle();
790
791 Self {
792 peer_store: Some(peer_store),
793 peer_store_handle,
794 notification_protocols: Vec::new(),
795 request_response_protocols: Vec::new(),
796 network_config: network_config.clone(),
797 metrics_registry,
798 }
799 }
800
801 pub fn add_notification_protocol(&mut self, config: N::NotificationProtocolConfig) {
803 self.notification_protocols.push(config);
804 }
805
806 pub fn notification_protocols(&self) -> &Vec<N::NotificationProtocolConfig> {
808 &self.notification_protocols
809 }
810
811 pub fn add_request_response_protocol(&mut self, config: N::RequestResponseProtocolConfig) {
813 self.request_response_protocols.push(config);
814 }
815
816 pub fn peer_store_handle(&self) -> Arc<dyn PeerStoreProvider> {
818 Arc::clone(&self.peer_store_handle)
819 }
820
821 pub fn take_peer_store(&mut self) -> N::PeerStore {
829 self.peer_store
830 .take()
831 .expect("`PeerStore` can only be taken once when it's started; qed")
832 }
833
834 pub fn sanity_check_addresses(&self) -> Result<(), crate::error::Error> {
836 ensure_addresses_consistent_with_transport(
837 self.network_config.listen_addresses.iter(),
838 &self.network_config.transport,
839 )?;
840 ensure_addresses_consistent_with_transport(
841 self.network_config.boot_nodes.iter().map(|x| &x.multiaddr),
842 &self.network_config.transport,
843 )?;
844 ensure_addresses_consistent_with_transport(
845 self.network_config
846 .default_peers_set
847 .reserved_nodes
848 .iter()
849 .map(|x| &x.multiaddr),
850 &self.network_config.transport,
851 )?;
852
853 for notification_protocol in &self.notification_protocols {
854 ensure_addresses_consistent_with_transport(
855 notification_protocol.set_config().reserved_nodes.iter().map(|x| &x.multiaddr),
856 &self.network_config.transport,
857 )?;
858 }
859 ensure_addresses_consistent_with_transport(
860 self.network_config.public_addresses.iter(),
861 &self.network_config.transport,
862 )?;
863
864 Ok(())
865 }
866
867 pub fn sanity_check_bootnodes(&self) -> Result<(), crate::error::Error> {
869 self.network_config.boot_nodes.iter().try_for_each(|bootnode| {
870 if let Some(other) = self
871 .network_config
872 .boot_nodes
873 .iter()
874 .filter(|o| o.multiaddr == bootnode.multiaddr)
875 .find(|o| o.peer_id != bootnode.peer_id)
876 {
877 Err(crate::error::Error::DuplicateBootnode {
878 address: bootnode.multiaddr.clone().into(),
879 first_id: bootnode.peer_id.into(),
880 second_id: other.peer_id.into(),
881 })
882 } else {
883 Ok(())
884 }
885 })
886 }
887
888 pub fn known_addresses(&self) -> Vec<(PeerId, Multiaddr)> {
890 let mut addresses: Vec<_> = self
891 .network_config
892 .default_peers_set
893 .reserved_nodes
894 .iter()
895 .map(|reserved| (reserved.peer_id, reserved.multiaddr.clone()))
896 .chain(self.notification_protocols.iter().flat_map(|protocol| {
897 protocol
898 .set_config()
899 .reserved_nodes
900 .iter()
901 .map(|reserved| (reserved.peer_id, reserved.multiaddr.clone()))
902 }))
903 .chain(
904 self.network_config
905 .boot_nodes
906 .iter()
907 .map(|bootnode| (bootnode.peer_id, bootnode.multiaddr.clone())),
908 )
909 .collect();
910
911 addresses.sort();
913 addresses.dedup();
914
915 addresses
916 }
917}
918
919#[derive(Debug, Clone, Default, Copy)]
921pub enum NetworkBackendType {
922 #[default]
926 Litep2p,
927
928 Libp2p,
935}
936
937#[cfg(test)]
938mod tests {
939 use super::*;
940 use tempfile::TempDir;
941
942 fn tempdir_with_prefix(prefix: &str) -> TempDir {
943 tempfile::Builder::new().prefix(prefix).tempdir().unwrap()
944 }
945
946 fn secret_bytes(kp: ed25519::Keypair) -> Vec<u8> {
947 kp.secret().to_bytes().into()
948 }
949
950 #[test]
951 fn test_secret_file() {
952 let tmp = tempdir_with_prefix("x");
953 std::fs::remove_dir(tmp.path()).unwrap(); let file = tmp.path().join("x").to_path_buf();
955 let kp1 = NodeKeyConfig::Ed25519(Secret::File(file.clone())).into_keypair().unwrap();
956 let kp2 = NodeKeyConfig::Ed25519(Secret::File(file.clone())).into_keypair().unwrap();
957 assert!(file.is_file() && secret_bytes(kp1) == secret_bytes(kp2))
958 }
959
960 #[test]
961 fn test_secret_input() {
962 let sk = ed25519::SecretKey::generate();
963 let kp1 = NodeKeyConfig::Ed25519(Secret::Input(sk.clone())).into_keypair().unwrap();
964 let kp2 = NodeKeyConfig::Ed25519(Secret::Input(sk)).into_keypair().unwrap();
965 assert!(secret_bytes(kp1) == secret_bytes(kp2));
966 }
967
968 #[test]
969 fn test_secret_new() {
970 let kp1 = NodeKeyConfig::Ed25519(Secret::New).into_keypair().unwrap();
971 let kp2 = NodeKeyConfig::Ed25519(Secret::New).into_keypair().unwrap();
972 assert!(secret_bytes(kp1) != secret_bytes(kp2));
973 }
974}