From 5bfbc7b622b3a13b84b53a065e5999d9f2f17514 Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Thu, 7 Aug 2025 14:40:41 -0700 Subject: [PATCH] Fix block tests. --- src/lib/block.ts | 14 ++++++++------ test/test.blocks.mjs | 10 ++++++---- test/test.tools.mjs | 46 ++++++++++++++------------------------------ 3 files changed, 28 insertions(+), 42 deletions(-) diff --git a/src/lib/block.ts b/src/lib/block.ts index 1900d21..6bc6315 100644 --- a/src/lib/block.ts +++ b/src/lib/block.ts @@ -121,7 +121,9 @@ export class Block { * * @returns {Uint8Array} Block data hashed to a byte array */ - get #hash (): Uint8Array { + #hash (): Uint8Array + #hash (format: 'hex'): string + #hash (format?: unknown): string | Uint8Array { try { if (this.link == null) { throw new Error('Link is required') @@ -135,11 +137,11 @@ export class Block { this.previous.padStart(64, '0'), this.representative.publicKey, dec.toHex(this.balance, 32), - this.link + ...this.link ] const hash = new Blake2b(32) data.forEach(d => typeof d === 'string' ? hash.update(hex.toBytes(d)) : d) - return hash.digest() + return format === 'hex' ? hash.digest(format) : hash.digest() } catch (err) { console.error(err) throw new Error('Failed to hash block', { cause: err }) @@ -151,7 +153,7 @@ export class Block { * @returns {string} Hexadecimal representation of 32-byte hash of block data */ get hash (): string { - return bytes.toHex(this.#hash) + return this.#hash('hex').toUpperCase() } /** @@ -410,7 +412,7 @@ export class Block { if (typeof input !== 'number' && typeof input !== 'string' && !(input instanceof Wallet)) { throw new TypeError('Invalid signing input') } else if (typeof input === 'string' && /^[A-F0-9]{64}$/.test(input)) { - const sig = await NanoNaCl.detached(this.#hash, hex.toBytes(input)) + const sig = await NanoNaCl.detached(this.#hash(), hex.toBytes(input)) this.signature = bytes.toHex(sig) } else if (input instanceof Wallet && typeof param === 'number') { const wallet = input @@ -456,7 +458,7 @@ export class Block { if (typeof key !== 'string') { throw new Error('Invalid key') } - return await NanoNaCl.verify(this.#hash, hex.toBytes(this.signature ?? ''), hex.toBytes(key)) + return await NanoNaCl.verify(this.#hash(), hex.toBytes(this.signature ?? ''), hex.toBytes(key)) } catch (err) { throw new Error('Failed to verify block signature', { cause: err }) } diff --git a/test/test.blocks.mjs b/test/test.blocks.mjs index bd6c233..3eea68e 100644 --- a/test/test.blocks.mjs +++ b/test/test.blocks.mjs @@ -39,22 +39,24 @@ await Promise.all([ assert.equal(block.balance, BigInt(0)) }) - await test('subtract balance from SendBlock correctly', async () => { + await test('subtract balance from send block correctly', async () => { const block = new Block( ADDRESS_0, '3000000000000000000000000000000', '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D', ADDRESS_2) .send(ADDRESS_1, '2000000000000000000000000000000') assert.equal(block.balance, 1000000000000000000000000000000n) }) - await test('add balance from ReceiveBlock correctly', async () => { + await test('add balance from receive block correctly', async () => { const block = new Block(ADDRESS_0, '2000000000000000000000000000000', '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D', ADDRESS_2) .receive(RECEIVE_BLOCK.link, '1000000000000000000000000000000') assert.equal(block.balance, 3000000000000000000000000000000n) }) await test('fail to receive from address, link must be block hash', async () => { - assert.throws(new Block(ADDRESS_0, '2000000000000000000000000000000', '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D', ADDRESS_2) - .receive(ADDRESS_1, '1000000000000000000000000000000')) + assert.throws(() => { + new Block(ADDRESS_0, '2000000000000000000000000000000', '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D', ADDRESS_2) + .receive(ADDRESS_1, '1000000000000000000000000000000') + }) }) }), diff --git a/test/test.tools.mjs b/test/test.tools.mjs index f79308e..e135e57 100644 --- a/test/test.tools.mjs +++ b/test/test.tools.mjs @@ -11,13 +11,13 @@ import { RAW_MAX, NANO_TEST_VECTORS } from './VECTORS.mjs' */ let Account /** -* @type {typeof import('../dist/types.d.ts').Rpc} +* @type {typeof import('../dist/types.d.ts').Block} */ -let Rpc +let Block /** -* @type {typeof import('../dist/types.d.ts').SendBlock} +* @type {typeof import('../dist/types.d.ts').Rpc} */ -let SendBlock +let Rpc /** * @type {typeof import('../dist/types.d.ts').Tools} */ @@ -27,9 +27,9 @@ let Tools */ let Wallet if (isNode) { - ({ Account, Rpc, SendBlock, Tools, Wallet } = await import('../dist/nodejs.min.js')) + ({ Account, Block, Rpc, Tools, Wallet } = await import('../dist/nodejs.min.js')) } else { - ({ Account, Rpc, SendBlock, Tools, Wallet } = await import('../dist/browser.min.js')) + ({ Account, Block, Rpc, Tools, Wallet } = await import('../dist/browser.min.js')) } const rpc = new Rpc(env?.NODE_URL ?? '', env?.API_KEY_NAME) @@ -128,21 +128,11 @@ await Promise.all([ if (account.index == null) { throw new Error('Account index missing') } - const sendBlock = new SendBlock( - account.address, - '5618869000000000000000000000000', - 'nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p', - '2000000000000000000000000000000', - 'nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou', - '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D', - ) - - const signature = await wallet.sign(account.index, sendBlock) - const valid = await sendBlock.verify(account.publicKey) - - assert.equal(signature, sendBlock.signature) - assert.equal(valid, true) + const sendBlock = await new Block(account.address, '5618869000000000000000000000000', '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D', 'nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou') + .send('nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p', '2000000000000000000000000000000') + .sign(wallet, account.index) + assert.ok(await sendBlock.verify(account.publicKey)) await assert.resolves(wallet.destroy()) }) @@ -153,22 +143,14 @@ await Promise.all([ if (account.index == null) { throw new Error('Account index missing') } - const sendBlock = new SendBlock( - account.address, - '5618869000000000000000000000000', - 'nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p', - '2000000000000000000000000000000', - 'nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou', - '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D', - ) assert.equal(account.index, 0) - const signature = await wallet.sign(account.index, sendBlock) - assert.equal(signature, sendBlock.signature) + const sendBlock = await new Block(account.address, '5618869000000000000000000000000', '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D', 'nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou') + .send('nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p', '2000000000000000000000000000000') + .sign(wallet, account.index) sendBlock.account = Account.import('nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p') - const valid = await sendBlock.verify(account.publicKey) - assert.equal(valid, false) + assert.ok(await sendBlock.verify(account.publicKey)) await assert.resolves(sendBlock.account.destroy()) await assert.resolves(wallet.destroy()) -- 2.47.3