Skip to content

Commit

Permalink
DSN external addresses. (#1753)
Browse files Browse the repository at this point in the history
* Add external DSN addresses.

* networking: Add observed external address handling.

* networking: Add filter for observed external addresses.

- add observed addresses only if no external addresses were specified manually
  • Loading branch information
shamil-gadelshin authored Aug 3, 2023
1 parent fc107b3 commit 13c49a0
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub(super) fn configure_dsn(
pending_in_connections,
pending_out_connections,
target_connections,
external_addresses,
}: DsnArgs,
readers_and_pieces: &Arc<Mutex<Option<ReadersAndPieces>>>,
node_client: NodeRpcClient,
Expand Down Expand Up @@ -271,6 +272,7 @@ pub(super) fn configure_dsn(
!PeerInfo::is_farmer(peer_info)
})),
bootstrap_addresses: bootstrap_nodes,
external_addresses,
..default_config
};

Expand Down
4 changes: 4 additions & 0 deletions crates/subspace-farmer/src/bin/subspace-farmer/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ struct DsnArgs {
/// Defines target total (in and out) connection number that should be maintained.
#[arg(long, default_value_t = 50)]
target_connections: u32,
/// Known external addresses
#[arg(long, alias = "external-address")]
external_addresses: Vec<Multiaddr>,
}

#[derive(Debug, Clone, Copy, ValueEnum)]
Expand All @@ -118,6 +121,7 @@ impl Default for WriteToDisk {
}
}

#[allow(clippy::large_enum_variant)] // we allow large function parameter list and enums
#[derive(Debug, clap::Subcommand)]
enum Subcommand {
/// Wipes plot and identity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ enum Command {
/// production use.
#[arg(long)]
protocol_version: String,
/// Known external addresses
#[arg(long, alias = "external-address")]
external_addresses: Vec<Multiaddr>,
},
/// Generate a new keypair
GenerateKeypair {
Expand Down Expand Up @@ -126,6 +129,7 @@ async fn main() -> anyhow::Result<()> {
db_path,
piece_providers_cache_size,
protocol_version,
external_addresses,
} => {
debug!(
"Libp2p protocol stack instantiated with version: {} ",
Expand Down Expand Up @@ -178,6 +182,7 @@ async fn main() -> anyhow::Result<()> {
general_connected_peers_handler: None,
special_connected_peers_handler: None,
bootstrap_addresses: bootstrap_nodes,
external_addresses,

..Config::new(
protocol_version.to_string(),
Expand Down
12 changes: 12 additions & 0 deletions crates/subspace-networking/src/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,9 @@ pub struct Config<ProviderStorage> {
pub bootstrap_addresses: Vec<Multiaddr>,
/// Kademlia mode. None means "automatic mode".
pub kademlia_mode: Option<Mode>,
/// Known external addresses to the local peer. The addresses will be added on the swarm start
/// and enable peer to notify others about its reachable address.
pub external_addresses: Vec<Multiaddr>,
}

impl<ProviderStorage> fmt::Debug for Config<ProviderStorage> {
Expand Down Expand Up @@ -341,6 +344,7 @@ where
special_target_connections: SWARM_TARGET_CONNECTION_NUMBER,
bootstrap_addresses: Vec::new(),
kademlia_mode: Some(Mode::Server),
external_addresses: Vec::new(),
}
}
}
Expand Down Expand Up @@ -405,6 +409,7 @@ where
special_target_connections,
bootstrap_addresses,
kademlia_mode,
external_addresses,
} = config;
let local_peer_id = peer_id(&keypair);

Expand Down Expand Up @@ -487,6 +492,12 @@ where
}
}

// Setup external addresses
for addr in external_addresses.iter().cloned() {
info!("DSN external address added: {addr}");
swarm.add_external_address(addr);
}

// Create final structs
let (command_sender, command_receiver) = mpsc::channel(1);

Expand Down Expand Up @@ -518,6 +529,7 @@ where
special_connection_decision_handler,
bootstrap_addresses,
kademlia_mode,
external_addresses,
});

