From 578b280831303a50077795d52c7d43620ce731fa Mon Sep 17 00:00:00 2001 From: Ian Clarke Date: Mon, 24 Nov 2025 23:02:50 -0600 Subject: [PATCH 1/2] build: bump versions to 0.1.39 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - freenet: → 0.1.39 - fdev: → 0.3.17 🤖 Automated release commit --- Cargo.lock | 4 ++-- crates/core/Cargo.toml | 2 +- crates/fdev/Cargo.toml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 622f6ae0e..83cd5b921 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1505,7 +1505,7 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fdev" -version = "0.3.16" +version = "0.3.17" dependencies = [ "anyhow", "axum", @@ -1635,7 +1635,7 @@ dependencies = [ [[package]] name = "freenet" -version = "0.1.38" +version = "0.1.39" dependencies = [ "aes-gcm", "ahash", diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index f387d8476..c8c2ecb1d 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "freenet" -version = "0.1.38" +version = "0.1.39" edition = "2021" rust-version = "1.80" publish = true diff --git a/crates/fdev/Cargo.toml b/crates/fdev/Cargo.toml index c434dd744..449e3e301 100644 --- a/crates/fdev/Cargo.toml +++ b/crates/fdev/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fdev" -version = "0.3.16" +version = "0.3.17" edition = "2021" rust-version = "1.80" publish = true @@ -39,7 +39,7 @@ reqwest = { version = "0.12", features = ["json"] } http = "1.4" # internal -freenet = { path = "../core", version = "0.1.38" } +freenet = { path = "../core", version = "0.1.39" } freenet-stdlib = { workspace = true } [features] From 867d4006300bc197195e5d7067197ad036fb648b Mon Sep 17 00:00:00 2001 From: Ian Clarke Date: Mon, 24 Nov 2025 23:29:28 -0600 Subject: [PATCH 2/2] fix: strengthen self-connection guard to check pub_key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous self-connection guard only checked peer_key, which can be None early during initialization. This caused self-connections to slip through when combined with PR #2142's response_target change. The fix adds a secondary check that compares pub_key directly. Since pub_key is always set in ConnectionManager, this catches self-connections even when peer_key is not yet initialized. This fixes the test_three_node_network_connectivity failure in the release/v0.1.39 CI. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- crates/core/src/ring/connection_manager.rs | 54 +++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/crates/core/src/ring/connection_manager.rs b/crates/core/src/ring/connection_manager.rs index 2ffadb5e2..8ba4bfb31 100644 --- a/crates/core/src/ring/connection_manager.rs +++ b/crates/core/src/ring/connection_manager.rs @@ -148,13 +148,25 @@ impl ConnectionManager { /// Will panic if the node checking for this condition has no location assigned. pub fn should_accept(&self, location: Location, peer_id: &PeerId) -> bool { // Don't accept connections from ourselves + // Primary check: compare full PeerId (address-based equality) if let Some(own_id) = self.get_peer_key() { if &own_id == peer_id { - tracing::warn!(%peer_id, "should_accept: rejecting self-connection attempt"); + tracing::warn!(%peer_id, "should_accept: rejecting self-connection attempt (address match)"); return false; } } + // Secondary check: compare pub_key directly + // This catches self-connections even when peer_key is not yet set, + // which can happen early in initialization. Same pub_key means same node. + if *self.pub_key == peer_id.pub_key { + tracing::warn!( + %peer_id, + "should_accept: rejecting self-connection attempt (pub_key match)" + ); + return false; + } + tracing::info!("Checking if should accept connection"); let open = self.connection_count(); let reserved_before = self.pending_reservations.read().len(); @@ -725,4 +737,44 @@ mod tests { "should_accept must accept connection from different peer" ); } + + #[test] + fn rejects_self_connection_by_pubkey_when_peer_key_not_set() { + // Create a keypair for our node + let keypair = TransportKeypair::new(); + + // Create connection manager WITHOUT peer_id set (simulating early initialization) + let cm = ConnectionManager::init( + Rate::new_per_second(1_000_000.0), + Rate::new_per_second(1_000_000.0), + 1, + 10, + 7, + ( + keypair.public().clone(), + None, // peer_id is None - simulating early initialization + AtomicU64::new(u64::from_le_bytes(0.5f64.to_le_bytes())), + ), + false, + 10, + Duration::from_secs(60), + ); + + // Verify the connection manager does NOT have peer_key set + assert_eq!(cm.get_peer_key(), None); + + // Create a PeerId with our pub_key but a different address + // This simulates a scenario where we receive a connection request + // that somehow references our own pub_key + let self_like_addr: SocketAddr = "127.0.0.1:9999".parse().unwrap(); + let self_like_peer_id = PeerId::new(self_like_addr, keypair.public().clone()); + + // Attempt to accept - should be rejected because pub_key matches + let location = Location::new(0.5); + let accepted = cm.should_accept(location, &self_like_peer_id); + assert!( + !accepted, + "should_accept must reject self-connection by pub_key even when peer_key is not set" + ); + } }