diff --git a/Cargo.lock b/Cargo.lock index eb3ed33..4ea03ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -266,13 +266,14 @@ dependencies = [ [[package]] name = "alloy-eip7928" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8222b1d88f9a6d03be84b0f5e76bb60cd83991b43ad8ab6477f0e4a7809b98d" +checksum = "407510740da514b694fecb44d8b3cebdc60d448f70cc5d24743e8ba273448a6e" dependencies = [ "alloy-primitives", "alloy-rlp", "borsh", + "once_cell", "serde", ] @@ -904,8 +905,7 @@ dependencies = [ [[package]] name = "ant-node" version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac042e69f7dff2136deee542d66fceb5631474869ea4da9875185a9ad3329cc" +source = "git+https://github.com/withAutonomi/ant-node.git?branch=mick%2Falways-masque-relay-rebased#5d25e1f1ac91cd82d24116a085dfc1c26d0096ae" dependencies = [ "aes-gcm-siv", "blake3", @@ -2445,6 +2445,18 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "enum_dispatch" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -3986,9 +3998,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.77" +version = "0.10.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe4646e360ec77dff7dde40ed3d6c5fee52d156ef4a62f53973d38294dad87f" +checksum = "f38c4372413cdaaf3cc79dd92d29d7d9f5ab09b51b10dded508fb90bb70b9222" dependencies = [ "bitflags", "cfg-if", @@ -4027,9 +4039,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.113" +version = "0.9.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad2f2c0eba47118757e4c6d2bff2838f3e0523380021356e7875e858372ce644" +checksum = "13ce1245cd07fcc4cfdb438f7507b0c7e4f3849a69fd84d52374c66d83741bb6" dependencies = [ "cc", "libc", @@ -4884,9 +4896,9 @@ dependencies = [ [[package]] name = "ruint" -version = "1.17.2" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c141e807189ad38a07276942c6623032d3753c8859c146104ac2e4d68865945a" +checksum = "0298da754d1395046b0afdc2f20ee76d29a8ae310cd30ffa84ed42acba9cb12a" dependencies = [ "alloy-rlp", "ark-ff 0.3.0", @@ -5060,9 +5072,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.12" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8279bb85272c9f10811ae6a6c547ff594d6a7f3c6c6b02ee9726d1d0dcfcdd06" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "aws-lc-rs", "ring", @@ -5114,9 +5126,8 @@ dependencies = [ [[package]] name = "saorsa-core" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d459ba0e4f1a3ac918a1d6b17db392cccde2ee74569545d171d7644fc6463cc7" +version = "0.22.0" +source = "git+https://github.com/saorsa-labs/saorsa-core.git?branch=mick%2Falways-masque-relay-rebased#d37491fd2ead4b2e81f85a8d3c43e707bbafacc7" dependencies = [ "anyhow", "async-trait", @@ -5229,9 +5240,8 @@ dependencies = [ [[package]] name = "saorsa-transport" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "250826f52ac60992947359218d83c21f658aa85407e3980a5dbb258eff4c0cc3" +version = "0.31.0" +source = "git+https://github.com/saorsa-labs/saorsa-transport.git?branch=mick%2Falways-masque-relay-rebased#ec163406f526f42667f12a1ed4f5b6ec0ed4e02e" dependencies = [ "anyhow", "async-trait", @@ -5243,6 +5253,7 @@ dependencies = [ "core-foundation 0.9.4", "dashmap", "dirs 5.0.1", + "enum_dispatch", "futures-util", "hex", "igd-next", @@ -5644,9 +5655,9 @@ dependencies = [ [[package]] name = "sha3" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874" dependencies = [ "digest 0.10.7", "keccak", @@ -6202,7 +6213,7 @@ dependencies = [ "indexmap 2.14.0", "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow 1.0.1", + "winnow 1.0.2", ] [[package]] @@ -6211,7 +6222,7 @@ version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow 1.0.1", + "winnow 1.0.2", ] [[package]] @@ -6373,9 +6384,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "ucd-trie" @@ -6562,11 +6573,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.2+wasi-0.2.9" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.57.1", ] [[package]] @@ -6575,7 +6586,7 @@ version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.51.0", ] [[package]] @@ -7206,9 +7217,9 @@ dependencies = [ [[package]] name = "winnow" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" +checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" dependencies = [ "memchr", ] @@ -7222,6 +7233,12 @@ dependencies = [ "wit-bindgen-rust-macro", ] +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + [[package]] name = "wit-bindgen-core" version = "0.51.0" diff --git a/ant-cli/src/main.rs b/ant-cli/src/main.rs index 69e7267..04739d3 100644 --- a/ant-cli/src/main.rs +++ b/ant-cli/src/main.rs @@ -9,10 +9,11 @@ use std::time::Duration; use clap::Parser; use indicatif::{ProgressBar, ProgressStyle}; use tracing::info; +use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; use ant_core::data::{ Client, ClientConfig, CoreNodeConfig, CustomNetwork, DevnetManifest, EvmAddress, EvmNetwork, - MultiAddr, NodeMode, P2PNode, Wallet, MAX_WIRE_MESSAGE_SIZE, + IPDiversityConfig, MultiAddr, NodeMode, P2PNode, Wallet, MAX_WIRE_MESSAGE_SIZE, }; use cli::{Cli, Commands}; @@ -46,21 +47,24 @@ async fn main() { async fn run() -> anyhow::Result<()> { let cli = Cli::parse(); - // Privacy by design: no logs unless the user explicitly opts in with -v. - // A decentralized network client must not emit metadata by default. + // Privacy by design: no logs unless the user explicitly opts in with -v + // or by setting RUST_LOG. A decentralized network client must not emit + // metadata by default. let needs_tracing = !matches!(cli.command, Commands::Node { .. }); - if needs_tracing && cli.verbose > 0 { - use tracing_subscriber::{fmt, prelude::*, EnvFilter}; - - let filter = match cli.verbose { - 1 => EnvFilter::new("ant_core=info,ant_cli=info"), - 2 => EnvFilter::new("ant_core=debug,ant_cli=debug"), - _ => EnvFilter::new("trace"), + if needs_tracing { + let filter = match (EnvFilter::try_from_default_env().ok(), cli.verbose) { + (Some(f), _) => Some(f), + (None, 0) => None, + (None, 1) => Some(EnvFilter::new("ant_core=info,ant_cli=info")), + (None, 2) => Some(EnvFilter::new("ant_core=debug,ant_cli=debug")), + (None, _) => Some(EnvFilter::new("trace")), }; - tracing_subscriber::registry() - .with(fmt::layer().with_writer(std::io::stderr)) - .with(filter) - .init(); + if let Some(filter) = filter { + tracing_subscriber::registry() + .with(fmt::layer().with_writer(std::io::stderr)) + .with(filter) + .init(); + } } // Separate the command from the rest of the CLI args to avoid partial-move issues. @@ -399,6 +403,12 @@ async fn create_client_node_raw( .build() .map_err(|e| anyhow::anyhow!("Failed to create core config: {e}"))?; + // Clients never enforce IP-diversity limits: they don't host data and + // their routing table exists only to find peers, not to be defended + // against Sybil clustering. Strict per-IP / per-subnet caps would + // silently drop legitimate testnet peers that share an IP or /24. + core_config.diversity_config = Some(IPDiversityConfig::permissive()); + core_config.bootstrap_peers = bootstrap .iter() .map(|addr| MultiAddr::quic(*addr)) diff --git a/ant-core/Cargo.toml b/ant-core/Cargo.toml index e15abd7..9b2ac3f 100644 --- a/ant-core/Cargo.toml +++ b/ant-core/Cargo.toml @@ -38,7 +38,7 @@ tracing = "0.1" bytes = "1" lru = "0.16" rand = "0.8" -ant-node = "0.10.1" +ant-node = { git = "https://github.com/withAutonomi/ant-node.git", branch = "mick/always-masque-relay-rebased" } saorsa-pqc = "0.5" tracing-subscriber = { version = "0.3", features = ["env-filter"] } diff --git a/ant-core/src/data/client/quote.rs b/ant-core/src/data/client/quote.rs index 3e13626..8da0115 100644 --- a/ant-core/src/data/client/quote.rs +++ b/ant-core/src/data/client/quote.rs @@ -15,7 +15,7 @@ use evmlib::common::Amount; use evmlib::PaymentQuote; use futures::stream::{FuturesUnordered, StreamExt}; use std::time::Duration; -use tracing::{debug, warn}; +use tracing::{debug, info, warn}; /// Compute XOR distance between a peer's ID bytes and a target address. /// @@ -167,7 +167,7 @@ impl Client { quotes.push((peer_id, addrs, quote, price)); } Err(Error::AlreadyStored) => { - debug!("Peer {peer_id} reports chunk already stored"); + info!("Peer {peer_id} reports chunk already stored"); let dist = xor_distance(&peer_id, address); already_stored_peers.push((peer_id, dist)); } @@ -221,9 +221,12 @@ impl Client { } } - if quotes.len() >= CLOSE_GROUP_SIZE { - let total_responses = quotes.len() + failures.len() + already_stored_peers.len(); + let already_stored_count = already_stored_peers.len(); + let failure_count = failures.len(); + let quote_count = quotes.len(); + let total_responses = quote_count + failure_count + already_stored_count; + if quotes.len() >= CLOSE_GROUP_SIZE { // Sort by XOR distance to target, keep the closest CLOSE_GROUP_SIZE. quotes.sort_by(|a, b| { let dist_a = xor_distance(&a.0, address); @@ -232,8 +235,8 @@ impl Client { }); quotes.truncate(CLOSE_GROUP_SIZE); - debug!( - "Collected {} quotes for address {} (from {total_responses} responses)", + info!( + "Collected {} quotes for address {} ({total_responses} responses: {quote_count} ok, {already_stored_count} already_stored, {failure_count} failed)", quotes.len(), hex::encode(address), ); @@ -241,8 +244,7 @@ impl Client { } Err(Error::InsufficientPeers(format!( - "Got {} quotes, need {CLOSE_GROUP_SIZE}. Failures: [{}]", - quotes.len(), + "Got {quote_count} quotes, need {CLOSE_GROUP_SIZE} ({total_responses} responses: {already_stored_count} already_stored, {failure_count} failed). Failures: [{}]", failures.join("; ") ))) } diff --git a/ant-core/src/data/mod.rs b/ant-core/src/data/mod.rs index 7d5c676..38cc7da 100644 --- a/ant-core/src/data/mod.rs +++ b/ant-core/src/data/mod.rs @@ -34,7 +34,7 @@ pub use self_encryption::DataMap; // Re-export networking types needed by CLI for P2P node creation pub use ant_node::ant_protocol::{MAX_CHUNK_SIZE, MAX_WIRE_MESSAGE_SIZE}; -pub use ant_node::core::{CoreNodeConfig, MultiAddr, NodeMode, P2PNode}; +pub use ant_node::core::{CoreNodeConfig, IPDiversityConfig, MultiAddr, NodeMode, P2PNode}; pub use ant_node::devnet::DevnetManifest; // Re-export EVM types needed by CLI for wallet and network setup diff --git a/ant-core/src/data/network.rs b/ant-core/src/data/network.rs index da0835a..9d6ff45 100644 --- a/ant-core/src/data/network.rs +++ b/ant-core/src/data/network.rs @@ -5,7 +5,7 @@ use crate::data::error::{Error, Result}; use ant_node::ant_protocol::MAX_WIRE_MESSAGE_SIZE; -use ant_node::core::{CoreNodeConfig, MultiAddr, NodeMode, P2PNode, PeerId}; +use ant_node::core::{CoreNodeConfig, IPDiversityConfig, MultiAddr, NodeMode, P2PNode, PeerId}; use std::net::SocketAddr; use std::sync::Arc; @@ -41,6 +41,12 @@ impl Network { .build() .map_err(|e| Error::Network(format!("Failed to create core config: {e}")))?; + // Clients never enforce IP-diversity limits: they don't host data and + // their routing table exists only to find peers, not to be defended + // against Sybil clustering. Strict per-IP / per-subnet caps would + // silently drop legitimate testnet peers that share an IP or /24. + core_config.diversity_config = Some(IPDiversityConfig::permissive()); + core_config.bootstrap_peers = bootstrap_peers .iter() .map(|addr| MultiAddr::quic(*addr)) @@ -105,7 +111,10 @@ impl Network { .into_iter() .filter(|n| n.peer_id != *local_peer_id) .take(count) - .map(|n| (n.peer_id, n.addresses)) + .map(|n| { + let addrs = n.addresses_by_priority(); + (n.peer_id, addrs) + }) .collect()) }