verify_blocks(pub, blocks) // { hash, signature }[], up to 64 -> 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.
+Inputs are `Uint8Array`, `ArrayBuffer`, or hex strings. `derive` and `sign`
+**always return a hex string**, unless the optional preallocated output buffer
+is passed as a trailing argument — then the bytes are written there and the
+return is `undefined`.
`verify_blocks` is the Nano account-chain case — many block hashes against one
public key. It has vector coverage, but do **not** read that as verified correct
| 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 `constants`, the mutex-gated `Pointers`, `Mutex`, `normalize()`, `clearMemory()` |
+| `src/lib/wasm.ts` | Instantiates the module; exports `constants`, the mutex-gated `Pointers`, `Mutex`, `clearMemory()` |
+| `src/lib/primordials.ts` | Trust root: built-ins captured at load, plus `normalize()`. Imports nothing, by design |
| `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 |
| `src/assembly/utils.ts` | `equalbytes` and the other constant-time helpers |
| `src/assembly/tests.ts` | Start-function build guard — see **Testing** |
| `test/node.mjs`, `test/vectors.mjs` | Suite, and the vectors it is built from |
-| `test/python_ed25519_blake2b_vectors.mjs` | The bulk vector set, split out to stop crashing the IDE |
+| `test/vectors/python_ed25519_blake2b.ts` | The bulk vector set, split out to stop crashing the IDE |
| `test/index.html` | Browser test and benchmark page |
## The wasm ABI
- A loop bound of `SIG_LEN` or `KEY_LEN` where the intent was "per item" reads
the right number of bytes for the wrong reason.
-One instance is still open: `crypto_verify.ts:62` passes a literal `32` to
-`equalbytes` where the line above it already reads `KEY_BYTELENGTH`. The literal
-is correct, so this is cosmetic — but it is a length argument on the one
-comparison carrying the batch path's whole security property. It used to be
-blocked by an import cycle through `index.ts`; `constants.ts` removed that, so
-the fix is now a one-word edit.
+`crypto_verify.ts:62` used to pass a literal `32` to `equalbytes` where the line
+above it already read `KEY_BYTELENGTH`. The literal was correct, so it was only
+cosmetic — but it was a length argument on the one comparison carrying the batch
+path's whole security property, so it now reads `KEY_BYTELENGTH`. Keep it that
+way, including in the staged cofactorless line commented beneath
+`crypto_verify_sodium`.
**Do not add JS-side suspension points.** The safety of hashing straight out of
the shared message buffer rests on there being no `await`, no yield, and no
## Testing
-`node ./test/node.mjs` after a build. Current state is **6178 passing, 0
+`node ./test/node.mjs` after a build. Current state is **6194 passing, 0
failing**. There is no longer an expected failure — if anything fails, it is a
regression.