Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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"),
}
}
AnchorBehaviourEvent::PeerManager(peer_manager::Event::Heartbeat(heartbeat)) => {
if let Some(actions) = heartbeat.connect_actions {
self.handle_connect_actions(actions);
Expand Down