← RFC

Stage 4 Results — The INFRA Node on Real Hardware (Checkpoint D package)

Status: Stage-4 milestone summary for Checkpoint D review. Date: 2026-06-11. Code: Loomwave/loomwave (infra/ Rust workspace + client/ T114 firmware). Every result below ran on real radios on the bench (Pi 5 + Nebra Duo + Heltec T114), all at −9 dBm chip power.

What was built (one day of bench bring-up, milestones M1–M3 + C1–C5)

Milestone Result
M1 stub core beacon/superframe/slot math, 15 unit tests, exact 2000 ms cadence on the Pi
M2 SX1262 bespoke driver (kernel-managed CS, TCXO 1.8 V, DIO2 switch); RX proven against live third-party Meshtastic traffic (913.125 MHz MediumFast — found via djb2 channel math); first Loomwave beacons on air
M3 LR1121 bespoke driver (16-bit ops, two-phase reads); over-the-air loop 5/5 SX1262→LR1121, RSSI −45 dBm
daemon loop 30/30 beacons, arrival jitter −1/0/+1 ms vs the 3 ms guard — the GPS-free beacon-anchored timing thesis validated on hardware
desense 1 dB median floor rise at 10.6 MHz separation (bench power)
C1 T114 client independent C++ wire-format implementation decodes beacons 8/8 — spec-as-contract demonstrated
C2 join loop SCANNING→REGISTERING→SCHEDULED on hardware: REGISTER → SLOTMAP grant → 17/17 scheduled DATA, ±1 ms
C3 security two independent crypto stacks interoperate, 0 rejects: X25519+HKDF+ChaCha20-Poly1305 (truncated-tag) + Ed25519 TOFU; sealed DATA 28/28; epoch persistence; Ed25519 on the M4 = 229 ms verify / 145 ms sign (acquisition-only)
C4 multi-client LR1121 Rust client + T114 share the cell (slots 0+1, 66 sealed DATA); membership expiry reclaims a killed client's slot; replay rejection live
C5 dual-cell REGISTER bodies sealed (3 impls); one identity, two radios, two cells (SF9 reach + SF7/BW250 capacity) concurrent — node-roles §4.3 running

Spec findings from implementation (the reason Checkpoint D exists)

  1. ERRATUM (fixed): truncated Ed25519 signatures are unverifiable — Ed25519 needs the full 64-byte (R,S). SIG fields corrected to 64 B on signed control frames; beacon grows ~36→92 B (≈190 ms at SF9 — inside the <15 % control budget). DATA's 8 B AEAD tag is unaffected (MACs do verify truncated, by recomputation).
  2. Geometry must be computed from airtimes, not chosen: a 135 B identity advert at SF9/BW125 is ~670 ms — longer than a 4-slot superframe's whole contention window at FRAME_T = 2 s. Found as a 100 % advert-loss bug; fixed as 3×300 ms slots (≈940 ms CW) with long frames restricted to early micro-slots. → mac-spec.md §2 should gain a normative sizing inequality: CW ≥ ToA(largest contention frame) + guard.
  3. The coordinator must obey its own schedule: transmitting its identity advert right after the beacon trampled slot 0 (a perfect every-Nth-DATA loss signature). All coordinator-originated non-beacon traffic now goes through the contention window like everyone else's.
  4. Two MAC-implementation hazards worth a spec implementation-note: blocking RX must be chunked so a coordinator's own scheduled TX fires on time; client identity re-advertisement is needed because a restarted coordinator loses volatile TOFU state.

What is NOT yet done (honest list)

Checkpoint D ask

Review the above + the running code, then green-light the next phase, whose natural order is: 1. Tower deployment (single-radio Nebra HAT node, already mast-mounted; install over SSH when ready) → first outdoor cell, real link budgets, drive-around with the T114, desense at field power done properly outdoors. 2. Spec refresh fold-in (the §2 sizing inequality, advert scheduling rule, re-verify cadence). 3. Stage 5/6 ports per the roadmap (RAK4631 first, then Heltec V3/ESP32 leg, XiaoGator truck node).