From e7477c7adec4af6981a4cadb9a5fdaa5e6181076 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 31 Mar 2026 03:44:54 +0000 Subject: [PATCH 1/2] Remove --ip-version CLI flag, always use dual-stack The --ip-version flag allowed users to restrict the node to IPv4-only or IPv6-only mode. This was flagged for removal as it enables misconfiguration ("we cannot go back to tweakers"). The node now always runs in dual-stack mode (both IPv4 and IPv6), which was already the default. Changes: - Remove --ip-version CLI arg and ANT_IP_VERSION env var - Remove IpVersion enum from config - Remove ip_version field from NodeConfig - Remove CliIpVersion enum and From impl - Hardcode ipv6=true in core config builder (dual-stack) - Update production.toml, testnet scripts, and README https://claude.ai/code/session_01ApfhBFUhWMnYoZj7P1VkvU --- README.md | 5 ----- config/production.toml | 3 --- scripts/testnet/spawn-nodes.sh | 1 - scripts/testnet/start-genesis.sh | 2 -- src/bin/ant-node/cli.rs | 30 ++---------------------------- src/config.rs | 18 ------------------ src/node.rs | 5 ++--- 7 files changed, 4 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index 95463e4..97de20e 100644 --- a/README.md +++ b/README.md @@ -907,7 +907,6 @@ You can also specify bootstrap peers explicitly: ./target/release/ant-node \ --root-dir ~/.ant-node \ --port 12000 \ - --ip-version dual \ --upgrade-channel stable \ --migrate-ant-data auto \ --log-level info @@ -929,9 +928,6 @@ Options: Listening port (0 for automatic selection) [default: 0] - --ip-version - IP version to use: ipv4, ipv6, or dual - [default: dual] --bootstrap Bootstrap peer socket addresses (can be specified multiple times) @@ -1016,7 +1012,6 @@ export ANT_UPGRADE_CHANNEL=stable ```toml root_dir = "~/.ant-node" port = 0 # Auto-select -ip_version = "dual" bootstrap = [ "10.0.0.1:10000", "10.0.0.2:10000", diff --git a/config/production.toml b/config/production.toml index 3e83ed0..bbcb1a2 100644 --- a/config/production.toml +++ b/config/production.toml @@ -9,9 +9,6 @@ root_dir = "/var/lib/ant" # Listening port (10000-10999 for production) port = 10000 -# IP version: "ipv4", "ipv6", or "dual" -ip_version = "dual" - # Bootstrap peer addresses (socket addrs) bootstrap = [] diff --git a/scripts/testnet/spawn-nodes.sh b/scripts/testnet/spawn-nodes.sh index 15ba852..374a077 100755 --- a/scripts/testnet/spawn-nodes.sh +++ b/scripts/testnet/spawn-nodes.sh @@ -58,7 +58,6 @@ Type=simple ExecStart=/usr/local/bin/ant-node \\ --root-dir ${NODE_DIR} \\ --port ${PORT} \\ - --ip-version ipv4 \\ --network-mode testnet \\ ${BOOTSTRAP_FLAGS} \\ --metrics-port ${METRICS} \\ diff --git a/scripts/testnet/start-genesis.sh b/scripts/testnet/start-genesis.sh index 913e901..0d60cb7 100755 --- a/scripts/testnet/start-genesis.sh +++ b/scripts/testnet/start-genesis.sh @@ -23,7 +23,6 @@ Type=simple ExecStart=/usr/local/bin/ant-node \ --root-dir /var/lib/ant/nodes/node-0 \ --port 12000 \ - --ip-version ipv4 \ --metrics-port 9100 \ --log-level info \ --upgrade-channel stable \ @@ -64,7 +63,6 @@ Type=simple ExecStart=/usr/local/bin/ant-node \ --root-dir /var/lib/ant/nodes/node-50 \ --port 12000 \ - --ip-version ipv4 \ -b 142.93.52.129:12000 \ --metrics-port 9100 \ --log-level info \ diff --git a/src/bin/ant-node/cli.rs b/src/bin/ant-node/cli.rs index 861c78c..9249fd8 100644 --- a/src/bin/ant-node/cli.rs +++ b/src/bin/ant-node/cli.rs @@ -1,8 +1,8 @@ //! Command-line interface definition. use ant_node::config::{ - BootstrapCacheConfig, BootstrapPeersConfig, BootstrapSource, EvmNetworkConfig, IpVersion, - NetworkMode, NodeConfig, PaymentConfig, UpgradeChannel, + BootstrapCacheConfig, BootstrapPeersConfig, BootstrapSource, EvmNetworkConfig, NetworkMode, + NodeConfig, PaymentConfig, UpgradeChannel, }; use clap::{Parser, ValueEnum}; use std::net::SocketAddr; @@ -21,10 +21,6 @@ pub struct Cli { #[arg(long, short, default_value = "0", env = "ANT_PORT")] pub port: u16, - /// IP version to use. - #[arg(long, value_enum, default_value = "dual", env = "ANT_IP_VERSION")] - pub ip_version: CliIpVersion, - /// Bootstrap peer addresses. #[arg(long, short, env = "ANT_BOOTSTRAP")] pub bootstrap: Vec, @@ -112,17 +108,6 @@ pub struct Cli { pub bootstrap_cache_capacity: usize, } -/// IP version CLI enum. -#[derive(Debug, Clone, Copy, ValueEnum)] -pub enum CliIpVersion { - /// IPv4 only. - Ipv4, - /// IPv6 only. - Ipv6, - /// Dual-stack (both IPv4 and IPv6). - Dual, -} - /// Upgrade channel CLI enum. #[derive(Debug, Clone, Copy, ValueEnum)] pub enum CliUpgradeChannel { @@ -215,7 +200,6 @@ impl Cli { } config.port = self.port; - config.ip_version = self.ip_version.into(); config.log_level = self.log_level.into(); config.network_mode = self.network_mode.into(); @@ -266,16 +250,6 @@ impl Cli { } } -impl From for IpVersion { - fn from(v: CliIpVersion) -> Self { - match v { - CliIpVersion::Ipv4 => Self::Ipv4, - CliIpVersion::Ipv6 => Self::Ipv6, - CliIpVersion::Dual => Self::Dual, - } - } -} - impl From for UpgradeChannel { fn from(c: CliUpgradeChannel) -> Self { match c { diff --git a/src/config.rs b/src/config.rs index 2c478f1..25dc102 100644 --- a/src/config.rs +++ b/src/config.rs @@ -10,19 +10,6 @@ pub const NODE_IDENTITY_FILENAME: &str = "node_identity.key"; /// Subdirectory under the root dir that contains per-node data directories. pub const NODES_SUBDIR: &str = "nodes"; -/// IP version configuration. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)] -#[serde(rename_all = "lowercase")] -pub enum IpVersion { - /// IPv4 only. - Ipv4, - /// IPv6 only. - Ipv6, - /// Dual-stack (both IPv4 and IPv6). - #[default] - Dual, -} - /// Upgrade channel for auto-updates. #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] @@ -99,10 +86,6 @@ pub struct NodeConfig { #[serde(default)] pub port: u16, - /// IP version to use. - #[serde(default)] - pub ip_version: IpVersion, - /// Bootstrap peer addresses. #[serde(default)] pub bootstrap: Vec, @@ -249,7 +232,6 @@ impl Default for NodeConfig { Self { root_dir: default_root_dir(), port: 0, - ip_version: IpVersion::default(), bootstrap: Vec::new(), network_mode: NetworkMode::default(), testnet: TestnetConfig::default(), diff --git a/src/node.rs b/src/node.rs index 7c833f8..fb6eecf 100644 --- a/src/node.rs +++ b/src/node.rs @@ -2,7 +2,7 @@ use crate::ant_protocol::{CHUNK_PROTOCOL_ID, MAX_CHUNK_SIZE}; use crate::config::{ - default_nodes_dir, default_root_dir, EvmNetworkConfig, IpVersion, NetworkMode, NodeConfig, + default_nodes_dir, default_root_dir, EvmNetworkConfig, NetworkMode, NodeConfig, NODE_IDENTITY_FILENAME, }; use crate::error::{Error, Result}; @@ -151,12 +151,11 @@ impl NodeBuilder { /// Build the saorsa-core `NodeConfig` from our config. fn build_core_config(config: &NodeConfig) -> Result { - let ipv6 = matches!(config.ip_version, IpVersion::Ipv6 | IpVersion::Dual); let local = matches!(config.network_mode, NetworkMode::Development); let mut core_config = CoreNodeConfig::builder() .port(config.port) - .ipv6(ipv6) + .ipv6(true) .local(local) .max_message_size(config.max_message_size) .build() From 202f41a09a2fc6decd2c8f0713d5385966aaff65 Mon Sep 17 00:00:00 2001 From: grumbach Date: Tue, 31 Mar 2026 17:28:46 +0900 Subject: [PATCH 2/2] Address review: add --ipv4-only escape hatch, remove stale ANT_IP_VERSION Instead of removing IP version control entirely, add a simple --ipv4-only boolean flag as an opt-out for hosts without working IPv6. This addresses the reachability risk on IPv4-only kernels and hosts with non-routable IPv6 addresses, while keeping dual-stack as the default. - Add ipv4_only field to NodeConfig - Add --ipv4-only CLI flag (ANT_IPV4_ONLY env var) - Use ipv4_only in build_core_config to conditionally set ipv6 - Add --ipv4-only to testnet scripts (VPS nodes need it) - Remove stale ANT_IP_VERSION=dual from README env vars section - Document --ipv4-only in README CLI options - Add tests for ipv4_only and dual-stack default behavior --- README.md | 4 +++- scripts/testnet/spawn-nodes.sh | 1 + scripts/testnet/start-genesis.sh | 2 ++ src/bin/ant-node/cli.rs | 7 +++++++ src/config.rs | 9 +++++++++ src/node.rs | 19 ++++++++++++++++++- 6 files changed, 40 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 97de20e..33c47f4 100644 --- a/README.md +++ b/README.md @@ -928,6 +928,9 @@ Options: Listening port (0 for automatic selection) [default: 0] + --ipv4-only + Force IPv4-only mode (disable dual-stack). + Use on hosts without working IPv6. --bootstrap Bootstrap peer socket addresses (can be specified multiple times) @@ -999,7 +1002,6 @@ peers = [ ```bash export ANT_ROOT_DIR=~/.ant-node export ANT_PORT=12000 -export ANT_IP_VERSION=dual export ANT_LOG_LEVEL=info export ANT_AUTO_UPGRADE=true export ANT_UPGRADE_CHANNEL=stable diff --git a/scripts/testnet/spawn-nodes.sh b/scripts/testnet/spawn-nodes.sh index 374a077..90610ef 100755 --- a/scripts/testnet/spawn-nodes.sh +++ b/scripts/testnet/spawn-nodes.sh @@ -58,6 +58,7 @@ Type=simple ExecStart=/usr/local/bin/ant-node \\ --root-dir ${NODE_DIR} \\ --port ${PORT} \\ + --ipv4-only \\ --network-mode testnet \\ ${BOOTSTRAP_FLAGS} \\ --metrics-port ${METRICS} \\ diff --git a/scripts/testnet/start-genesis.sh b/scripts/testnet/start-genesis.sh index 0d60cb7..bd1ca1c 100755 --- a/scripts/testnet/start-genesis.sh +++ b/scripts/testnet/start-genesis.sh @@ -23,6 +23,7 @@ Type=simple ExecStart=/usr/local/bin/ant-node \ --root-dir /var/lib/ant/nodes/node-0 \ --port 12000 \ + --ipv4-only \ --metrics-port 9100 \ --log-level info \ --upgrade-channel stable \ @@ -63,6 +64,7 @@ Type=simple ExecStart=/usr/local/bin/ant-node \ --root-dir /var/lib/ant/nodes/node-50 \ --port 12000 \ + --ipv4-only \ -b 142.93.52.129:12000 \ --metrics-port 9100 \ --log-level info \ diff --git a/src/bin/ant-node/cli.rs b/src/bin/ant-node/cli.rs index 9249fd8..0d6509c 100644 --- a/src/bin/ant-node/cli.rs +++ b/src/bin/ant-node/cli.rs @@ -21,6 +21,12 @@ pub struct Cli { #[arg(long, short, default_value = "0", env = "ANT_PORT")] pub port: u16, + /// Force IPv4-only mode (disable dual-stack). + /// Use on hosts without working IPv6 to avoid advertising + /// unreachable addresses to the DHT. + #[arg(long, env = "ANT_IPV4_ONLY")] + pub ipv4_only: bool, + /// Bootstrap peer addresses. #[arg(long, short, env = "ANT_BOOTSTRAP")] pub bootstrap: Vec, @@ -200,6 +206,7 @@ impl Cli { } config.port = self.port; + config.ipv4_only = self.ipv4_only; config.log_level = self.log_level.into(); config.network_mode = self.network_mode.into(); diff --git a/src/config.rs b/src/config.rs index 25dc102..47cfbeb 100644 --- a/src/config.rs +++ b/src/config.rs @@ -86,6 +86,14 @@ pub struct NodeConfig { #[serde(default)] pub port: u16, + /// Force IPv4-only mode. + /// + /// When true, the node binds only on IPv4 instead of dual-stack. + /// Use this on hosts without working IPv6 to avoid advertising + /// unreachable addresses to the DHT. + #[serde(default)] + pub ipv4_only: bool, + /// Bootstrap peer addresses. #[serde(default)] pub bootstrap: Vec, @@ -232,6 +240,7 @@ impl Default for NodeConfig { Self { root_dir: default_root_dir(), port: 0, + ipv4_only: false, bootstrap: Vec::new(), network_mode: NetworkMode::default(), testnet: TestnetConfig::default(), diff --git a/src/node.rs b/src/node.rs index fb6eecf..2a2e724 100644 --- a/src/node.rs +++ b/src/node.rs @@ -155,7 +155,7 @@ impl NodeBuilder { let mut core_config = CoreNodeConfig::builder() .port(config.port) - .ipv6(true) + .ipv6(!config.ipv4_only) .local(local) .max_message_size(config.max_message_size) .build() @@ -861,6 +861,23 @@ mod tests { assert!(core.diversity_config.is_some()); } + #[test] + fn test_build_core_config_ipv4_only() { + let config = NodeConfig { + ipv4_only: true, + ..Default::default() + }; + let core = NodeBuilder::build_core_config(&config).expect("core config"); + assert!(!core.ipv6, "ipv4_only should disable IPv6"); + } + + #[test] + fn test_build_core_config_dual_stack_by_default() { + let config = NodeConfig::default(); + let core = NodeBuilder::build_core_config(&config).expect("core config"); + assert!(core.ipv6, "dual-stack should be the default"); + } + #[test] fn test_build_core_config_sets_development_mode_permissive() { let config = NodeConfig {