From 65d6245e5aabb3e7019b0ab23f7e801d3ff6b019 Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Thu, 27 Aug 2026 09:04:41 -0700 Subject: [PATCH] Refactor I/O buffers to separate per primitive. Reduce bulk block verification size, see src/assembly/index.ts > verify_blocks for more info. --- src/assembly/index.ts | 139 +++++++++++++++++++++++------------------- src/index.ts | 4 +- src/lib/derive.ts | 16 ++--- src/lib/sign.ts | 24 ++++---- src/lib/verify.ts | 46 +++++++------- src/lib/wasm.ts | 59 +++++++++--------- test/index.html | 4 +- test/node.mjs | 8 +-- 8 files changed, 157 insertions(+), 143 deletions(-) diff --git a/src/assembly/index.ts b/src/assembly/index.ts index 12e0dae..6be7f02 100644 --- a/src/assembly/index.ts +++ b/src/assembly/index.ts @@ -7,45 +7,54 @@ import { crypto_verify_pubkey, crypto_verify_relaxed, crypto_verify_strict } fro export const BLOCKHASH_BYTELENGTH: i32 = 32 export const KEY_BYTELENGTH: i32 = 32 +export const MAX_VERIFY_BLOCKS: i32 = 32 +export const MAX_MESSAGE_BYTELENGTH: i32 = MAX_VERIFY_BLOCKS << 10 export const SIGNATURE_BYTELENGTH: i32 = 64 export const SIGNEDBLOCK_BYTELENGTH: i32 = BLOCKHASH_BYTELENGTH + SIGNATURE_BYTELENGTH -export const MESSAGE_BUFFER_BYTELENGTH: i32 = BLOCKHASH_BYTELENGTH << 10 -export const PRV_BUFFER_BYTELENGTH: i32 = KEY_BYTELENGTH -export const PUB_BUFFER_BYTELENGTH: i32 = KEY_BYTELENGTH -export const OUTPUT_BUFFER_BYTELENGTH: i32 = MESSAGE_BUFFER_BYTELENGTH / SIGNEDBLOCK_BYTELENGTH -export const SIGNATURE_BUFFER_BYTELENGTH: i32 = SIGNATURE_BYTELENGTH - // Static I/O buffers -const MESSAGE_BUFFER = new StaticArray(MESSAGE_BUFFER_BYTELENGTH) -const OUTPUT_BUFFER = new StaticArray(OUTPUT_BUFFER_BYTELENGTH) -const PRV_BUFFER = new StaticArray(PRV_BUFFER_BYTELENGTH) -const PUB_BUFFER = new StaticArray(PUB_BUFFER_BYTELENGTH) -const SIGNATURE_BUFFER = new StaticArray(SIGNATURE_BUFFER_BYTELENGTH) +const INPUT_MSG = new StaticArray(MAX_MESSAGE_BYTELENGTH) +const INPUT_PRV = new StaticArray(KEY_BYTELENGTH) +const INPUT_PUB = new StaticArray(KEY_BYTELENGTH) +const INPUT_SIG = new StaticArray(SIGNATURE_BYTELENGTH) -/** Returns the pointer to the static message input buffer (32 KiB). */ -export function getMessagePointer (): usize { - return changetype(MESSAGE_BUFFER) -} +const OUTPUT_DERIVE = new StaticArray(KEY_BYTELENGTH) +const OUTPUT_SIGN = new StaticArray(SIGNATURE_BYTELENGTH) +const OUTPUT_VERIFY = new StaticArray(MAX_VERIFY_BLOCKS) -/** Returns the pointer to the static output buffer (341 bytes). */ -export function getOutputPointer (): usize { - return changetype(OUTPUT_BUFFER) +/** Returns the pointer to the static message input buffer (32 KiB). */ +export function ptrInputMsg (): usize { + return changetype(INPUT_MSG) } /** Returns the pointer to the static private key input buffer (32 bytes). */ -export function getPrivateKeyPointer (): usize { - return changetype(PRV_BUFFER) +export function ptrInputPrv (): usize { + return changetype(INPUT_PRV) } /** Returns the pointer to the static public key input buffer (32 bytes). */ -export function getPublicKeyPointer (): usize { - return changetype(PUB_BUFFER) +export function ptrInputPub (): usize { + return changetype(INPUT_PUB) } /** Returns the pointer to the static signature input buffer (64 bytes). */ -export function getSignaturePointer (): usize { - return changetype(SIGNATURE_BUFFER) +export function ptrInputSig (): usize { + return changetype(INPUT_SIG) +} + +/** Returns the pointer to the derive() static output buffer (64 bytes). */ +export function ptrOutputDerive (): usize { + return changetype(OUTPUT_DERIVE) +} + +/** Returns the pointer to the sign() static output buffer (64 bytes). */ +export function ptrOutputSign (): usize { + return changetype(OUTPUT_SIGN) +} + +/** Returns the pointer to the verify() static output buffer (64 bytes). */ +export function ptrOutputVerify (): usize { + return changetype(OUTPUT_VERIFY) } const h = new StaticArray(BLOCKHASH_BYTELENGTH) @@ -63,22 +72,22 @@ const sig = new StaticArray(SIGNATURE_BYTELENGTH) */ export function derive (): void { // Clear output buffer so errors do not retain stale prior data - OUTPUT_BUFFER.fill(0) + OUTPUT_DERIVE.fill(0) // Clear local buffers prv.fill(0) pub.fill(0) // Copy input buffer to local parameterss, then clear input buffer - memory.copy(changetype(prv), changetype(PRV_BUFFER), KEY_BYTELENGTH) - PRV_BUFFER.fill(0) + memory.copy(changetype(prv), changetype(INPUT_PRV), KEY_BYTELENGTH) + INPUT_PRV.fill(0) // Derive, then clear local input crypto_derive(pub, prv) prv.fill(0) // Copy local result to output buffer - memory.copy(changetype(OUTPUT_BUFFER), changetype(pub), KEY_BYTELENGTH) + memory.copy(changetype(OUTPUT_DERIVE), changetype(pub), KEY_BYTELENGTH) // Clear local result pub.fill(0) @@ -97,7 +106,7 @@ export function derive (): void { */ export function sign (mlen: i32): void { // Clear output buffer so errors do not retain stale prior data - OUTPUT_BUFFER.fill(0) + OUTPUT_SIGN.fill(0) // Clear local buffers prv.fill(0) @@ -105,27 +114,27 @@ export function sign (mlen: i32): void { sig.fill(0) // Check message length - if (mlen < 0 || mlen > MESSAGE_BUFFER_BYTELENGTH) { - PRV_BUFFER.fill(0) - PUB_BUFFER.fill(0) - MESSAGE_BUFFER.fill(0) + if (mlen < 0 || mlen > MAX_MESSAGE_BYTELENGTH) { + INPUT_PRV.fill(0) + INPUT_PUB.fill(0) + INPUT_MSG.fill(0) throw new Error('Invalid message length') } // Copy input buffers to local parameters, then clear input buffer - memory.copy(changetype(prv), changetype(PRV_BUFFER), KEY_BYTELENGTH) - PRV_BUFFER.fill(0) - memory.copy(changetype(pub), changetype(PUB_BUFFER), KEY_BYTELENGTH) - PUB_BUFFER.fill(0) + memory.copy(changetype(prv), changetype(INPUT_PRV), KEY_BYTELENGTH) + INPUT_PRV.fill(0) + memory.copy(changetype(pub), changetype(INPUT_PUB), KEY_BYTELENGTH) + INPUT_PUB.fill(0) // Sign message from buffer, then clear local input - crypto_sign(sig, MESSAGE_BUFFER, mlen, prv, pub) + crypto_sign(sig, INPUT_MSG, mlen, prv, pub) prv.fill(0) pub.fill(0) - MESSAGE_BUFFER.fill(0) + INPUT_MSG.fill(0) // Copy local result to output buffer - memory.copy(changetype(OUTPUT_BUFFER), changetype(sig), SIGNATURE_BYTELENGTH) + memory.copy(changetype(OUTPUT_SIGN), changetype(sig), SIGNATURE_BYTELENGTH) // Clear local result sig.fill(0) @@ -139,30 +148,30 @@ export function sign (mlen: i32): void { */ export function verify (mlen: i32): void { // Set all output to false so errors fail closed - OUTPUT_BUFFER.fill(255) + OUTPUT_VERIFY.fill(255) // Clear local buffers pub.fill(0) sig.fill(0) // Check message length - if (mlen < 0 || mlen > MESSAGE_BUFFER_BYTELENGTH) { - MESSAGE_BUFFER.fill(0) - PUB_BUFFER.fill(0) + if (mlen < 0 || mlen > MAX_MESSAGE_BYTELENGTH) { + INPUT_MSG.fill(0) + INPUT_PUB.fill(0) throw new Error('Invalid message length') } // Copy input buffer to local parameters, then clear input buffer - memory.copy(changetype(pub), changetype(PUB_BUFFER), KEY_BYTELENGTH) - PUB_BUFFER.fill(0) - memory.copy(changetype(sig), changetype(SIGNATURE_BUFFER), SIGNATURE_BYTELENGTH) - SIGNATURE_BUFFER.fill(0) + memory.copy(changetype(pub), changetype(INPUT_PUB), KEY_BYTELENGTH) + INPUT_PUB.fill(0) + memory.copy(changetype(sig), changetype(INPUT_SIG), SIGNATURE_BYTELENGTH) + INPUT_SIG.fill(0) // Verify message from buffer, then write result to output buffer - OUTPUT_BUFFER[0] = u8(crypto_verify_strict(sig, MESSAGE_BUFFER, mlen, pub)) + OUTPUT_VERIFY[0] = u8(crypto_verify_strict(sig, INPUT_MSG, mlen, pub)) // Clear message buffer and input locals - MESSAGE_BUFFER.fill(0) + INPUT_MSG.fill(0) pub.fill(0) sig.fill(0) } @@ -172,17 +181,21 @@ export function verify (mlen: i32): void { * 32-byte public key. Input parameters are read as bytes from separate buffers. * * The message buffer holds both the signature and the block hash as a 96-byte - * concatenated value. The 32 KiB message buffer cannot be divided evenly by 96, - * so up to 341 block signature/hash pairs are supported with an extra 32 bytes - * left at the end. + * concatenated value. The performance gain of verifying in bulk scales as + * `(1-(1/n)) x (k/(k+r))` where `n` is block count, `k` is the time required to + * verify the public key, and `r` is the time required to compute all the + * remaining verification steps. Testing shows `k` to be ~8.5% the total + * verification time, so batching up to 32 block signature/hash pairs reaches + * ~96% of that gain; any more blocks would simply add latency returning the + * final results. * * All pairs are verified against a single public key. The results are written * to the output buffer in the same order they were received. - * @param {i32} count Number of signatures to verify, up to 341 + * @param {i32} count Number of signatures to verify, up to 32 */ export function verify_blocks (count: i32): void { // Set all output to false so errors fail closed - OUTPUT_BUFFER.fill(255) + OUTPUT_VERIFY.fill(255) // Clear local buffers h.fill(0) @@ -190,32 +203,32 @@ export function verify_blocks (count: i32): void { sig.fill(0) // Check number of blocks is valid - if (count < 1 || OUTPUT_BUFFER_BYTELENGTH < count) { - MESSAGE_BUFFER.fill(0) - PUB_BUFFER.fill(0) + if (count < 1 || MAX_VERIFY_BLOCKS < count) { + INPUT_MSG.fill(0) + INPUT_PUB.fill(0) throw new Error('Invalid block count') } // Copy public key input buffer to local parameter, then clear input buffer - memory.copy(changetype(pub), changetype(PUB_BUFFER), KEY_BYTELENGTH) - PUB_BUFFER.fill(0) + memory.copy(changetype(pub), changetype(INPUT_PUB), KEY_BYTELENGTH) + INPUT_PUB.fill(0) // Verify public key before proceeding with signature verification if (crypto_verify_pubkey(pub) == 0) { // Iterate over block signature/hash pairs - for (let i = 0, ptr = changetype(MESSAGE_BUFFER); i < count; i++, ptr += 96) { + for (let i = 0, ptr = changetype(INPUT_MSG); i < count; i++, ptr += 96) { // Copy block signature/hash from message buffer to locals memory.copy(changetype(sig), ptr, SIGNATURE_BYTELENGTH) memory.copy(changetype(h), ptr + SIGNATURE_BYTELENGTH, BLOCKHASH_BYTELENGTH) // Verify hash and signature, then write result to output buffer - OUTPUT_BUFFER[i] = u8(crypto_verify_relaxed(sig, h, pub)) + OUTPUT_VERIFY[i] = u8(crypto_verify_relaxed(sig, h, pub)) } } // Clear message buffer and input locals - MESSAGE_BUFFER.fill(0) + INPUT_MSG.fill(0) h.fill(0) pub.fill(0) sig.fill(0) diff --git a/src/index.ts b/src/index.ts index e843a5c..4c53918 100644 --- a/src/index.ts +++ b/src/index.ts @@ -85,7 +85,7 @@ export function verify (sig: string | Uint8Array, msg: string | Uin /** * Nano block signature bulk verification using WebAssembly. * @param {Uint8Array} publicKey - 32-byte public key - * @param {object[]} blocks - Array of up to 341 block signature/hash pairs + * @param {object[]} blocks - Array of up to 32 block signature/hash pairs * @param {Uint8Array} blocks.signature - 64-byte block signature * @param {Uint8Array} blocks.hash - 32-byte block hash * @returns Array of results with, for each case, true if signature matches block hash and public key, else false @@ -94,7 +94,7 @@ export function verify_blocks (publicKey: Uint8Array, blocks: { has /** * Nano block signature bulk verification using WebAssembly. * @param {string} publicKey - 64-character hexadecimal public key - * @param {object[]} blocks - Array of up to 341 block signature/hash pairs + * @param {object[]} blocks - Array of up to 32 block signature/hash pairs * @param {string} blocks.signature - 128-character hexadecimal block signature * @param {string} blocks.hash - 64-character hexadecimal block hash * @returns Array of results with, for each case, true if signature matches block hash and public key, else false diff --git a/src/lib/derive.ts b/src/lib/derive.ts index 28e28f6..6eed51e 100644 --- a/src/lib/derive.ts +++ b/src/lib/derive.ts @@ -1,23 +1,23 @@ //! SPDX-FileCopyrightText: 2026 Chris Duncan //! SPDX-License-Identifier: GPL-3.0-or-later -import { clear, exports, isBytes, KEY_LEN, normalize, OUT_PTR, PRV_PTR } from './wasm' +import { clear, exports, INPUT_PRV, isBytes, KEY_BYTELENGTH, normalize, OUTPUT_DERIVE } from './wasm' export function derive (prv: unknown, out?: unknown): string | Uint8Array | void { - if (typeof out !== 'undefined' && !(isBytes(out) && out.byteLength === KEY_LEN)) { + if (typeof out !== 'undefined' && !(isBytes(out) && out.byteLength === KEY_BYTELENGTH)) { throw new TypeError('Derive output buffer must be 32-byte Uint8Array') } - const privateKey = normalize('private key', KEY_LEN, KEY_LEN, prv) - const publicKey = new Uint8Array(KEY_LEN) + const privateKey = normalize('private key', KEY_BYTELENGTH, KEY_BYTELENGTH, prv) + const publicKey = new Uint8Array(KEY_BYTELENGTH) let buffer = new Uint8Array(exports.memory.buffer) try { - for (let i = 0; i < KEY_LEN; i++) { - buffer[PRV_PTR + i] = privateKey[i] + for (let i = 0; i < KEY_BYTELENGTH; i++) { + buffer[INPUT_PRV + i] = privateKey[i] } exports.derive() buffer = new Uint8Array(exports.memory.buffer) - for (let i = 0; i < KEY_LEN; i++) { - publicKey[i] = buffer[OUT_PTR + i] + for (let i = 0; i < KEY_BYTELENGTH; i++) { + publicKey[i] = buffer[OUTPUT_DERIVE + i] } if (typeof prv === 'string') { let hex = '' diff --git a/src/lib/sign.ts b/src/lib/sign.ts index c3c3361..402dea9 100644 --- a/src/lib/sign.ts +++ b/src/lib/sign.ts @@ -1,31 +1,31 @@ //! SPDX-FileCopyrightText: 2026 Chris Duncan //! SPDX-License-Identifier: GPL-3.0-or-later -import { clear, exports, isBytes, KEY_LEN, MSG_BUF_LEN, MSG_PTR, normalize, OUT_PTR, PRV_PTR, PUB_PTR, SIG_LEN } from './wasm' +import { clear, exports, INPUT_MSG, INPUT_PRV, INPUT_PUB, isBytes, KEY_BYTELENGTH, MAX_MESSAGE_BYTELENGTH, normalize, OUTPUT_SIGN, SIGNATURE_BYTELENGTH } from './wasm' export function sign (msg: unknown, prv: unknown, pub: unknown, out?: unknown): string | Uint8Array | void { if (typeof out !== 'undefined' && !(isBytes(out) && out.byteLength === 64)) { throw new TypeError('Sign output buffer must be 64-byte Uint8Array') } - const message = normalize('message', 0, MSG_BUF_LEN, msg) - const privateKey = normalize('private key', KEY_LEN, KEY_LEN, prv) - const publicKey = normalize('public key', KEY_LEN, KEY_LEN, pub) - const signature = new Uint8Array(SIG_LEN) + const message = normalize('message', 0, MAX_MESSAGE_BYTELENGTH, msg) + 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) try { for (let i = 0; i < message.byteLength; i++) { - buffer[MSG_PTR + i] = message[i] + buffer[INPUT_MSG + i] = message[i] } - for (let i = 0; i < KEY_LEN; i++) { - buffer[PRV_PTR + i] = privateKey[i] + for (let i = 0; i < KEY_BYTELENGTH; i++) { + buffer[INPUT_PRV + i] = privateKey[i] } - for (let i = 0; i < KEY_LEN; i++) { - buffer[PUB_PTR + i] = publicKey[i] + for (let i = 0; i < KEY_BYTELENGTH; i++) { + buffer[INPUT_PUB + i] = publicKey[i] } exports.sign(message.byteLength) buffer = new Uint8Array(exports.memory.buffer) - for (let i = 0; i < SIG_LEN; i++) { - signature[i] = buffer[OUT_PTR + i] + for (let i = 0; i < SIGNATURE_BYTELENGTH; i++) { + signature[i] = buffer[OUTPUT_SIGN + i] } if (typeof prv === 'string') { let hex = '' diff --git a/src/lib/verify.ts b/src/lib/verify.ts index e61efd7..f2e433c 100644 --- a/src/lib/verify.ts +++ b/src/lib/verify.ts @@ -1,26 +1,26 @@ //! SPDX-FileCopyrightText: 2026 Chris Duncan //! SPDX-License-Identifier: GPL-3.0-or-later -import { BLK_LEN, KEY_LEN, MSG_BUF_LEN, MSG_PTR, OUT_BUF_LEN, OUT_PTR, PUB_PTR, SIG_LEN, SIG_PTR, clear, exports, normalize } from './wasm' +import { BLOCKHASH_BYTELENGTH, INPUT_MSG, INPUT_PUB, INPUT_SIG, KEY_BYTELENGTH, MAX_MESSAGE_BYTELENGTH, MAX_VERIFY_BLOCKS, OUTPUT_VERIFY, SIGNATURE_BYTELENGTH, clear, exports, normalize } from './wasm' export function verify (sig: unknown, msg: unknown, pub: unknown): boolean { let buffer = new Uint8Array(exports.memory.buffer) try { - const message = normalize('message', 0, MSG_BUF_LEN, msg) - const publicKey = normalize('public key', KEY_LEN, KEY_LEN, pub) - const signature = normalize('signature', SIG_LEN, SIG_LEN, sig) + const message = normalize('message', 0, MAX_MESSAGE_BYTELENGTH, msg) + const publicKey = normalize('public key', KEY_BYTELENGTH, KEY_BYTELENGTH, pub) + const signature = normalize('signature', SIGNATURE_BYTELENGTH, SIGNATURE_BYTELENGTH, sig) for (let i = 0; i < message.byteLength; i++) { - buffer[MSG_PTR + i] = message[i] + buffer[INPUT_MSG + i] = message[i] } - for (let i = 0; i < KEY_LEN; i++) { - buffer[PUB_PTR + i] = publicKey[i] + for (let i = 0; i < KEY_BYTELENGTH; i++) { + buffer[INPUT_PUB + i] = publicKey[i] } - for (let i = 0; i < SIG_LEN; i++) { - buffer[SIG_PTR + i] = signature[i] + for (let i = 0; i < SIGNATURE_BYTELENGTH; i++) { + buffer[INPUT_SIG + i] = signature[i] } exports.verify(message.byteLength) buffer = new Uint8Array(exports.memory.buffer) - const verified = buffer[OUT_PTR] + const verified = buffer[OUTPUT_VERIFY] return verified === 0 } finally { clear(buffer) @@ -33,17 +33,17 @@ export function verify_blocks (pub: unknown, data: unknown): boolean[] { if (count < 1) { throw new RangeError('Must pass at least one block', { cause: data }) } - if (OUT_BUF_LEN < count) { - throw new RangeError(`Bulk Nano block verification must be no more than ${OUT_BUF_LEN} blocks`, { cause: count }) + if (MAX_VERIFY_BLOCKS < count) { + 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) try { - const publicKey = normalize('public key', KEY_LEN, KEY_LEN, pub) - for (let i = 0; i < KEY_LEN; i++) { - buffer[PUB_PTR + i] = publicKey[i] + const publicKey = normalize('public key', KEY_BYTELENGTH, KEY_BYTELENGTH, pub) + for (let i = 0; i < KEY_BYTELENGTH; i++) { + buffer[INPUT_PUB + i] = publicKey[i] } - for (let b = 0, p = MSG_PTR; b < count; b++) { + for (let b = 0, p = INPUT_MSG; b < count; b++) { const block = blocks[b] if (block == null || typeof block !== 'object') { throw new TypeError('Invalid block', { cause: block }) @@ -54,20 +54,20 @@ export function verify_blocks (pub: unknown, data: unknown): boolean[] { if (!('hash' in block)) { throw new TypeError('Block hash is required to verify', { cause: block }) } - const signature = normalize('signature', SIG_LEN, SIG_LEN, block.signature) - const hash = normalize('hash', BLK_LEN, BLK_LEN, block.hash) - for (let i = 0; i < SIG_LEN; i++) { + const signature = normalize('signature', SIGNATURE_BYTELENGTH, SIGNATURE_BYTELENGTH, block.signature) + const hash = normalize('hash', BLOCKHASH_BYTELENGTH, BLOCKHASH_BYTELENGTH, block.hash) + for (let i = 0; i < SIGNATURE_BYTELENGTH; i++) { buffer[p + i] = signature[i] } - p += SIG_LEN - for (let i = 0; i < BLK_LEN; i++) { + p += SIGNATURE_BYTELENGTH + for (let i = 0; i < BLOCKHASH_BYTELENGTH; i++) { buffer[p + i] = hash[i] } - p += BLK_LEN + p += BLOCKHASH_BYTELENGTH } exports.verify_blocks(blocks.length) for (let i = 0; i < count; i++) { - verified[i] = buffer[OUT_PTR + i] + verified[i] = buffer[OUTPUT_VERIFY + i] } return [...verified].map(v => v === 0) } finally { diff --git a/src/lib/wasm.ts b/src/lib/wasm.ts index 138a555..1bd81d3 100644 --- a/src/lib/wasm.ts +++ b/src/lib/wasm.ts @@ -10,19 +10,19 @@ type Exports = { sign: (mlen: number) => void verify: (mlen: number) => void verify_blocks: (count: number) => void - getMessagePointer: () => number - getOutputPointer: () => number - getPrivateKeyPointer: () => number - getPublicKeyPointer: () => number - getSignaturePointer: () => number + ptrInputMsg: () => number + ptrInputPrv: () => number + ptrInputPub: () => number + ptrInputSig: () => number + ptrOutputDerive: () => number + ptrOutputSign: () => number + ptrOutputVerify: () => number BLOCKHASH_BYTELENGTH: WebAssembly.Global KEY_BYTELENGTH: WebAssembly.Global + MAX_VERIFY_BLOCKS: WebAssembly.Global + MAX_MESSAGE_BYTELENGTH: WebAssembly.Global SIGNATURE_BYTELENGTH: WebAssembly.Global - MESSAGE_BUFFER_BYTELENGTH: WebAssembly.Global - OUTPUT_BUFFER_BYTELENGTH: WebAssembly.Global - PRV_BUFFER_BYTELENGTH: WebAssembly.Global - PUB_BUFFER_BYTELENGTH: WebAssembly.Global - SIGNATURE_BUFFER_BYTELENGTH: WebAssembly.Global + SIGNEDBLOCK_BYTELENGTH: WebAssembly.Global memory: WebAssembly.Memory } } @@ -54,28 +54,29 @@ export const { exports } = new WebAssembly.Instance(module, { } }) as Exports -export const BLK_LEN = exports.BLOCKHASH_BYTELENGTH.value -export const KEY_LEN = exports.KEY_BYTELENGTH.value -export const SIG_LEN = exports.SIGNATURE_BYTELENGTH.value +export const BLOCKHASH_BYTELENGTH = exports.BLOCKHASH_BYTELENGTH.value +export const KEY_BYTELENGTH = exports.KEY_BYTELENGTH.value +export const MAX_MESSAGE_BYTELENGTH = exports.MAX_MESSAGE_BYTELENGTH.value +export const MAX_VERIFY_BLOCKS = exports.MAX_VERIFY_BLOCKS.value +export const SIGNATURE_BYTELENGTH = exports.SIGNATURE_BYTELENGTH.value +export const SIGNEDBLOCK_BYTELENGTH = exports.SIGNEDBLOCK_BYTELENGTH.value -export const MSG_BUF_LEN = exports.MESSAGE_BUFFER_BYTELENGTH.value -export const OUT_BUF_LEN = exports.OUTPUT_BUFFER_BYTELENGTH.value -export const PRV_BUF_LEN = exports.PRV_BUFFER_BYTELENGTH.value -export const PUB_BUF_LEN = exports.PUB_BUFFER_BYTELENGTH.value -export const SIG_BUF_LEN = exports.SIGNATURE_BUFFER_BYTELENGTH.value - -export const MSG_PTR = exports.getMessagePointer() -export const OUT_PTR = exports.getOutputPointer() -export const PRV_PTR = exports.getPrivateKeyPointer() -export const PUB_PTR = exports.getPublicKeyPointer() -export const SIG_PTR = exports.getSignaturePointer() +export const INPUT_MSG = exports.ptrInputMsg() +export const INPUT_PRV = exports.ptrInputPrv() +export const INPUT_PUB = exports.ptrInputPub() +export const INPUT_SIG = exports.ptrInputSig() +export const OUTPUT_DERIVE = exports.ptrOutputDerive() +export const OUTPUT_SIGN = exports.ptrOutputSign() +export const OUTPUT_VERIFY = exports.ptrOutputVerify() export function clear (memory: Uint8Array): void { - memory.fill(0, MSG_PTR, MSG_PTR + MSG_BUF_LEN) - memory.fill(0, OUT_PTR, OUT_PTR + OUT_BUF_LEN) - memory.fill(0, PRV_PTR, PRV_PTR + KEY_LEN) - memory.fill(0, PUB_PTR, PUB_PTR + KEY_LEN) - memory.fill(0, SIG_PTR, SIG_PTR + SIG_LEN) + 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(0, OUTPUT_VERIFY, OUTPUT_VERIFY + MAX_VERIFY_BLOCKS) } export function isBytes (a: unknown): a is Uint8Array { diff --git a/test/index.html b/test/index.html index 87542cd..c74d091 100644 --- a/test/index.html +++ b/test/index.html @@ -380,7 +380,7 @@ SPDX-License-Identifier: GPL-3.0-or-later if (api === 'nano25519 with bulk block verification') { publicKey = derive(privateKey, 'nano25519') const blocks = [] - for (let i = 0; i < 341; i++) { + for (let i = 0; i < 32; i++) { blockHash = random() signature = sign(blockHash, privateKey, publicKey, 'nano25519') blocks[i] = { hash: blockHash, signature } @@ -391,7 +391,7 @@ SPDX-License-Identifier: GPL-3.0-or-later if (verified.some(v => v !== true)) { throw new Error(`invalid result\nsignature: ${signature}\nblock hash: ${blockHash}\npublic key: ${publicKey}`) } - duration = (end - start) / 341 + duration = (end - start) / 32 deriveTimes[i].push(0) signTimes[i].push(0) verifyTimes[i].push(duration) diff --git a/test/node.mjs b/test/node.mjs index 3f646bc..467c379 100644 --- a/test/node.mjs +++ b/test/node.mjs @@ -385,7 +385,7 @@ failures += +!test try { const blocks = [] - for (let i = 0; i < 341; i++) { + for (let i = 0; i < 32; i++) { blocks[i] = { hash: NANO_ORG_VECTOR.blockHashBytes, signature: NANO_ORG_VECTOR.signatureBytes } } const verified = verify_blocks(NANO_ORG_VECTOR.publicKeyBytes, blocks) @@ -395,7 +395,7 @@ try { result = false } test = result === true -check(`verify_blocks 341 max`, test) +check(`verify_blocks 32 max`, test) passes += +test failures += +!test @@ -420,14 +420,14 @@ failures += +!test try { const blocks = [] - for (let i = 0; i < 342; i++) { + for (let i = 0; i < 33; i++) { blocks[i] = { hash: NANO_ORG_VECTOR.blockHashBytes, signature: NANO_ORG_VECTOR.signatureBytes } } verify_blocks(NANO_ORG_VECTOR.publicKeyBytes, blocks) result = false } catch (err) { if (err != null && typeof err === 'object' && 'message' in err) { - result = err.message === 'Bulk Nano block verification must be no more than 341 blocks' + result = err.message === 'Bulk Nano block verification must be no more than 32 blocks' } else { result = false } -- 2.52.0