Skip to content

Commit

Permalink
networking: Introduce automatic Kademlia mode.
Browse files Browse the repository at this point in the history
  • Loading branch information
shamil-gadelshin committed Oct 9, 2023
1 parent fdddc4a commit db8cabb
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ use subspace_farmer::piece_cache::PieceCache;
use subspace_farmer::utils::readers_and_pieces::ReadersAndPieces;
use subspace_farmer::{NodeClient, NodeRpcClient};
use subspace_networking::libp2p::identity::Keypair;
use subspace_networking::libp2p::kad::RecordKey;
use subspace_networking::libp2p::kad::{Mode, RecordKey};
use subspace_networking::libp2p::metrics::Metrics;
use subspace_networking::libp2p::multiaddr::Protocol;
use subspace_networking::utils::multihash::ToMultihash;
use subspace_networking::utils::strip_peer_id;
use subspace_networking::{
construct, Config, NetworkingParametersManager, Node, NodeRunner, PeerInfo, PeerInfoProvider,
PieceByIndexRequest, PieceByIndexRequestHandler, PieceByIndexResponse,
construct, Config, KademliaMode, NetworkingParametersManager, Node, NodeRunner, PeerInfo,
PeerInfoProvider, PieceByIndexRequest, PieceByIndexRequestHandler, PieceByIndexResponse,
SegmentHeaderBySegmentIndexesRequestHandler, SegmentHeaderRequest, SegmentHeaderResponse,
};
use subspace_rpc_primitives::MAX_SEGMENT_HEADERS_PER_REQUEST;
Expand Down Expand Up @@ -189,6 +189,9 @@ pub(super) fn configure_dsn(
!PeerInfo::is_farmer(peer_info)
})),
bootstrap_addresses: bootstrap_nodes,
kademlia_mode: KademliaMode::Dynamic {
initial_mode: Mode::Client,
},
external_addresses,
metrics,
..default_config
Expand Down
2 changes: 0 additions & 2 deletions crates/subspace-networking/examples/benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use futures::future::pending;
use futures::stream::FuturesUnordered;
use futures::StreamExt;
use libp2p::identity::Keypair;
use libp2p::kad::Mode;
use libp2p::multiaddr::Protocol;
use libp2p::Multiaddr;
use parking_lot::Mutex;
Expand Down Expand Up @@ -273,7 +272,6 @@ pub async fn configure_dsn(
let config = Config {
listen_on: vec!["/ip4/0.0.0.0/tcp/0".parse().unwrap()],
allow_non_global_addresses_in_dht: enable_private_ips,
kademlia_mode: Some(Mode::Client),
request_response_protocols: vec![PieceByIndexRequestHandler::create(|_, _| async { None })],
bootstrap_addresses,
enable_autonat: false,
Expand Down
2 changes: 0 additions & 2 deletions crates/subspace-networking/examples/random-walker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use futures::channel::oneshot;
use futures::future::pending;
use futures::StreamExt;
use libp2p::identity::Keypair;
use libp2p::kad::Mode;
use libp2p::multiaddr::Protocol;
use libp2p::{Multiaddr, PeerId};
use parking_lot::Mutex;
Expand Down Expand Up @@ -366,7 +365,6 @@ async fn configure_dsn(
let config = Config {
listen_on: vec!["/ip4/0.0.0.0/tcp/0".parse().unwrap()],
allow_non_global_addresses_in_dht: enable_private_ips,
kademlia_mode: Some(Mode::Client),
request_response_protocols: vec![PieceByIndexRequestHandler::create(|_, _| async { None })],
bootstrap_addresses,
enable_autonat: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use futures::{select, FutureExt};
use libp2p::identity::ed25519::Keypair;
use libp2p::metrics::Metrics;
use libp2p::{identity, Multiaddr, PeerId};
use libp2p_kad::Mode;
use prometheus_client::registry::Registry;
use serde::{Deserialize, Serialize};
use std::error::Error;
Expand All @@ -15,7 +16,7 @@ use std::net::SocketAddr;
use std::sync::Arc;
use subspace_metrics::{start_prometheus_metrics_server, RegistryAdapter};
use subspace_networking::libp2p::multiaddr::Protocol;
use subspace_networking::{peer_id, Config};
use subspace_networking::{peer_id, Config, KademliaMode};
use tracing::{debug, info, Level};
use tracing_subscriber::fmt::Subscriber;
use tracing_subscriber::util::SubscriberInitExt;
Expand Down Expand Up @@ -163,6 +164,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
general_connected_peers_handler: None,
special_connected_peers_handler: None,
bootstrap_addresses: bootstrap_nodes,
kademlia_mode: KademliaMode::Static(Mode::Server),
external_addresses,
metrics,

Expand Down
21 changes: 18 additions & 3 deletions crates/subspace-networking/src/constructor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,20 @@ const TEMPORARY_BANS_DEFAULT_BACKOFF_RANDOMIZATION_FACTOR: f64 = 0.1;
const TEMPORARY_BANS_DEFAULT_BACKOFF_MULTIPLIER: f64 = 1.5;
const TEMPORARY_BANS_DEFAULT_MAX_INTERVAL: Duration = Duration::from_secs(30 * 60);

/// Max confidence for autonat protocol. Could affect Kademlia mode change.
pub(crate) const AUTONAT_MAX_CONFIDENCE: usize = 3;

/// Defines Kademlia mode
pub enum KademliaMode {
/// The Kademlia mode is static for the duration of the application.
Static(Mode),
/// Kademlia mode will be changed using Autonat protocol when max confidence reached.
Dynamic {
/// Defines initial Kademlia mode.
initial_mode: Mode,
},
}

/// Trait to be implemented on providers of local records
pub trait LocalRecordProvider {
/// Gets a provider record for key that is stored locally
Expand Down Expand Up @@ -221,8 +235,8 @@ pub struct Config<LocalRecordProvider> {
pub special_target_connections: u32,
/// Addresses to bootstrap Kademlia network
pub bootstrap_addresses: Vec<Multiaddr>,
/// Kademlia mode. None means "automatic mode".
pub kademlia_mode: Option<Mode>,
/// Kademlia mode.
pub kademlia_mode: KademliaMode,
/// 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>,
Expand Down Expand Up @@ -340,7 +354,7 @@ where
general_target_connections: SWARM_TARGET_CONNECTION_NUMBER,
special_target_connections: SWARM_TARGET_CONNECTION_NUMBER,
bootstrap_addresses: Vec::new(),
kademlia_mode: Some(Mode::Server),
kademlia_mode: KademliaMode::Static(Mode::Client),
external_addresses: Vec::new(),
enable_autonat: true,
}
Expand Down Expand Up @@ -468,6 +482,7 @@ where
autonat: enable_autonat.then(|| AutonatConfig {
use_connected: true,
only_global_ips: !config.allow_non_global_addresses_in_dht,
confidence_max: AUTONAT_MAX_CONFIDENCE,
..Default::default()
}),
});
Expand Down
4 changes: 3 additions & 1 deletion crates/subspace-networking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ pub use crate::node_runner::NodeRunner;
pub use crate::protocols::peer_info::{
Config as PeerInfoConfig, Notification, NotificationHandler, PeerInfo, PeerInfoProvider,
};
pub use constructor::{construct, peer_id, Config, CreationError, LocalRecordProvider};
pub use constructor::{
construct, peer_id, Config, CreationError, KademliaMode, LocalRecordProvider,
};
pub use libp2p;
pub use protocols::request_response::handlers::generic_request_handler::{
GenericRequest, GenericRequestHandler,
Expand Down
54 changes: 44 additions & 10 deletions crates/subspace-networking/src/node_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::behavior::{
};
use crate::constructor;
use crate::constructor::temporary_bans::TemporaryBans;
use crate::constructor::{ConnectedPeersHandler, LocalOnlyRecordStore};
use crate::constructor::{ConnectedPeersHandler, KademliaMode, LocalOnlyRecordStore};
use crate::protocols::connected_peers::Event as ConnectedPeersEvent;
use crate::protocols::peer_info::{Event as PeerInfoEvent, PeerInfoSuccess};
use crate::protocols::request_response::request_response_factory::{
Expand All @@ -22,18 +22,19 @@ use event_listener_primitives::HandlerId;
use futures::channel::mpsc;
use futures::future::Fuse;
use futures::{FutureExt, StreamExt};
use libp2p::autonat::Event as AutonatEvent;
use libp2p::autonat::{Event as AutonatEvent, NatStatus};
use libp2p::core::{address_translation, ConnectedPoint};
use libp2p::gossipsub::{Event as GossipsubEvent, TopicHash};
use libp2p::identify::Event as IdentifyEvent;
use libp2p::kad::{
BootstrapOk, GetClosestPeersError, GetClosestPeersOk, GetProvidersError, GetProvidersOk,
GetRecordError, GetRecordOk, InboundRequest, Kademlia, KademliaEvent, Mode, PeerRecord,
ProgressStep, PutRecordOk, QueryId, QueryResult, Quorum, Record,
GetRecordError, GetRecordOk, InboundRequest, Kademlia, KademliaEvent, PeerRecord, ProgressStep,
PutRecordOk, QueryId, QueryResult, Quorum, Record,
};
use libp2p::metrics::{Metrics, Recorder};
use libp2p::swarm::{DialError, SwarmEvent};
use libp2p::{futures, Multiaddr, PeerId, Swarm, TransportError};
use libp2p_kad::Mode;
use nohash_hasher::IntMap;
use parking_lot::Mutex;
use rand::rngs::StdRng;
Expand Down Expand Up @@ -137,8 +138,8 @@ where
bootstrap_addresses: Vec<Multiaddr>,
/// Ensures a single bootstrap on run() invocation.
bootstrap_command_state: Arc<AsyncMutex<BootstrapCommandState>>,
/// Kademlia mode. None means "automatic mode".
kademlia_mode: Option<Mode>,
/// Kademlia mode.
kademlia_mode: KademliaMode,
/// 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>,
Expand Down Expand Up @@ -167,7 +168,7 @@ where
pub(crate) general_connection_decision_handler: Option<ConnectedPeersHandler>,
pub(crate) special_connection_decision_handler: Option<ConnectedPeersHandler>,
pub(crate) bootstrap_addresses: Vec<Multiaddr>,
pub(crate) kademlia_mode: Option<Mode>,
pub(crate) kademlia_mode: KademliaMode,
pub(crate) external_addresses: Vec<Multiaddr>,
}

Expand Down Expand Up @@ -318,11 +319,17 @@ where

debug!("Bootstrap started.");

let initial_mode = match self.kademlia_mode {
KademliaMode::Static(mode) => mode,
KademliaMode::Dynamic { initial_mode } => initial_mode,
};

self.swarm
.behaviour_mut()
.kademlia
.set_mode(self.kademlia_mode);
debug!("Kademlia mode set: {:?}.", self.kademlia_mode);
.set_mode(Some(initial_mode));

debug!("Kademlia mode set: {:?}.", initial_mode);

let mut bootstrap_step = 0;
loop {
Expand Down Expand Up @@ -1186,7 +1193,34 @@ where
}

if let AutonatEvent::StatusChanged { old, new } = event {
info!(?old, ?new, "Public address status changed.")
info!(?old, ?new, "Public address status changed.");

if let KademliaMode::Dynamic { .. } = self.kademlia_mode {
let mode = match &new {
NatStatus::Public(address) => {
if is_global_address_or_dns(address)
|| self.allow_non_global_addresses_in_dht
{
Mode::Server
} else {
debug!(
?old,
?new,
?address,
non_global_addresses=%self.allow_non_global_addresses_in_dht,
"Kademlia mode wasn't set."
);
Mode::Client
}
}
NatStatus::Private => Mode::Client,
NatStatus::Unknown => Mode::Client,
};

self.swarm.behaviour_mut().kademlia.set_mode(Some(mode));

debug!("Kademlia mode set: {:?}.", mode);
};
}
}

Expand Down
8 changes: 4 additions & 4 deletions crates/subspace-service/src/dsn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ use std::fs;
use std::path::PathBuf;
use std::sync::Arc;
use subspace_core_primitives::{SegmentHeader, SegmentIndex};
use subspace_networking::libp2p::kad::Mode as KademliaMode;
use subspace_networking::libp2p::kad::Mode;
use subspace_networking::libp2p::metrics::Metrics;
use subspace_networking::libp2p::{identity, Multiaddr};
use subspace_networking::utils::strip_peer_id;
use subspace_networking::{
CreationError, NetworkParametersPersistenceError, NetworkingParametersManager, Node,
NodeRunner, PeerInfoProvider, PieceByIndexRequestHandler,
CreationError, KademliaMode, NetworkParametersPersistenceError, NetworkingParametersManager,
Node, NodeRunner, PeerInfoProvider, PieceByIndexRequestHandler,
SegmentHeaderBySegmentIndexesRequestHandler, SegmentHeaderRequest, SegmentHeaderResponse,
};
use thiserror::Error;
Expand Down Expand Up @@ -183,7 +183,7 @@ where
general_connected_peers_handler: Some(Arc::new(|_| true)),
bootstrap_addresses: dsn_config.bootstrap_nodes,
external_addresses: dsn_config.external_addresses,
kademlia_mode: Some(KademliaMode::Client),
kademlia_mode: KademliaMode::Static(Mode::Client),
metrics,

..default_networking_config
Expand Down

0 comments on commit db8cabb

Please sign in to comment.