peer: remove the dead PeerSlot enum and PeerConnection resend API

PeerSlot (and its entire impl surface) was referenced only by its own
module tests and the lib.rs re-export; peer storage has always used the
separate connections/peers maps. PeerConnection's resend_count/
next_resend_at_ms/record_resend delegations had no production callers:
the live resend counter is machine-sourced (connection_resend_count reads
the per-peer machine), and the FSP session layer uses SessionEntry's own
methods. ConnectionState::next_resend_at_ms is now test-only (its
remaining callers are the fmp state unit tests) and marked cfg(test).

The PeerSlot unit tests go with the enum; test_resend_count_tracking is
dropped because the delegation target's schedule arithmetic is already
covered by the fmp resend_bookkeeping test.
This commit is contained in:
Johnathan Corgan
2026-07-17 01:32:49 +00:00
parent e42598a86e
commit 74245e80ac
5 changed files with 2 additions and 212 deletions
+1 -3
View File
@@ -92,9 +92,7 @@ pub use cache::{CacheEntry, CacheError, CacheStats, CoordCache};
pub use proto::fmp::{PromotionResult, cross_connection_winner};
// Re-export peer types
pub use peer::{
ActivePeer, ConnectivityState, HandshakeState, PeerConnection, PeerError, PeerSlot,
};
pub use peer::{ActivePeer, ConnectivityState, HandshakeState, PeerConnection, PeerError};
// Re-export node types
pub use node::{Node, NodeError, NodeState, UpdatePeersOutcome};
-27
View File
@@ -819,8 +819,6 @@ async fn test_msg1_stored_for_resend() {
// Verify stored msg1 matches what was built
assert_eq!(conn.handshake_msg1().unwrap(), &wire_msg1);
assert_eq!(conn.resend_count(), 0);
assert!(conn.next_resend_at_ms() > now_ms);
}
/// Test that resend scheduling respects max_resends and backoff.
@@ -993,31 +991,6 @@ fn test_msg2_stored_on_connection() {
assert_eq!(conn.handshake_msg2().unwrap(), &msg2_bytes);
}
/// Test that resend_count and next_resend_at_ms track correctly.
#[test]
fn test_resend_count_tracking() {
let peer_identity = make_peer_identity();
let mut conn = PeerConnection::outbound(LinkId::new(1), peer_identity, 1000);
assert_eq!(conn.resend_count(), 0);
assert_eq!(conn.next_resend_at_ms(), 0);
// Simulate storing msg1 and scheduling first resend
conn.set_handshake_msg1(vec![0x01], 2000);
assert_eq!(conn.resend_count(), 0);
assert_eq!(conn.next_resend_at_ms(), 2000);
// Record first resend
conn.record_resend(4000); // next at 4000 (2s backoff)
assert_eq!(conn.resend_count(), 1);
assert_eq!(conn.next_resend_at_ms(), 4000);
// Record second resend
conn.record_resend(8000); // next at 8000 (4s backoff)
assert_eq!(conn.resend_count(), 2);
assert_eq!(conn.next_resend_at_ms(), 8000);
}
/// Test that duplicate msg2 is silently dropped when pending_outbound is already cleared.
#[tokio::test]
async fn test_duplicate_msg2_dropped() {
-15
View File
@@ -237,21 +237,6 @@ impl PeerConnection {
self.state.handshake_msg2()
}
/// Number of resends performed.
pub fn resend_count(&self) -> u32 {
self.state.resend_count()
}
/// When the next resend is scheduled (Unix ms).
pub fn next_resend_at_ms(&self) -> u64 {
self.state.next_resend_at_ms()
}
/// Record a resend and schedule the next one.
pub fn record_resend(&mut self, next_resend_at_ms: u64) {
self.state.record_resend(next_resend_at_ms);
}
// === Noise Handshake Operations (shell: drives crypto, updates pure state) ===
/// Start the handshake as initiator and generate message 1.
-167
View File
@@ -3,9 +3,6 @@
//! Two-phase peer lifecycle:
//! 1. **PeerConnection** - Handshake phase, before identity is verified
//! 2. **ActivePeer** - Authenticated phase, after successful Noise handshake
//!
//! The PeerSlot enum represents either phase, enabling unified storage
//! while maintaining type safety for phase-specific operations.
mod active;
#[cfg(any(target_os = "linux", target_os = "macos"))]
@@ -18,7 +15,6 @@ pub use connection::{HandshakeState, PeerConnection};
use crate::NodeAddr;
use crate::transport::LinkId;
use std::fmt;
use thiserror::Error;
// ============================================================================
@@ -62,127 +58,12 @@ pub enum PeerError {
MaxPeersExceeded { max: usize },
}
// ============================================================================
// PeerSlot
// ============================================================================
/// A slot in the peer table, representing either connection or active phase.
#[derive(Debug)]
pub enum PeerSlot {
/// Connection in handshake phase.
Connecting(Box<PeerConnection>),
/// Authenticated peer.
Active(Box<ActivePeer>),
}
impl PeerSlot {
/// Create a new connecting slot (outbound).
pub fn outbound(conn: PeerConnection) -> Self {
PeerSlot::Connecting(Box::new(conn))
}
/// Create a new connecting slot (inbound).
pub fn inbound(conn: PeerConnection) -> Self {
PeerSlot::Connecting(Box::new(conn))
}
/// Create a new active slot.
pub fn active(peer: ActivePeer) -> Self {
PeerSlot::Active(Box::new(peer))
}
/// Check if this is a connecting slot.
pub fn is_connecting(&self) -> bool {
matches!(self, PeerSlot::Connecting(_))
}
/// Check if this is an active slot.
pub fn is_active(&self) -> bool {
matches!(self, PeerSlot::Active(_))
}
/// Get the link ID for this slot.
pub fn link_id(&self) -> LinkId {
match self {
PeerSlot::Connecting(conn) => conn.link_id(),
PeerSlot::Active(peer) => peer.link_id(),
}
}
/// Get as connection reference, if connecting.
pub fn as_connection(&self) -> Option<&PeerConnection> {
match self {
PeerSlot::Connecting(conn) => Some(conn),
PeerSlot::Active(_) => None,
}
}
/// Get as mutable connection reference, if connecting.
pub fn as_connection_mut(&mut self) -> Option<&mut PeerConnection> {
match self {
PeerSlot::Connecting(conn) => Some(conn),
PeerSlot::Active(_) => None,
}
}
/// Get as active peer reference, if active.
pub fn as_active(&self) -> Option<&ActivePeer> {
match self {
PeerSlot::Active(peer) => Some(peer),
PeerSlot::Connecting(_) => None,
}
}
/// Get as mutable active peer reference, if active.
pub fn as_active_mut(&mut self) -> Option<&mut ActivePeer> {
match self {
PeerSlot::Active(peer) => Some(peer),
PeerSlot::Connecting(_) => None,
}
}
/// Get the known node_addr, if any.
///
/// For connections, this is the expected identity (may be None for inbound).
/// For active peers, this is always known.
pub fn node_addr(&self) -> Option<&NodeAddr> {
match self {
PeerSlot::Connecting(conn) => conn.expected_identity().map(|id| id.node_addr()),
PeerSlot::Active(peer) => Some(peer.node_addr()),
}
}
}
impl fmt::Display for PeerSlot {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
PeerSlot::Connecting(conn) => {
write!(
f,
"connecting(link={}, state={})",
conn.link_id(),
conn.handshake_state()
)
}
PeerSlot::Active(peer) => {
write!(
f,
"active(node={:?}, link={})",
peer.node_addr(),
peer.link_id()
)
}
}
}
}
// ============================================================================
// Tests
// ============================================================================
#[cfg(test)]
mod tests {
use super::*;
use crate::proto::fmp::PromotionResult;
use crate::transport::LinkId;
use crate::{Identity, PeerIdentity};
@@ -192,32 +73,6 @@ mod tests {
PeerIdentity::from_pubkey(identity.pubkey())
}
#[test]
fn test_peer_slot_connecting() {
let identity = make_peer_identity();
let conn = PeerConnection::outbound(LinkId::new(1), identity, 1000);
let slot = PeerSlot::Connecting(Box::new(conn));
assert!(slot.is_connecting());
assert!(!slot.is_active());
assert!(slot.as_connection().is_some());
assert!(slot.as_active().is_none());
assert_eq!(slot.link_id(), LinkId::new(1));
}
#[test]
fn test_peer_slot_active() {
let identity = make_peer_identity();
let peer = ActivePeer::new(identity, LinkId::new(2), 2000);
let slot = PeerSlot::Active(Box::new(peer));
assert!(!slot.is_connecting());
assert!(slot.is_active());
assert!(slot.as_connection().is_none());
assert!(slot.as_active().is_some());
assert_eq!(slot.link_id(), LinkId::new(2));
}
#[test]
fn test_promotion_result_promoted() {
let identity = make_peer_identity();
@@ -255,26 +110,4 @@ mod tests {
assert!(!result.should_close_this_connection());
assert_eq!(result.link_to_close(), Some(LinkId::new(1)));
}
#[test]
fn test_peer_slot_node_addr() {
// Outbound connection knows expected identity
let identity = make_peer_identity();
let expected_node_addr = *identity.node_addr();
let conn = PeerConnection::outbound(LinkId::new(1), identity, 1000);
let slot = PeerSlot::Connecting(Box::new(conn));
assert_eq!(slot.node_addr(), Some(&expected_node_addr));
// Inbound connection doesn't know identity yet
let conn_inbound = PeerConnection::inbound(LinkId::new(2), 2000);
let slot_inbound = PeerSlot::Connecting(Box::new(conn_inbound));
assert!(slot_inbound.node_addr().is_none());
// Active peer always knows identity
let identity2 = make_peer_identity();
let active_node_addr = *identity2.node_addr();
let peer = ActivePeer::new(identity2, LinkId::new(3), 3000);
let slot_active = PeerSlot::Active(Box::new(peer));
assert_eq!(slot_active.node_addr(), Some(&active_node_addr));
}
}
+1
View File
@@ -421,6 +421,7 @@ impl ConnectionState {
}
/// When the next resend is scheduled (Unix ms).
#[cfg(test)]
pub fn next_resend_at_ms(&self) -> u64 {
self.next_resend_at_ms
}