]> git.codecow.com Git - nano25519.git/commitdiff
Import initial memory instead of exporting so that build tests can run and throw...
authorChris Duncan <chris@zoso.dev>
Tue, 1 Sep 2026 06:02:16 +0000 (23:02 -0700)
committerChris Duncan <chris@zoso.dev>
Tue, 1 Sep 2026 06:02:16 +0000 (23:02 -0700)
asconfig.json
src/assembly/utils.ts
src/lib/derive.ts
src/lib/sign.ts
src/lib/verify.ts
src/lib/wasm.ts

index f75849a29dda576eedf7e143e2eb1df9f027a20a..5aad30a843547d134ab445ceac9cf9e8aaf3f743 100644 (file)
@@ -11,6 +11,7 @@
                "sourceMap": false,
                "debug": false,
                "initialMemory": 4,
+               "importMemory": true,
                "runtime": "stub",
                "exportRuntime": false,
                "enable": [
index d8cb54f42a01484e92f666a15dc5e43dee2198da..91140a0cb14b094d9995c503034fecb9640deda2 100644 (file)
@@ -83,7 +83,9 @@ const testbytesB = new StaticArray<u8>(32).fill(0)
 for (let i = 0; i < 32; i++) {
        for (let j: u8 = 0; j < 8; j++) {
                testbytesA[i] = 1 << j
-               if (equalbytes(testbytesA, testbytesB, 32)) { throw new Error('equalbytes failed unit test') }
+               if (equalbytes(testbytesA, testbytesB, 32)) {
+                       throw new Error('equalbytes failed unit test')
+               }
                testbytesA[i] = 0
        }
 }
index ae9f83409ecfd87a18bb8fd95504e6029ecc5155..1a1288ffaa8eb8ab4dd91cf29abdfcb2583aebaa 100644 (file)
@@ -1,7 +1,7 @@
 //! SPDX-FileCopyrightText: 2026 Chris Duncan <chris@codecow.com>
 //! SPDX-License-Identifier: GPL-3.0-or-later
 
-import { Mutex, Nano25519TypeError, Pointers, clearMemory, constants, exports, isBytes, normalize } from './wasm'
+import { Mutex, Nano25519TypeError, Pointers, clearMemory, constants, exports, isBytes, memory, normalize } from './wasm'
 
 const { KEY_BYTELENGTH, } = constants
 
@@ -11,14 +11,14 @@ export function derive (prv: unknown, out?: unknown): string | Uint8Array<ArrayB
        }
        const privateKey = normalize('private key', KEY_BYTELENGTH, KEY_BYTELENGTH, prv)
        const publicKey = new Uint8Array(KEY_BYTELENGTH)
