mirror of
https://github.com/jmcorgan/fips.git
synced 2026-08-09 00:04:54 +00:00
Merge sole-store context change into the next-side
Bring the immutable-state single-store change onto the Noise XX line. The shared NodeContext is now the sole store; this merge applies the next-only adaptations the master-side change couldn't carry: - Remove node_profile from the Node struct (next-only field) so it lives solely in NodeContext; migrate its readers (tree/bloom/discovery/ handshake negotiation) onto the node_profile() accessor. The two FMP negotiation sites hoist node_profile() into a local to avoid borrowing &self while a connection is mutably borrowed. - leaf_only sets both is_leaf_only and node_profile via the context swap. - Preserve the XX handshake/rekey structure (no identity-in-msg1; XX/XK initiator/responder constructors) while applying the startup_epoch() accessor migration. - Tests: route profile selection through a make_test_node_with_profile helper (profile is immutable, set via Config flags) instead of poking the removed field. cargo test --lib 1369/0; clippy -D warnings and release build clean.
This commit is contained in:
@@ -53,13 +53,13 @@ async fn test_outbound_msg2_denied_after_acl_reload() {
|
||||
let node_b = make_node();
|
||||
let transport_id = TransportId::new(1);
|
||||
let remote_addr = TransportAddr::from_string("127.0.0.1:5001");
|
||||
let peer_b_identity = PeerIdentity::from_pubkey_full(node_b.identity.pubkey_full());
|
||||
let peer_b_identity = PeerIdentity::from_pubkey_full(node_b.identity().pubkey_full());
|
||||
|
||||
let link_id_a = node_a.allocate_link_id();
|
||||
let mut conn_a = PeerConnection::outbound(link_id_a, peer_b_identity, 1000);
|
||||
let our_index_a = node_a.index_allocator.allocate().unwrap();
|
||||
let noise_msg1 = conn_a
|
||||
.start_handshake(node_a.identity.keypair(), node_a.startup_epoch, 1000)
|
||||
.start_handshake(node_a.identity().keypair(), node_a.startup_epoch(), 1000)
|
||||
.unwrap();
|
||||
conn_a.set_our_index(our_index_a);
|
||||
conn_a.set_transport_id(transport_id);
|
||||
@@ -85,7 +85,7 @@ async fn test_outbound_msg2_denied_after_acl_reload() {
|
||||
let responder_epoch = [0x11; 8];
|
||||
let noise_msg2 = conn_b
|
||||
.receive_handshake_init(
|
||||
node_b.identity.keypair(),
|
||||
node_b.identity().keypair(),
|
||||
responder_epoch,
|
||||
&noise_msg1,
|
||||
None,
|
||||
@@ -173,12 +173,12 @@ async fn test_inbound_msg3_denied_triggers_disconnect() {
|
||||
|
||||
// === A initiates the handshake ===
|
||||
|
||||
let peer_b_identity = PeerIdentity::from_pubkey_full(node_b.identity.pubkey_full());
|
||||
let peer_b_identity = PeerIdentity::from_pubkey_full(node_b.identity().pubkey_full());
|
||||
let link_id_a = node_a.allocate_link_id();
|
||||
let mut conn_a = PeerConnection::outbound(link_id_a, peer_b_identity, 1000);
|
||||
let our_index_a = node_a.index_allocator.allocate().unwrap();
|
||||
let noise_msg1 = conn_a
|
||||
.start_handshake(node_a.identity.keypair(), node_a.startup_epoch, 1000)
|
||||
.start_handshake(node_a.identity().keypair(), node_a.startup_epoch(), 1000)
|
||||
.unwrap();
|
||||
conn_a.set_our_index(our_index_a);
|
||||
conn_a.set_transport_id(transport_id_a);
|
||||
|
||||
@@ -78,9 +78,9 @@ async fn test_adopted_udp_traversal_completes_handshake() {
|
||||
node_b.handle_msg3(pkt_at_b).await;
|
||||
|
||||
let peer_a_node_addr =
|
||||
*PeerIdentity::from_pubkey_full(node_a.identity.pubkey_full()).node_addr();
|
||||
*PeerIdentity::from_pubkey_full(node_a.identity().pubkey_full()).node_addr();
|
||||
let peer_b_node_addr =
|
||||
*PeerIdentity::from_pubkey_full(node_b.identity.pubkey_full()).node_addr();
|
||||
*PeerIdentity::from_pubkey_full(node_b.identity().pubkey_full()).node_addr();
|
||||
|
||||
assert_eq!(
|
||||
node_a.peer_count(),
|
||||
@@ -248,7 +248,7 @@ async fn test_third_peer_can_handshake_via_adopted_transport_socket() {
|
||||
assert_eq!(pkt_at_a.data[0] & 0x0f, PHASE_MSG3);
|
||||
node_a.handle_msg3(pkt_at_a).await;
|
||||
|
||||
let node_a_addr = *PeerIdentity::from_pubkey_full(node_a.identity.pubkey_full()).node_addr();
|
||||
let node_a_addr = *PeerIdentity::from_pubkey_full(node_a.identity().pubkey_full()).node_addr();
|
||||
assert!(
|
||||
node_b.get_peer(&node_a_addr).is_some(),
|
||||
"node_b should first be connected to node_a via adopted transport"
|
||||
@@ -262,7 +262,7 @@ async fn test_third_peer_can_handshake_via_adopted_transport_socket() {
|
||||
.transports
|
||||
.insert(transport_id_c, TransportHandle::Udp(transport_c));
|
||||
|
||||
let peer_b_identity = PeerIdentity::from_pubkey_full(node_b.identity.pubkey_full());
|
||||
let peer_b_identity = PeerIdentity::from_pubkey_full(node_b.identity().pubkey_full());
|
||||
let adopted_addr = TransportAddr::from_string(&handoff_result.local_addr.to_string());
|
||||
node_c
|
||||
.initiate_connection(transport_id_c, adopted_addr, Some(peer_b_identity))
|
||||
@@ -314,7 +314,7 @@ async fn test_third_peer_can_handshake_via_adopted_transport_socket() {
|
||||
};
|
||||
node_b.handle_msg3(pkt_at_b).await;
|
||||
|
||||
let node_c_addr = *PeerIdentity::from_pubkey_full(node_c.identity.pubkey_full()).node_addr();
|
||||
let node_c_addr = *PeerIdentity::from_pubkey_full(node_c.identity().pubkey_full()).node_addr();
|
||||
assert!(
|
||||
node_b.get_peer(&node_c_addr).is_some(),
|
||||
"node_b should promote node_c when node_c handshakes via adopted socket"
|
||||
|
||||
@@ -1170,7 +1170,7 @@ async fn test_check_pending_lookups_default_sequence_unreachable() {
|
||||
// Default attempt_timeouts_secs is [1, 2, 4, 8]. Confirm so the test
|
||||
// cannot silently drift if the default changes.
|
||||
assert_eq!(
|
||||
node.config.node.discovery.attempt_timeouts_secs,
|
||||
node.config().node.discovery.attempt_timeouts_secs,
|
||||
vec![1, 2, 4, 8],
|
||||
"test pins the [1,2,4,8] default; update the test if the default changes"
|
||||
);
|
||||
|
||||
+29
-26
@@ -1,6 +1,8 @@
|
||||
//! Integration tests for end-to-end Noise XX handshake scenarios.
|
||||
|
||||
use super::spanning_tree::{cleanup_nodes, drain_all_packets, initiate_handshake, make_test_node};
|
||||
use super::spanning_tree::{
|
||||
cleanup_nodes, drain_all_packets, initiate_handshake, make_test_node_with_profile,
|
||||
};
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
@@ -50,7 +52,7 @@ async fn test_two_node_handshake_udp() {
|
||||
// === Phase 1: Node A initiates handshake to Node B ===
|
||||
|
||||
// Create peer identity for B (must use full key for ECDH parity)
|
||||
let peer_b_identity = PeerIdentity::from_pubkey_full(node_b.identity.pubkey_full());
|
||||
let peer_b_identity = PeerIdentity::from_pubkey_full(node_b.identity().pubkey_full());
|
||||
let peer_b_node_addr = *peer_b_identity.node_addr();
|
||||
|
||||
let link_id_a = node_a.allocate_link_id();
|
||||
@@ -60,9 +62,9 @@ async fn test_two_node_handshake_udp() {
|
||||
let our_index_a = node_a.index_allocator.allocate().unwrap();
|
||||
|
||||
// Start handshake (generates Noise XX msg1)
|
||||
let our_keypair_a = node_a.identity.keypair();
|
||||
let our_keypair_a = node_a.identity().keypair();
|
||||
let noise_msg1 = conn_a
|
||||
.start_handshake(our_keypair_a, node_a.startup_epoch, 1000)
|
||||
.start_handshake(our_keypair_a, node_a.startup_epoch(), 1000)
|
||||
.unwrap();
|
||||
conn_a.set_our_index(our_index_a);
|
||||
conn_a.set_transport_id(transport_id_a);
|
||||
@@ -101,7 +103,7 @@ async fn test_two_node_handshake_udp() {
|
||||
node_b.handle_msg1(packet_b).await;
|
||||
|
||||
let peer_a_node_addr =
|
||||
*PeerIdentity::from_pubkey_full(node_a.identity.pubkey_full()).node_addr();
|
||||
*PeerIdentity::from_pubkey_full(node_a.identity().pubkey_full()).node_addr();
|
||||
|
||||
// XX: B has NOT promoted yet (needs msg3)
|
||||
assert_eq!(
|
||||
@@ -313,16 +315,16 @@ async fn test_run_rx_loop_handshake() {
|
||||
|
||||
// === Phase 1: Node A initiates handshake to Node B ===
|
||||
|
||||
let peer_b_identity = PeerIdentity::from_pubkey_full(node_b.identity.pubkey_full());
|
||||
let peer_b_identity = PeerIdentity::from_pubkey_full(node_b.identity().pubkey_full());
|
||||
let peer_b_node_addr = *peer_b_identity.node_addr();
|
||||
|
||||
let link_id_a = node_a.allocate_link_id();
|
||||
let mut conn_a = PeerConnection::outbound(link_id_a, peer_b_identity, 1000);
|
||||
|
||||
let our_index_a = node_a.index_allocator.allocate().unwrap();
|
||||
let our_keypair_a = node_a.identity.keypair();
|
||||
let our_keypair_a = node_a.identity().keypair();
|
||||
let noise_msg1 = conn_a
|
||||
.start_handshake(our_keypair_a, node_a.startup_epoch, 1000)
|
||||
.start_handshake(our_keypair_a, node_a.startup_epoch(), 1000)
|
||||
.unwrap();
|
||||
conn_a.set_our_index(our_index_a);
|
||||
conn_a.set_transport_id(transport_id_a);
|
||||
@@ -494,9 +496,9 @@ async fn test_cross_connection_both_initiate() {
|
||||
.insert(transport_id_b, TransportHandle::Udp(transport_b));
|
||||
|
||||
// Peer identities (must use full key for ECDH parity)
|
||||
let peer_b_identity = PeerIdentity::from_pubkey_full(node_b.identity.pubkey_full());
|
||||
let peer_b_identity = PeerIdentity::from_pubkey_full(node_b.identity().pubkey_full());
|
||||
let peer_b_node_addr = *peer_b_identity.node_addr();
|
||||
let peer_a_identity = PeerIdentity::from_pubkey_full(node_a.identity.pubkey_full());
|
||||
let peer_a_identity = PeerIdentity::from_pubkey_full(node_a.identity().pubkey_full());
|
||||
let peer_a_node_addr = *peer_a_identity.node_addr();
|
||||
|
||||
// === Phase 1: Both nodes initiate handshakes (simulate auto_connect) ===
|
||||
@@ -505,9 +507,9 @@ async fn test_cross_connection_both_initiate() {
|
||||
let link_id_a_out = node_a.allocate_link_id();
|
||||
let mut conn_a = PeerConnection::outbound(link_id_a_out, peer_b_identity, 1000);
|
||||
let our_index_a = node_a.index_allocator.allocate().unwrap();
|
||||
let our_keypair_a = node_a.identity.keypair();
|
||||
let our_keypair_a = node_a.identity().keypair();
|
||||
let noise_msg1_a = conn_a
|
||||
.start_handshake(our_keypair_a, node_a.startup_epoch, 1000)
|
||||
.start_handshake(our_keypair_a, node_a.startup_epoch(), 1000)
|
||||
.unwrap();
|
||||
conn_a.set_our_index(our_index_a);
|
||||
conn_a.set_transport_id(transport_id_a);
|
||||
@@ -535,9 +537,9 @@ async fn test_cross_connection_both_initiate() {
|
||||
let link_id_b_out = node_b.allocate_link_id();
|
||||
let mut conn_b = PeerConnection::outbound(link_id_b_out, peer_a_identity, 1000);
|
||||
let our_index_b = node_b.index_allocator.allocate().unwrap();
|
||||
let our_keypair_b = node_b.identity.keypair();
|
||||
let our_keypair_b = node_b.identity().keypair();
|
||||
let noise_msg1_b = conn_b
|
||||
.start_handshake(our_keypair_b, node_b.startup_epoch, 1000)
|
||||
.start_handshake(our_keypair_b, node_b.startup_epoch(), 1000)
|
||||
.unwrap();
|
||||
conn_b.set_our_index(our_index_b);
|
||||
conn_b.set_transport_id(transport_id_b);
|
||||
@@ -705,9 +707,9 @@ async fn test_stale_connection_cleanup() {
|
||||
|
||||
// Allocate session index and set transport info
|
||||
let our_index = node.index_allocator.allocate().unwrap();
|
||||
let our_keypair = node.identity.keypair();
|
||||
let our_keypair = node.identity().keypair();
|
||||
let _noise_msg1 = conn
|
||||
.start_handshake(our_keypair, node.startup_epoch, past_time_ms)
|
||||
.start_handshake(our_keypair, node.startup_epoch(), past_time_ms)
|
||||
.unwrap();
|
||||
conn.set_our_index(our_index);
|
||||
conn.set_transport_id(transport_id);
|
||||
@@ -783,9 +785,9 @@ async fn test_failed_connection_cleanup() {
|
||||
let mut conn = PeerConnection::outbound(link_id, peer_identity, now_ms);
|
||||
|
||||
let our_index = node.index_allocator.allocate().unwrap();
|
||||
let our_keypair = node.identity.keypair();
|
||||
let our_keypair = node.identity().keypair();
|
||||
let _noise_msg1 = conn
|
||||
.start_handshake(our_keypair, node.startup_epoch, now_ms)
|
||||
.start_handshake(our_keypair, node.startup_epoch(), now_ms)
|
||||
.unwrap();
|
||||
conn.set_our_index(our_index);
|
||||
conn.set_transport_id(transport_id);
|
||||
@@ -843,9 +845,9 @@ async fn test_msg1_stored_for_resend() {
|
||||
let mut conn = PeerConnection::outbound(link_id, peer_identity, now_ms);
|
||||
|
||||
let our_index = node.index_allocator.allocate().unwrap();
|
||||
let our_keypair = node.identity.keypair();
|
||||
let our_keypair = node.identity().keypair();
|
||||
let noise_msg1 = conn
|
||||
.start_handshake(our_keypair, node.startup_epoch, now_ms)
|
||||
.start_handshake(our_keypair, node.startup_epoch(), now_ms)
|
||||
.unwrap();
|
||||
conn.set_our_index(our_index);
|
||||
conn.set_transport_id(transport_id);
|
||||
@@ -853,7 +855,7 @@ async fn test_msg1_stored_for_resend() {
|
||||
|
||||
// Build wire msg1 and store it (as initiate_peer_connection does)
|
||||
let wire_msg1 = build_msg1(our_index, &noise_msg1);
|
||||
let resend_interval = node.config.node.rate_limit.handshake_resend_interval_ms;
|
||||
let resend_interval = node.config().node.rate_limit.handshake_resend_interval_ms;
|
||||
conn.set_handshake_msg1(wire_msg1.clone(), now_ms + resend_interval);
|
||||
|
||||
// Verify stored msg1 matches what was built
|
||||
@@ -876,9 +878,9 @@ async fn test_resend_scheduling() {
|
||||
let mut conn = PeerConnection::outbound(link_id, peer_identity, now_ms);
|
||||
|
||||
let our_index = node.index_allocator.allocate().unwrap();
|
||||
let our_keypair = node.identity.keypair();
|
||||
let our_keypair = node.identity().keypair();
|
||||
let noise_msg1 = conn
|
||||
.start_handshake(our_keypair, node.startup_epoch, now_ms)
|
||||
.start_handshake(our_keypair, node.startup_epoch(), now_ms)
|
||||
.unwrap();
|
||||
conn.set_our_index(our_index);
|
||||
conn.set_transport_id(transport_id);
|
||||
@@ -999,9 +1001,10 @@ async fn attempt_profile_handshake(
|
||||
profile_a: crate::protocol::NodeProfile,
|
||||
profile_b: crate::protocol::NodeProfile,
|
||||
) -> (usize, usize) {
|
||||
let mut nodes = vec![make_test_node().await, make_test_node().await];
|
||||
nodes[0].node.node_profile = profile_a;
|
||||
nodes[1].node.node_profile = profile_b;
|
||||
let mut nodes = vec![
|
||||
make_test_node_with_profile(profile_a).await,
|
||||
make_test_node_with_profile(profile_b).await,
|
||||
];
|
||||
|
||||
initiate_handshake(&mut nodes, 0, 1).await;
|
||||
drain_all_packets(&mut nodes, false).await;
|
||||
|
||||
+21
-6
@@ -28,14 +28,29 @@ pub(super) fn make_node() -> Node {
|
||||
make_node_with(Config::new())
|
||||
}
|
||||
|
||||
/// Build a test node from an explicit `Config`. Prefer this over poking
|
||||
/// `node.config.*` after construction: immutable fields are mirrored into the
|
||||
/// shared `NodeContext` at build time, so a post-construction field poke is
|
||||
/// invisible to any reader that has migrated onto the `config()` accessor.
|
||||
/// Build a test node from an explicit `Config`. Immutable state lives solely in
|
||||
/// the shared `NodeContext`, built once at construction — there is no
|
||||
/// post-construction field to poke, so set limits/config on the `Config` here.
|
||||
pub(super) fn make_node_with(config: Config) -> Node {
|
||||
Node::new(config).unwrap()
|
||||
}
|
||||
|
||||
/// Build a test node with an explicit `max_peers` limit (replaces the removed
|
||||
/// `set_max_peers` setter; resource limits are immutable post-construction).
|
||||
pub(super) fn make_node_with_max_peers(max_peers: usize) -> Node {
|
||||
let mut config = Config::new();
|
||||
config.node.limits.max_peers = max_peers;
|
||||
make_node_with(config)
|
||||
}
|
||||
|
||||
/// Build a test node with an explicit `max_links` limit (replaces the removed
|
||||
/// `set_max_links` setter; resource limits are immutable post-construction).
|
||||
pub(super) fn make_node_with_max_links(max_links: usize) -> Node {
|
||||
let mut config = Config::new();
|
||||
config.node.limits.max_links = max_links;
|
||||
make_node_with(config)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(super) fn make_node_addr(val: u8) -> NodeAddr {
|
||||
let mut bytes = [0u8; 16];
|
||||
@@ -66,9 +81,9 @@ pub(super) fn make_completed_connection(
|
||||
let mut conn = PeerConnection::outbound(link_id, peer_identity, current_time_ms);
|
||||
|
||||
// Run initiator side of handshake
|
||||
let our_keypair = node.identity.keypair();
|
||||
let our_keypair = node.identity().keypair();
|
||||
let msg1 = conn
|
||||
.start_handshake(our_keypair, node.startup_epoch, current_time_ms)
|
||||
.start_handshake(our_keypair, node.startup_epoch(), current_time_ms)
|
||||
.unwrap();
|
||||
|
||||
// Run responder side to generate msg2
|
||||
|
||||
@@ -1628,8 +1628,9 @@ fn test_coords_warmup_config_default() {
|
||||
|
||||
#[test]
|
||||
fn test_identity_cache_lru_eviction() {
|
||||
let mut node = make_node();
|
||||
node.config.node.cache.identity_size = 2;
|
||||
let mut config = crate::Config::new();
|
||||
config.node.cache.identity_size = 2;
|
||||
let mut node = make_node_with(config);
|
||||
|
||||
let id1 = Identity::generate();
|
||||
let id2 = Identity::generate();
|
||||
@@ -1791,7 +1792,7 @@ async fn test_session_handshake_timeout() {
|
||||
let mut node = make_node();
|
||||
|
||||
let identity_b = Identity::generate();
|
||||
let handshake = HandshakeState::new_initiator(node.identity.keypair());
|
||||
let handshake = HandshakeState::new_initiator(node.identity().keypair());
|
||||
|
||||
let dest_addr = *identity_b.node_addr();
|
||||
|
||||
@@ -1808,7 +1809,7 @@ async fn test_session_handshake_timeout() {
|
||||
assert!(node.sessions.contains_key(&dest_addr));
|
||||
|
||||
// Before timeout: session should remain
|
||||
let timeout_secs = node.config.node.rate_limit.handshake_timeout_secs;
|
||||
let timeout_secs = node.config().node.rate_limit.handshake_timeout_secs;
|
||||
let before_timeout = 1000 + timeout_secs * 1000 - 1;
|
||||
node.resend_pending_session_handshakes(before_timeout).await;
|
||||
assert!(
|
||||
@@ -1852,7 +1853,7 @@ async fn test_session_awaiting_msg3_timeout() {
|
||||
assert!(node.sessions.contains_key(&src_addr));
|
||||
|
||||
// After timeout: session should be removed
|
||||
let timeout_secs = node.config.node.rate_limit.handshake_timeout_secs;
|
||||
let timeout_secs = node.config().node.rate_limit.handshake_timeout_secs;
|
||||
let after_timeout = 1000 + timeout_secs * 1000 + 1;
|
||||
node.resend_pending_session_handshakes(after_timeout).await;
|
||||
assert!(
|
||||
@@ -2298,7 +2299,7 @@ fn install_established_session_with_mmp(node: &mut Node, remote: &Identity) {
|
||||
1000,
|
||||
true,
|
||||
);
|
||||
entry.init_mmp(&node.config.node.session_mmp);
|
||||
entry.init_mmp(&node.config().node.session_mmp);
|
||||
node.sessions.insert(remote_addr, entry);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,10 +30,29 @@ pub(super) async fn make_test_node() -> TestNode {
|
||||
|
||||
/// Create a test node with a specific transport MTU.
|
||||
pub(super) async fn make_test_node_with_mtu(mtu: u16) -> TestNode {
|
||||
make_test_node_inner(Config::new(), mtu).await
|
||||
}
|
||||
|
||||
/// Create a test node with a specific routing profile. Profile is immutable
|
||||
/// (lives in the shared context), so it is set via the `Config` flags that
|
||||
/// `Config::node_profile()` reads rather than poked post-construction.
|
||||
pub(super) async fn make_test_node_with_profile(profile: crate::protocol::NodeProfile) -> TestNode {
|
||||
use crate::protocol::NodeProfile;
|
||||
let mut config = Config::new();
|
||||
match profile {
|
||||
NodeProfile::Leaf => config.node.leaf_only = true,
|
||||
NodeProfile::NonRouting => config.node.disable_routing = true,
|
||||
NodeProfile::Full => {}
|
||||
}
|
||||
make_test_node_inner(config, 1280).await
|
||||
}
|
||||
|
||||
/// Shared builder: a test node from an explicit `Config` and transport MTU.
|
||||
async fn make_test_node_inner(config: Config, mtu: u16) -> TestNode {
|
||||
use crate::config::UdpConfig;
|
||||
use crate::transport::udp::UdpTransport;
|
||||
|
||||
let mut node = make_node();
|
||||
let mut node = make_node_with(config);
|
||||
let transport_id = TransportId::new(1);
|
||||
|
||||
// recv_buf_size and packet_channel are sized for large-network harness
|
||||
@@ -90,7 +109,7 @@ pub(super) async fn initiate_handshake(nodes: &mut [TestNode], i: usize, j: usiz
|
||||
let our_index = initiator.node.index_allocator.allocate().unwrap();
|
||||
let our_keypair = initiator.node.identity().keypair();
|
||||
let noise_msg1 = conn
|
||||
.start_handshake(our_keypair, initiator.node.startup_epoch, 1000)
|
||||
.start_handshake(our_keypair, initiator.node.startup_epoch(), 1000)
|
||||
.unwrap();
|
||||
conn.set_our_index(our_index);
|
||||
conn.set_transport_id(transport_id);
|
||||
|
||||
+32
-37
@@ -250,8 +250,7 @@ fn test_node_link_management() {
|
||||
|
||||
#[test]
|
||||
fn test_node_link_limit() {
|
||||
let mut node = make_node();
|
||||
node.set_max_links(2);
|
||||
let mut node = make_node_with_max_links(2);
|
||||
|
||||
for i in 0..2 {
|
||||
let link_id = node.allocate_link_id();
|
||||
@@ -383,9 +382,8 @@ fn test_node_cross_connection_resolution() {
|
||||
|
||||
#[test]
|
||||
fn test_node_peer_limit() {
|
||||
let mut node = make_node();
|
||||
let mut node = make_node_with_max_peers(2);
|
||||
let transport_id = TransportId::new(1);
|
||||
node.set_max_peers(2);
|
||||
|
||||
// Add two peers via promotion
|
||||
for i in 0..2 {
|
||||
@@ -601,9 +599,9 @@ fn test_promote_cleans_up_pending_outbound_to_same_peer() {
|
||||
let mut pending_conn =
|
||||
PeerConnection::outbound(pending_link_id, peer_b_identity, pending_time_ms);
|
||||
|
||||
let our_keypair = node.identity.keypair();
|
||||
let our_keypair = node.identity().keypair();
|
||||
let _msg1 = pending_conn
|
||||
.start_handshake(our_keypair, node.startup_epoch, pending_time_ms)
|
||||
.start_handshake(our_keypair, node.startup_epoch(), pending_time_ms)
|
||||
.unwrap();
|
||||
|
||||
let pending_index = node.index_allocator.allocate().unwrap();
|
||||
@@ -640,9 +638,9 @@ fn test_promote_cleans_up_pending_outbound_to_same_peer() {
|
||||
let mut completing_conn =
|
||||
PeerConnection::outbound(completing_link_id, peer_b_identity, completing_time_ms);
|
||||
|
||||
let our_keypair = node.identity.keypair();
|
||||
let our_keypair = node.identity().keypair();
|
||||
let msg1 = completing_conn
|
||||
.start_handshake(our_keypair, node.startup_epoch, completing_time_ms)
|
||||
.start_handshake(our_keypair, node.startup_epoch(), completing_time_ms)
|
||||
.unwrap();
|
||||
|
||||
// B responds
|
||||
@@ -989,7 +987,7 @@ fn active_peer_same_path_discovery_refreshes_stale_peer() {
|
||||
let transport_id = TransportId::new(1);
|
||||
let current_addr = TransportAddr::from_string("127.0.0.1:9");
|
||||
let stale_at = Node::now_ms().saturating_sub(
|
||||
node.config
|
||||
node.config()
|
||||
.node
|
||||
.heartbeat_interval_secs
|
||||
.saturating_add(1)
|
||||
@@ -1040,7 +1038,20 @@ async fn node_context_mirrors_config_and_immutable_facades() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn update_peers_races_new_alternative_without_dropping_active_peer() {
|
||||
let mut node = make_node();
|
||||
// The node's *current* (pre-update) peer set must contain `old_peer`, so it
|
||||
// is baked into the Config at construction (immutable context = sole store).
|
||||
let peer_full = Identity::generate();
|
||||
let old_peer = crate::config::PeerConfig {
|
||||
npub: peer_full.npub(),
|
||||
alias: None,
|
||||
addresses: vec![crate::config::PeerAddress::new("udp", "127.0.0.1:9")],
|
||||
connect_policy: crate::config::ConnectPolicy::AutoConnect,
|
||||
auto_reconnect: true,
|
||||
via_nostr: false,
|
||||
};
|
||||
let mut config = Config::new();
|
||||
config.peers = vec![old_peer.clone()];
|
||||
let mut node = make_node_with(config);
|
||||
let (packet_tx, packet_rx) = packet_channel(64);
|
||||
node.packet_tx = Some(packet_tx.clone());
|
||||
node.packet_rx = Some(packet_rx);
|
||||
@@ -1059,7 +1070,6 @@ async fn update_peers_races_new_alternative_without_dropping_active_peer() {
|
||||
node.transports
|
||||
.insert(transport_id, TransportHandle::Udp(udp));
|
||||
|
||||
let peer_full = Identity::generate();
|
||||
let peer_identity = PeerIdentity::from_pubkey_full(peer_full.pubkey_full());
|
||||
let peer_node_addr = *peer_identity.node_addr();
|
||||
let current_addr = TransportAddr::from_string("127.0.0.1:9");
|
||||
@@ -1079,14 +1089,6 @@ async fn update_peers_races_new_alternative_without_dropping_active_peer() {
|
||||
),
|
||||
);
|
||||
|
||||
let old_peer = crate::config::PeerConfig {
|
||||
npub: peer_full.npub(),
|
||||
alias: None,
|
||||
addresses: vec![crate::config::PeerAddress::new("udp", "127.0.0.1:9")],
|
||||
connect_policy: crate::config::ConnectPolicy::AutoConnect,
|
||||
auto_reconnect: true,
|
||||
via_nostr: false,
|
||||
};
|
||||
let new_peer = crate::config::PeerConfig {
|
||||
addresses: vec![
|
||||
crate::config::PeerAddress::new("udp", "127.0.0.1:9"),
|
||||
@@ -1094,7 +1096,6 @@ async fn update_peers_races_new_alternative_without_dropping_active_peer() {
|
||||
],
|
||||
..old_peer.clone()
|
||||
};
|
||||
node.config.peers = vec![old_peer];
|
||||
|
||||
let outcome = node.update_peers(vec![new_peer]).await.unwrap();
|
||||
|
||||
@@ -1260,8 +1261,8 @@ fn test_schedule_reconnect_preserves_backoff() {
|
||||
);
|
||||
|
||||
// With count=3, backoff should be 5s * 2^3 = 40s.
|
||||
let base_ms = node.config.node.retry.base_interval_secs * 1000;
|
||||
let max_ms = node.config.node.retry.max_backoff_secs * 1000;
|
||||
let base_ms = node.config().node.retry.base_interval_secs * 1000;
|
||||
let max_ms = node.config().node.retry.max_backoff_secs * 1000;
|
||||
let expected_delay = state.backoff_ms(base_ms, max_ms);
|
||||
assert_eq!(
|
||||
state.retry_after_ms,
|
||||
@@ -1296,8 +1297,8 @@ fn test_schedule_reconnect_fresh_state() {
|
||||
"Fresh reconnect should start at count=0"
|
||||
);
|
||||
// Base delay: 5s * 2^0 = 5s
|
||||
let base_ms = node.config.node.retry.base_interval_secs * 1000;
|
||||
let max_ms = node.config.node.retry.max_backoff_secs * 1000;
|
||||
let base_ms = node.config().node.retry.base_interval_secs * 1000;
|
||||
let max_ms = node.config().node.retry.max_backoff_secs * 1000;
|
||||
let expected_delay = state.backoff_ms(base_ms, max_ms);
|
||||
assert_eq!(state.retry_after_ms, 1_000 + expected_delay);
|
||||
}
|
||||
@@ -1628,8 +1629,7 @@ fn inject_dummy_peers(node: &mut Node, count: usize) {
|
||||
#[test]
|
||||
fn outbound_admission_check_direct() {
|
||||
// max_peers cap honored: above-cap returns false, below-cap returns true.
|
||||
let mut node = make_node();
|
||||
node.set_max_peers(3);
|
||||
let mut node = make_node_with_max_peers(3);
|
||||
|
||||
assert!(node.outbound_admission_check(), "0/3 should be admissible");
|
||||
inject_dummy_peers(&mut node, 2);
|
||||
@@ -1646,8 +1646,7 @@ fn outbound_admission_check_direct() {
|
||||
);
|
||||
|
||||
// No-cap sentinel: max_peers == 0 admits unconditionally.
|
||||
let mut uncapped = make_node();
|
||||
uncapped.set_max_peers(0);
|
||||
let mut uncapped = make_node_with_max_peers(0);
|
||||
assert!(uncapped.outbound_admission_check());
|
||||
inject_dummy_peers(&mut uncapped, 50);
|
||||
assert!(
|
||||
@@ -1658,8 +1657,7 @@ fn outbound_admission_check_direct() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn process_pending_retries_gated_at_capacity() {
|
||||
let mut node = make_node();
|
||||
node.set_max_peers(2);
|
||||
let mut node = make_node_with_max_peers(2);
|
||||
inject_dummy_peers(&mut node, 2);
|
||||
|
||||
// Queue a retry that would otherwise be due.
|
||||
@@ -1717,8 +1715,7 @@ async fn poll_nostr_discovery_established_gated_at_capacity() {
|
||||
use crate::discovery::EstablishedTraversal;
|
||||
use std::net::UdpSocket;
|
||||
|
||||
let mut node = make_node();
|
||||
node.set_max_peers(2);
|
||||
let mut node = make_node_with_max_peers(2);
|
||||
inject_dummy_peers(&mut node, 2);
|
||||
|
||||
let bootstrap = Arc::new(NostrDiscovery::new_for_test());
|
||||
@@ -1797,7 +1794,7 @@ async fn craft_and_send_msg1(
|
||||
use crate::node::wire::build_msg1;
|
||||
use crate::utils::index::SessionIndex;
|
||||
|
||||
let peer_b_identity = PeerIdentity::from_pubkey_full(node_b.identity.pubkey_full());
|
||||
let peer_b_identity = PeerIdentity::from_pubkey_full(node_b.identity().pubkey_full());
|
||||
let sender_pubkey_id = PeerIdentity::from_pubkey_full(sender_identity.pubkey_full());
|
||||
let sender_node_addr = *sender_pubkey_id.node_addr();
|
||||
|
||||
@@ -1859,8 +1856,7 @@ async fn handle_msg1_silent_drops_at_cap_for_new_peer() {
|
||||
use crate::config::UdpConfig;
|
||||
use tokio::time::{Duration, timeout};
|
||||
|
||||
let mut node = make_node();
|
||||
node.set_max_peers(2);
|
||||
let mut node = make_node_with_max_peers(2);
|
||||
inject_dummy_peers(&mut node, 2);
|
||||
assert_eq!(node.peer_count(), 2, "precondition: at cap");
|
||||
|
||||
@@ -1941,8 +1937,7 @@ async fn handle_msg1_silent_drops_at_cap_for_new_peer() {
|
||||
async fn handle_msg1_admits_existing_peer_at_cap() {
|
||||
use crate::config::UdpConfig;
|
||||
|
||||
let mut node = make_node();
|
||||
node.set_max_peers(2);
|
||||
let mut node = make_node_with_max_peers(2);
|
||||
|
||||
inject_dummy_peers(&mut node, 1);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user