Implement spanning tree announcement send/receive protocol

Add TreeAnnounce v1 wire format with versioned encoding (version byte
0x01), slim ancestry entries (32 bytes each, no per-entry signatures),
and transitive trust model where only the direct peer's declaration
signature is verified.

Key changes:
- Enrich TreeCoordinate with CoordEntry metadata (sequence, timestamp)
- TreeAnnounce encode/decode with roundtrip tests
- Per-peer rate limiting (500ms minimum interval) on ActivePeer
- Parent selection: depth-based algorithm with broken-path detection
- New node/tree.rs module: send/receive, periodic refresh, cleanup
- Wire up dispatch, initial announce on promotion, tick integration
- Update gossip protocol design doc with trust model (§2.7)

304 tests pass, clean build.
This commit is contained in:
Johnathan Corgan
2026-02-10 23:35:09 +00:00
parent 9d36977ec8
commit 1c2cda480d
9 changed files with 1260 additions and 126 deletions
+7
View File
@@ -7,6 +7,7 @@
mod handlers;
mod lifecycle;
mod retry;
mod tree;
#[cfg(test)]
mod tests;
@@ -255,6 +256,10 @@ pub struct Node {
/// Rate limiter for msg1 processing (DoS protection).
msg1_rate_limiter: HandshakeRateLimiter,
// === Tree Announce Timing ===
/// Last time we refreshed our root announcement (Unix seconds).
last_root_refresh_secs: u64,
// === Connection Retry ===
/// Retry state for peers whose outbound connections have failed.
/// Keyed by NodeAddr. Entries are created when a handshake times out
@@ -317,6 +322,7 @@ impl Node {
peers_by_index: HashMap::new(),
pending_outbound: HashMap::new(),
msg1_rate_limiter: HandshakeRateLimiter::new(),
last_root_refresh_secs: 0,
retry_pending: HashMap::new(),
})
}
@@ -365,6 +371,7 @@ impl Node {
peers_by_index: HashMap::new(),
pending_outbound: HashMap::new(),
msg1_rate_limiter: HandshakeRateLimiter::new(),
last_root_refresh_secs: 0,
retry_pending: HashMap::new(),
}
}