Skip to content

Commit 61c5907

Browse files
committed
plan: mark 2.4 (128-bit NodeId) done; move sub-plan to plan/done/
1 parent 7377583 commit 61c5907

2 files changed

Lines changed: 15 additions & 10 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Widen NodeId to 128 bits (hardening plan, item 2.4)
22

3+
**Status: DONE** (commit `harden: widen NodeId to 128 bits`). All 8 stages landed; unit suite
4+
68/278 green and `run.sh`/`fuzz_udp.sh`/`config_posture.sh` acceptance all pass with real 128-bit
5+
ids over UDP (the notary id is now 32 hex chars). The OMNeT++ sim app is source-compatible and
6+
needed no edits (NodeId appears only as `= 0`, `static_cast(getId())`, and map keys), but is built
7+
only under OMNeT++, not in CI here.
8+
39
A sub-plan split out of `hardening.md` because it is a wire / on-disk / snapshot **format
410
change**, not a localized fix. No backward compatibility is required (the operator confirmed):
511
format versions are bumped freely and old stores/proofs/packets are simply incompatible.

plan/pending/hardening.md

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ guarantees directly.
9191

9292
**Status: partial.** 2.1 (reject empty signatures) and 2.2 (0600 key file) are DONE, along with
9393
2.x below (an upper-bound linkage soundness bug found while fixing 2.1); 2.3 (fail-loud key + backup writes)
94-
is done, as is 2.5 (warn on unsigned mode). 2.4 (wider NodeId) and 2.6 (key scrub) remain. Full
94+
is done, as is 2.5 (warn on unsigned mode) and 2.4 (128-bit NodeId — see plan/done/wider-node-id.md).
95+
Only 2.6 (key scrub) remains. Full
9596
suite + acceptance green.
9697

9798
- [x] **2.1 — Reject unsigned/empty signatures in validation.** `Ed25519KeyStore::verify` returns
@@ -127,14 +128,11 @@ suite + acceptance green.
127128
unconditionally**. Check every write/rename; propagate failure; make `db-backup` reply `ERR`
128129
when the blob was not durably written. A backup that can silently write nothing is worse than
129130
none.
130-
- [ ] **2.4 — Widen `NodeId` to ≥128 bits.** The identity is the first **8 bytes** of
131-
SHA-256(pubkey) ([keystore.cpp:99](../../src/adapters/os/keystore.cpp#L99),
132-
[proof.cpp:15](../../src/core/proof/proof.cpp#L15)). At the paper's "few billion nodes" (~2³²)
133-
target, 64 bits gives a ~50% birthday-collision probability among honest nodes, and ~2⁶⁴ targeted
134-
impersonation grinding. Move to a wider id (≥16 bytes, or the full 32-byte fingerprint). This is a
135-
**wire/format change** (`NodeId` is a `u64` in [domain/types.hpp](../../src/core/domain/types.hpp#L21)
136-
and in every packet/snapshot) — bump the snapshot + on-disk + protocol versions together, or
137-
scope it as its own sub-plan. Decide and record the chosen width here.
131+
- [x] **2.4 — Widen `NodeId` to 128 bits.** DONE via the sub-plan
132+
[plan/done/wider-node-id.md](../done/wider-node-id.md): `NodeId` is now a 16-byte struct (first 16
133+
bytes of SHA-256(pubkey)) — ~2⁶⁴ birthday safety, 2¹²⁸ impersonation resistance. Wire, snapshot
134+
(v2→v3), and LMDB (v3→v4) formats bumped; CLI parses/prints 32-hex ids. No backward compat (the
135+
operator confirmed). Verified: unit 68/278, acceptance 10/0 with real 128-bit ids over UDP.
138136
- [x] **2.5 — Gate/annotate unsigned mode.** DONE: `lotid` prints a loud startup WARNING when run
139137
unsigned (`--id`) — no cryptographic identity, and (since 2.1) its events verify under no signed
140138
peer; `status` already reports `mode: signed|unsigned`. (Kept `--id` for the simulation/test path
@@ -385,7 +383,8 @@ in the production binary).
385383
- **upper-bound linkage (2.x) — a real soundness bug, not just hardening.** The first upper-bound
386384
element's linkage to the event was unchecked; a disconnected upper bound validated. Fixed by
387385
requiring every upper element to reference its predecessor (the first references the event).
388-
- **2.4 (wider NodeId) deliberately NOT bundled.** It is a wire/on-disk/snapshot format change
386+
- **2.4 (wider NodeId) — later done as its own sub-plan** (plan/done/wider-node-id.md), 128-bit.
387+
It was deliberately NOT bundled into a security patch at first: it is a wire/on-disk/snapshot format change
389388
(version bumps across `domain::NodeId`, packets, snapshot) and must be its own sub-plan — mixing a
390389
format break into a security patch is how you ship a migration bug.
391390

0 commit comments

Comments
 (0)