mirror of
https://github.com/jmcorgan/fips.git
synced 2026-10-06 11:38:24 +00:00
Session 50: Design document reorganization and gossip protocol
- Create fips-gossip-protocol.md with wire formats for TreeAnnounce, FilterAnnounce, LookupRequest/LookupResponse - Refactor fips-routing.md to reference gossip protocol for wire formats - Update fips-session-protocol.md: remove reconciliation section, condense peer connection section - Update spanning-tree-dynamics.md with gossip protocol reference - Reorganize README.md with suggested reading order - Remove obsolete fips-architecture-review.md
This commit is contained in:
+58
-15
@@ -2,22 +2,65 @@
|
||||
|
||||
Protocol design specifications and analysis for the Federated Interoperable Peering System.
|
||||
|
||||
## Protocol Design
|
||||
## Suggested Reading Order
|
||||
|
||||
| Document | Description |
|
||||
| ------------------------------------------------------ | -------------------------------------------------------------------------------------- |
|
||||
| [fips-design.md](fips-design.md) | Core protocol specification: goals, architecture, identity, addressing, spanning tree |
|
||||
| [fips-routing.md](fips-routing.md) | Routing architecture: Bloom filters, discovery protocol, session establishment |
|
||||
| [fips-wire-protocol.md](fips-wire-protocol.md) | Wire protocol: format, session indices, roaming, replay protection, DoS defense |
|
||||
| [fips-transports.md](fips-transports.md) | Transport protocol characteristics: UDP, Ethernet, Tor, radio, and other link types |
|
||||
| [spanning-tree-dynamics.md](spanning-tree-dynamics.md) | Detailed study of spanning tree gossip protocol behavior and convergence |
|
||||
Start with the high-level architecture, then work through session flow, routing
|
||||
concepts, and finally the wire-level protocol details.
|
||||
|
||||
### 1. Architecture and Overview
|
||||
|
||||
| Document | Description |
|
||||
|------------------------------------------|-------------------------------------------------------------|
|
||||
| [fips-design.md](fips-design.md) | Core protocol: goals, identity, addressing, spanning tree |
|
||||
|
||||
### 2. Protocol Flow (How Traffic Works)
|
||||
|
||||
| Document | Description |
|
||||
|------------------------------------------------------|-----------------------------------------------------------|
|
||||
| [fips-session-protocol.md](fips-session-protocol.md) | End-to-end session flow, Noise KK encryption, terminology |
|
||||
|
||||
### 3. Routing (How Packets Find Their Way)
|
||||
|
||||
| Document | Description |
|
||||
|--------------------------------------------------------|-------------------------------------------------------------|
|
||||
| [fips-routing.md](fips-routing.md) | Routing concepts: bloom filters, discovery, greedy routing |
|
||||
| [spanning-tree-dynamics.md](spanning-tree-dynamics.md) | Tree protocol behavior: convergence, partitions, recovery |
|
||||
| [fips-gossip-protocol.md](fips-gossip-protocol.md) | Wire formats: TreeAnnounce, FilterAnnounce, Lookup messages |
|
||||
|
||||
### 4. Link Layer (How Peer Connections Work)
|
||||
|
||||
| Document | Description |
|
||||
|------------------------------------------------|---------------------------------------------------------------|
|
||||
| [fips-wire-protocol.md](fips-wire-protocol.md) | Transport layer: Noise IK, session indices, roaming, security |
|
||||
| [fips-transports.md](fips-transports.md) | Transport-specific: UDP, Ethernet, Tor, radio characteristics |
|
||||
|
||||
## Implementation
|
||||
|
||||
| Document | Description |
|
||||
| ---------------------------------------------------------- | --------------------------------------------------------------------------------------- |
|
||||
| [fips-architecture.md](fips-architecture.md) | Software architecture: entities, state machines, transport abstractions, configuration |
|
||||
| [fips-architecture-review.md](fips-architecture-review.md) | Architecture review issues and resolution status |
|
||||
| [fips-tun-driver.md](fips-tun-driver.md) | TUN interface driver: reader/writer threads, ICMPv6, packet flow |
|
||||
| [fips-state-machines.md](fips-state-machines.md) | Phase-based state machine pattern: peer lifecycle, transitions, timeout handling |
|
||||
| [fips-session-protocol.md](fips-session-protocol.md) | Session protocol: traffic flow, crypto sessions, terminology |
|
||||
| Document | Description |
|
||||
|--------------------------------------------------|------------------------------------------------------------------|
|
||||
| [fips-architecture.md](fips-architecture.md) | Software architecture: entities, state machines, configuration |
|
||||
| [fips-tun-driver.md](fips-tun-driver.md) | TUN interface driver: reader/writer threads, ICMPv6, packet flow |
|
||||
| [fips-state-machines.md](fips-state-machines.md) | Phase-based state machine pattern: peer lifecycle, transitions |
|
||||
|
||||
## Document Cross-References
|
||||
|
||||
```text
|
||||
fips-design.md
|
||||
│
|
||||
▼
|
||||
fips-session-protocol.md
|
||||
│ │
|
||||
┌─────────┘ └─────────┐
|
||||
▼ ▼
|
||||
fips-routing.md fips-wire-protocol.md
|
||||
│ │
|
||||
▼ │
|
||||
spanning-tree-dynamics.md │
|
||||
│ │
|
||||
└───────────┬───────────────────┘
|
||||
▼
|
||||
fips-gossip-protocol.md
|
||||
│
|
||||
▼
|
||||
fips-transports.md
|
||||
```
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
# FIPS Architecture Document Review
|
||||
|
||||
**Document reviewed**: fips-architecture.md
|
||||
**Last updated**: 2025-01-29
|
||||
|
||||
This document tracks open issues and deferred items for the FIPS architecture.
|
||||
Issues are organized by priority. Resolved items have been archived.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| # | Issue | Priority | Status | Notes |
|
||||
| -- | ---------------------- | -------- | -------- | -------------------- |
|
||||
| 11 | Config validation | Low | OPEN | Add validation rules |
|
||||
| 12 | Default rationales | Low | OPEN | Document reasoning |
|
||||
| 14 | Gateway details | Low | OPEN | Incomplete spec |
|
||||
| 15 | DiscoveredPeer hint | Low | OPEN | Type mismatch |
|
||||
| 2 | Auth protocol ref | High | DEFERRED | Wire protocol work |
|
||||
| 3 | Concurrency model | High | DEFERRED | Future iteration |
|
||||
| 4 | Keepalive format | High | DEFERRED | Wire protocol work |
|
||||
| 7 | Error handling | Medium | DEFERRED | Future iteration |
|
||||
| 10 | Init/shutdown | Medium | DEFERRED | Future iteration |
|
||||
|
||||
**Resolved (archived):** 1, 5, 6, 8, 9, 13
|
||||
|
||||
---
|
||||
|
||||
## Open Issues - Low Priority
|
||||
|
||||
### 11. Configuration Validation Rules
|
||||
|
||||
**Issue**: No validation rules specified:
|
||||
|
||||
- What if `filter.size` is not a power of 2?
|
||||
- What if `peer.keepalive.timeout` < `peer.keepalive.interval`?
|
||||
- What if `timeout.adaptive.min` > `timeout.adaptive.max`?
|
||||
|
||||
**Resolution needed**: Add validation rules or defer to implementation.
|
||||
|
||||
---
|
||||
|
||||
### 12. Default Value Rationales
|
||||
|
||||
**Issue**: Several defaults lack rationale:
|
||||
|
||||
- `filter.scope = 2`: Why 2?
|
||||
- `tree.parent.hold_time = 10s`: Why 10 seconds?
|
||||
- `filter.stale.threshold = 300s`: Based on what analysis?
|
||||
|
||||
**Resolution needed**: Add brief rationale comments or design rationale document.
|
||||
|
||||
---
|
||||
|
||||
### 14. Gateway/Subnet Routing Details Incomplete
|
||||
|
||||
**Issue**: Document mentions `leaf_dependents` but doesn't explain:
|
||||
|
||||
- How a node becomes a gateway for a subnet
|
||||
- How gateway prefixes are advertised in Bloom filters
|
||||
- Configuration for gateway mode
|
||||
|
||||
**Resolution needed**: Expand gateway section or reference future gateway
|
||||
design document.
|
||||
|
||||
---
|
||||
|
||||
### 15. DiscoveredPeer Hint Field Mismatch
|
||||
|
||||
**Issue**: Transport trait shows `discover() -> Result<Vec<DiscoveredPeer>>` but
|
||||
event shows `DiscoveredPeer { transport_id, addr, hint: Option<PublicKey> }`.
|
||||
The discover() return type doesn't show the hint field.
|
||||
|
||||
**Resolution needed**: Align trait signature with event structure.
|
||||
|
||||
---
|
||||
|
||||
## Deferred Items
|
||||
|
||||
### Wire Protocol (Future Work)
|
||||
|
||||
These items will be addressed when the wire protocol section is developed:
|
||||
|
||||
| # | Issue | Description |
|
||||
| --- | ----------------------- | ----------------------------------------------------------------------------------------- |
|
||||
| 2 | Auth protocol reference | Architecture references "FIPS auth handshake" but doesn't define or reference fips-design |
|
||||
| 4 | Keepalive format | `peer.keepalive.interval` configured but no message type defined; RTT measurement unclear |
|
||||
|
||||
### Future Architecture Iterations
|
||||
|
||||
These items are deferred to future design iterations:
|
||||
|
||||
| # | Issue | Description |
|
||||
| --- | ----------------- | -------------------------------------------------------------------------------------------- |
|
||||
| 3 | Concurrency model | No specification for threading model, state machine driving, or transport isolation |
|
||||
| 7 | Error handling | No systematic error handling definitions for signature failures, malformed packets, or codes |
|
||||
| 10 | Init/shutdown | Startup sequence, transport ordering, shutdown procedure, departure announcement |
|
||||
|
||||
---
|
||||
|
||||
## Edge Cases for Future Consideration
|
||||
|
||||
### Network Dynamics
|
||||
|
||||
- **Root node failure**: Election timing, in-flight session impact, proactive backup
|
||||
- **Rapid peer churn**: 500ms debounce may cause filter oscillation
|
||||
- **Network partition healing**: Session conflicts, stale cache recovery
|
||||
|
||||
### Transport Edge Cases
|
||||
|
||||
- **Startup timing**: Tor takes 30s-2min while UDP is instant; node status during window
|
||||
- **MTU mismatch**: Path includes links with different MTUs (Ethernet 1500 vs LoRa 222)
|
||||
- **Clock skew**: TreeAnnounce timestamps; 5-minute tolerance from fips-design.md
|
||||
|
||||
### Security Considerations
|
||||
|
||||
- **Memory exhaustion**: Many fake peers
|
||||
- **CPU exhaustion**: Signature verification flooding
|
||||
- **Bandwidth exhaustion**: Bloom filter spam
|
||||
|
||||
### Configuration Edge Cases
|
||||
|
||||
- **Conflicting peers**: Same npub with different addresses; discovered vs configured conflict
|
||||
- **TUN unavailable**: Permissions, kernel module; relay-only mode possibility
|
||||
|
||||
---
|
||||
|
||||
## Resolved Items (Archived)
|
||||
|
||||
| # | Issue | Resolution |
|
||||
| --- | ------------------- | -------------------------------------------------------------------------------------- |
|
||||
| 1 | Coordinate ordering | Standardized on `[self, parent, ..., root]` (node→root) in all documents |
|
||||
| 5 | Cache naming | Removed misplaced `coord_cache` from TreeState; clarified config sections |
|
||||
| 6 | Peer/Link lifecycle | Clarified: transports static, links on-demand driven by peer lifecycle |
|
||||
| 8 | Memory bounds | Added Resource Limits config: max_peers, max_transports, pending limits, memory budget |
|
||||
| 9 | Timer management | Non-issue: async runtimes (tokio) handle hundreds of timers efficiently at this scale |
|
||||
| 13 | Terminology | Standardized Transport/Link terminology in fips-design.md and fips-transports.md |
|
||||
@@ -0,0 +1,376 @@
|
||||
# FIPS Gossip Protocol
|
||||
|
||||
This document specifies the wire formats and exchange rules for FIPS gossip
|
||||
messages: TreeAnnounce, FilterAnnounce, and the discovery protocol
|
||||
(LookupRequest/LookupResponse).
|
||||
|
||||
For conceptual background on how these protocols work:
|
||||
|
||||
- Spanning tree dynamics: [spanning-tree-dynamics.md](spanning-tree-dynamics.md)
|
||||
- Routing design and bloom filter concepts: [fips-routing.md](fips-routing.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. Message Type Summary
|
||||
|
||||
All gossip messages are link-layer messages, encrypted with per-peer Noise IK
|
||||
session keys. They travel one hop (peer-to-peer), though their effects may
|
||||
propagate further through subsequent gossip.
|
||||
|
||||
| Type | Purpose | Direction | Trigger |
|
||||
|------|---------|-----------|---------|
|
||||
| TreeAnnounce | Spanning tree state | Bidirectional | Peer connect, parent change, periodic |
|
||||
| FilterAnnounce | Bloom filter reachability | Bidirectional | Peer connect, filter change |
|
||||
| LookupRequest | Coordinate discovery | Flooded | Route cache miss |
|
||||
| LookupResponse | Return coordinates | Routed back | LookupRequest reaches target |
|
||||
|
||||
---
|
||||
|
||||
## 2. TreeAnnounce
|
||||
|
||||
TreeAnnounce messages propagate spanning tree state between peers. Each node
|
||||
announces its parent selection and ancestry, enabling peers to compute tree
|
||||
coordinates and distances.
|
||||
|
||||
### 2.1 Wire Format
|
||||
|
||||
```text
|
||||
TreeAnnounce {
|
||||
sequence: u64, // Monotonic, increments on parent change
|
||||
timestamp: u64, // Unix timestamp (seconds)
|
||||
parent: NodeId, // 32 bytes, SHA-256(npub) of selected parent
|
||||
ancestry: Vec<AncestryEntry>, // Path from self to root
|
||||
signature: Signature, // 64 bytes, signs (sequence || timestamp || parent || ancestry)
|
||||
}
|
||||
|
||||
AncestryEntry {
|
||||
node_id: NodeId, // 32 bytes
|
||||
sequence: u64, // That node's sequence number
|
||||
timestamp: u64, // That node's timestamp
|
||||
signature: Signature, // That node's signature over its declaration
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 Field Semantics
|
||||
|
||||
**sequence**: Incremented each time the node changes its parent declaration.
|
||||
Higher sequence numbers supersede lower ones for conflict resolution.
|
||||
|
||||
**timestamp**: Used for distributed consistency. A declaration is considered
|
||||
stale if `now - timestamp > ROOT_TIMEOUT` (default 60 minutes for root).
|
||||
|
||||
**parent**: The node_id of the selected parent. If `parent == self.node_id`,
|
||||
the node is declaring itself as root.
|
||||
|
||||
**ancestry**: The chain from this node up to the root. The first entry is this
|
||||
node's own declaration, followed by parent, grandparent, etc. Each entry is
|
||||
signed by the declaring node, allowing verification of the entire chain.
|
||||
|
||||
### 2.3 Size Estimate
|
||||
|
||||
| Component | Size |
|
||||
|-----------|------|
|
||||
| sequence | 8 bytes |
|
||||
| timestamp | 8 bytes |
|
||||
| parent | 32 bytes |
|
||||
| signature | 64 bytes |
|
||||
| Per ancestry entry | 32 + 8 + 8 + 64 = 112 bytes |
|
||||
|
||||
For tree depth D: `112 + D * 112` bytes. At depth 10: ~1.2 KB.
|
||||
|
||||
### 2.4 Exchange Rules
|
||||
|
||||
**On peer connection:**
|
||||
|
||||
1. After Noise IK handshake completes, both peers send TreeAnnounce
|
||||
2. Each peer processes the received announcement (see §2.5)
|
||||
3. If processing triggers a parent change, send updated TreeAnnounce to all peers
|
||||
|
||||
**On parent change:**
|
||||
|
||||
1. Increment sequence number
|
||||
2. Update timestamp
|
||||
3. Sign new declaration
|
||||
4. Send TreeAnnounce to all peers
|
||||
|
||||
**Periodic refresh:**
|
||||
|
||||
1. Root refreshes every 30 minutes (prevents stale root detection)
|
||||
2. Non-root nodes forward root refresh when received
|
||||
3. Nodes may refresh their own declaration periodically (implementation choice)
|
||||
|
||||
### 2.5 Processing Rules
|
||||
|
||||
When receiving TreeAnnounce from peer P:
|
||||
|
||||
```text
|
||||
1. Verify signature on sender's declaration
|
||||
2. Verify signatures on all ancestry entries
|
||||
3. For each entry in ancestry:
|
||||
- If entry.sequence > stored.sequence: update stored entry
|
||||
- If entry.sequence == stored.sequence && entry.timestamp > stored.timestamp: update
|
||||
- Otherwise: keep existing entry
|
||||
4. Update peer P's record with new ancestry
|
||||
5. Re-evaluate parent selection:
|
||||
- If better path to root available: change parent, announce to all peers
|
||||
- Apply stability threshold to prevent flapping
|
||||
```
|
||||
|
||||
### 2.6 Rate Limiting
|
||||
|
||||
To prevent announcement storms during reconvergence:
|
||||
|
||||
- Minimum interval between announcements to same peer: 500ms
|
||||
- If change occurs during cooldown: mark pending, send after cooldown
|
||||
- Coalesce multiple pending changes into single announcement
|
||||
|
||||
---
|
||||
|
||||
## 3. FilterAnnounce
|
||||
|
||||
FilterAnnounce messages propagate Bloom filter reachability information. Each
|
||||
node's filter indicates which destinations are reachable through it.
|
||||
|
||||
### 3.1 Wire Format
|
||||
|
||||
```text
|
||||
FilterAnnounce {
|
||||
filter: BloomFilter, // 4096 bytes (32,768 bits)
|
||||
ttl: u8, // Remaining propagation hops
|
||||
sequence: u64, // For freshness/deduplication
|
||||
}
|
||||
|
||||
BloomFilter {
|
||||
bits: [u8; 4096], // Bit array
|
||||
hash_count: u8, // Number of hash functions (typically 7)
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 Field Semantics
|
||||
|
||||
**filter**: Contains node_ids reachable through this peer. Uses k=7 hash
|
||||
functions for near-optimal false positive rate at expected fill levels.
|
||||
|
||||
**ttl**: Remaining propagation depth. Starts at K (typically 2), decremented
|
||||
each hop. At TTL=0, entries are not propagated further.
|
||||
|
||||
**sequence**: Monotonic counter for this node's filter. Allows receivers to
|
||||
detect stale or duplicate announcements.
|
||||
|
||||
### 3.3 Filter Contents
|
||||
|
||||
A node's outgoing filter to peer Q contains:
|
||||
|
||||
1. This node's own node_id
|
||||
2. Node_ids of leaf-only dependents (nodes using this node as sole peer)
|
||||
3. Entries from filters received from other peers (not Q) with TTL > 0
|
||||
|
||||
This creates K-hop reachability scope. With K=2, entries propagate ~4 hops
|
||||
before TTL exhaustion.
|
||||
|
||||
### 3.4 Exchange Rules
|
||||
|
||||
**On peer connection:**
|
||||
|
||||
1. After TreeAnnounce exchange, send FilterAnnounce
|
||||
2. Filter contains current reachability view
|
||||
|
||||
**On filter change:**
|
||||
|
||||
Triggering events:
|
||||
|
||||
- Peer connects or disconnects
|
||||
- Received filter changes outgoing filter
|
||||
- Local state change (new leaf dependent, become gateway)
|
||||
|
||||
Rate limiting:
|
||||
|
||||
- Minimum interval between filter announcements: 500ms
|
||||
- Debounce rapid changes into single announcement
|
||||
|
||||
**Processing received filter:**
|
||||
|
||||
```text
|
||||
1. Store: peer_filters[P] = received.filter
|
||||
2. If received.ttl > 0:
|
||||
- Include entries in next announcement to other peers
|
||||
- Decrement TTL for propagated entries
|
||||
3. Recompute own outgoing filters if changed
|
||||
```
|
||||
|
||||
### 3.5 Filter Expiration
|
||||
|
||||
Bloom filters cannot remove individual entries. Expiration handled by:
|
||||
|
||||
- **Peer disconnect**: Remove that peer's filter entirely, recompute
|
||||
- **Filter replacement**: Each FilterAnnounce replaces the previous one
|
||||
- **Implicit timeout**: If no updates from peer within threshold, consider stale
|
||||
|
||||
---
|
||||
|
||||
## 4. LookupRequest
|
||||
|
||||
LookupRequest initiates coordinate discovery for destinations not covered by
|
||||
local Bloom filters.
|
||||
|
||||
### 4.1 Wire Format
|
||||
|
||||
```text
|
||||
LookupRequest {
|
||||
request_id: u64, // Unique identifier for this request
|
||||
target: NodeId, // 32 bytes, who we're looking for
|
||||
origin: NodeId, // 32 bytes, who's asking
|
||||
origin_coords: Vec<NodeId>, // Origin's ancestry (for return path)
|
||||
ttl: u8, // Remaining propagation hops
|
||||
visited: CompactBloomFilter,// ~256 bytes, prevents loops
|
||||
}
|
||||
|
||||
CompactBloomFilter {
|
||||
bits: [u8; 256], // Smaller filter for visited set
|
||||
hash_count: u8,
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 Field Semantics
|
||||
|
||||
**request_id**: Randomly generated, used to match responses and detect
|
||||
duplicates.
|
||||
|
||||
**target**: The node_id being searched for.
|
||||
|
||||
**origin**: The node_id of the original requester. Used for response routing.
|
||||
|
||||
**origin_coords**: The requester's current tree coordinates. Enables greedy
|
||||
routing of the response back to origin.
|
||||
|
||||
**ttl**: Propagation limit. Prevents unbounded flooding.
|
||||
|
||||
**visited**: Compact Bloom filter tracking nodes that have seen this request.
|
||||
Prevents redundant processing and loops.
|
||||
|
||||
### 4.3 Propagation Rules
|
||||
|
||||
When receiving LookupRequest:
|
||||
|
||||
```text
|
||||
1. Check visited filter - if self likely present, drop (already processed)
|
||||
2. Add self to visited filter
|
||||
3. Decrement TTL
|
||||
|
||||
4. Check if target is local:
|
||||
- If target == self.node_id: generate LookupResponse
|
||||
- If target in local peer_filters: may respond on behalf (optional)
|
||||
|
||||
5. If TTL > 0 and not found locally:
|
||||
- Forward to peers not in visited filter
|
||||
- Optionally prioritize peers whose filter indicates target "maybe" present
|
||||
```
|
||||
|
||||
### 4.4 Rate Limiting
|
||||
|
||||
- Track recently seen request_ids, drop duplicates
|
||||
- Limit requests per origin per time window
|
||||
- Limit total outstanding requests
|
||||
|
||||
---
|
||||
|
||||
## 5. LookupResponse
|
||||
|
||||
LookupResponse returns the target's coordinates to the requester.
|
||||
|
||||
### 5.1 Wire Format
|
||||
|
||||
```text
|
||||
LookupResponse {
|
||||
request_id: u64, // Echoes LookupRequest.request_id
|
||||
target: NodeId, // 32 bytes, confirms who was found
|
||||
target_coords: Vec<NodeId>, // Target's ancestry (the key payload)
|
||||
proof: Signature, // 64 bytes, target signs to prove existence
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 Field Semantics
|
||||
|
||||
**request_id**: Matches the original request, allowing requester to correlate.
|
||||
|
||||
**target**: Confirms the identity found.
|
||||
|
||||
**target_coords**: The target's current tree coordinates. This is the primary
|
||||
payload - enables greedy routing to the target.
|
||||
|
||||
**proof**: Target's signature over `(request_id || target || target_coords)`.
|
||||
Prevents malicious nodes from claiming reachability and blackholing traffic.
|
||||
|
||||
### 5.3 Routing
|
||||
|
||||
LookupResponse uses greedy tree routing based on `origin_coords` from the
|
||||
request:
|
||||
|
||||
```text
|
||||
1. Response created at target (or node with target in filter)
|
||||
2. Each hop forwards toward origin using tree distance
|
||||
3. Origin receives response, caches target_coords
|
||||
```
|
||||
|
||||
### 5.4 Security
|
||||
|
||||
The proof signature is critical:
|
||||
|
||||
- Without it, any node could claim to be (or know) any target
|
||||
- Requester verifies signature against target's known public key
|
||||
- Invalid signatures cause response to be dropped
|
||||
|
||||
---
|
||||
|
||||
## 6. Message Type Codes
|
||||
|
||||
Within the link-layer message framing:
|
||||
|
||||
| Type Code | Message |
|
||||
|-----------|---------|
|
||||
| 0x10 | TreeAnnounce |
|
||||
| 0x11 | FilterAnnounce |
|
||||
| 0x12 | LookupRequest |
|
||||
| 0x13 | LookupResponse |
|
||||
|
||||
These are carried inside the encrypted link-layer payload after Noise IK
|
||||
handshake completion.
|
||||
|
||||
---
|
||||
|
||||
## 7. Timing Parameters
|
||||
|
||||
| Parameter | Default | Notes |
|
||||
|-----------|---------|-------|
|
||||
| ROOT_REFRESH_INTERVAL | 30 min | Root regenerates timestamp |
|
||||
| ROOT_TIMEOUT | 60 min | Root declaration considered stale |
|
||||
| TREE_ENTRY_TTL | 5-10 min | Individual entry expiration |
|
||||
| FILTER_TTL_HOPS | 2 | Bloom filter propagation depth |
|
||||
| ANNOUNCE_MIN_INTERVAL | 500 ms | Rate limit for announcements |
|
||||
| LOOKUP_TTL | 8 | Discovery request propagation limit |
|
||||
| LOOKUP_TIMEOUT | 5 sec | Time to wait for response |
|
||||
|
||||
---
|
||||
|
||||
## 8. Encoding
|
||||
|
||||
All multi-byte integers are little-endian. NodeId is 32 bytes (SHA-256 hash).
|
||||
Signatures are 64 bytes (secp256k1 Schnorr).
|
||||
|
||||
Variable-length fields (ancestry, coordinates) are prefixed with a 2-byte
|
||||
length count indicating number of entries.
|
||||
|
||||
```text
|
||||
Vec<T> encoding:
|
||||
count: u16 (little-endian)
|
||||
items: T[count]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [spanning-tree-dynamics.md](spanning-tree-dynamics.md) - Tree protocol behavior
|
||||
- [fips-routing.md](fips-routing.md) - Routing concepts and algorithms
|
||||
- [fips-wire-protocol.md](fips-wire-protocol.md) - Link-layer framing
|
||||
- [fips-session-protocol.md](fips-session-protocol.md) - End-to-end sessions
|
||||
+22
-70
@@ -1,10 +1,11 @@
|
||||
# FIPS Routing Design
|
||||
|
||||
**Status**: Work in Progress
|
||||
|
||||
This document describes the routing architecture for FIPS, including Bloom
|
||||
filter reachability, discovery protocol, greedy tree routing, and session
|
||||
establishment.
|
||||
filter reachability, discovery protocol, greedy tree routing, and routing
|
||||
session establishment.
|
||||
|
||||
For wire formats and exchange rules, see [fips-gossip-protocol.md](fips-gossip-protocol.md).
|
||||
For spanning tree dynamics and convergence, see [spanning-tree-dynamics.md](spanning-tree-dynamics.md).
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -107,45 +108,19 @@ Filters are updated on events rather than periodic refresh:
|
||||
3. Received filter changes outgoing filter — recompute, send updates
|
||||
4. Local state change — new leaf dependent, become gateway, etc.
|
||||
|
||||
**Rate limiting:**
|
||||
Updates are rate-limited to prevent storms during reconvergence. See
|
||||
[fips-gossip-protocol.md](fips-gossip-protocol.md) §3 for FilterAnnounce wire
|
||||
format and exchange rules.
|
||||
|
||||
To prevent update storms, rate-limit or debounce updates:
|
||||
### Filter Contents
|
||||
|
||||
```rust
|
||||
const MIN_UPDATE_INTERVAL: Duration = Duration::from_millis(500);
|
||||
A node's outgoing filter to peer Q contains:
|
||||
|
||||
fn maybe_send_update(&mut self, peer: PeerId) {
|
||||
if self.last_send_time[peer].elapsed() < MIN_UPDATE_INTERVAL {
|
||||
self.pending_update[peer] = true;
|
||||
return;
|
||||
}
|
||||
// ... send update
|
||||
}
|
||||
```
|
||||
1. This node's own Node ID
|
||||
2. Node IDs of leaf-only dependents
|
||||
3. Entries from filters received from other peers (not Q) with TTL > 0
|
||||
|
||||
### Filter Announcement Message
|
||||
|
||||
```rust
|
||||
struct FilterAnnounce {
|
||||
filter: BloomFilter, // 4 KB
|
||||
ttl: u8, // Remaining propagation hops
|
||||
sequence: u64, // Freshness / deduplication
|
||||
}
|
||||
```
|
||||
|
||||
### Propagation Rules
|
||||
|
||||
When node N sends a FilterAnnounce to peer Q:
|
||||
|
||||
1. Include N's own Node ID
|
||||
2. Include N's leaf-only dependents
|
||||
3. Include entries from filters received from other peers (not Q) with TTL > 0
|
||||
|
||||
When node N receives FilterAnnounce from peer P:
|
||||
|
||||
1. Store: `peer_filters[P] = received.filter`
|
||||
2. If `received.ttl > 0`: include P's filter contents in N's next announcement
|
||||
to other peers, with TTL decremented
|
||||
This creates K-hop reachability scope through TTL-based propagation.
|
||||
|
||||
### K-Hop Scope Emergence
|
||||
|
||||
@@ -179,25 +154,7 @@ Bloom filters.
|
||||
- Route cache miss
|
||||
- After cached route failure
|
||||
|
||||
### Message Formats
|
||||
|
||||
```rust
|
||||
struct LookupRequest {
|
||||
request_id: u64,
|
||||
target: NodeId, // Who we're looking for
|
||||
origin: NodeId, // Who's asking
|
||||
origin_coords: Vec<NodeId>, // Origin's ancestry (for return path)
|
||||
ttl: u8, // Propagation limit
|
||||
visited: BloomFilter, // Prevent loops (compact, ~256 bytes)
|
||||
}
|
||||
|
||||
struct LookupResponse {
|
||||
request_id: u64,
|
||||
target: NodeId,
|
||||
target_coords: Vec<NodeId>, // Target's ancestry — the key payload
|
||||
proof: Signature, // Target signs to prove existence
|
||||
}
|
||||
```
|
||||
For wire formats, see [fips-gossip-protocol.md](fips-gossip-protocol.md) §4-5.
|
||||
|
||||
### Discovery Flow
|
||||
|
||||
@@ -234,17 +191,10 @@ Each router forwards toward the origin using tree distance.
|
||||
|
||||
### Security
|
||||
|
||||
**Target signs response:**
|
||||
|
||||
```rust
|
||||
struct LookupResponse {
|
||||
// ...
|
||||
proof: Signature, // Sign(request_id || target || target_coords)
|
||||
}
|
||||
```
|
||||
|
||||
Without this, a malicious node could claim reachability for any target and
|
||||
blackhole traffic. The signature proves the target authorized the route.
|
||||
The target signs the LookupResponse with a proof covering
|
||||
`(request_id || target || target_coords)`. Without this signature, a malicious
|
||||
node could claim reachability for any target and blackhole traffic. The
|
||||
signature proves the target authorized the route.
|
||||
|
||||
### Caching
|
||||
|
||||
@@ -621,6 +571,8 @@ When nodes join/leave:
|
||||
## References
|
||||
|
||||
- [fips-design.md](fips-design.md) — Overall FIPS architecture
|
||||
- [fips-gossip-protocol.md](fips-gossip-protocol.md) — Wire formats for TreeAnnounce, FilterAnnounce, Lookup
|
||||
- [fips-session-protocol.md](fips-session-protocol.md) — Traffic flow, crypto sessions, terminology
|
||||
- [fips-wire-protocol.md](fips-wire-protocol.md) — Link-layer transport and Noise IK handshake
|
||||
- [fips-transports.md](fips-transports.md) — Transport protocol characteristics
|
||||
- [spanning-tree-dynamics.md](spanning-tree-dynamics.md) — Tree protocol details
|
||||
- [spanning-tree-dynamics.md](spanning-tree-dynamics.md) — Tree protocol dynamics and convergence
|
||||
|
||||
@@ -456,116 +456,23 @@ Per-packet signatures would add:
|
||||
Since Noise already provides authentication through key binding, signatures
|
||||
are redundant. This matches WireGuard and Lightning's approach.
|
||||
|
||||
**Reconciliation note**: §3.1 mentions packets being "signed by source" -
|
||||
this should be updated to reflect AEAD-only authentication.
|
||||
|
||||
---
|
||||
|
||||
## 7. Peer Connection Establishment
|
||||
|
||||
Before any of the traffic flows described above can occur, nodes must establish
|
||||
authenticated peer connections using Noise IK. See [fips-design.md](fips-design.md)
|
||||
§1 for full protocol details and [fips-architecture.md](fips-architecture.md)
|
||||
for the startup sequence.
|
||||
Before any session-layer traffic can flow, nodes must establish authenticated
|
||||
link-layer connections with their peers using Noise IK. See
|
||||
[fips-wire-protocol.md](fips-wire-protocol.md) for the complete wire protocol
|
||||
specification including handshake flow, session lifecycle, index management,
|
||||
roaming support, and transport-specific considerations.
|
||||
|
||||
### 7.1 Connection Flow Summary (Noise IK)
|
||||
|
||||
All messages use TLV framing (see fips-design.md §6 Wire Format):
|
||||
|
||||
```text
|
||||
┌────────┬────────┬────────────────────────────────────┐
|
||||
│ Type │ Length │ Payload │
|
||||
│ 1 byte │ 2 bytes│ Variable │
|
||||
└────────┴────────┴────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Outbound (to static peer):**
|
||||
|
||||
```text
|
||||
Config: npub + transport hint (e.g., "udp:192.168.1.1:4000")
|
||||
│
|
||||
▼
|
||||
Create link via transport
|
||||
│
|
||||
▼
|
||||
Send: [0x01][0x00 0x52][82-byte Noise msg1]
|
||||
Type=NoiseIKMsg1, Length=82
|
||||
│
|
||||
▼
|
||||
Recv: [0x02][0x00 0x21][33-byte Noise msg2]
|
||||
Type=NoiseIKMsg2, Length=33
|
||||
│
|
||||
▼
|
||||
Noise session established → link encrypted → begins tree gossip
|
||||
```
|
||||
|
||||
**Inbound (peer connects to us):**
|
||||
|
||||
```text
|
||||
Transport receives packet from unknown address
|
||||
│
|
||||
▼
|
||||
Parse TLV: Type=0x01 (NoiseIKMsg1)
|
||||
│
|
||||
▼
|
||||
Process msg1 → learn peer's identity from encrypted static key
|
||||
│
|
||||
▼
|
||||
Send: [0x02][0x00 0x21][33-byte Noise msg2]
|
||||
│
|
||||
▼
|
||||
Noise session established → link encrypted → begins tree gossip
|
||||
```
|
||||
|
||||
### 7.2 Post-Authentication
|
||||
|
||||
After successful Noise handshake:
|
||||
After successful Noise IK handshake:
|
||||
|
||||
1. **Link encrypted**: All subsequent messages use AEAD encryption
|
||||
2. **TreeAnnounce exchange**: Both peers send their current tree state
|
||||
2. **TreeAnnounce exchange**: Both peers send their current spanning tree state
|
||||
3. **FilterAnnounce exchange**: Both peers send their bloom filters
|
||||
4. **Peer is Active**: Can now participate in routing and forwarding
|
||||
|
||||
The first TreeAnnounce from a new peer may trigger parent reselection if that
|
||||
peer offers a better path to root.
|
||||
|
||||
---
|
||||
|
||||
## 8. Document Reconciliation
|
||||
|
||||
This section tracks items that need reconciliation with existing design docs
|
||||
or earlier sections of this document.
|
||||
|
||||
### 8.1 Completed Updates (Session 47)
|
||||
|
||||
| Location | Status | Notes |
|
||||
|----------------------------------|--------|----------------------------------------------------|
|
||||
| fips-design.md §1 Peer Auth | ✓ Done | Replaced custom handshake with Noise IK |
|
||||
| fips-design.md §6 Messages | ✓ Done | Split into LinkMessageType + SessionMessageType |
|
||||
| protocol.rs | ✓ Done | Removed Hello/Challenge/Auth/AuthAck types |
|
||||
| protocol.rs | ✓ Done | Added SessionDatagram for link-layer encapsulation |
|
||||
| This document §6 | ✓ Done | Updated to two-layer Noise IK architecture |
|
||||
| This document §7 | ✓ Done | Updated connection flow for Noise IK |
|
||||
|
||||
### 8.2 Previous Updates (Session 40)
|
||||
|
||||
| Location | Status | Notes |
|
||||
|----------------------------------|--------|-----------------------------------------------------|
|
||||
| §3.1 | ✓ Done | Updated to AEAD authentication |
|
||||
| fips-routing.md Part 4 | ✓ Done | Renamed to "Routing Session Establishment" |
|
||||
| fips-routing.md SessionSetup/Ack | ✓ Done | Added `handshake_payload` for crypto handshake |
|
||||
| fips-design.md §7 Encryption | ✓ Done | Updated to reference Noise instead of NIP-44 |
|
||||
| fips-architecture.md Config | ✓ Done | Renamed to "Routing Session", added "Crypto Session"|
|
||||
|
||||
### 8.3 Design Doc Alignment Summary
|
||||
|
||||
The following decisions from this document have been propagated:
|
||||
|
||||
1. **Two-layer architecture**: Link layer (Noise IK peer auth) and session layer
|
||||
(Noise KK end-to-end) operate independently with separate keys
|
||||
2. **Session terminology** (§5.4): "Routing Session" vs "Crypto Session" distinction
|
||||
now consistent across all docs
|
||||
3. **Combined establishment** (§5.5): SessionSetup/SessionAck carry optional
|
||||
`handshake_payload` for session-layer Noise KK handshake
|
||||
4. **Message type split**: LinkMessageType for hop-by-hop, SessionMessageType for
|
||||
end-to-end (carried inside SessionDatagram)
|
||||
peer offers a better path to root. See [fips-gossip-protocol.md](fips-gossip-protocol.md)
|
||||
for TreeAnnounce and FilterAnnounce wire formats.
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
|
||||
A detailed study of the gossip-based spanning tree protocol, focusing on
|
||||
operational behavior under various mesh conditions. This document complements
|
||||
[FIPS-DESIGN.md](FIPS-DESIGN.md) with step-by-step walkthroughs of protocol
|
||||
[fips-design.md](fips-design.md) with step-by-step walkthroughs of protocol
|
||||
dynamics rather than message formats and data structures.
|
||||
|
||||
For wire formats, see [fips-gossip-protocol.md](fips-gossip-protocol.md) §2 (TreeAnnounce).
|
||||
|
||||
The protocol is based on Yggdrasil v0.5's CRDT gossip design.
|
||||
|
||||
## Contents
|
||||
|
||||
Reference in New Issue
Block a user