Skip to content

feat: multibyte capability map overlay (#903)#916

Open
efiten wants to merge 14 commits intoKpa-clawbot:masterfrom
efiten:feat/multibyte-cap-903
Open

feat: multibyte capability map overlay (#903)#916
efiten wants to merge 14 commits intoKpa-clawbot:masterfrom
efiten:feat/multibyte-cap-903

Conversation

@efiten
Copy link
Copy Markdown
Contributor

@efiten efiten commented Apr 27, 2026

Summary

  • Adds multibyte_sup / multibyte_evidence columns to nodes + inactive_nodes via ingestor migration (multibyte_sup_v1)
  • Server detects the columns at startup and enriches all /api/nodes responses: multibyte_sup = 0/1/2, multibyte_evidence = "advert" / "path" / null
  • Capability detection runs from the existing analytics hash-size cycle (~15s) — no startup scan, no per-packet cost, no downgrade possible
  • Map controls get a "Show multibyte capability" toggle (under Byte Size, persisted in localStorage); repeater markers: solid green = confirmed, light green dashed = suspected, dimmed = unknown
  • Popup shows evidence label when overlay is active
  • Also fixes OOM crash on cold start with large DB: Load() now applies the retentionHours cutoff at startup, matching EvictStale() behaviour

Test plan

  • cd cmd/ingestor && go test ./... — covers multibyte_sup_v1 migration for nodes + inactive_nodes
  • cd cmd/server && go test ./... — covers node enrichment, multibyte capability detection, bounded_load OOM fix
  • Open Map, toggle "Show multibyte capability" — repeater markers change color; toggle survives reload
  • Click a repeater with overlay active — popup shows confirmed/suspected/not detected
  • Verify non-repeater nodes are unaffected by the multibyte toggle
  • Restart server with a large DB — verify it reaches "listening" within the retention window load time

Closes #903

Generated with Claude Code

efiten and others added 14 commits April 27, 2026 11:36
…ot#903)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…old start

Load() previously loaded all transmissions regardless of retentionHours,
causing buildSubpathIndex() to process the full DB history on every startup.
On a DB with 277K paths this produces 13.5M subpath index entries, OOM-killing
the process before it ever starts listening.

Apply the same retentionHours cutoff to Load()'s SQL that Evict() already uses
at runtime. Startup now builds indexes only over the retention window, matching
steady-state behaviour and keeping index size proportional to recent activity.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The server opens SQLite with mode=ro so persistMultiByteCapability()
silently failed on every UPDATE, leaving all nodes at multibyte_sup=0.

Replace DB persist with an in-memory cache: GetHashSizes() stores the
computeMultiByteCapability() result in mbCapSnapshot (under cacheMu),
GetMultibyteCapMap() exposes a pubkey→entry snapshot, and routes enrich
node responses from that map alongside EnrichNodeWithHashSize — the same
pattern already used for hash_size. Data refreshes each analytics cycle
(~15s); no DB writes needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
loadNodes() is called on every incoming ADVERT packet, which called
renderMarkers() and destroyed any open popup. Track popup visibility
via Leaflet's popupopen/popupclose map events; skip renderMarkers()
during data refresh while a popup is open so the user can read it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…yte suspected detection

A node whose own adverts confirm hash_size=1 cannot forward multibyte
packets. If it appeared as a 'suspected' hop it was due to a prefix
collision (1-byte hash prefix shared with a multibyte-capable node), not
actual multibyte capability. Mark it 'unknown' instead of 'suspected'.

Adds TestMultiByteCapability_SuspectedGuard_OwnHashSize1.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
A node can send hash_size=1 adverts but still have multibyte firmware
and forward multibyte packets. The guard incorrectly suppressed
legitimate suspected classifications.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ction

Pre-Kpa-clawbot#886 ingestor data stored path bytes individually (1-byte entries per
hop) even for hs=2 packets. This caused 1-byte node prefixes to match
single-byte path fragments from hs=2 packets, incorrectly marking nodes
as suspected.

Fix: require hop string length (len(pfx)/2) to equal the packet hash_size.
A 1-byte hop in an hs=2 packet is stale/malformed data and must not
trigger a suspected classification.

Adds TestMultiByteCapability_HopLengthMismatch; updates PrefixCollision
test to use proper 2-byte hops instead of the now-filtered 1-byte case.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: map that shows if repeater supports 2bytes

1 participant