-       let buffer = new Uint8Array(exports.memory.buffer)
+       let buffer = new Uint8Array(memory.buffer)
        Mutex.lock()
        try {
                for (let i = 0; i < KEY_BYTELENGTH; i++) {
                        buffer[Pointers.INPUT_PRV + i] = privateKey[i]
                }
                exports.derive()
-               if (exports.memory.buffer !== buffer.buffer) {
+               if (memory.buffer !== buffer.buffer) {
                        throw new Nano25519TypeError('WASM memory buffer detached')
                }
                for (let i = 0; i < KEY_BYTELENGTH; i++) {
index a7aafc423ab6d37cfb2b0b81a0a02cd466ab0853..8bbefcd1ae3550d0be1ba0dc9b0eeebb0aecd064 100644 (file)
@@ -1,7 +1,7 @@
 //! SPDX-FileCopyrightText: 2026 Chris Duncan <chris@codecow.com>
 //! SPDX-License-Identifier: GPL-3.0-or-later
 
-import { Mutex, Nano25519TypeError, Pointers, clearMemory, constants, exports, isBytes, normalize } from './wasm'
+import { Mutex, Nano25519TypeError, Pointers, clearMemory, constants, exports, isBytes, memory, normalize } from './wasm'
 
 const { KEY_BYTELENGTH, MAX_MESSAGE_BYTELENGTH, SIGNATURE_BYTELENGTH, } = constants
 
@@ -13,7 +13,7 @@ export function sign (msg: unknown, prv: unknown, pub: unknown, out?: unknown):
        const privateKey = normalize('private key', KEY_BYTELENGTH, KEY_BYTELENGTH, prv)
        const publicKey = normalize('public key', KEY_BYTELENGTH, KEY_BYTELENGTH, pub)
        const signature = new Uint8Array(SIGNATURE_BYTELENGTH)
-       let buffer = new Uint8Array(exports.memory.buffer)
+       let buffer = new Uint8Array(memory.buffer)
        Mutex.lock()
        try {
                for (let i = 0; i < message.byteLength; i++) {
@@ -26,7 +26,7 @@ export function sign (msg: unknown, prv: unknown, pub: unknown, out?: unknown):
                        buffer[Pointers.INPUT_PUB + i] = publicKey[i]
                }
                exports.sign(message.byteLength)
-               if (exports.memory.buffer !== buffer.buffer) {
+               if (memory.buffer !== buffer.buffer) {
                        throw new Nano25519TypeError('WASM memory buffer detached')
                }
                for (let i = 0; i < SIGNATURE_BYTELENGTH; i++) {
index c001ea7b847be7888d7f243acb5fd21f08754af6..34dfd0308056673fc45aa747393ab471cdf2c237 100644 (file)
@@ -1,12 +1,12 @@
 //! SPDX-FileCopyrightText: 2026 Chris Duncan <chris@codecow.com>
 //! SPDX-License-Identifier: GPL-3.0-or-later
 
-import { Mutex, Nano25519TypeError, Pointers, clearMemory, constants, exports, normalize, } from './wasm'
+import { Mutex, Nano25519TypeError, Pointers, clearMemory, constants, exports, memory, normalize } from './wasm'
 
 const { BLOCKHASH_BYTELENGTH, KEY_BYTELENGTH, MAX_MESSAGE_BYTELENGTH, MAX_VERIFY_BLOCKS, SIGNATURE_BYTELENGTH, } = constants
 
 export function verify (sig: unknown, msg: unknown, pub: unknown): boolean {
-       let buffer = new Uint8Array(exports.memory.buffer)
+       let buffer = new Uint8Array(memory.buffer)
        Mutex.lock()
        try {
                const message = normalize('message', 0, MAX_MESSAGE_BYTELENGTH, msg)
@@ -22,7 +22,7 @@ export function verify (sig: unknown, msg: unknown, pub: unknown): boolean {
                        buffer[Pointers.INPUT_SIG + i] = signature[i]
                }
                exports.verify(message.byteLength)
-               if (exports.memory.buffer !== buffer.buffer) {
+               if (memory.buffer !== buffer.buffer) {
                        throw new Nano25519TypeError('WASM memory buffer detached')
                }
                const verified = buffer[Pointers.OUTPUT_VERIFY]
@@ -42,7 +42,7 @@ export function verify_blocks (pub: unknown, data: unknown): boolean[] {
                throw new RangeError(`Bulk Nano block verification must be no more than ${MAX_VERIFY_BLOCKS} blocks`, { cause: count })
        }
        const verified = new Uint8Array(count)
-       let buffer = new Uint8Array(exports.memory.buffer)
+       let buffer = new Uint8Array(memory.buffer)
        Mutex.lock()
        try {
                const publicKey = normalize('public key', KEY_BYTELENGTH, KEY_BYTELENGTH, pub)
@@ -72,7 +72,7 @@ export function verify_blocks (pub: unknown, data: unknown): boolean[] {
                        p += BLOCKHASH_BYTELENGTH
                }
                exports.verify_blocks(count)
-               if (exports.memory.buffer !== buffer.buffer) {
+               if (memory.buffer !== buffer.buffer) {
                        throw new Nano25519TypeError('WASM memory buffer detached')
                }
                for (let i = 0; i < count; i++) {
index 61e332aa2747e037e718714610acdc1ca23bf466..50f4bf143bd904f39f7993ffcec7a4bcbd55b944 100644 (file)
@@ -23,7 +23,6 @@ type Exports = {
                MAX_VERIFY_BLOCKS: WebAssembly.Global
                MAX_VERIFY_BLOCKS_BYTELENGTH: WebAssembly.Global
                MAX_MESSAGE_BYTELENGTH: WebAssembly.Global
-               memory: WebAssembly.Memory
        }
 }
 
@@ -37,15 +36,25 @@ export const Mutex = {
        }
 }
 
+/**
+ * WASM memory created here and imported, instead of building and exporting, so
+ * that top-level WASM abort calls work while `exports` is still instantiating.
+ * Host-owned memory means abort handler can always read the error message.
+ *
+ * NOTE: `initial` must match `initialMemory` in `asconfig.json`.
+ */
+export const memory = new WebAssembly.Memory({ initial: 4 })
+
 const wasm: Uint8Array<ArrayBuffer> = Uint8Array.from(nano25519_wasm)
 const module = new WebAssembly.Module(wasm)
 
 export const { exports } = new WebAssembly.Instance(module, {
        env: {
+               memory,
                abort: (msg: any, file: any, row: any, col: any): never => {
                        const getString = (pointer: number): string | null => {
-                               const end = pointer + new Uint32Array(exports.memory.buffer)[pointer - 4 >>> 2] >>> 1
-                               const buf = new Uint16Array(exports.memory.buffer)
+                               const end = pointer + new Uint32Array(memory.buffer)[pointer - 4 >>> 2] >>> 1
+                               const buf = new Uint16Array(memory.buffer)
                                let start = pointer >>> 1
                                let string = ''
                                while (end - start > 1024) {
@@ -104,14 +113,14 @@ export class Pointers {
 }
 
 export function clearMemory (): void {
-       const memory = new Uint8Array(exports.memory.buffer)
-       memory.fill(0, INPUT_MSG, INPUT_MSG + MAX_MESSAGE_BYTELENGTH)
-       memory.fill(0, INPUT_PRV, INPUT_PRV + KEY_BYTELENGTH)
-       memory.fill(0, INPUT_PUB, INPUT_PUB + KEY_BYTELENGTH)
-       memory.fill(0, INPUT_SIG, INPUT_SIG + SIGNATURE_BYTELENGTH)
-       memory.fill(0, OUTPUT_DERIVE, OUTPUT_DERIVE + KEY_BYTELENGTH)
-       memory.fill(0, OUTPUT_SIGN, OUTPUT_SIGN + SIGNATURE_BYTELENGTH)
-       memory.fill(255, OUTPUT_VERIFY, OUTPUT_VERIFY + MAX_VERIFY_BLOCKS)
+       const bytes = new Uint8Array(memory.buffer)
+       bytes.fill(0, INPUT_MSG, INPUT_MSG + MAX_MESSAGE_BYTELENGTH)
+       bytes.fill(0, INPUT_PRV, INPUT_PRV + KEY_BYTELENGTH)
+       bytes.fill(0, INPUT_PUB, INPUT_PUB + KEY_BYTELENGTH)
+       bytes.fill(0, INPUT_SIG, INPUT_SIG + SIGNATURE_BYTELENGTH)
+       bytes.fill(0, OUTPUT_DERIVE, OUTPUT_DERIVE + KEY_BYTELENGTH)
+       bytes.fill(0, OUTPUT_SIGN, OUTPUT_SIGN + SIGNATURE_BYTELENGTH)
+       bytes.fill(255, OUTPUT_VERIFY, OUTPUT_VERIFY + MAX_VERIFY_BLOCKS)
        locked = false
 }