Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
8 changes: 8 additions & 0 deletions anchor/client/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,14 @@ pub struct Node {
)]
pub use_zero_ports: bool,

#[clap(
long,
help = "Disables UPnP support. Setting this will prevent Anchor \
from attempting to automatically establish external port mappings.",
default_value = "false"
)]
pub disable_upnp: bool,

// Prometheus metrics HTTP server related arguments
#[clap(
long,
Expand Down
3 changes: 3 additions & 0 deletions anchor/client/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ pub fn from_cli(cli_args: &Node, global_config: GlobalConfig) -> Result<Config,

config.network.subscribe_all_subnets = cli_args.subscribe_all_subnets;

// If the flag was set (true), it means we disable upnp so upnp_enabled should be false
config.network.upnp_enabled = !cli_args.disable_upnp;

// Network related - set peer scoring configuration
config.network.disable_gossipsub_peer_scoring = cli_args.disable_gossipsub_peer_scoring;
config.network.disable_gossipsub_topic_scoring = cli_args.disable_gossipsub_topic_scoring;
Expand Down
1 change: 1 addition & 0 deletions anchor/network/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ libp2p = { workspace = true, default-features = false, features = [
"quic",
"ping",
"request-response",
"upnp",
"dns",
] }
message_receiver = { workspace = true }
Expand Down
15 changes: 14 additions & 1 deletion anchor/network/src/behaviour.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ use std::time::Duration;

use discv5::enr::k256::sha2::{Digest, Sha256};
use gossipsub::{ConfigBuilderError, MessageAuthenticity, ValidationMode};
use libp2p::{identify, ping, swarm::NetworkBehaviour};
use libp2p::{
identify, ping,
swarm::{NetworkBehaviour, behaviour::toggle::Toggle},
upnp::tokio::Behaviour as Upnp,
};
use prometheus_client::registry::Registry;
use thiserror::Error;
use types::{ChainSpec, EthSpec};
Expand Down Expand Up @@ -44,6 +48,8 @@ pub struct AnchorBehaviour {
/// Anchor peer manager, wrapping libp2p behaviours with minimal added logic for peer
/// selection.
pub peer_manager: PeerManager,
/// Libp2p UPnP port mapping.
pub upnp: Toggle<Upnp>,

pub handshake: handshake::Behaviour,
}
Expand Down Expand Up @@ -136,13 +142,20 @@ impl AnchorBehaviour {

let handshake = handshake::create_behaviour(local_keypair);

let upnp = Toggle::from(
network_config
.upnp_enabled
.then(libp2p::upnp::tokio::Behaviour::default),
);

Ok(AnchorBehaviour {
identify,
ping: ping::Behaviour::default(),
gossipsub,
discovery,
peer_manager,
handshake,
upnp,
})
}
}
4 changes: 4 additions & 0 deletions anchor/network/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ pub struct Config {
/// Target number of connected peers.
pub target_peers: usize,

/// Attempt to construct external port mappings with UPnP.
pub upnp_enabled: bool,

pub domain_type: DomainType,
}

Expand Down Expand Up @@ -109,6 +112,7 @@ impl Config {
disable_quic_support: false,
subscribe_all_subnets: false,
domain_type: DomainType::default(),
upnp_enabled: true,
}
}
}
38 changes: 38 additions & 0 deletions anchor/network/src/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,44 @@ impl<R: MessageReceiver> Network<R> {
self.handle_handshake_result(result);
}
}
AnchorBehaviourEvent::Upnp(upnp_event) => {
match upnp_event {
libp2p::upnp::Event::NewExternalAddr(addr) => {
info!(%addr, "UPnP route established");
let mut iter = addr.iter();
let is_ipv6 = {
let addr = iter.next();
matches!(addr, Some(Protocol::Ip6(_)))
};
match iter.next() {
Some(Protocol::Udp(udp_port)) => match iter.next() {
Some(Protocol::QuicV1) => {
if let Err(e) =
self.discovery().try_update_port(false, is_ipv6, udp_port)
{
warn!(error = e, "Failed to update ENR");
}
}
_ => {
trace!(%addr, "UPnP address mapped multiaddr from unknown transport");
}
},
Some(Protocol::Tcp(tcp_port)) => {
if let Err(e) = self.discovery().try_update_port(true, is_ipv6, tcp_port) {
warn!(error = e, "Failed to update ENR");
}
}
_ => {
trace!(%addr, "UPnP address mapped multiaddr from unknown transport");
}
}

},
libp2p::upnp::Event::ExpiredExternalAddr(_) => {},
libp2p::upnp::Event::GatewayNotFound => info!("UPnP not available."),
libp2p::upnp::Event::NonRoutableGateway => info!("UPnP is available but gateway is not exposed to public network"),
}
Comment on lines +218 to +253
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move this into it's own function?

}
AnchorBehaviourEvent::PeerManager(peer_manager::Event::Heartbeat(heartbeat)) => {
if let Some(actions) = heartbeat.connect_actions {
self.handle_connect_actions(actions);
Expand Down