Fix transit node coord_cache expiry breaking multi-hop routing

Transit nodes cache destination coordinates when they forward
SessionSetup messages (via try_warm_coord_cache). These coord_cache
entries have a 5-minute TTL, after which they expire. Once expired,
the transit node can no longer forward data packets for that
destination — find_next_hop returns None and the node sends
CoordsRequired errors back to the source. This creates a permanent
routing failure for any multi-hop path after 5 minutes of the initial
session establishment, even if traffic is actively flowing.

The root cause was that find_next_hop used coord_cache.get(), a
read-only lookup that checks expiry but never extends it. Active
forwarding did not keep the cache warm. Meanwhile, get_and_touch()
existed but only updated last_used without extending expires_at.

Fix:
- find_next_hop now calls coord_cache.get_and_touch() instead of get()
- get_and_touch now calls entry.refresh() instead of entry.touch(),
  which extends expires_at by the default TTL on each access
- find_next_hop signature changed from &self to &mut self to allow
  the mutable cache access

This ensures that as long as traffic flows through a transit node,
the coord_cache entries stay warm and routing continues to work.
Entries still expire after 5 minutes of inactivity as designed.
This commit is contained in:
Johnathan Corgan
2026-02-16 12:41:45 +00:00
parent 930f139787
commit 5987cbfb69
3 changed files with 64 additions and 19 deletions
+3 -3
View File
@@ -111,7 +111,7 @@ impl CoordCache {
})
}
/// Look up coordinates and touch (update last_used).
/// Look up coordinates and refresh (update last_used and extend TTL).
pub fn get_and_touch(
&mut self,
addr: &NodeAddr,
@@ -125,9 +125,9 @@ impl CoordCache {
return None;
}
// Touch and return
// Refresh TTL and return
if let Some(entry) = self.entries.get_mut(addr) {
entry.touch(current_time_ms);
entry.refresh(current_time_ms, self.default_ttl_ms);
Some(entry.coords())
} else {
None