diff --git a/docs/design/fips-routing.md b/docs/design/fips-routing.md index cd2e408..2d8e480 100644 --- a/docs/design/fips-routing.md +++ b/docs/design/fips-routing.md @@ -584,7 +584,7 @@ enum RouteState { | LookupResponse | Return coordinates | ~400 bytes | Reply to discovery | | SessionSetup | Warm router caches + crypto init | ~400-700 bytes | Before data transfer | | SessionAck | Confirm session + crypto response | ~300-500 bytes | Session confirmation | -| DataPacket | Application data | 36 bytes + payload (minimal) | Bulk of traffic | +| DataPacket | Application data | 68 bytes + payload (minimal) | Bulk of traffic | | DataPacket | With coordinates | ~300-500 bytes + payload | After CoordsRequired | | CoordsRequired | Request coords in next packet | ~50 bytes | Cache miss recovery | @@ -601,7 +601,7 @@ enum RouteState { - **Bloom filter traffic**: Near zero (event-driven, no changes) - **Discovery traffic**: Rare (warm caches) - **Session traffic**: Rare (established sessions) -- **Data traffic**: Minimal overhead (36-byte header) +- **Data traffic**: Minimal overhead (68-byte header) ### Network Churn diff --git a/docs/design/fips-session-protocol.md b/docs/design/fips-session-protocol.md index 178d9a3..f3ac417 100644 --- a/docs/design/fips-session-protocol.md +++ b/docs/design/fips-session-protocol.md @@ -288,7 +288,7 @@ The crypto session handshake (SessionSetup/SessionAck) warms route caches at intermediate routers as it transits. Each message carries the sender's coordinates; routers extract and cache `(src_addr, dest_addr) → next_hop` for both directions. After the handshake completes, data packets use minimal -36-byte headers and routers forward based on cached routes. +68-byte headers and routers forward based on cached routes. ### 5.2 Cache Miss Recovery @@ -715,7 +715,7 @@ A DataPacket from source S to destination D, transiting router R: │ │ SESSION LAYER (S↔D encrypted) │ │ │ ├───────────┬───────┬──────────┬──────────┬─────────────────────────────┤ │ │ │ 0x10 │ flags │ hop_limit│ pay_len │ src_addr │ dest_addr │ │ -│ │ DataPacket│ 0x00 │ 64 │ 1400 │ 16 bytes │ 16 bytes │ │ +│ │ DataPacket│ 0x00 │ 64 │ 1400 │ 32 bytes │ 32 bytes │ │ │ ├───────────┴───────┴──────────┴──────────┴──────────────┴──────────────┤ │ │ │ │ │ │ │ ENCRYPTED PAYLOAD (S↔D session keys) │ │ diff --git a/src/cache.rs b/src/cache.rs index a34561a..95a7ecc 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -5,7 +5,7 @@ //! RouteCache stores coordinates learned from discovery queries. use crate::tree::TreeCoordinate; -use crate::{FipsAddress, NodeAddr}; +use crate::NodeAddr; use std::collections::HashMap; use thiserror::Error; @@ -116,13 +116,13 @@ impl CacheEntry { /// Coordinate cache for routing decisions. /// -/// Maps FIPS addresses to their tree coordinates, enabling data packets +/// Maps node addresses to their tree coordinates, enabling data packets /// to be routed without carrying coordinates in every packet. Populated /// by SessionSetup packets. #[derive(Clone, Debug)] pub struct CoordCache { - /// Address -> coordinates mapping. - entries: HashMap, + /// NodeAddr -> coordinates mapping. + entries: HashMap, /// Maximum number of entries. max_entries: usize, /// Default TTL for entries (milliseconds). @@ -160,7 +160,7 @@ impl CoordCache { } /// Insert or update a cache entry. - pub fn insert(&mut self, addr: FipsAddress, coords: TreeCoordinate, current_time_ms: u64) { + pub fn insert(&mut self, addr: NodeAddr, coords: TreeCoordinate, current_time_ms: u64) { // Update existing entry if present if let Some(entry) = self.entries.get_mut(&addr) { entry.update(coords, current_time_ms, self.default_ttl_ms); @@ -179,7 +179,7 @@ impl CoordCache { /// Insert with a custom TTL. pub fn insert_with_ttl( &mut self, - addr: FipsAddress, + addr: NodeAddr, coords: TreeCoordinate, current_time_ms: u64, ttl_ms: u64, @@ -198,7 +198,7 @@ impl CoordCache { } /// Look up coordinates for an address (without touching). - pub fn get(&self, addr: &FipsAddress, current_time_ms: u64) -> Option<&TreeCoordinate> { + pub fn get(&self, addr: &NodeAddr, current_time_ms: u64) -> Option<&TreeCoordinate> { self.entries.get(addr).and_then(|entry| { if entry.is_expired(current_time_ms) { None @@ -211,7 +211,7 @@ impl CoordCache { /// Look up coordinates and touch (update last_used). pub fn get_and_touch( &mut self, - addr: &FipsAddress, + addr: &NodeAddr, current_time_ms: u64, ) -> Option<&TreeCoordinate> { // Check and remove if expired @@ -232,17 +232,17 @@ impl CoordCache { } /// Get the full cache entry. - pub fn get_entry(&self, addr: &FipsAddress) -> Option<&CacheEntry> { + pub fn get_entry(&self, addr: &NodeAddr) -> Option<&CacheEntry> { self.entries.get(addr) } /// Remove an entry. - pub fn remove(&mut self, addr: &FipsAddress) -> Option { + pub fn remove(&mut self, addr: &NodeAddr) -> Option { self.entries.remove(addr) } /// Check if an address is cached (and not expired). - pub fn contains(&self, addr: &FipsAddress, current_time_ms: u64) -> bool { + pub fn contains(&self, addr: &NodeAddr, current_time_ms: u64) -> bool { self.get(addr, current_time_ms).is_some() } @@ -413,7 +413,7 @@ impl CachedCoords { /// /// Separate from CoordCache, this stores routes learned from the discovery /// protocol (LookupRequest/LookupResponse) rather than session establishment. -/// Keyed by NodeAddr rather than FipsAddress. +/// Keyed by NodeAddr. #[derive(Clone, Debug)] pub struct RouteCache { /// NodeAddr -> discovered coordinates. @@ -539,12 +539,6 @@ mod tests { NodeAddr::from_bytes(bytes) } - fn make_address(val: u8) -> FipsAddress { - let mut bytes = [0xfdu8; 16]; - bytes[1] = val; - FipsAddress::from_bytes(bytes).unwrap() - } - fn make_coords(ids: &[u8]) -> TreeCoordinate { TreeCoordinate::new(ids.iter().map(|&v| make_node_addr(v)).collect()).unwrap() } @@ -595,7 +589,7 @@ mod tests { #[test] fn test_coord_cache_basic() { let mut cache = CoordCache::new(100, 1000); - let addr = make_address(1); + let addr = make_node_addr(1); let coords = make_coords(&[1, 0]); cache.insert(addr, coords.clone(), 0); @@ -608,7 +602,7 @@ mod tests { #[test] fn test_coord_cache_expiry() { let mut cache = CoordCache::new(100, 1000); - let addr = make_address(1); + let addr = make_node_addr(1); let coords = make_coords(&[1, 0]); cache.insert(addr, coords, 0); @@ -620,7 +614,7 @@ mod tests { #[test] fn test_coord_cache_update() { let mut cache = CoordCache::new(100, 1000); - let addr = make_address(1); + let addr = make_node_addr(1); cache.insert(addr, make_coords(&[1, 0]), 0); cache.insert(addr, make_coords(&[1, 2, 0]), 500); @@ -634,9 +628,9 @@ mod tests { fn test_coord_cache_eviction() { let mut cache = CoordCache::new(2, 10000); - let addr1 = make_address(1); - let addr2 = make_address(2); - let addr3 = make_address(3); + let addr1 = make_node_addr(1); + let addr2 = make_node_addr(2); + let addr3 = make_node_addr(3); cache.insert(addr1, make_coords(&[1, 0]), 0); cache.insert(addr2, make_coords(&[2, 0]), 100); @@ -656,25 +650,25 @@ mod tests { fn test_coord_cache_evict_expired_first() { let mut cache = CoordCache::new(2, 100); - cache.insert(make_address(1), make_coords(&[1, 0]), 0); - cache.insert(make_address(2), make_coords(&[2, 0]), 50); + cache.insert(make_node_addr(1), make_coords(&[1, 0]), 0); + cache.insert(make_node_addr(2), make_coords(&[2, 0]), 50); // At time 150, addr1 is expired, addr2 is not - cache.insert(make_address(3), make_coords(&[3, 0]), 150); + cache.insert(make_node_addr(3), make_coords(&[3, 0]), 150); // addr1 should be evicted (expired), not addr2 (LRU but not expired) - assert!(!cache.contains(&make_address(1), 150)); - assert!(cache.contains(&make_address(2), 150)); - assert!(cache.contains(&make_address(3), 150)); + assert!(!cache.contains(&make_node_addr(1), 150)); + assert!(cache.contains(&make_node_addr(2), 150)); + assert!(cache.contains(&make_node_addr(3), 150)); } #[test] fn test_coord_cache_purge_expired() { let mut cache = CoordCache::new(100, 100); - cache.insert(make_address(1), make_coords(&[1, 0]), 0); // expires at 100 - cache.insert(make_address(2), make_coords(&[2, 0]), 50); // expires at 150 - cache.insert(make_address(3), make_coords(&[3, 0]), 200); // expires at 300 + cache.insert(make_node_addr(1), make_coords(&[1, 0]), 0); // expires at 100 + cache.insert(make_node_addr(2), make_coords(&[2, 0]), 50); // expires at 150 + cache.insert(make_node_addr(3), make_coords(&[3, 0]), 200); // expires at 300 assert_eq!(cache.len(), 3); @@ -683,15 +677,15 @@ mod tests { // Entry 1 and 2 expired, entry 3 still valid assert_eq!(purged, 2); assert_eq!(cache.len(), 1); - assert!(cache.contains(&make_address(3), 151)); + assert!(cache.contains(&make_node_addr(3), 151)); } #[test] fn test_coord_cache_stats() { let mut cache = CoordCache::new(100, 100); - cache.insert(make_address(1), make_coords(&[1, 0]), 0); - cache.insert(make_address(2), make_coords(&[2, 0]), 50); + cache.insert(make_node_addr(1), make_coords(&[1, 0]), 0); + cache.insert(make_node_addr(2), make_coords(&[2, 0]), 50); let stats = cache.stats(150); diff --git a/src/protocol.rs b/src/protocol.rs index be68aee..e7d2e15 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -22,7 +22,7 @@ use crate::bloom::BloomFilter; use crate::tree::{ParentDeclaration, TreeCoordinate}; -use crate::{FipsAddress, NodeAddr}; +use crate::NodeAddr; use secp256k1::schnorr::Signature; use std::fmt; use thiserror::Error; @@ -31,7 +31,8 @@ use thiserror::Error; pub const PROTOCOL_VERSION: u8 = 1; /// Data packet header size in bytes (excluding payload). -pub const DATA_HEADER_SIZE: usize = 36; +/// flags(1) + hop_limit(1) + payload_length(2) + src_addr(32) + dest_addr(32) = 68 +pub const DATA_HEADER_SIZE: usize = 68; // ============================================================================ // Link Layer Message Types (peer-to-peer, hop-by-hop) @@ -496,8 +497,8 @@ impl LookupResponse { /// address but cannot decrypt the payload. #[derive(Clone, Debug)] pub struct SessionDatagram { - /// Destination FIPS address (for routing decisions). - pub dest_addr: FipsAddress, + /// Destination node address (for routing decisions). + pub dest_addr: NodeAddr, /// Hop limit (decremented at each hop). pub hop_limit: u8, /// Encrypted session-layer payload (opaque to intermediate nodes). @@ -506,7 +507,7 @@ pub struct SessionDatagram { impl SessionDatagram { /// Create a new session datagram. - pub fn new(dest_addr: FipsAddress, payload: Vec) -> Self { + pub fn new(dest_addr: NodeAddr, payload: Vec) -> Self { Self { dest_addr, hop_limit: 64, @@ -594,10 +595,10 @@ impl SessionFlags { /// information. Routers along the path cache the mappings. #[derive(Clone, Debug)] pub struct SessionSetup { - /// Source FIPS address. - pub src_addr: FipsAddress, - /// Destination FIPS address. - pub dest_addr: FipsAddress, + /// Source node address. + pub src_addr: NodeAddr, + /// Destination node address. + pub dest_addr: NodeAddr, /// Source coordinates (for return path caching). pub src_coords: TreeCoordinate, /// Destination coordinates (for forward routing). @@ -609,8 +610,8 @@ pub struct SessionSetup { impl SessionSetup { /// Create a new session setup message. pub fn new( - src_addr: FipsAddress, - dest_addr: FipsAddress, + src_addr: NodeAddr, + dest_addr: NodeAddr, src_coords: TreeCoordinate, dest_coords: TreeCoordinate, ) -> Self { @@ -635,17 +636,17 @@ impl SessionSetup { /// Sent in response to SessionSetup when request_ack is set. #[derive(Clone, Debug)] pub struct SessionAck { - /// Source address (the acknowledger). - pub src_addr: FipsAddress, - /// Destination address (original session initiator). - pub dest_addr: FipsAddress, + /// Source node address (the acknowledger). + pub src_addr: NodeAddr, + /// Destination node address (original session initiator). + pub dest_addr: NodeAddr, /// Acknowledger's coordinates. pub src_coords: TreeCoordinate, } impl SessionAck { /// Create a new session acknowledgement. - pub fn new(src_addr: FipsAddress, dest_addr: FipsAddress, src_coords: TreeCoordinate) -> Self { + pub fn new(src_addr: NodeAddr, dest_addr: NodeAddr, src_coords: TreeCoordinate) -> Self { Self { src_addr, dest_addr, @@ -715,12 +716,12 @@ impl DataFlags { /// Minimal data packet with addresses only (no coordinates). /// -/// The 36-byte header contains: +/// The 68-byte header contains: /// - flags (1 byte) /// - hop_limit (1 byte) /// - payload_length (2 bytes) -/// - src_addr (16 bytes) -/// - dest_addr (16 bytes) +/// - src_addr (32 bytes) +/// - dest_addr (32 bytes) /// /// Routers use cached coordinates for routing decisions. #[derive(Clone, Debug)] @@ -729,17 +730,17 @@ pub struct DataPacket { pub flags: DataFlags, /// Hop limit (TTL). pub hop_limit: u8, - /// Source FIPS address. - pub src_addr: FipsAddress, - /// Destination FIPS address. - pub dest_addr: FipsAddress, + /// Source node address. + pub src_addr: NodeAddr, + /// Destination node address. + pub dest_addr: NodeAddr, /// Payload data. pub payload: Vec, } impl DataPacket { /// Create a new data packet. - pub fn new(src_addr: FipsAddress, dest_addr: FipsAddress, payload: Vec) -> Self { + pub fn new(src_addr: NodeAddr, dest_addr: NodeAddr, payload: Vec) -> Self { Self { flags: DataFlags::new(), hop_limit: 64, @@ -801,14 +802,14 @@ impl DataPacket { #[derive(Clone, Debug)] pub struct CoordsRequired { /// Destination that couldn't be routed. - pub dest_addr: FipsAddress, + pub dest_addr: NodeAddr, /// Router reporting the miss. pub reporter: NodeAddr, } impl CoordsRequired { /// Create a new CoordsRequired error. - pub fn new(dest_addr: FipsAddress, reporter: NodeAddr) -> Self { + pub fn new(dest_addr: NodeAddr, reporter: NodeAddr) -> Self { Self { dest_addr, reporter } } } @@ -819,9 +820,9 @@ impl CoordsRequired { #[derive(Clone, Debug)] pub struct PathBroken { /// Original source of the failed packet. - pub original_src: FipsAddress, + pub original_src: NodeAddr, /// Destination that couldn't be reached. - pub dest_addr: FipsAddress, + pub dest_addr: NodeAddr, /// Node that detected the failure. pub reporter: NodeAddr, /// Optional: last known coordinates of destination. @@ -830,7 +831,7 @@ pub struct PathBroken { impl PathBroken { /// Create a new PathBroken error. - pub fn new(original_src: FipsAddress, dest_addr: FipsAddress, reporter: NodeAddr) -> Self { + pub fn new(original_src: NodeAddr, dest_addr: NodeAddr, reporter: NodeAddr) -> Self { Self { original_src, dest_addr, @@ -856,12 +857,6 @@ mod tests { NodeAddr::from_bytes(bytes) } - fn make_address(val: u8) -> FipsAddress { - let mut bytes = [0xfdu8; 16]; - bytes[1] = val; - FipsAddress::from_bytes(bytes).unwrap() - } - fn make_coords(ids: &[u8]) -> TreeCoordinate { TreeCoordinate::new(ids.iter().map(|&v| make_node_addr(v)).collect()).unwrap() } @@ -974,17 +969,17 @@ mod tests { #[test] fn test_data_packet_size() { - let packet = DataPacket::new(make_address(1), make_address(2), vec![0u8; 100]); + let packet = DataPacket::new(make_node_addr(1), make_node_addr(2), vec![0u8; 100]); - // 36 byte header + 100 byte payload - assert_eq!(packet.total_size(), 136); - assert_eq!(packet.header_size(), 36); + // 68 byte header + 100 byte payload + assert_eq!(packet.total_size(), 168); + assert_eq!(packet.header_size(), 68); assert_eq!(packet.payload_len(), 100); } #[test] fn test_data_packet_hop_limit() { - let mut packet = DataPacket::new(make_address(1), make_address(2), vec![]); + let mut packet = DataPacket::new(make_node_addr(1), make_node_addr(2), vec![]); packet.hop_limit = 2; assert!(packet.can_forward()); @@ -1002,7 +997,7 @@ mod tests { #[test] fn test_data_packet_builder() { - let packet = DataPacket::new(make_address(1), make_address(2), vec![1, 2, 3]) + let packet = DataPacket::new(make_node_addr(1), make_node_addr(2), vec![1, 2, 3]) .with_hop_limit(32) .with_flags(DataFlags::from_byte(0x80)); @@ -1151,8 +1146,8 @@ mod tests { #[test] fn test_session_setup() { let setup = SessionSetup::new( - make_address(1), - make_address(2), + make_node_addr(1), + make_node_addr(2), make_coords(&[1, 0]), make_coords(&[2, 0]), ) @@ -1166,9 +1161,9 @@ mod tests { #[test] fn test_coords_required() { - let err = CoordsRequired::new(make_address(1), make_node_addr(2)); + let err = CoordsRequired::new(make_node_addr(1), make_node_addr(2)); - assert_eq!(err.dest_addr, make_address(1)); + assert_eq!(err.dest_addr, make_node_addr(1)); assert_eq!(err.reporter, make_node_addr(2)); } @@ -1176,7 +1171,7 @@ mod tests { #[test] fn test_path_broken() { - let err = PathBroken::new(make_address(1), make_address(2), make_node_addr(3)) + let err = PathBroken::new(make_node_addr(1), make_node_addr(2), make_node_addr(3)) .with_last_coords(make_coords(&[2, 0])); assert!(err.last_known_coords.is_some());