]> git.codecow.com Git - nano25519.git/commitdiff
Split up error messaging for bulk block verification and add unit tests.
authorChris Duncan <chris@codecow.com>
Thu, 27 Aug 2026 04:13:31 +0000 (21:13 -0700)
committerChris Duncan <chris@codecow.com>
Thu, 27 Aug 2026 04:13:31 +0000 (21:13 -0700)
src/lib/verify.ts
test/node.mjs

index cc1984e468d9a1bf01d655a1b7ad9cb582b49cc4..356fee55924fa7e83cf4d6f7e39483b5bbac32dc 100644 (file)
@@ -34,7 +34,7 @@ export function verify_blocks (pub: unknown, data: unknown): boolean[] {
                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 256 blocks', { cause: data })
+               throw new RangeError('Bulk Nano block verification must be no more than 256 blocks', { cause: count })
        }
        const verified = new Uint8Array(count)
        let buffer = new Uint8Array(exports.memory.buffer)
@@ -45,8 +45,14 @@ export function verify_blocks (pub: unknown, data: unknown): boolean[] {
                }
                for (let b = 0, p = MSG_PTR; b < count; b++) {
                        const block = blocks[b]
-                       if (!(block != null && typeof block === 'object' && 'hash' in block && 'signature' in block)) {
-                               throw new TypeError('invalid block', { cause: block })
+                       if (block == null || typeof block !== 'object') {
+                               throw new TypeError('Invalid block', { cause: block })
+                       }
+                       if (!('hash' in block)) {
+                               throw new TypeError('Block hash is required to verify', { cause: block })
+                       }
+                       if (!('signature' in block)) {
+                               throw new TypeError('Block signature is required to verify', { cause: block })
                        }
                        const hash = normalize('hash', BLK_LEN, BLK_LEN, block.hash)
                        const signature = normalize('signature', SIG_LEN, SIG_LEN, block.signature)
index 0c9b9517c49611be9dcd86840cd1b1652914d170..d3ea7aaf42039a2b99d5cd2b9fb52a284f090d07 100644 (file)
@@ -1,7 +1,7 @@
 //! SPDX-FileCopyrightText: 2026 Chris Duncan <chris@codecow.com>
 //! SPDX-License-Identifier: GPL-3.0-or-later
 
-import { derive, sign, verify } from 'nano25519'
+import { derive, sign, verify, verify_blocks } from 'nano25519'
 import { NANO_ORG_VECTOR, PROBLEM_VECTOR, PYTHON_ED25519_BLAKE2B_VECTORS } from './vectors.mjs'
 
 /**
@@ -179,7 +179,6 @@ try {
        result = false
 } catch (err) {
        if (err != null && typeof err === 'object' && 'message' in err && typeof err.message === 'string') {
-               console.log(err.message.substring(0, 38))
                result = err.message.includes('Nano25519WasmError') && err.message.includes('Invalid public key')
        } else {
                result = false
@@ -372,6 +371,121 @@ for (const { privateKey, publicKey, message, signature } of PYTHON_ED25519_BLAKE
        failures += +!test
 }
 
+// Check bulk verification of Nano blocks
+try {
+       result = verify_blocks(NANO_ORG_VECTOR.publicKeyBytes, [{ hash: NANO_ORG_VECTOR.blockHashBytes, signature: NANO_ORG_VECTOR.signatureBytes }])[0]
+} catch (err) {
+       console.log(err)
+       result = false
+}
+test = result === true
+check(`verify_blocks single hash bytes ${NANO_ORG_VECTOR.blockHash} with signature bytes ${NANO_ORG_VECTOR.signature}`, test)
+passes += +test
+failures += +!test
+
+try {
+       const blocks = []
+       for (let i = 0; i < 256; i++) {
+               blocks[i] = { hash: NANO_ORG_VECTOR.blockHashBytes, signature: NANO_ORG_VECTOR.signatureBytes }
+       }
+       const verified = verify_blocks(NANO_ORG_VECTOR.publicKeyBytes, blocks)
+       result = verified.every(v => v === true)
+} catch (err) {
+       console.log(err)
+       result = false
+}
+test = result === true
+check(`verify_blocks 256 max`, test)
+passes += +test
+failures += +!test
+
+// Check min and max ranges of bulk verification
+try {
+       //@ts-expect-error
+       const blocks = []
+       //@ts-expect-error
+       verify_blocks(NANO_ORG_VECTOR.publicKeyBytes, blocks)
+       result = false
+} catch (err) {
+       if (err != null && typeof err === 'object' && 'message' in err) {
+               result = err.message === 'Must pass at least one block'
+       } else {
+               result = false
+       }
+}
+test = result === true
+check(`verify_blocks empty blocks`, test)
+passes += +test
+failures += +!test
+
+try {
+       const blocks = []
+       for (let i = 0; i < 257; 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 256 blocks'
+       } else {
+               result = false
+       }
+}
+test = result === true
+check(`verify_blocks too many blocks`, test)
+passes += +test
+failures += +!test
+
+// Check proper format of bulk block verification
+try {
+       //@ts-expect-error
+       verify_blocks(NANO_ORG_VECTOR.publicKeyBytes, [null])
+       result = false
+} catch (err) {
+       if (err != null && typeof err === 'object' && 'message' in err) {
+               result = err.message === 'Invalid block'
+       } else {
+               result = false
+       }
+}
+test = result === true
+check(`verify_blocks null block`, test)
+passes += +test
+failures += +!test
+
+try {
+       //@ts-expect-error
+       verify_blocks(NANO_ORG_VECTOR.publicKeyBytes, [{ signature: NANO_ORG_VECTOR.signatureBytes }])
+       result = false
+} catch (err) {
+       if (err != null && typeof err === 'object' && 'message' in err) {
+               result = err.message === 'Block hash is required to verify'
+       } else {
+               result = false
+       }
+}
+test = result === true
+check(`verify_blocks missing hash`, test)
+passes += +test
+failures += +!test
+
+try {
+       //@ts-expect-error
+       verify_blocks(NANO_ORG_VECTOR.publicKeyBytes, [{ hash: NANO_ORG_VECTOR.blockHashBytes }])
+       result = false
+} catch (err) {
+       if (err != null && typeof err === 'object' && 'message' in err) {
+               result = err.message === 'Block signature is required to verify'
+       } else {
+               result = false
+       }
+}
+test = result === true
+check(`verify_blocks missing signature`, test)
+passes += +test
+failures += +!test
+
 console.log(`${passes} \x1b[32mPASSED\x1b[0m`)
 console.log(`${failures} \x1b[31mFAILED\x1b[0m`)