Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce automatic Kademlia mode for subspace-networking. #2076

Merged
merged 2 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
shamil-gadelshin marked this conversation as resolved.
Show resolved Hide resolved
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 {
shamil-gadelshin marked this conversation as resolved.
Show resolved Hide resolved
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