From 166478076d70e960d886842f7b1db4a1066046eb Mon Sep 17 00:00:00 2001 From: Alan Shaw Date: Tue, 9 May 2023 12:35:03 +0100 Subject: [PATCH] feat: disambiguate errors --- src/index.js | 19 +++++++++++++++++-- test/test.spec.js | 22 ++++++++++++++++++++-- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/index.js b/src/index.js index d8199e9..0b3740f 100644 --- a/src/index.js +++ b/src/index.js @@ -32,6 +32,21 @@ export const hashMap = new Map( ].map(hash => [hash.code, hash]) ) +/** The multihash hasher is not supported by this library. */ +export class UnsupportedHashError extends Error { + /** @param {number} code */ + constructor (code) { + super(`multihash code ${code} is not supported`) + } +} + +/** The bytes did not hash to the same value as the passed multihash. */ +export class HashMismatchError extends Error { + constructor () { + super('CID hash does not match bytes') + } +} + /** * Validates IPLD block bytes. * @param {Block} block @@ -39,7 +54,7 @@ export const hashMap = new Map( export function validateBlock (block) { const hasher = hashMap.get(block.cid.multihash.code) if (!hasher) { - throw new Error(`multihash code ${block.cid.multihash.code} is not supported`) + throw new UnsupportedHashError(block.cid.multihash.code) } const result = hasher.digest(block.bytes) @@ -47,7 +62,7 @@ export function validateBlock (block) { /** @param {import('multiformats/hashes/interface').MultihashDigest} h */ const compareDigests = h => { if (!equals(h.digest, block.cid.multihash.digest)) { - throw new Error('CID hash does not match bytes') + throw new HashMismatchError() } } diff --git a/test/test.spec.js b/test/test.spec.js index fc7766e..4058344 100644 --- a/test/test.spec.js +++ b/test/test.spec.js @@ -2,8 +2,9 @@ import test from 'ava' import * as pb from '@ipld/dag-pb' import { CID } from 'multiformats/cid' import { CarWriter, CarBlockIterator } from '@ipld/car' +import { blake2b512 } from '@multiformats/blake2/blake2b' -import { validateBlock, hashMap } from '../src/index.js' +import { validateBlock, hashMap, HashMismatchError, UnsupportedHashError } from '../src/index.js' const bytes = pb.encode({ Data: new Uint8Array([1, 2, 3]), Links: [] }) @@ -37,7 +38,24 @@ for (const [code, hasher] of hashMap) { const reader = await CarBlockIterator.fromIterable(out) for await (const block of reader) { - t.throwsAsync(async () => validateBlock(block)) + const err = await t.throwsAsync(async () => validateBlock(block)) + t.true(err instanceof HashMismatchError) } }) } + +test('throws when validating blocks with unsupported hashers', async (t) => { + const hash = await blake2b512.digest(bytes) + const cid = CID.create(1, pb.code, hash) + + const { writer, out } = CarWriter.create([cid]) + writer.put({ cid, bytes }) + writer.close() + + const reader = await CarBlockIterator.fromIterable(out) + + for await (const block of reader) { + const err = await t.throwsAsync(async () => validateBlock(block)) + t.true(err instanceof UnsupportedHashError) + } +})