mirror of
https://github.com/jmcorgan/fips.git
synced 2026-08-12 09:33:23 +00:00
node: seed control machines directly in tests, ahead of removing the leg
Tests built a free-standing PeerConnection, mutated it, and handed it to Node::add_connection by value. None of those sites survives the removal of PeerConnection, so converting them afterwards would mean one enormous commit that cannot be reviewed honestly. Convert them now, while the struct still exists and the conversion can be validated against a green tree. Adds a cfg(test) Node::seed_handshake_machine plus a HandshakeSeed builder, and rewrites make_completed_connection (now seed_completed_connection) and the twenty inline builders onto it. add_connection keeps its body and loses its test callers. The builder's carrier seeding is a verbatim copy of add_connection's: the two conditional writes for their_index and transport_id, then set_leg, through the same entry().or_insert_with() so an existing leg-less machine keeps its constructor-side fields. Nothing else reaches the carrier -- our_index, source_addr, post-construction started_at and the stored handshake bytes stay leg-only. Seeding more than that would let these tests observe a carrier richer than production's and keep passing even if a later production write-lift were missed. The Noise exchange now runs on the already-seeded leg rather than before the hand-over. That is neutral because the only read of expected_identity is guarded by is_outbound, and no crypto method allocates a session index. Also adds a compile-time check that PeerAction is Clone + Eq, which is what keeps a runtime handle from being smuggled into an action payload.
This commit is contained in:
+36
-18
@@ -84,27 +84,49 @@ pub(super) fn make_peer_identity() -> PeerIdentity {
|
||||
PeerIdentity::from_pubkey(identity.pubkey())
|
||||
}
|
||||
|
||||
/// Create a PeerConnection with a completed Noise IK handshake.
|
||||
/// Seed a control machine whose leg carries a completed Noise IK handshake.
|
||||
///
|
||||
/// Returns (connection, peer_identity) where the connection is outbound,
|
||||
/// in Complete state, with session, indices, and transport info set.
|
||||
pub(super) fn make_completed_connection(
|
||||
/// Returns the peer identity. The leg is outbound, in Complete state, with
|
||||
/// session, indices, and transport info set, and is installed on the node
|
||||
/// through [`Node::seed_handshake_machine`] — the test-surface twin of
|
||||
/// `Node::add_connection`.
|
||||
///
|
||||
/// The Noise exchange runs on the already-seeded leg, where it used to run
|
||||
/// before the leg was handed over. That reordering is neutral, but not
|
||||
/// because the handshake leaves the seeded fields alone —
|
||||
/// `receive_handshake_init` does write `expected_identity`. It is neutral
|
||||
/// because the only read of `expected_identity` is guarded by `is_outbound`:
|
||||
/// an inbound leg takes the `new_inbound` arm whether or not the identity has
|
||||
/// been learned, and an outbound leg never runs that method. The remaining
|
||||
/// reads (`link_id`, `started_at`, `is_outbound`, `their_index`,
|
||||
/// `transport_id`) are genuinely untouched by the handshake.
|
||||
pub(super) fn seed_completed_connection(
|
||||
node: &mut Node,
|
||||
link_id: LinkId,
|
||||
transport_id: TransportId,
|
||||
current_time_ms: u64,
|
||||
) -> (PeerConnection, PeerIdentity) {
|
||||
) -> PeerIdentity {
|
||||
let peer_identity_full = Identity::generate();
|
||||
// Must use from_pubkey_full to preserve parity for ECDH
|
||||
let peer_identity = PeerIdentity::from_pubkey_full(peer_identity_full.pubkey_full());
|
||||
|
||||
// Create outbound connection
|
||||
let mut conn = PeerConnection::outbound(link_id, peer_identity, current_time_ms);
|
||||
let our_index = node.index_allocator.allocate().unwrap();
|
||||
node.seed_handshake_machine(
|
||||
HandshakeSeed::outbound(link_id, peer_identity, current_time_ms)
|
||||
.with_our_index(our_index)
|
||||
.with_their_index(SessionIndex::new(42))
|
||||
.with_transport_id(transport_id)
|
||||
.with_source_addr(TransportAddr::from_string("127.0.0.1:5000")),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Run initiator side of handshake
|
||||
let our_keypair = node.identity().keypair();
|
||||
let msg1 = conn
|
||||
.start_handshake(our_keypair, node.startup_epoch(), current_time_ms)
|
||||
let startup_epoch = node.startup_epoch();
|
||||
let msg1 = node
|
||||
.get_connection_mut(&link_id)
|
||||
.unwrap()
|
||||
.start_handshake(our_keypair, startup_epoch, current_time_ms)
|
||||
.unwrap();
|
||||
|
||||
// Run responder side to generate msg2
|
||||
@@ -117,14 +139,10 @@ pub(super) fn make_completed_connection(
|
||||
.unwrap();
|
||||
|
||||
// Complete initiator handshake
|
||||
conn.complete_handshake(&msg2, current_time_ms).unwrap();
|
||||
node.get_connection_mut(&link_id)
|
||||
.unwrap()
|
||||
.complete_handshake(&msg2, current_time_ms)
|
||||
.unwrap();
|
||||
|
||||
// Set indices and transport info
|
||||
let our_index = node.index_allocator.allocate().unwrap();
|
||||
conn.set_our_index(our_index);
|
||||
conn.set_their_index(SessionIndex::new(42));
|
||||
conn.set_transport_id(transport_id);
|
||||
conn.set_source_addr(TransportAddr::from_string("127.0.0.1:5000"));
|
||||
|
||||
(conn, peer_identity)
|
||||
peer_identity
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user