From 89a7d9e8ed0af63083959acf71c4c8deed88952c Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Sat, 29 Aug 2026 19:02:30 -0700 Subject: [PATCH] Retract unsupported verify_blocks correctness claim in agent file. --- AGENTS.md | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index a014cce..aca5f68 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -22,10 +22,14 @@ type. `derive` and `sign` take an optional preallocated output buffer as a trailing argument. `verify_blocks` is the Nano account-chain case — many block hashes against one -public key. It is correct across the full range and has vector coverage. The -public-key decompression is hoisted into `crypto_verify_decodepubkey` and run -once per batch, which saves `(1 - 1/n) * k` where `k` is the key work's share of -one verification: **measured k = 8.84%**, realising **~8.7%** at the cap of 64. +public key. It has vector coverage, but do **not** read that as verified correct +across the range: both of the bugs this path has shipped passed the full suite, +and the more recent one left signatures forgeable at ~2³² offline work. What +guards it now is the `equalbytes` self-test in the module start function, not +the vectors — see **Testing**. The public-key decompression is hoisted into +`crypto_verify_decodepubkey` and run once per batch, which saves +`(1 - 1/n) * k` where `k` is the key work's share of one verification: +**measured k = 8.84%**, realising **~8.7%** at the cap of 64. ⚠️ **`verify` and `verify_blocks` have different acceptance sets, on purpose.** @@ -85,7 +89,7 @@ stale `dist/` will silently test the previous revision. | Path | What it is | | --- | --- | | `src/index.ts` | Public API and its overloads: `derive`, `sign`, `verify`, `verify_blocks` | -| `src/lib/wasm.ts` | Instantiates the module; exports pointers, byte lengths, `normalize()`, `clear()` | +| `src/lib/wasm.ts` | Instantiates the module; exports `constants`, the mutex-gated `Pointers`, `Mutex`, `normalize()`, `clearMemory()` | | `src/lib/{derive,sign,verify}.ts` | Host-side marshalling, one file per primitive | | `src/assembly/index.ts` | Wasm entry points, static I/O buffers, exported pointers and byte-length globals | | `src/assembly/crypto_{derive,sign,verify}.ts` | RFC 8032-shaped primitives over BLAKE2b | @@ -151,9 +155,10 @@ These sizes are a **public API**: `nano25519.constants` carries `BLOCKHASH_BYTELENGTH`, `KEY_BYTELENGTH`, `SIGNATURE_BYTELENGTH`, `MAX_VERIFY_BLOCKS`, `MAX_VERIFY_BLOCKS_BYTELENGTH` and `MAX_MESSAGE_BYTELENGTH`. Read them rather than hardcoding, on both sides of the -boundary and in consumers. Buffer **pointers** are grouped as `pointers` inside -`src/lib` and deliberately not exported from the package — the buffer-scrub -guarantee is a property of the module, not a promise about callers. +boundary and in consumers. Buffer **pointers** are the mutex-gated `Pointers` +class in `src/lib`, deliberately not exported from the package — the +buffer-scrub guarantee is a property of the module, not a promise about +callers. `test/index.html` reads `nano25519.constants.MAX_VERIFY_BLOCKS` for its loop bound, its per-block divisor and its default test size — which is why the 32 → 64 @@ -183,8 +188,8 @@ and hands back results read from a different buffer than the one written. **`OUTPUT_VERIFY` is fail-closed at every point it could be read.** It is filled with `255` at instantiation, again at the top of `verify_blocks` before the count -check, and again by the host's `clear()`. `0` means verified, so a buffer that was -never written must never read as zero. +check, and again by the host's `clearMemory()`. `0` means verified, so a buffer +that was never written must never read as zero. ## Wasm error reporting -- 2.52.0