Merge master into next (coord cache surgical invalidation)

# Conflicts:
#	CHANGELOG.md
This commit is contained in:
Johnathan Corgan
2026-05-17 01:12:44 +00:00
27 changed files with 1377 additions and 77 deletions
+45
View File
@@ -133,6 +133,51 @@ async fn test_failed_adopted_traversal_cleans_up_transport() {
);
}
#[tokio::test]
async fn test_adopted_traversal_skips_already_connected_peer() {
let mut node = make_node();
let (packet_tx, packet_rx) = packet_channel(64);
node.packet_tx = Some(packet_tx);
node.packet_rx = Some(packet_rx);
node.state = NodeState::Running;
let transport_id = TransportId::new(1);
let link_id = LinkId::new(1);
let (conn, peer_identity) = make_completed_connection(&mut node, link_id, transport_id, 1_000);
let peer_node_addr = *peer_identity.node_addr();
node.add_connection(conn).unwrap();
node.promote_connection(link_id, peer_identity, 2_000)
.unwrap();
let link_count = node.link_count();
let transport_count = node.transport_count();
let adopted_socket = std::net::UdpSocket::bind("127.0.0.1:0").unwrap();
let handoff = EstablishedTraversal::new(
"sess-stale",
peer_identity.npub(),
"127.0.0.1:9".parse().unwrap(),
adopted_socket,
)
.with_transport_name("nostr-stale");
let result = node.adopt_established_traversal(handoff).await;
assert!(
matches!(result, Err(NodeError::PeerAlreadyExists(addr)) if addr == peer_node_addr),
"stale traversal handoff should be ignored once the peer is already active"
);
assert_eq!(
node.link_count(),
link_count,
"ignored traversal must not create a duplicate link"
);
assert_eq!(
node.transport_count(),
transport_count,
"ignored traversal must not leak an adopted transport"
);
}
#[tokio::test]
async fn test_third_peer_can_handshake_via_adopted_transport_socket() {
let mut node_a = make_node(); // Existing traversal peer (Alice)
+131
View File
@@ -1,7 +1,9 @@
use super::*;
use crate::discovery::nostr::{BootstrapEvent, NostrDiscovery};
use crate::peer::PromotionResult;
use crate::transport::udp::UdpTransport;
use crate::transport::{TransportHandle, packet_channel};
use std::sync::Arc;
#[test]
fn test_node_creation() {
@@ -782,6 +784,135 @@ fn test_schedule_retry_skips_connected_peer() {
);
}
#[tokio::test]
async fn test_try_peer_addresses_skips_connected_peer() {
let mut node = make_node();
let transport_id = TransportId::new(1);
let link_id = LinkId::new(1);
let (conn, peer_identity) = make_completed_connection(&mut node, link_id, transport_id, 1000);
let peer_config = crate::config::PeerConfig::new(peer_identity.npub(), "udp", "127.0.0.1:9");
node.add_connection(conn).unwrap();
node.promote_connection(link_id, peer_identity, 2000)
.unwrap();
let link_count = node.link_count();
let connection_count = node.connection_count();
node.try_peer_addresses(&peer_config, peer_identity, true)
.await
.unwrap();
assert_eq!(
node.link_count(),
link_count,
"stale retry/traversal fallback must not create a duplicate link"
);
assert_eq!(
node.connection_count(),
connection_count,
"stale retry/traversal fallback must not create a duplicate handshake"
);
}
#[tokio::test]
async fn test_try_peer_addresses_skips_connecting_peer() {
let mut node = make_node();
let peer_identity = make_peer_identity();
let peer_config = crate::config::PeerConfig::new(peer_identity.npub(), "udp", "127.0.0.1:9");
let pending = PeerConnection::outbound(LinkId::new(1), peer_identity, 1000);
node.add_connection(pending).unwrap();
node.try_peer_addresses(&peer_config, peer_identity, true)
.await
.unwrap();
assert_eq!(
node.connection_count(),
1,
"stale retry/traversal fallback must not start a second handshake"
);
assert_eq!(
node.link_count(),
0,
"stale retry/traversal fallback must not allocate a link while a handshake is pending"
);
}
#[tokio::test]
async fn test_nostr_traversal_failure_skips_connected_peer() {
let mut node = make_node();
let transport_id = TransportId::new(1);
let link_id = LinkId::new(1);
let (conn, peer_identity) = make_completed_connection(&mut node, link_id, transport_id, 1000);
node.add_connection(conn).unwrap();
node.promote_connection(link_id, peer_identity, 2000)
.unwrap();
let bootstrap = Arc::new(NostrDiscovery::new_for_test());
bootstrap.push_event_for_test(BootstrapEvent::Failed {
peer_config: crate::config::PeerConfig::new(peer_identity.npub(), "udp", "127.0.0.1:9"),
reason: "stale traversal failure".to_string(),
});
node.nostr_discovery = Some(bootstrap.clone());
node.poll_nostr_discovery().await;
assert!(
bootstrap.failure_state_snapshot().is_empty(),
"stale failures for connected peers must not affect traversal cooldown"
);
assert!(
node.retry_pending.is_empty(),
"stale failures for connected peers must not enqueue reconnect attempts"
);
}
#[tokio::test]
async fn test_nostr_traversal_established_skips_connected_peer() {
use crate::discovery::EstablishedTraversal;
use std::net::UdpSocket;
let mut node = make_node();
let transport_id = TransportId::new(1);
let link_id = LinkId::new(1);
let (conn, peer_identity) = make_completed_connection(&mut node, link_id, transport_id, 1000);
node.add_connection(conn).unwrap();
node.promote_connection(link_id, peer_identity, 2000)
.unwrap();
let link_count = node.link_count();
let connection_count = node.connection_count();
let bootstrap = Arc::new(NostrDiscovery::new_for_test());
let socket = UdpSocket::bind("127.0.0.1:0").expect("bind local UDP socket");
let remote_addr = "127.0.0.1:9999".parse().expect("parse remote addr");
bootstrap.push_event_for_test(BootstrapEvent::Established {
traversal: EstablishedTraversal::new(
"test-session",
peer_identity.npub(),
remote_addr,
socket,
),
});
node.nostr_discovery = Some(bootstrap.clone());
node.poll_nostr_discovery().await;
assert_eq!(
node.link_count(),
link_count,
"stale established handoff must not allocate a new link"
);
assert_eq!(
node.connection_count(),
connection_count,
"stale established handoff must not start a new handshake"
);
assert!(
node.retry_pending.is_empty(),
"stale established handoff must not enqueue a reconnect"
);
}
#[tokio::test]
async fn test_process_pending_retries_drops_expired_entries() {
let mut node = make_node();