Ok((node, node_runner))
Expand Down
47 changes: 47 additions & 0 deletions crates/subspace-networking/src/node_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use libp2p::kad::{
ProgressStep, ProviderRecord, PutRecordOk, QueryId, QueryResult, Quorum, Record,
};
use libp2p::metrics::{Metrics, Recorder};
use libp2p::multiaddr::Protocol;
use libp2p::swarm::{DialError, SwarmEvent};
use libp2p::{futures, Multiaddr, PeerId, Swarm, TransportError};
use nohash_hasher::IntMap;
Expand Down Expand Up @@ -141,6 +142,9 @@ where
bootstrap_command_state: Arc<AsyncMutex<BootstrapCommandState>>,
/// Kademlia mode. None means "automatic mode".
kademlia_mode: Option<Mode>,
/// Known external addresses to the local peer. The addresses are added on the swarm start
/// and enable peer to notify others about its reachable address.
external_addresses: Vec<Multiaddr>,
}

// Helper struct for NodeRunner configuration (clippy requirement).
Expand All @@ -162,6 +166,7 @@ where
pub(crate) special_connection_decision_handler: Option<ConnectedPeersHandler>,
pub(crate) bootstrap_addresses: Vec<Multiaddr>,
pub(crate) kademlia_mode: Option<Mode>,
pub(crate) external_addresses: Vec<Multiaddr>,
}

impl<ProviderStorage> NodeRunner<ProviderStorage>
Expand All @@ -184,6 +189,7 @@ where
special_connection_decision_handler,
bootstrap_addresses,
kademlia_mode,
external_addresses,
}: NodeRunnerConfig<ProviderStorage>,
) -> Self {
Self {
Expand Down Expand Up @@ -211,6 +217,7 @@ where
bootstrap_addresses,
bootstrap_command_state: Arc::new(AsyncMutex::new(BootstrapCommandState::default())),
kademlia_mode,
external_addresses,
}
}

Expand Down Expand Up @@ -657,7 +664,47 @@ where

kademlia.remove_peer(&peer_id);
}

self.add_observed_external_address(info.observed_addr);
}
}

fn add_observed_external_address(&mut self, observed_addr: Multiaddr) {
if !self.external_addresses.is_empty() {
debug!(
"Observed address wasn't added as external (manual external addresses set): {}",
observed_addr
);
return;
}

// TODO: replace with Autonat
// TODO: won't work with QUIC
let mut listen_ports = HashSet::new();
for mut listen_address in self.swarm.listeners().cloned() {
while let Some(protocol) = listen_address.pop() {
if let Protocol::Tcp(port) = protocol {
listen_ports.insert(port);
}
}
}

let mut observed_addr_candidate = observed_addr.clone();
while let Some(protocol) = observed_addr_candidate.pop() {
if let Protocol::Tcp(port) = protocol {
if listen_ports.contains(&port) {
debug!("Added observed address as external: {}", observed_addr);
self.swarm.add_external_address(observed_addr);

return;
}
}
}

debug!(
"Observed address wasn't added as external (different port): {}",
observed_addr
);
}

async fn handle_kademlia_event(&mut self, event: KademliaEvent) {
Expand Down
1 change: 1 addition & 0 deletions crates/subspace-node/src/bin/subspace-node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ fn main() -> Result<(), Error> {
max_pending_in_connections: cli.dsn_pending_in_connections,
max_pending_out_connections: cli.dsn_pending_out_connections,
target_connections: cli.dsn_target_connections,
external_addresses: cli.dsn_external_addresses,
}
};

Expand Down
4 changes: 4 additions & 0 deletions crates/subspace-node/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ pub struct Cli {
#[arg(long, default_value_t = true, action = clap::ArgAction::Set)]
pub sync_from_dsn: bool,

/// Known external addresses
#[arg(long, alias = "dsn-external-address")]
pub dsn_external_addresses: Vec<Multiaddr>,

/// Piece cache size in human readable format (e.g. 10GB, 2TiB) or just bytes (e.g. 4096).
#[arg(long, default_value = "1GiB")]
pub piece_cache_size: ByteSize,
Expand Down
4 changes: 4 additions & 0 deletions crates/subspace-service/src/dsn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ pub struct DsnConfig {

/// Defines target total (in and out) connection number for DSN that should be maintained.
pub target_connections: u32,

/// Known external addresses
pub external_addresses: Vec<Multiaddr>,
}

pub(crate) fn create_dsn_instance<AS>(
Expand Down Expand Up @@ -181,6 +184,7 @@ where
// maintain permanent connections with any peer
general_connected_peers_handler: Some(Arc::new(|_| true)),
bootstrap_addresses: dsn_config.bootstrap_nodes,
external_addresses: dsn_config.external_addresses,

..default_networking_config
};
Expand Down

0 comments on commit 13c49a0

Please sign in to comment.