From 2b1cbbd6f472a362969ac5102bd409a46703a064 Mon Sep 17 00:00:00 2001 From: Warm Beer Date: Tue, 10 Mar 2026 18:54:11 +0100 Subject: [PATCH 1/8] fix: set SAORSA_TRANSPORT_ALLOW_LOOPBACK=true for devnet and testnet modes Local devnets and testnets run all nodes on 127.0.0.1, which requires the transport layer to accept loopback connections. Set the env var in Devnet::start(), TestNetwork::start(), and NodeBuilder::build_core_config() for Development and Testnet network modes. Co-Authored-By: Claude Opus 4.6 --- src/config.rs | 5 +++++ src/devnet.rs | 7 ++++++- src/node.rs | 8 +++++++- tests/e2e/testnet.rs | 4 ++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/config.rs b/src/config.rs index 008d54ba..0c0d95c9 100644 --- a/src/config.rs +++ b/src/config.rs @@ -10,6 +10,11 @@ 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"; +/// Environment variable that tells saorsa-core's transport layer to accept +/// loopback (127.0.0.1) connections. Set to `"true"` for local devnets and +/// testnets where all nodes run on the same machine. +pub const TRANSPORT_ALLOW_LOOPBACK_ENV: &str = "SAORSA_TRANSPORT_ALLOW_LOOPBACK"; + /// IP version configuration. #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] diff --git a/src/devnet.rs b/src/devnet.rs index 3059f475..81339f63 100644 --- a/src/devnet.rs +++ b/src/devnet.rs @@ -4,7 +4,9 @@ //! multi-node networks on a single machine. use crate::ant_protocol::CHUNK_PROTOCOL_ID; -use crate::config::{default_root_dir, NODES_SUBDIR, NODE_IDENTITY_FILENAME}; +use crate::config::{ + default_root_dir, NODES_SUBDIR, NODE_IDENTITY_FILENAME, TRANSPORT_ALLOW_LOOPBACK_ENV, +}; use crate::payment::{ EvmVerifierConfig, PaymentVerifier, PaymentVerifierConfig, QuoteGenerator, QuotingMetricsTracker, @@ -388,6 +390,9 @@ impl Devnet { /// Returns `DevnetError::Startup` if any node fails to start, or /// `DevnetError::Stabilization` if the network does not stabilize within the timeout. pub async fn start(&mut self) -> Result<()> { + // Allow loopback connections — devnet nodes all run on 127.0.0.1. + std::env::set_var(TRANSPORT_ALLOW_LOOPBACK_ENV, "true"); + info!( "Starting devnet with {} nodes ({} bootstrap)", self.config.node_count, self.config.bootstrap_count diff --git a/src/node.rs b/src/node.rs index 8a3f1ea0..463bc09d 100644 --- a/src/node.rs +++ b/src/node.rs @@ -3,7 +3,7 @@ use crate::ant_protocol::{CHUNK_PROTOCOL_ID, MAX_CHUNK_SIZE}; use crate::config::{ default_nodes_dir, default_root_dir, EvmNetworkConfig, IpVersion, NetworkMode, NodeConfig, - NODE_IDENTITY_FILENAME, + NODE_IDENTITY_FILENAME, TRANSPORT_ALLOW_LOOPBACK_ENV, }; use crate::error::{Error, Result}; use crate::event::{create_event_channel, NodeEvent, NodeEventsChannel, NodeEventsSender}; @@ -206,6 +206,9 @@ impl NodeBuilder { core_config.diversity_config = Some(CoreDiversityConfig::default()); } NetworkMode::Testnet => { + // Allow loopback connections for local testnet deployments. + std::env::set_var(TRANSPORT_ALLOW_LOOPBACK_ENV, "true"); + core_config.production_config = Some(CoreProductionConfig::default()); let mut diversity = CoreDiversityConfig::testnet(); diversity.max_nodes_per_asn = config.testnet.max_nodes_per_asn; @@ -226,6 +229,9 @@ impl NodeBuilder { } } NetworkMode::Development => { + // Allow loopback connections for local development. + std::env::set_var(TRANSPORT_ALLOW_LOOPBACK_ENV, "true"); + core_config.production_config = None; core_config.diversity_config = Some(CoreDiversityConfig::permissive()); } diff --git a/tests/e2e/testnet.rs b/tests/e2e/testnet.rs index 7460b74e..c2967505 100644 --- a/tests/e2e/testnet.rs +++ b/tests/e2e/testnet.rs @@ -29,6 +29,7 @@ use saorsa_node::ant_protocol::{ ChunkPutResponse, CHUNK_PROTOCOL_ID, }; use saorsa_node::client::{send_and_await_chunk_response, DataChunk, QuantumClient, XorName}; +use saorsa_node::config::TRANSPORT_ALLOW_LOOPBACK_ENV; use saorsa_node::payment::{ EvmVerifierConfig, PaymentProof, PaymentVerifier, PaymentVerifierConfig, QuoteGenerator, QuotingMetricsTracker, @@ -1058,6 +1059,9 @@ impl TestNetwork { /// Returns an error if any node fails to start or the network /// fails to stabilize within the timeout. pub async fn start(&mut self) -> Result<()> { + // Allow loopback connections — test nodes all run on 127.0.0.1. + std::env::set_var(TRANSPORT_ALLOW_LOOPBACK_ENV, "true"); + info!( "Starting test network with {} nodes ({} bootstrap)", self.config.node_count, self.config.bootstrap_count From 8db55f25c53227c6a153651ea1c3d213bcfdc985 Mon Sep 17 00:00:00 2001 From: Warm Beer Date: Tue, 10 Mar 2026 21:07:31 +0100 Subject: [PATCH 2/8] refactor: use allow_loopback config field instead of env var Replace SAORSA_TRANSPORT_ALLOW_LOOPBACK env var with the new NodeConfig.allow_loopback config field from saorsa-core. Set it on the core config in devnet start_node(), testnet start_node(), and NodeBuilder::build_core_config() for Development/Testnet modes. Remove the now-unused TRANSPORT_ALLOW_LOOPBACK_ENV constant. Co-Authored-By: Claude Opus 4.6 --- src/config.rs | 5 ----- src/devnet.rs | 9 +++------ src/node.rs | 6 +++--- tests/e2e/testnet.rs | 6 ++---- 4 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/config.rs b/src/config.rs index 0c0d95c9..008d54ba 100644 --- a/src/config.rs +++ b/src/config.rs @@ -10,11 +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"; -/// Environment variable that tells saorsa-core's transport layer to accept -/// loopback (127.0.0.1) connections. Set to `"true"` for local devnets and -/// testnets where all nodes run on the same machine. -pub const TRANSPORT_ALLOW_LOOPBACK_ENV: &str = "SAORSA_TRANSPORT_ALLOW_LOOPBACK"; - /// IP version configuration. #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] diff --git a/src/devnet.rs b/src/devnet.rs index 81339f63..a1a4451e 100644 --- a/src/devnet.rs +++ b/src/devnet.rs @@ -4,9 +4,7 @@ //! multi-node networks on a single machine. use crate::ant_protocol::CHUNK_PROTOCOL_ID; -use crate::config::{ - default_root_dir, NODES_SUBDIR, NODE_IDENTITY_FILENAME, TRANSPORT_ALLOW_LOOPBACK_ENV, -}; +use crate::config::{default_root_dir, NODES_SUBDIR, NODE_IDENTITY_FILENAME}; use crate::payment::{ EvmVerifierConfig, PaymentVerifier, PaymentVerifierConfig, QuoteGenerator, QuotingMetricsTracker, @@ -390,9 +388,6 @@ impl Devnet { /// Returns `DevnetError::Startup` if any node fails to start, or /// `DevnetError::Stabilization` if the network does not stabilize within the timeout. pub async fn start(&mut self) -> Result<()> { - // Allow loopback connections — devnet nodes all run on 127.0.0.1. - std::env::set_var(TRANSPORT_ALLOW_LOOPBACK_ENV, "true"); - info!( "Starting devnet with {} nodes ({} bootstrap)", self.config.node_count, self.config.bootstrap_count @@ -645,6 +640,8 @@ impl Devnet { .clone_from(&node.bootstrap_addrs); core_config.max_message_size = Some(crate::ant_protocol::MAX_WIRE_MESSAGE_SIZE); core_config.diversity_config = Some(IPDiversityConfig::permissive()); + // Devnet nodes all run on 127.0.0.1. + core_config.allow_loopback = true; let index = node.index; let p2p_node = P2PNode::new(core_config) diff --git a/src/node.rs b/src/node.rs index 463bc09d..679967b6 100644 --- a/src/node.rs +++ b/src/node.rs @@ -3,7 +3,7 @@ use crate::ant_protocol::{CHUNK_PROTOCOL_ID, MAX_CHUNK_SIZE}; use crate::config::{ default_nodes_dir, default_root_dir, EvmNetworkConfig, IpVersion, NetworkMode, NodeConfig, - NODE_IDENTITY_FILENAME, TRANSPORT_ALLOW_LOOPBACK_ENV, + NODE_IDENTITY_FILENAME, }; use crate::error::{Error, Result}; use crate::event::{create_event_channel, NodeEvent, NodeEventsChannel, NodeEventsSender}; @@ -207,7 +207,7 @@ impl NodeBuilder { } NetworkMode::Testnet => { // Allow loopback connections for local testnet deployments. - std::env::set_var(TRANSPORT_ALLOW_LOOPBACK_ENV, "true"); + core_config.allow_loopback = true; core_config.production_config = Some(CoreProductionConfig::default()); let mut diversity = CoreDiversityConfig::testnet(); @@ -230,7 +230,7 @@ impl NodeBuilder { } NetworkMode::Development => { // Allow loopback connections for local development. - std::env::set_var(TRANSPORT_ALLOW_LOOPBACK_ENV, "true"); + core_config.allow_loopback = true; core_config.production_config = None; core_config.diversity_config = Some(CoreDiversityConfig::permissive()); diff --git a/tests/e2e/testnet.rs b/tests/e2e/testnet.rs index c2967505..7a5b7c35 100644 --- a/tests/e2e/testnet.rs +++ b/tests/e2e/testnet.rs @@ -29,7 +29,6 @@ use saorsa_node::ant_protocol::{ ChunkPutResponse, CHUNK_PROTOCOL_ID, }; use saorsa_node::client::{send_and_await_chunk_response, DataChunk, QuantumClient, XorName}; -use saorsa_node::config::TRANSPORT_ALLOW_LOOPBACK_ENV; use saorsa_node::payment::{ EvmVerifierConfig, PaymentProof, PaymentVerifier, PaymentVerifierConfig, QuoteGenerator, QuotingMetricsTracker, @@ -1059,9 +1058,6 @@ impl TestNetwork { /// Returns an error if any node fails to start or the network /// fails to stabilize within the timeout. pub async fn start(&mut self) -> Result<()> { - // Allow loopback connections — test nodes all run on 127.0.0.1. - std::env::set_var(TRANSPORT_ALLOW_LOOPBACK_ENV, "true"); - info!( "Starting test network with {} nodes ({} bootstrap)", self.config.node_count, self.config.bootstrap_count @@ -1299,6 +1295,8 @@ impl TestNetwork { // Allow localhost peers in DHT routing for test environments // This prevents diversity filters from excluding peers on 127.0.0.1 core_config.diversity_config = Some(CoreDiversityConfig::permissive()); + // Test nodes all run on 127.0.0.1. + core_config.allow_loopback = true; // Inject the ML-DSA identity so the P2PNode's transport peer ID // matches the pub_key embedded in payment quotes. From a43a034781a2e98e737e686e672bfc0c40313434 Mon Sep 17 00:00:00 2001 From: Warm Beer Date: Wed, 11 Mar 2026 16:25:19 +0100 Subject: [PATCH 3/8] fix: convert SocketAddr to Multiaddr for bootstrap_peers saorsa-core changed bootstrap_peers from Vec to Vec. Use .iter().map(Into::into).collect() to convert at each assignment site. Co-Authored-By: Claude Opus 4.6 --- src/bin/saorsa-cli/main.rs | 2 +- src/devnet.rs | 4 +--- src/node.rs | 2 +- tests/e2e/live_testnet.rs | 2 +- tests/e2e/testnet.rs | 4 +--- 5 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/bin/saorsa-cli/main.rs b/src/bin/saorsa-cli/main.rs index 9d8d778f..54cbb289 100644 --- a/src/bin/saorsa-cli/main.rs +++ b/src/bin/saorsa-cli/main.rs @@ -337,7 +337,7 @@ async fn create_client_node(bootstrap: Vec) -> Result P2PNode { println!("Connecting to testnet via: {bootstrap_addrs:?}"); let mut config = CoreNodeConfig::new().expect("Failed to create config"); - config.bootstrap_peers = bootstrap_addrs; + config.bootstrap_peers = bootstrap_addrs.iter().map(Into::into).collect(); // Use a random port for the client config.listen_addr = "127.0.0.1:0".parse().unwrap(); diff --git a/tests/e2e/testnet.rs b/tests/e2e/testnet.rs index 7a5b7c35..cf7b579a 100644 --- a/tests/e2e/testnet.rs +++ b/tests/e2e/testnet.rs @@ -1277,9 +1277,7 @@ impl TestNetwork { core_config.listen_addrs = vec![node.address]; core_config.enable_ipv6 = false; // Disable IPv6 for local testing to avoid dual-stack binding issues core_config.connection_timeout = Duration::from_secs(TEST_CORE_CONNECTION_TIMEOUT_SECS); - core_config - .bootstrap_peers - .clone_from(&node.bootstrap_addrs); + core_config.bootstrap_peers = node.bootstrap_addrs.iter().map(Into::into).collect(); // Override the transport-layer message size to accommodate max-size // chunks (4 MiB payload + serialization overhead = 5 MiB wire). core_config.max_message_size = Some(saorsa_node::ant_protocol::MAX_WIRE_MESSAGE_SIZE); From c4d91178d3455c2212fad01562202721bb76f1ce Mon Sep 17 00:00:00 2001 From: Warm Beer Date: Fri, 13 Mar 2026 10:48:40 +0100 Subject: [PATCH 4/8] feat: add --allow-loopback flag to saorsa-cli Enables loopback connections for devnet/local testing when using saorsa-cli for uploads and downloads. Co-Authored-By: Claude Opus 4.6 --- src/bin/saorsa-cli/cli.rs | 4 ++++ src/bin/saorsa-cli/main.rs | 8 ++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/bin/saorsa-cli/cli.rs b/src/bin/saorsa-cli/cli.rs index 18cd926c..17434346 100644 --- a/src/bin/saorsa-cli/cli.rs +++ b/src/bin/saorsa-cli/cli.rs @@ -21,6 +21,10 @@ pub struct Cli { #[arg(long, default_value_t = 60)] pub timeout_secs: u64, + /// Allow loopback connections (required for devnet/local testing). + #[arg(long)] + pub allow_loopback: bool, + /// Log level. #[arg(long, default_value = "info")] pub log_level: String, diff --git a/src/bin/saorsa-cli/main.rs b/src/bin/saorsa-cli/main.rs index 54cbb289..8acdf3da 100644 --- a/src/bin/saorsa-cli/main.rs +++ b/src/bin/saorsa-cli/main.rs @@ -59,7 +59,7 @@ async fn main() -> color_eyre::Result<()> { } let (bootstrap, manifest) = resolve_bootstrap(&cli)?; - let node = create_client_node(bootstrap).await?; + let node = create_client_node(bootstrap, cli.allow_loopback).await?; // Build client with timeout let mut client = QuantumClient::new(QuantumConfig { @@ -329,7 +329,10 @@ fn resolve_bootstrap( )) } -async fn create_client_node(bootstrap: Vec) -> Result, Error> { +async fn create_client_node( + bootstrap: Vec, + allow_loopback: bool, +) -> Result, Error> { let mut core_config = saorsa_core::NodeConfig::new() .map_err(|e| Error::Config(format!("Failed to create core config: {e}")))?; core_config.listen_addr = "0.0.0.0:0" @@ -340,6 +343,7 @@ async fn create_client_node(bootstrap: Vec) -> Result Date: Sat, 14 Mar 2026 14:13:09 +0100 Subject: [PATCH 5/8] chore: bump saorsa-core to 0.15 in Cargo.toml --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 87d84089..e8b0e0de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ path = "src/bin/saorsa-cli/main.rs" [dependencies] # Core (provides EVERYTHING: networking, DHT, security, trust, storage) -saorsa-core = "0.14.1" +saorsa-core = "0.15" saorsa-pqc = "0.5" # Payment verification - autonomi network lookup + EVM payment From 1a959252c5af80a03d0fbabdaa9714408e8d7dcb Mon Sep 17 00:00:00 2001 From: Warm Beer Date: Sat, 14 Mar 2026 17:29:09 +0100 Subject: [PATCH 6/8] refactor: switch bootstrap addresses from SocketAddr to MultiAddr Update all references to bootstrap addresses to use `MultiAddr` instead of `SocketAddr` following updates in `saorsa-core`. Adjust imports, configuration, and mappings accordingly. --- Cargo.toml | 2 +- src/bin/saorsa-cli/main.rs | 13 +++++++++---- src/devnet.rs | 20 +++++++++++--------- src/node.rs | 10 +++++++--- tests/e2e/live_testnet.rs | 7 +++++-- tests/e2e/testnet.rs | 14 +++++++------- 6 files changed, 40 insertions(+), 26 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e8b0e0de..9bce78b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ path = "src/bin/saorsa-cli/main.rs" [dependencies] # Core (provides EVERYTHING: networking, DHT, security, trust, storage) -saorsa-core = "0.15" +saorsa-core = { git = "https://github.com/saorsa-labs/saorsa-core", branch = "feat/multiaddr-multi-transport" } saorsa-pqc = "0.5" # Payment verification - autonomi network lookup + EVM payment diff --git a/src/bin/saorsa-cli/main.rs b/src/bin/saorsa-cli/main.rs index 8acdf3da..aaa1e0b6 100644 --- a/src/bin/saorsa-cli/main.rs +++ b/src/bin/saorsa-cli/main.rs @@ -312,9 +312,14 @@ fn resolve_evm_network( fn resolve_bootstrap( cli: &Cli, -) -> color_eyre::Result<(Vec, Option)> { +) -> color_eyre::Result<(Vec, Option)> { if !cli.bootstrap.is_empty() { - return Ok((cli.bootstrap.clone(), None)); + let addrs = cli + .bootstrap + .iter() + .map(|addr| saorsa_core::MultiAddr::quic(*addr)) + .collect(); + return Ok((addrs, None)); } if let Some(ref manifest_path) = cli.devnet_manifest { @@ -330,7 +335,7 @@ fn resolve_bootstrap( } async fn create_client_node( - bootstrap: Vec, + bootstrap: Vec, allow_loopback: bool, ) -> Result, Error> { let mut core_config = saorsa_core::NodeConfig::new() @@ -340,7 +345,7 @@ async fn create_client_node( .map_err(|e| Error::Config(format!("Invalid listen addr: {e}")))?; core_config.listen_addrs = vec![core_config.listen_addr]; core_config.enable_ipv6 = false; - core_config.bootstrap_peers = bootstrap.iter().map(Into::into).collect(); + core_config.bootstrap_peers = bootstrap; core_config.max_message_size = Some(MAX_WIRE_MESSAGE_SIZE); core_config.mode = saorsa_core::NodeMode::Client; core_config.allow_loopback = allow_loopback; diff --git a/src/devnet.rs b/src/devnet.rs index 59c58d59..26956fdc 100644 --- a/src/devnet.rs +++ b/src/devnet.rs @@ -14,7 +14,9 @@ use ant_evm::RewardsAddress; use evmlib::Network as EvmNetwork; use rand::Rng; use saorsa_core::identity::NodeIdentity; -use saorsa_core::{IPDiversityConfig, NodeConfig as CoreNodeConfig, P2PEvent, P2PNode, PeerId}; +use saorsa_core::{ + IPDiversityConfig, MultiAddr, NodeConfig as CoreNodeConfig, P2PEvent, P2PNode, PeerId, +}; use serde::{Deserialize, Serialize}; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::path::PathBuf; @@ -228,7 +230,7 @@ pub struct DevnetManifest { /// Node count. pub node_count: usize, /// Bootstrap addresses. - pub bootstrap: Vec, + pub bootstrap: Vec, /// Data directory. pub data_dir: PathBuf, /// Creation time in RFC3339. @@ -300,7 +302,7 @@ pub struct DevnetNode { ant_protocol: Option>, is_bootstrap: bool, state: Arc>, - bootstrap_addrs: Vec, + bootstrap_addrs: Vec, protocol_task: Option>, } @@ -465,11 +467,11 @@ impl Devnet { /// Get bootstrap addresses. #[must_use] - pub fn bootstrap_addrs(&self) -> Vec { + pub fn bootstrap_addrs(&self) -> Vec { self.nodes .iter() .take(self.config.bootstrap_count) - .map(|n| n.address) + .map(|n| MultiAddr::quic(n.address)) .collect() } @@ -493,7 +495,7 @@ impl Devnet { let regular_count = self.config.node_count - self.config.bootstrap_count; info!("Starting {} regular nodes", regular_count); - let bootstrap_addrs: Vec = self + let bootstrap_addrs: Vec = self .nodes .get(0..self.config.bootstrap_count) .ok_or_else(|| { @@ -504,7 +506,7 @@ impl Devnet { )) })? .iter() - .map(|n| n.address) + .map(|n| MultiAddr::quic(n.address)) .collect(); for i in self.config.bootstrap_count..self.config.node_count { @@ -521,7 +523,7 @@ impl Devnet { &self, index: usize, is_bootstrap: bool, - bootstrap_addrs: Vec, + bootstrap_addrs: Vec, ) -> Result { let index_u16 = u16::try_from(index) .map_err(|_| DevnetError::Config(format!("Node index {index} exceeds u16::MAX")))?; @@ -635,7 +637,7 @@ impl Devnet { core_config.listen_addr = node.address; core_config.listen_addrs = vec![node.address]; core_config.enable_ipv6 = false; - core_config.bootstrap_peers = node.bootstrap_addrs.iter().map(Into::into).collect(); + core_config.bootstrap_peers = node.bootstrap_addrs.clone(); core_config.max_message_size = Some(crate::ant_protocol::MAX_WIRE_MESSAGE_SIZE); core_config.diversity_config = Some(IPDiversityConfig::permissive()); // Devnet nodes all run on 127.0.0.1. diff --git a/src/node.rs b/src/node.rs index db899077..a6a00812 100644 --- a/src/node.rs +++ b/src/node.rs @@ -17,8 +17,8 @@ use evmlib::Network as EvmNetwork; use saorsa_core::identity::NodeIdentity; use saorsa_core::{ BootstrapConfig as CoreBootstrapConfig, BootstrapManager, - IPDiversityConfig as CoreDiversityConfig, NodeConfig as CoreNodeConfig, P2PEvent, P2PNode, - ProductionConfig as CoreProductionConfig, + IPDiversityConfig as CoreDiversityConfig, MultiAddr, NodeConfig as CoreNodeConfig, P2PEvent, + P2PNode, ProductionConfig as CoreProductionConfig, }; use std::net::SocketAddr; use std::path::PathBuf; @@ -194,7 +194,11 @@ impl NodeBuilder { core_config.enable_ipv6 = matches!(config.ip_version, IpVersion::Ipv6 | IpVersion::Dual); // Add bootstrap peers. - core_config.bootstrap_peers = config.bootstrap.iter().map(Into::into).collect(); + core_config.bootstrap_peers = config + .bootstrap + .iter() + .map(|addr| MultiAddr::quic(*addr)) + .collect(); // Forward max_message_size to the transport layer. core_config.max_message_size = Some(config.max_message_size); diff --git a/tests/e2e/live_testnet.rs b/tests/e2e/live_testnet.rs index cda10aeb..bad06199 100644 --- a/tests/e2e/live_testnet.rs +++ b/tests/e2e/live_testnet.rs @@ -13,7 +13,7 @@ clippy::too_many_lines )] -use saorsa_core::{NodeConfig as CoreNodeConfig, P2PNode}; +use saorsa_core::{MultiAddr, NodeConfig as CoreNodeConfig, P2PNode}; use std::env; use std::fs::File; use std::io::{BufRead, BufReader, Write}; @@ -42,7 +42,10 @@ async fn create_testnet_client() -> P2PNode { println!("Connecting to testnet via: {bootstrap_addrs:?}"); let mut config = CoreNodeConfig::new().expect("Failed to create config"); - config.bootstrap_peers = bootstrap_addrs.iter().map(Into::into).collect(); + config.bootstrap_peers = bootstrap_addrs + .iter() + .map(|addr| MultiAddr::quic(*addr)) + .collect(); // Use a random port for the client config.listen_addr = "127.0.0.1:0".parse().unwrap(); diff --git a/tests/e2e/testnet.rs b/tests/e2e/testnet.rs index cf7b579a..7e38050c 100644 --- a/tests/e2e/testnet.rs +++ b/tests/e2e/testnet.rs @@ -21,8 +21,8 @@ use futures::future::join_all; use rand::Rng; use saorsa_core::identity::PeerId; use saorsa_core::{ - identity::NodeIdentity, IPDiversityConfig as CoreDiversityConfig, NodeConfig as CoreNodeConfig, - P2PEvent, P2PNode, + identity::NodeIdentity, IPDiversityConfig as CoreDiversityConfig, MultiAddr, + NodeConfig as CoreNodeConfig, P2PEvent, P2PNode, }; use saorsa_node::ant_protocol::{ ChunkGetRequest, ChunkGetResponse, ChunkMessage, ChunkMessageBody, ChunkPutRequest, @@ -384,7 +384,7 @@ pub struct TestNode { pub state: Arc>, /// Bootstrap addresses this node connects to. - pub bootstrap_addrs: Vec, + pub bootstrap_addrs: Vec, /// ML-DSA-65 identity used for quote signing. /// @@ -1109,12 +1109,12 @@ impl TestNetwork { let regular_count = self.config.node_count - self.config.bootstrap_count; info!("Starting {} regular nodes", regular_count); - let bootstrap_addrs: Vec = self + let bootstrap_addrs: Vec = self .nodes .get(0..self.config.bootstrap_count) .unwrap_or_default() .iter() - .map(|n| n.address) + .map(|n| MultiAddr::quic(n.address)) .collect(); for i in self.config.bootstrap_count..self.config.node_count { @@ -1139,7 +1139,7 @@ impl TestNetwork { &self, index: usize, is_bootstrap: bool, - bootstrap_addrs: Vec, + bootstrap_addrs: Vec, ) -> Result { // Safe: node_count is validated in TestNetwork::new() to fit in u16 let index_u16 = u16::try_from(index) @@ -1277,7 +1277,7 @@ impl TestNetwork { core_config.listen_addrs = vec![node.address]; core_config.enable_ipv6 = false; // Disable IPv6 for local testing to avoid dual-stack binding issues core_config.connection_timeout = Duration::from_secs(TEST_CORE_CONNECTION_TIMEOUT_SECS); - core_config.bootstrap_peers = node.bootstrap_addrs.iter().map(Into::into).collect(); + core_config.bootstrap_peers = node.bootstrap_addrs.clone(); // Override the transport-layer message size to accommodate max-size // chunks (4 MiB payload + serialization overhead = 5 MiB wire). core_config.max_message_size = Some(saorsa_node::ant_protocol::MAX_WIRE_MESSAGE_SIZE); From 37c16993c33d6d9235ac10244227873b39afbacf Mon Sep 17 00:00:00 2001 From: Warm Beer Date: Sat, 14 Mar 2026 22:29:03 +0100 Subject: [PATCH 7/8] chore: bump saorsa-core to 0.16 in Cargo.toml --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 9bce78b1..0dd429fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ path = "src/bin/saorsa-cli/main.rs" [dependencies] # Core (provides EVERYTHING: networking, DHT, security, trust, storage) -saorsa-core = { git = "https://github.com/saorsa-labs/saorsa-core", branch = "feat/multiaddr-multi-transport" } +saorsa-core = "0.16" saorsa-pqc = "0.5" # Payment verification - autonomi network lookup + EVM payment From 4ae5576ac0fa38f8181a219ebc6fcc4631b84bcf Mon Sep 17 00:00:00 2001 From: Warm Beer Date: Sun, 15 Mar 2026 12:17:56 +0100 Subject: [PATCH 8/8] refactor: remove redundant listen_addr and enable_ipv6 fields Update configurations to use `listen_addrs` with `MultiAddr::quic()` exclusively, simplifying node setup and aligning with recent changes in `saorsa-core`. --- src/bin/saorsa-cli/main.rs | 6 +++--- src/devnet.rs | 4 +--- src/node.rs | 6 +----- tests/e2e/live_testnet.rs | 3 +-- tests/e2e/testnet.rs | 4 +--- 5 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/bin/saorsa-cli/main.rs b/src/bin/saorsa-cli/main.rs index aaa1e0b6..a52319b6 100644 --- a/src/bin/saorsa-cli/main.rs +++ b/src/bin/saorsa-cli/main.rs @@ -16,6 +16,7 @@ use saorsa_node::client::{ use saorsa_node::devnet::DevnetManifest; use saorsa_node::error::Error; use std::io::Read as _; +use std::net::SocketAddr; use std::path::{Path, PathBuf}; use std::sync::Arc; use tracing::info; @@ -340,11 +341,10 @@ async fn create_client_node( ) -> Result, Error> { let mut core_config = saorsa_core::NodeConfig::new() .map_err(|e| Error::Config(format!("Failed to create core config: {e}")))?; - core_config.listen_addr = "0.0.0.0:0" + let listen_addr: SocketAddr = "0.0.0.0:0" .parse() .map_err(|e| Error::Config(format!("Invalid listen addr: {e}")))?; - core_config.listen_addrs = vec![core_config.listen_addr]; - core_config.enable_ipv6 = false; + core_config.listen_addrs = vec![saorsa_core::MultiAddr::quic(listen_addr)]; core_config.bootstrap_peers = bootstrap; core_config.max_message_size = Some(MAX_WIRE_MESSAGE_SIZE); core_config.mode = saorsa_core::NodeMode::Client; diff --git a/src/devnet.rs b/src/devnet.rs index 26956fdc..af0ecee5 100644 --- a/src/devnet.rs +++ b/src/devnet.rs @@ -634,9 +634,7 @@ impl Devnet { .map_err(|e| DevnetError::Core(format!("Failed to load node identity: {e}")))?; core_config.node_identity = Some(Arc::new(identity)); - core_config.listen_addr = node.address; - core_config.listen_addrs = vec![node.address]; - core_config.enable_ipv6 = false; + core_config.listen_addrs = vec![MultiAddr::quic(node.address)]; core_config.bootstrap_peers = node.bootstrap_addrs.clone(); core_config.max_message_size = Some(crate::ant_protocol::MAX_WIRE_MESSAGE_SIZE); core_config.diversity_config = Some(IPDiversityConfig::permissive()); diff --git a/src/node.rs b/src/node.rs index a6a00812..9db965a5 100644 --- a/src/node.rs +++ b/src/node.rs @@ -187,11 +187,7 @@ impl NodeBuilder { .map_err(|e| Error::Config(format!("Failed to create core config: {e}")))?; // Set listen address - core_config.listen_addr = listen_addr; - core_config.listen_addrs = vec![listen_addr]; - - // Enable IPv6 if configured - core_config.enable_ipv6 = matches!(config.ip_version, IpVersion::Ipv6 | IpVersion::Dual); + core_config.listen_addrs = vec![MultiAddr::quic(listen_addr)]; // Add bootstrap peers. core_config.bootstrap_peers = config diff --git a/tests/e2e/live_testnet.rs b/tests/e2e/live_testnet.rs index bad06199..c5ba6c6a 100644 --- a/tests/e2e/live_testnet.rs +++ b/tests/e2e/live_testnet.rs @@ -48,8 +48,7 @@ async fn create_testnet_client() -> P2PNode { .collect(); // Use a random port for the client - config.listen_addr = "127.0.0.1:0".parse().unwrap(); - config.listen_addrs = vec![]; + config.listen_addrs = vec![MultiAddr::quic("127.0.0.1:0".parse().unwrap())]; let node = P2PNode::new(config) .await diff --git a/tests/e2e/testnet.rs b/tests/e2e/testnet.rs index 7e38050c..fe576174 100644 --- a/tests/e2e/testnet.rs +++ b/tests/e2e/testnet.rs @@ -1273,9 +1273,7 @@ impl TestNetwork { let mut core_config = CoreNodeConfig::new() .map_err(|e| TestnetError::Core(format!("Failed to create core config: {e}")))?; - core_config.listen_addr = node.address; - core_config.listen_addrs = vec![node.address]; - core_config.enable_ipv6 = false; // Disable IPv6 for local testing to avoid dual-stack binding issues + core_config.listen_addrs = vec![MultiAddr::quic(node.address)]; core_config.connection_timeout = Duration::from_secs(TEST_CORE_CONNECTION_TIMEOUT_SECS); core_config.bootstrap_peers = node.bootstrap_addrs.clone(); // Override the transport-layer message size to accommodate max-size