From: Chris Duncan Date: Mon, 18 May 2026 13:55:13 +0000 (-0700) Subject: Extract entire signing function and use input-dependent functions internally. X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=458bd4d9004ffb1936dffc4cb8e62e124badd3dc;p=libnemo.git Extract entire signing function and use input-dependent functions internally. --- diff --git a/src/lib/ledger/index.ts b/src/lib/ledger/index.ts index 238fc18..7e8a8ad 100644 --- a/src/lib/ledger/index.ts +++ b/src/lib/ledger/index.ts @@ -12,12 +12,12 @@ import { Rpc } from '../rpc' import { Wallet } from '../wallet' import { _account } from './account' import { _cache } from './cache' -import { _connect } from './connect' -import { queue } from './queue' -import { signBlock, signNonce } from './sign' -import { _open } from './open' import { _close } from './close' +import { _connect } from './connect' import { _disconnect } from './disconnect' +import { _open } from './open' +import { queue } from './queue' +import { _sign } from './sign' export type LedgerStatus = 'UNSUPPORTED' | 'DISCONNECTED' | 'BUSY' | 'LOCKED' | 'CONNECTED' export type LedgerTransport = typeof TransportHID | typeof TransportBLE | typeof TransportUSB @@ -214,40 +214,7 @@ export class Ledger { */ static async sign (index: number, block: Block, frontier?: Block): Promise static async sign (index: number, data: string | Block, frontier?: Block): Promise { - try { - if (typeof index !== 'number') { - throw new TypeError('Index must be a number', { cause: index }) - } - if (index < 0 || index >= HARDENED_OFFSET) { - throw new RangeError(`Index outside allowed range 0-${HARDENED_OFFSET}`, { cause: index }) - } - if (typeof data !== 'string' && !(data instanceof Block)) { - throw new TypeError('Data to be signed must be a string nonce or a Block', { cause: data }) - } - if (frontier != null) { - const { status } = await _cache(this.#transport, index, frontier) - if (status !== 'OK') { - throw new Error('Failed to cache frontier block in ledger', { cause: status }) - } - } - console.log('Waiting for signature confirmation on Ledger device...') - const { status, signature, hash } = data instanceof Block - ? await signBlock(this.#transport, index, data) - : await signNonce(this.#transport, index, utf8.toBytes(data)) - if (status !== 'OK') { - throw new Error('Signing with ledger failed', { cause: status }) - } - if (data instanceof Block && hash !== data.hash) { - throw new Error('Hash from Ledger does not match hash from block', { cause: `${hash} | ${data.hash}` }) - } - if (signature == null) { - throw new Error('Ledger silently failed to return signature') - } - return signature - } catch (err) { - console.error('Ledger.sign()', err) - throw new Error('Failed to sign block with Ledger', { cause: err }) - } + return queue(async () => _sign(this.#transport, index, data, frontier)) } /** diff --git a/src/lib/ledger/sign.ts b/src/lib/ledger/sign.ts index a520822..f10ec9c 100644 --- a/src/lib/ledger/sign.ts +++ b/src/lib/ledger/sign.ts @@ -5,9 +5,47 @@ import { APDU_CODES, DERIVATION_PATH, LedgerSignResponse, LedgerTransport, STATU import { Account } from '../account' import { Block } from '../block' import { HARDENED_OFFSET } from '../constants' -import { bytes, dec, hex } from '../convert' +import { bytes, dec, hex, utf8 } from '../convert' +import { _cache } from './cache' import { queue } from './queue' +export async function _sign (transport: LedgerTransport, index: number, data: string | Block, frontier?: Block): Promise { + try { + if (typeof index !== 'number') { + throw new TypeError('Index must be a number', { cause: index }) + } + if (index < 0 || index >= HARDENED_OFFSET) { + throw new RangeError(`Index outside allowed range 0-${HARDENED_OFFSET}`, { cause: index }) + } + if (typeof data !== 'string' && !(data instanceof Block)) { + throw new TypeError('Data to be signed must be a string nonce or a Block', { cause: data }) + } + if (frontier != null) { + const { status } = await _cache(transport, index, frontier) + if (status !== 'OK') { + throw new Error('Failed to cache frontier block in ledger', { cause: status }) + } + } + console.log('Waiting for signature confirmation on Ledger device...') + const { status, signature, hash } = data instanceof Block + ? await signBlock(transport, index, data) + : await signNonce(transport, index, utf8.toBytes(data)) + if (status !== 'OK') { + throw new Error('Signing with ledger failed', { cause: status }) + } + if (data instanceof Block && hash !== data.hash) { + throw new Error('Hash from Ledger does not match hash from block', { cause: `${hash} | ${data.hash}` }) + } + if (signature == null) { + throw new Error('Ledger silently failed to return signature') + } + return signature + } catch (err) { + console.error('Ledger.sign()', err) + throw new Error('Failed to sign block with Ledger', { cause: err }) + } +} + /** * Sign a block with the Ledger device. * @@ -15,7 +53,7 @@ import { queue } from './queue' * @param {object} block - Block data to sign * @returns {Promise} Status, signature, and block hash */ -export async function signBlock (transport: LedgerTransport, index: number, block: Block): Promise { +async function signBlock (transport: LedgerTransport, index: number, block: Block): Promise { if (block.signature !== undefined) { throw new TypeError('Block signature already exists', { cause: block.signature }) } @@ -71,7 +109,7 @@ export async function signBlock (transport: LedgerTransport, index: number, bloc * @param {Uint8Array} nonce - 128-bit value to sign * @returns {Promise} Status and signature */ -export async function signNonce (transport: LedgerTransport, index: number, nonce: Uint8Array): Promise { +async function signNonce (transport: LedgerTransport, index: number, nonce: Uint8Array): Promise { return queue(async () => { if (typeof index !== 'number' || index < 0 || index >= HARDENED_OFFSET) { throw new TypeError('Invalid account index')