Add dest_coords to SessionAck for return-path routing

SessionAck previously only carried the responder's coordinates
(src_coords). When the return path diverged from the forward path
(e.g., after tree reconvergence), transit nodes on the return path
lacked the initiator's coordinates and couldn't route the SessionAck
back, causing handshake timeouts.

Add dest_coords (initiator's coordinates) to the SessionAck wire
format, mirroring SessionSetup's design. Transit nodes now cache both
endpoints' coordinates when forwarding a SessionAck, making the return
path self-sufficient regardless of path asymmetry.

Root cause confirmed by churn-20 sim log analysis: the n04-n14
handshake failure was caused by n15 (return-path transit) lacking
n04's coordinates, not by stale tree routes through a downed node.
This commit is contained in:
Johnathan Corgan
2026-02-21 14:18:48 +00:00
parent cfb087a95d
commit 19efe06622
8 changed files with 50 additions and 21 deletions
+6 -4
View File
@@ -220,7 +220,7 @@ transit, CP-flagged data packets, LookupResponse — write to the same cache.
| Source | When | What |
| ------ | ---- | ---- |
| SessionSetup transit | Session establishment | Both src and dest coordinates |
| SessionAck transit | Session establishment | Responder's coordinates |
| SessionAck transit | Session establishment | Both src and dest coordinates |
| CP-flagged data packet | Warmup or recovery | Both src and dest coordinates (cleartext) |
| LookupResponse | Discovery | Target's coordinates |
@@ -329,8 +329,10 @@ As the SessionSetup transits each intermediate node:
coordinate cache
3. Forwards the message using the cached destination coordinates
SessionAck returns along the reverse path, carrying the responder's
coordinates and warming caches in the other direction.
SessionAck returns along the reverse path, carrying both the responder's
and initiator's coordinates and warming caches in the other direction. This
ensures return-path transit nodes can route even when the reverse path
diverges from the forward path (e.g., after tree reconvergence).
### Result
@@ -532,7 +534,7 @@ routing decisions but retains its own end-to-end encryption and identity.
| LookupRequest | ~300 bytes | First contact, recovery | Yes (flood) |
| LookupResponse | ~400 bytes | Response to discovery | Yes (greedy routed) |
| SessionDatagram + SessionSetup | ~232402 bytes | Session establishment | Yes (routed) |
| SessionDatagram + SessionAck | ~122 bytes | Session confirmation | Yes (routed) |
| SessionDatagram + SessionAck | ~170 bytes | Session confirmation | Yes (routed) |
| SessionDatagram + Data (minimal) | 106 bytes + payload | Bulk traffic | Yes (routed) |
| SessionDatagram + Data (with CP) | 106 + coords + payload | Warmup/recovery | Yes (routed) |
| SessionDatagram + CoordsRequired | 70 bytes | Cache miss error | Yes (routed) |
+5 -3
View File
@@ -116,7 +116,7 @@ The handshake is carried in SessionSetup and SessionAck messages:
1. **Initiator** sends SessionSetup containing Noise IK msg1 and both
parties' tree coordinates
2. **Responder** processes msg1, learns initiator identity, sends SessionAck
containing Noise IK msg2 and its own coordinates
containing Noise IK msg2 and both parties' tree coordinates
3. Both parties derive identical symmetric session keys
Packets that trigger session establishment are queued (with bounded buffer)
@@ -130,8 +130,10 @@ As the message transits intermediate nodes, each node caches these coordinates,
warming the path for subsequent data packets that carry only addresses (no
coordinates).
SessionAck carries the responder's coordinates back along the reverse path,
warming caches in the other direction.
SessionAck carries both the responder's and initiator's coordinates back
along the reverse path, warming caches in the other direction. This ensures
return-path transit nodes can route even when the reverse path diverges from
the forward path (e.g., after tree reconvergence).
### Simultaneous Initiation
+4 -2
View File
@@ -566,8 +566,10 @@ Encoded with FSP prefix: ver=0, phase=0x2, flags=0, payload_len.
| Offset | Field | Size | Description |
| ------ | ----- | ---- | ----------- |
| 0 | flags | 1 byte | Reserved |
| 1 | src_coords_count | 2 bytes LE | Number of coordinate entries |
| 1 | src_coords_count | 2 bytes LE | Number of acknowledger coordinate entries |
| 3 | src_coords | 16 x n bytes | Acknowledger's ancestry (for cache warming) |
| ... | dest_coords_count | 2 bytes LE | Number of initiator coordinate entries |
| ... | dest_coords | 16 x m bytes | Initiator's ancestry (for return-path cache warming) |
| ... | handshake_len | 2 bytes LE | Noise payload length |
| ... | handshake_payload | variable | Noise IK msg2 (33 bytes typical) |
@@ -730,7 +732,7 @@ endpoint session keys).
| Message | Typical Size | Notes |
| ------- | ------------ | ----- |
| SessionSetup | ~200 bytes | Depth-dependent |
| SessionAck | ~80 bytes | Depth-dependent |
| SessionAck | ~130 bytes | Depth-dependent (carries both endpoints' coords) |
| Data (minimal) | 12 + 6 + payload + 16 bytes | Steady state |
| Data (with coords) | 12 + ~130 + 6 + payload + 16 bytes | Warmup/recovery |
| SenderReport | 12 + 6 + 46 + 16 bytes | MMP metrics |