]> git.codecow.com Git - libnemo.git/commitdiff
Miscellaneous fixes.
authorChris Duncan <chris@codecow.com>
Sat, 8 Aug 2026 08:35:57 +0000 (01:35 -0700)
committerChris Duncan <chris@codecow.com>
Sat, 8 Aug 2026 08:35:57 +0000 (01:35 -0700)
src/index.ts
src/lib/block/index.ts
src/lib/rolodex.ts
src/lib/rpc/block_info.ts
src/lib/vault/index.ts
src/lib/wallet/unopened.ts

index 65b53e9ba7b4646d56410887d70ad5a85aa6435c..933036fd1b41552f504cb152ed0860ad9fdc33e5 100644 (file)
@@ -11,7 +11,7 @@ declare global {
 export { Account } from './lib/account'
 export { Block } from './lib/block'
 export { Blake2b } from './lib/crypto'
-export { VaultError } from './lib/errors'
+export * from './lib/errors'
 export { Ledger } from './lib/ledger'
 export { Rolodex } from './lib/rolodex'
 export { Rpc } from './lib/rpc'
index 9fa41148e631f17d659d90710ef904c129a120ae..afa614c13dd83d4d756b3efed6e0efebcb72e3e2 100644 (file)
@@ -3,8 +3,8 @@
 
 import { NanoPow } from 'nano-pow'
 import { Account } from '../account'
-import { DIFFICULTY_RECEIVE, DIFFICULTY_SEND, PREAMBLE } from '../constants'
-import { bytes, dec, hex } from '../convert'
+import { BURN_PUBLIC_KEY, DIFFICULTY_RECEIVE, DIFFICULTY_SEND, PREAMBLE } from '../constants'
+import { bytes, dec, hex, utf8 } from '../convert'
 import { Blake2b } from '../crypto'
 import { Rpc } from '../rpc'
 import { ProcessRequest } from '../rpc/process'
@@ -32,7 +32,7 @@ export class Block {
                _validate(block)
        }
 
-       subtype?: 'send' | 'receive' | 'change'
+       subtype?: 'change' | 'epoch' | 'receive' | 'send'
        account: Account
        balance: bigint
        previous: Bytes
@@ -72,7 +72,7 @@ export class Block {
                                throw new TypeError('Invalid account')
                        }
                        balance ??= account.balance
-                       previous ??= account.frontier ?? '00'
+                       previous ??= account.frontier ?? BURN_PUBLIC_KEY
                        representative ??= account.representative
                        if (typeof balance !== 'bigint' && typeof balance !== 'number' && typeof balance !== 'string') {
                                throw new TypeError('Account balance is unknown')
@@ -80,6 +80,9 @@ export class Block {
                        if (typeof previous !== 'string') {
                                throw new TypeError('Account frontier is unknown')
                        }
+                       if (!(/^[0-9A-F]{64}$/i.test(previous))) {
+                               throw new RangeError('Invalid frontier hash')
+                       }
                        this.account = account
                        this.balance = convert(balance, 'raw', 'raw', 'bigint')
                        this.previous = hex.toBytes(previous, 32)
@@ -169,6 +172,9 @@ export class Block {
         * @returns {Block} This block unchanged
         */
        epoch (): Block {
+               const special = utf8.toHex('epoch v2 block')
+               this.link = hex.toBytes(`${special}000000000000000000000000000000000000`)
+               this.subtype = 'epoch'
                return this
        }
 
@@ -182,8 +188,9 @@ export class Block {
         * @returns {Block} This block with balance, link, and subtype configured
        */
        open (sendBlock: string | Block, amount: bigint | number | string, unit?: string): Block {
-               this.previous.fill(0)
-               return _receive(this, sendBlock, amount, unit)
+               const openBlock = _receive(this, sendBlock, amount, unit)
+               openBlock.previous.fill(0)
+               return openBlock
        }
 
        /**
@@ -237,6 +244,9 @@ export class Block {
                if (this.subtype == null) {
                        throw new Error('Block is missing subtype. Call respective method and try again.')
                }
+               if (this.subtype === 'epoch') {
+                       throw new Error('Only change, receive, and send blocks can be processed.')
+               }
                if (this.work == null) await this.pow()
                const data: ProcessRequest = {
                        async: false,
index 9791ff5c6cd434ee0413b5858e33d4b96456ef74..a84998622f7877254135c041c48370a4845399c7 100644 (file)
@@ -53,7 +53,7 @@ export class Rolodex {
                        if (existingName === name) {
                                return true
                        }
-                       const data: { [address: string]: { id: string, name: string } } | { [name: string]: { id: string, addresses: string[] } } = {}
+                       const data: { [address: string]: { id: string, name: string } } | { [name: string]: { id: string, addresses: string[] } } = Object.create(null)
                        data[address] = {
                                id: address,
                                name
index 19320ba453af7667415786b847be5d8757115be9..5344c7f66d7605892dcca97228c697a642520b55 100644 (file)
@@ -48,11 +48,11 @@ export function block_info (body: unknown): BlockInfoResponse {
                        && 'contents' in body && body.contents != null && typeof body.contents === 'object'
                        && 'account' in body.contents && typeof body.contents.account === 'string'
                        && 'balance' in body.contents && typeof body.contents.balance === 'string'
-                       && 'link' in body.contents && typeof body.contents.link === 'string'
+                       && 'link' in body.contents && typeof body.contents.link === 'string' && /^[0-9A-F]{64}$/i.test(body.contents.link)
                        && 'link_as_account' in body.contents && typeof body.contents.link_as_account === 'string'
-                       && 'previous' in body.contents && typeof body.contents.previous === 'string'
+                       && 'previous' in body.contents && typeof body.contents.previous === 'string' && /^[0-9A-F]{64}$/i.test(body.contents.previous)
                        && 'representative' in body.contents && typeof body.contents.representative === 'string'
-                       && 'signature' in body.contents && typeof body.contents.signature === 'string'
+                       && 'signature' in body.contents && typeof body.contents.signature === 'string' && /^[0-9A-F]{128}$/i.test(body.contents.signature)
                        && 'type' in body.contents && body.contents.type === 'state'
                        && 'work' in body.contents && typeof body.contents.work === 'string'
                ) {
index a021204270f129c54874216cb3215c9c6be208fb..52811d6dc92cd178848a32e5ba21af1e1e6884a2 100644 (file)
@@ -128,7 +128,7 @@ export class Vault {
 
        #report (message: unknown): void {
                if (message == null || typeof message !== 'object') return
-               if (!('data' in message) || message.data == null || typeof message !== 'object') return
+               if (!('data' in message) || message.data == null || typeof message.data !== 'object') return
                const results = message.data as Record<string, unknown>
                const { taskUrl, taskId, error, isLocked } = results
                if (taskUrl === this.#url) {
index ab8fb8b9d2c409231d408dd4d6de9eecee0e731e..49beff1140693e2a82934aeafb8d8cc3331f04b3 100644 (file)
@@ -42,5 +42,5 @@ export async function _unopened (wallet: Wallet, rpc: unknown, batchSize: unknow
        if (to >= 0xffffffff) {
                throw new RangeError('Max index reached')
        }
-       return await _unopened(wallet, rpc, batchSize, to)
+       return await _unopened(wallet, rpc, batchSize, to + 1)
 }