1use prometheus_client::registry::Registry;
2use std::collections::HashSet;
3use std::fs;
4use std::path::PathBuf;
5use subspace_networking::libp2p::kad::Mode;
6use subspace_networking::libp2p::{identity, Multiaddr};
7use subspace_networking::protocols::request_response::handlers::cached_piece_by_index::CachedPieceByIndexRequestHandler;
8use subspace_networking::protocols::request_response::handlers::piece_by_index::PieceByIndexRequestHandler;
9use subspace_networking::protocols::request_response::handlers::segment_header::SegmentHeaderBySegmentIndexesRequestHandler;
10use subspace_networking::utils::strip_peer_id;
11use subspace_networking::{
12 CreationError, KademliaMode, KnownPeersManager, KnownPeersManagerConfig,
13 KnownPeersManagerPersistenceError, Node, NodeRunner,
14};
15use thiserror::Error;
16use tracing::{error, trace};
17
18pub const KNOWN_PEERS_CACHE_SIZE: u32 = 100;
20
21#[derive(Debug, Error)]
23pub enum DsnConfigurationError {
24 #[error("Can't instantiate the DSN: {0}")]
26 CreationError(#[from] CreationError),
27 #[error("Network parameter manager error: {0}")]
29 NetworkParameterManagerError(#[from] KnownPeersManagerPersistenceError),
30}
31
32#[derive(Clone, Debug)]
34pub struct DsnConfig {
35 pub listen_on: Vec<Multiaddr>,
37
38 pub bootstrap_nodes: Vec<Multiaddr>,
40
41 pub reserved_peers: Vec<Multiaddr>,
43
44 pub keypair: identity::Keypair,
46
47 pub allow_non_global_addresses_in_dht: bool,
49
50 pub network_path: PathBuf,
52
53 pub max_in_connections: u32,
55
56 pub max_out_connections: u32,
58
59 pub max_pending_in_connections: u32,
61
62 pub max_pending_out_connections: u32,
64
65 pub external_addresses: Vec<Multiaddr>,
67}
68
69pub(crate) fn create_dsn_instance(
70 dsn_protocol_version: String,
71 dsn_config: DsnConfig,
72 prometheus_registry: Option<&mut Registry>,
73) -> Result<(Node, NodeRunner), DsnConfigurationError> {
74 trace!("Subspace networking starting.");
75
76 let known_peers_registry = {
77 let network_path = dsn_config.network_path;
78
79 if !network_path.is_dir() {
80 fs::create_dir(&network_path)
81 .map_err(|error| DsnConfigurationError::CreationError(CreationError::Io(error)))?;
82 }
83 let file_path = network_path.join("known_addresses.bin");
84
85 KnownPeersManager::new(KnownPeersManagerConfig {
86 path: Some(file_path.into_boxed_path()),
87 ignore_peer_list: strip_peer_id(dsn_config.bootstrap_nodes.clone())
88 .into_iter()
89 .map(|(peer_id, _)| peer_id)
90 .collect::<HashSet<_>>(),
91 cache_size: KNOWN_PEERS_CACHE_SIZE,
92 ..Default::default()
93 })
94 .map(KnownPeersManager::boxed)?
95 };
96
97 let keypair = dsn_config.keypair.clone();
98 let default_networking_config =
99 subspace_networking::Config::new(dsn_protocol_version, keypair, prometheus_registry);
100
101 let networking_config = subspace_networking::Config {
102 keypair: dsn_config.keypair.clone(),
103 listen_on: dsn_config.listen_on,
104 allow_non_global_addresses_in_dht: dsn_config.allow_non_global_addresses_in_dht,
105 known_peers_registry,
106 request_response_protocols: vec![
107 CachedPieceByIndexRequestHandler::create(|_, _| async { None }),
109 PieceByIndexRequestHandler::create(|_, _| async { None }),
111 SegmentHeaderBySegmentIndexesRequestHandler::create(move |_, _| async move { None }),
112 ],
113 max_established_incoming_connections: dsn_config.max_in_connections,
114 max_established_outgoing_connections: dsn_config.max_out_connections,
115 max_pending_incoming_connections: dsn_config.max_pending_in_connections,
116 max_pending_outgoing_connections: dsn_config.max_pending_out_connections,
117 reserved_peers: dsn_config.reserved_peers,
118 bootstrap_addresses: dsn_config.bootstrap_nodes,
119 external_addresses: dsn_config.external_addresses,
120 kademlia_mode: KademliaMode::Static(Mode::Client),
121
122 ..default_networking_config
123 };
124
125 subspace_networking::construct(networking_config).map_err(Into::into)
126}