Skip to content

Commit 4d55528

Browse files
committed
feat(p2p): add external address configuration for NAT/Docker
Validators can now announce their public IP instead of Docker internal IPs. Use --external-addr CLI flag or EXTERNAL_ADDR env variable. Example: --external-addr /ip4/1.2.3.4/tcp/8090
1 parent c82c1b7 commit 4d55528

4 files changed

Lines changed: 41 additions & 0 deletions

File tree

bins/validator-node/src/main.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,11 @@ struct Args {
157157
#[arg(long, default_value = "/ip4/0.0.0.0/tcp/8090")]
158158
listen_addr: String,
159159

160+
/// External address to announce to peers (multiaddr format, e.g. /ip4/1.2.3.4/tcp/8090)
161+
/// Use this when running behind NAT or in Docker to announce your public IP
162+
#[arg(long, env = "EXTERNAL_ADDR")]
163+
external_addr: Option<String>,
164+
160165
/// Bootstrap peers (multiaddr format)
161166
#[arg(long)]
162167
bootstrap: Vec<String>,
@@ -269,6 +274,12 @@ async fn main() -> Result<()> {
269274
.with_netuid(args.netuid)
270275
.with_min_stake(10_000_000_000_000); // 10000 TAO
271276

277+
// Set external address if provided (for NAT/Docker environments)
278+
if let Some(ref external_addr) = args.external_addr {
279+
p2p_config = p2p_config.with_external_addrs(vec![external_addr.clone()]);
280+
info!("External address configured: {}", external_addr);
281+
}
282+
272283
// Add CLI bootstrap peers to defaults (don't replace)
273284
for peer in &args.bootstrap {
274285
if !p2p_config.bootstrap_peers.contains(peer) {

crates/p2p-consensus/src/config.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ pub const DEFAULT_BOOTSTRAP_NODES: &[&str] = &[
2121
pub struct P2PConfig {
2222
/// Listen addresses (multiaddr format)
2323
pub listen_addrs: Vec<String>,
24+
/// External addresses to announce to peers (multiaddr format)
25+
/// If empty, the node will try to detect its public IP automatically
26+
pub external_addrs: Vec<String>,
2427
/// Bootstrap peers (multiaddr format)
2528
pub bootstrap_peers: Vec<String>,
2629
/// Gossipsub topic for consensus messages
@@ -50,6 +53,7 @@ impl Default for P2PConfig {
5053
fn default() -> Self {
5154
Self {
5255
listen_addrs: vec![format!("/ip4/0.0.0.0/tcp/{}", DEFAULT_P2P_PORT)],
56+
external_addrs: vec![],
5357
bootstrap_peers: DEFAULT_BOOTSTRAP_NODES
5458
.iter()
5559
.map(|s| s.to_string())
@@ -98,10 +102,17 @@ impl P2PConfig {
98102
self
99103
}
100104

105+
/// Add external addresses to announce
106+
pub fn with_external_addrs(mut self, addrs: Vec<String>) -> Self {
107+
self.external_addrs = addrs;
108+
self
109+
}
110+
101111
/// Create a development config with relaxed settings
102112
pub fn development() -> Self {
103113
Self {
104114
listen_addrs: vec!["/ip4/127.0.0.1/tcp/0".to_string()],
115+
external_addrs: vec![],
105116
bootstrap_peers: vec![],
106117
consensus_topic: "platform/consensus/dev".to_string(),
107118
challenge_topic: "platform/challenge/dev".to_string(),
@@ -122,6 +133,7 @@ impl P2PConfig {
122133
format!("/ip4/0.0.0.0/tcp/{}", DEFAULT_P2P_PORT),
123134
format!("/ip6/::/tcp/{}", DEFAULT_P2P_PORT),
124135
],
136+
external_addrs: vec![],
125137
bootstrap_peers: DEFAULT_BOOTSTRAP_NODES
126138
.iter()
127139
.map(|s| s.to_string())

crates/p2p-consensus/src/network.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,20 @@ impl P2PNetwork {
744744
}
745745
}
746746

747+
// Add external addresses for announcement to other peers
748+
// This is crucial for NAT traversal - we announce our public IP instead of internal Docker IPs
749+
for addr_str in &self.config.external_addrs {
750+
match addr_str.parse::<Multiaddr>() {
751+
Ok(addr) => {
752+
swarm.add_external_address(addr.clone());
753+
info!(addr = %addr, "Added external address for announcement");
754+
}
755+
Err(e) => {
756+
error!(addr = %addr_str, error = %e, "Invalid external address");
757+
}
758+
}
759+
}
760+
747761
// Connect to bootstrap peers
748762
for addr_str in &self.config.bootstrap_peers {
749763
match addr_str.parse::<Multiaddr>() {

docker/entrypoint.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ if [ -n "$BOOTSTRAP_PEERS" ]; then
6767
done
6868
fi
6969

70+
if [ -n "$EXTERNAL_ADDR" ]; then
71+
ARGS+=("--external-addr" "$EXTERNAL_ADDR")
72+
fi
73+
7074
# Cleanup crash file on successful start
7175
cleanup() {
7276
rm -f "$CRASH_FILE"

0 commit comments

Comments
 (0)