From 4523aa94307002e489610ef230d53f8863dab5cc Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Wed, 26 Aug 2026 01:40:19 -0700 Subject: [PATCH] Update agent file. --- AGENTS.md | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 6dc9825..3017260 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -20,8 +20,9 @@ verify_blocks(pub, blocks) // { hash, signature }[], up to 256 -> boolean[] Inputs are `Uint8Array` or hex strings, and the output type follows the input 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 — and is under active construction; check the -living context document before relying on it. +hashes against one public key. It is correct across the full range as of +`914c83c`, but not yet any faster than N sequential `verify()` calls — the +per-key work is still redone per block. ## Commands @@ -64,7 +65,12 @@ length once at module load and re-exports them. | `MESSAGE_BUFFER` | 32 KiB. A message for `sign`/`verify`, or packed 96-byte `hash \|\| signature` records for `verify_blocks` | | `PRV_BUFFER`, `PUB_BUFFER` | 32 bytes each | | `SIGNATURE_BUFFER` | one signature for single `verify` | -| `OUTPUT_BUFFER` | public key, signature, or one result byte per verified block | +| `OUTPUT_BUFFER` | 256 B. A public key, a signature, or one result byte per verified block | + +`verify_blocks` writes one result byte per block, so its cap **is** +`OUTPUT_BUFFER_BYTELENGTH` — both the wasm guard and the host guard derive from +it rather than hardcoding 256, and they cannot drift when the buffer is resized. +Preserve that coupling, and note it only holds while one byte per block does. Exported byte-length globals (`KEY_BYTELENGTH`, `MESSAGE_BUFFER_BYTELENGTH`, …) are the single source of truth for these sizes — read them rather than @@ -87,9 +93,10 @@ ordinary AssemblyScript: cannot be exported. Only compile-time constants survive as exported globals. - **`enable: ["simd"]`** — field elements are 12 `i32` limbs, not 10. The two trailing limbs are padding; respect the stride. -- **`initialMemory: 4`** — pins the module at 4 pages. Without it the stub - allocator doubles on growth (1→2→4→8). Re-derive this value when buffer - sizes change rather than leaving it stale. +- **`initialMemory: 2`** — pins the module at 2 pages. Without it the stub + allocator doubles on growth (1→2→4→8), so page counts are always powers of + two. Re-derive this whenever a buffer is resized rather than leaving it + stale; it has been wrong in both directions already. Memory growth *during* a call would detach every `Uint8Array` view the host holds, so keeping call paths allocation-free is a correctness requirement, not @@ -158,8 +165,9 @@ never show up on the clock; only the point arithmetic does. failing**, and that one failure is expected. `verify_blocks` has **no vector coverage yet** — a green suite says nothing -about it. Exercise it directly, and at batch sizes past 64 and past 256, where -the interesting boundaries are. +about it. Exercise it directly, and across the whole range rather than at one +size: its bugs have twice been invisible below a boundary (64, then 256) and +only appeared past it. The failing case is `PROBLEM_VECTOR`: a live cemented Nano block from a small-order account (`nano_11a11…`, public key `0100…00`) that network -- 2.52.0