- Full integration test: two nodes on localhost exercising identity creation, handshake, encrypted message exchange, UEPS packet routing via dispatcher, and graceful shutdown - Benchmarks: identity key generation, ECDH shared secret derivation, KD-tree peer scoring (10/100/1000 peers), message serialisation, SMSG encrypt/decrypt, challenge-response, UEPS marshal/unmarshal - bufpool.go tests: buffer reuse verification, oversized buffer discard, concurrent access, MarshalJSON correctness and safety - Coverage: node/ 72.1% -> 87.5%, ueps/ 88.5% -> 93.1% Co-Authored-By: Charon <developers@lethean.io>
6 KiB
6 KiB
Findings
Code Quality
- node/ 87.5% statement coverage — integration tests, bufpool tests, and benchmarks added (Phase 5)
- ueps/ 93.1% coverage — benchmarks added (Phase 5)
- logging/ fully tested (12 tests, 86.2% coverage)
go vetclean — no static analysis warningsgo test -raceclean — no data races- Zero TODOs/FIXMEs in codebase
Security Posture (Strong)
- X25519 ECDH key exchange with Borg STMF
- Challenge-response authentication (HMAC-SHA256)
- TLS 1.2+ with hardened cipher suites
- Message deduplication (5-min TTL, prevents amplification)
- Per-peer rate limiting (100 burst, 50 msg/sec)
- Tarball extraction: Zip Slip defence, 100 MB per-file limit, symlink/hardlink rejection
- Peer auth modes: open or public-key allowlist
- UEPS threat circuit breaker: packets with ThreatScore > 50,000 dropped before intent routing
Architecture Strengths
- Clean separation: identity / transport / peers / protocol / worker / controller
- KD-tree peer selection via Poindexter: [PingMS × 1.0, Hops × 0.7, GeoKM × 0.2, (100-Score) × 1.2]
- Debounced persistence (5s coalesce window for peer registry)
- Buffer pool for JSON encoding (reduces GC pressure)
- Decoupled MinerManager/ProfileManager interfaces
- UEPS dispatcher: functional IntentHandler type, RWMutex-protected handler map, sentinel errors
Test Coverage Summary
| File | Lines | Tests | Coverage |
|---|---|---|---|
| identity.go | 290 | 5 tests | Good |
| peer.go | 708 | 19 tests | Good |
| message.go | 237 | 8 tests | Good |
| worker.go | 402 | 10 tests | Good |
| bundle.go | 355 | 9 tests | Good |
| protocol.go | 88 | 5 tests | Good |
| transport.go | 934 | 11 tests | Good (Phase 2) |
| controller.go | 327 | 14 tests | Good (Phase 3) |
| dispatcher.go | 120 | 10 tests (17 subtests) | 100% (Phase 4) |
| bufpool.go | 55 | 11 tests | Good (Phase 5) |
| integration | — | 10 tests | Good (Phase 5) |
| ueps/packet.go | 124 | 9 tests | Good (Phase 1) |
| ueps/reader.go | 138 | 9 tests | Good (Phase 1) |
Known Issues
dispatcher.go is a stub— Fully implemented (Phase 4). Threat circuit breaker and intent routing operational.- UEPS 0xFF payload length ambiguous — Relies on external TCP framing, not self-delimiting. Comments note this but no solution implemented.
Potential race in controller.go—— Not a real issue. The pending map is initialised intransport.OnMessage(c.handleResponse)called during initNewControllerbeforeOnMessageis called, andhandleResponseuses a mutex. No panic possible.- No resource cleanup on some error paths — transport.handleWSUpgrade doesn't clean up on handshake timeout; transport.Connect doesn't clean up temp connection on error.
Threat score semantics undefined— ThreatScoreThreshold (50,000) defined in dispatcher. Packets above threshold dropped and logged. Intent routing implemented for 0x01/0x20/0x30/0xFF.
Phase 4 Design Decisions
- IntentHandler as func type, not interface — Matches the codebase's
MessageHandlerpattern in transport.go. Lighter weight than an interface for a single-method contract. - Sentinel errors over silent drops — The stub comments suggested silent drops, but returning typed errors (
ErrThreatScoreExceeded,ErrUnknownIntent,ErrNilPacket) gives callers the option to inspect outcomes. The dispatcher still logs at WARN level regardless. - Threat check before intent routing — A high-threat packet with an unknown intent returns
ErrThreatScoreExceeded, notErrUnknownIntent. The circuit breaker is the first line of defence; no packet metadata is inspected beyond ThreatScore before the drop. - Threshold at 50,000 (not configurable) — Kept as a constant to match the original stub. Can be made configurable via functional options if needed later.
- RWMutex for handler map — Read-heavy workload (dispatches far outnumber registrations), so RWMutex is appropriate. Registration takes a write lock, dispatch takes a read lock.
Phase 5 Benchmark Results (AMD Ryzen 9 9950X)
| Operation | Time/op | Allocs/op |
|---|---|---|
| Identity key generation (STMF) | 23 us | 6 |
| Full identity generation + disk | 74 us | 51 |
| Shared secret derivation (ECDH) | 46 us | 9 |
| KD-tree nearest (10 peers) | 247 ns | 2 |
| KD-tree nearest (100 peers) | 497 ns | 2 |
| KD-tree nearest (1000 peers) | 2.9 us | 2 |
| NewMessage (Ping) | 271 ns | 5 |
| NewMessage (Stats, 2 miners) | 701 ns | 5 |
| MarshalJSON (pooled buffer) | 375 ns | 2 |
| json.Marshal (stdlib) | 367 ns | 2 |
| SMSG Encrypt | 2.6 us | 34 |
| SMSG Decrypt | 3.9 us | 47 |
| SMSG Round-trip | 6.4 us | 81 |
| Challenge generate | 105 ns | 1 |
| Challenge sign (HMAC-SHA256) | 276 ns | 6 |
| Challenge verify | 295 ns | 6 |
| UEPS marshal+sign (64B payload) | 509 ns | 27 |
| UEPS marshal+sign (1KB payload) | 948 ns | 27 |
| UEPS marshal+sign (64KB payload) | 27.7 us | 27 |
| UEPS read+verify (64B payload) | 843 ns | 18 |
| UEPS read+verify (1KB payload) | 1.4 us | 20 |
| UEPS read+verify (64KB payload) | 44 us | 33 |
| UEPS round-trip (256B payload) | 1.5 us | 45 |
Observations:
- KD-tree peer scoring scales well: O(log n) with only 2 allocs regardless of tree size.
- MarshalJSON's buffer pool shows no measurable advantage at small message sizes — stdlib has been heavily optimised. The pool's value emerges under sustained load where GC pressure is reduced.
- SMSG is the dominant cost per-message (~6.4 us round-trip), making it the primary bottleneck for message throughput. At ~150K encrypted messages/sec/core, this is adequate for P2P mesh traffic.
- UEPS wire format is lightweight: signing a 64B packet costs ~500 ns, mostly HMAC computation.
Bugs Fixed
- P2P-RACE-1: GracefulClose data race (Phase 3) —
GracefulClosecalledpc.Conn.SetWriteDeadline()outside ofwriteMu, racing with concurrentSend()calls that also modify the write deadline. Fixed by removing the bareSetWriteDeadlinecall and relying onSend()which already manages deadlines under the lock. Detected bygo test -race.