From 93b2f4b6bb7754a5e8e6cf3926ce24b252f0b36e Mon Sep 17 00:00:00 2001 From: Kpa-clawbot Date: Thu, 28 May 2026 18:43:03 -0700 Subject: [PATCH] fix(#1473): treat 0x00 and 0xFF as reserved prefixes (matrix + generator) (#1474) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Two CoreScope surfaces treated `0x00` and `0xFF` as ordinary node prefixes, but the MeshCore firmware actively rerolls any identity whose public-key first byte is `0x00` or `0xFF` (see [`examples/simple_repeater/main.cpp:64`](https://github.com/meshcore-dev/MeshCore/blob/6b52fb32301c273fc78d96183501eb23ad33c5bb/examples/simple_repeater/main.cpp#L64)): ```cpp while (count < 10 && (the_mesh.self_id.pub_key[0] == 0x00 || the_mesh.self_id.pub_key[0] == 0xFF)) { // reserved id hashes the_mesh.self_id = radio_new_identity(); count++; } ``` As a result the analyzer was steering new operators toward identities the firmware will silently refuse — `0xFF` is also used as a wildcard flood marker in parts of the routing flow, so this isn't cosmetic. Reporter: **@halo779** (community). ## What this PR does * **`public/prefix-reserved.js`** — small new module, single source of truth. Exposes `isReservedPrefix`, `filterReserved`, `reservedCount`, `markReservedCells`. Firmware citation lives in the file header. * **Hash matrix (1-byte view)** — cells `00` and `FF` get the `.prefix-reserved` class, lose `.hash-active` so the matrix click handler skips them, and pick up an `aria-disabled` + a tooltip explaining why. * **Prefix generator** — random sampling, enumeration fallback, and the "available count" all filter out reserved prefixes. A visible note under the generator card cites `simple_repeater/main.cpp:64` directly. * **Prefix checker** — pasting a reserved prefix or full pubkey now surfaces a red `⚠️ Reserved prefix` alert above the per-tier breakdown. * **`public/style.css`** — `.prefix-reserved` greys + strikes through the cell and sets `pointer-events: none`. * **`public/index.html`** — loads `prefix-reserved.js` before `analytics.js`. ## Tests Red-then-green visible in commit history: * `test-issue-1473-reserved-prefixes.js` — `isReservedPrefix()` semantics (case + multi-byte) and `markReservedCells()` behavior on a mock 256-cell matrix. * `test-issue-1473-prefix-generator.js` — `filterReserved`, `reservedCount` per byte length, RNG-bias simulator showing the generator never returns a reserved prefix, enumeration-first-free skips `00`, and an assertion that `analytics.js` actually wires `PrefixReserved` into the generator. Both added to `test-all.sh`. Fixes #1473 --------- Co-authored-by: clawbot --- .eslintrc.json | 1 + public/analytics.js | 66 +++++++++++++--- public/index.html | 1 + public/prefix-reserved.js | 113 +++++++++++++++++++++++++++ public/style.css | 20 +++++ test-all.sh | 2 + test-issue-1473-prefix-generator.js | 110 ++++++++++++++++++++++++++ test-issue-1473-reserved-prefixes.js | 106 +++++++++++++++++++++++++ 8 files changed, 410 insertions(+), 9 deletions(-) create mode 100644 public/prefix-reserved.js create mode 100644 test-issue-1473-prefix-generator.js create mode 100644 test-issue-1473-reserved-prefixes.js diff --git a/.eslintrc.json b/.eslintrc.json index d7849a77..84e58b0c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -42,6 +42,7 @@ "PULL_THRESHOLD_PX": "readonly", "PacketFilter": "readonly", "PathInspector": "readonly", + "PrefixReserved": "readonly", "QRCode": "readonly", "ROLE_COLORS": "readonly", "ROLE_EMOJI": "readonly", diff --git a/public/analytics.js b/public/analytics.js index a198a6bb..cdef5317 100644 --- a/public/analytics.js +++ b/public/analytics.js @@ -1615,6 +1615,14 @@ html += hashMatrixLegendHtml(legendLabels); el.innerHTML = html; initMatrixTooltip(el); + // #1473 — Grey out cells whose first byte the MeshCore firmware keygen + // routine avoids (pub_key[0] in {0x00, 0xFF}). This is a keygen + // CONVENTION, not a protocol-level rejection — see firmware + // examples/simple_repeater/main.cpp:83 (HEAD 8ede7641). Must run BEFORE + // we wire click handlers so .hash-active is stripped first. + if (typeof PrefixReserved !== 'undefined' && PrefixReserved && typeof PrefixReserved.markReservedCells === 'function') { + PrefixReserved.markReservedCells(el); + } el.querySelectorAll('.hash-active').forEach(td => { td.addEventListener('click', () => { clickHandlerFn(td); @@ -2992,6 +3000,12 @@ function destroy() { _stopRolesRefresh(); _stopScopesRefresh(); _analyticsData =

Generate Available Prefix

Find a prefix with zero current collisions.

+

+ + 0x00 and 0xFF excluded as a first byte — the MeshCore firmware keygen routine re-rolls identities whose pub_key[0] is 00 or FF, so by convention you should not see those prefixes on real nodes (see + simple_repeater/main.cpp:83). +