subspace_service/
dsn.rs

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
18/// Size of the LRU cache for peers.
19pub const KNOWN_PEERS_CACHE_SIZE: u32 = 100;
20
21/// Errors that might happen during DSN configuration.
22#[derive(Debug, Error)]
23pub enum DsnConfigurationError {
24    /// Can't instantiate the DSN.
25    #[error("Can't instantiate the DSN: {0}")]
26    CreationError(#[from] CreationError),
27    /// Network parameter manager error.
28    #[error("Network parameter manager error: {0}")]
29    NetworkParameterManagerError(#[from] KnownPeersManagerPersistenceError),
30}
31
32/// DSN configuration parameters.
33#[derive(Clone, Debug)]
34pub struct DsnConfig {
35    /// Where local DSN node will listen for incoming connections.
36    pub listen_on: Vec<Multiaddr>,
37
38    /// Bootstrap nodes for DSN.
39    pub bootstrap_nodes: Vec<Multiaddr>,
40
41    /// Reserved nodes for DSN.
42    pub reserved_peers: Vec<Multiaddr>,
43
44    /// Identity keypair of a node used for authenticated connections.
45    pub keypair: identity::Keypair,
46
47    /// Determines whether we allow keeping non-global (private, shared, loopback..) addresses in Kademlia DHT.
48    pub allow_non_global_addresses_in_dht: bool,
49
50    /// System base path.
51    pub network_path: PathBuf,
52
53    /// Maximum established incoming swarm connection limit.
54    pub max_in_connections: u32,
55
56    /// Maximum established outgoing swarm connection limit.
57    pub max_out_connections: u32,
58
59    /// Maximum pending incoming swarm connection limit.
60    pub max_pending_in_connections: u32,
61
62    /// Maximum pending outgoing swarm connection limit.
63    pub max_pending_out_connections: u32,
64
65    /// Known external addresses
66    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            // We need to enable protocol to request pieces
108            CachedPieceByIndexRequestHandler::create(|_, _| async { None }),
109            // We need to enable protocol to request pieces
110            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}