From 68f3685243b2575552986a77d29c78e4e809cd0e Mon Sep 17 00:00:00 2001 From: Volker Mische Date: Sun, 21 Apr 2019 23:37:25 +0200 Subject: [PATCH] feat: new IPLD Format API BREAKING CHANGE: The API is now async/await based There are numerous changes, the most significant one is that the API is no longer callback based, but it using async/await. For the full new API please see the [IPLD Formats spec]. [IPLD Formats spec]: https://github.com/ipld/interface-ipld-format --- README.md | 8 +- package.json | 5 +- src/index.js | 2 + src/resolver.js | 159 +++++++++--------------------- src/util.js | 130 ++++++++++++------------- test/mod.spec.js | 20 ++++ test/resolver.spec.js | 219 ++++++++++++++++-------------------------- test/util.spec.js | 150 ++++++++++------------------- 8 files changed, 261 insertions(+), 432 deletions(-) create mode 100644 test/mod.spec.js diff --git a/README.md b/README.md index 2ed888f..998729d 100644 --- a/README.md +++ b/README.md @@ -70,12 +70,8 @@ Though it can also be used as a standalone module: const IpldZcash = require('ipld-zcash') // `zcashBlock` is some binary Zcash block -IpldZcash.util.deserialize(zcashBlock, (err, dagNode) => { - if (err) { - throw err - } - console.log(dagNode) -}) +const dagNode = IpldZcash.util.deserialize(zcashBlock) +console.log(dagNode) ``` ## Contribute diff --git a/package.json b/package.json index 85b0e4f..a4a816c 100644 --- a/package.json +++ b/package.json @@ -33,15 +33,16 @@ }, "homepage": "https://github.com/ipld/js-ipld-zcash#readme", "dependencies": { - "async": "^2.6.1", "cids": "~0.6.0", + "multicodec": "~0.5.1", "multihashes": "~0.4.12", - "multihashing-async": "~0.6.0", + "multihashing-async": "~0.7.0", "zcash-bitcore-lib": "~0.13.20-rc3" }, "devDependencies": { "aegir": "^18.2.0", "chai": "^4.1.2", + "chai-as-promised": "^7.1.1", "dirty-chai": "^2.0.1" }, "contributors": [ diff --git a/src/index.js b/src/index.js index 512e24a..1950bd0 100644 --- a/src/index.js +++ b/src/index.js @@ -2,3 +2,5 @@ exports.resolver = require('./resolver.js') exports.util = require('./util.js') +exports.codec = exports.util.codec +exports.defaultHashAlg = exports.util.defaultHashAlg diff --git a/src/resolver.js b/src/resolver.js index f4fe885..7c3b0b0 100644 --- a/src/resolver.js +++ b/src/resolver.js @@ -1,143 +1,70 @@ 'use strict' +const CID = require('cids') + const util = require('./util') /** - * @callback ResolveCallback - * @param {?Error} error - Error if path can't be resolved - * @param {Object} result - Result of the path it it was resolved successfully - * @param {*} result.value - Value the path resolves to - * @param {string} result.remainderPath - If the path resolves half-way to a - * link, then the `remainderPath` is the part after the link that can be used - * for further resolving. - */ -/** - * Resolves a path in a Zcash block. + * Resolves a path within a Zcash block. * * Returns the value or a link and the partial mising path. This way the * IPLD Resolver can fetch the link and continue to resolve. * * @param {Buffer} binaryBlob - Binary representation of a Zcash block * @param {string} [path='/'] - Path that should be resolved - * @param {ResolveCallback} callback - Callback that handles the return value - * @returns {void} + * @returns {Object} result - Result of the path it it was resolved successfully + * @returns {*} result.value - Value the path resolves to + * @returns {string} result.remainderPath - If the path resolves half-way to a + * link, then the `remainderPath` is the part after the link that can be used + * for further resolving */ -const resolve = (binaryBlob, path, callback) => { - if (typeof path === 'function') { - callback = path - path = undefined - } +exports.resolve = (binaryBlob, path) => { + let node = util.deserialize(binaryBlob) - util.deserialize(binaryBlob, (err, dagNode) => { - if (err) { - return callback(err) + const parts = path.split('/').filter(Boolean) + while (parts.length) { + const key = parts.shift() + if (node[key] === undefined) { + throw new Error(`Object has no property '${key}'`) } - // Return the deserialized block if no path is given - if (!path) { - return callback(null, { - value: dagNode, - remainderPath: '' - }) + node = node[key] + if (CID.isCID(node)) { + return { + value: node, + remainderPath: parts.join('/') + } } + } - const pathArray = path.split('/') - const value = resolveField(dagNode, pathArray[0]) - if (value === null) { - return callback(new Error('No such path'), null) - } + return { + value: node, + remainderPath: '' + } +} - let remainderPath = pathArray.slice(1).join('/') - // It is a link, hence it may have a remainder - if (value['/'] !== undefined) { - return callback(null, { - value: value, - remainderPath: remainderPath - }) - } else { - if (remainderPath.length > 0) { - return callback(new Error('No such path'), null) - } else { - return callback(null, { - value: value, - remainderPath: '' - }) - } - } - }) +const traverse = function * (node, path) { + // Traverse only objects and arrays + if (Buffer.isBuffer(node) || CID.isCID(node) || typeof node === 'string' || + node === null) { + return + } + for (const item of Object.keys(node)) { + const nextpath = path === undefined ? item : path + '/' + item + yield nextpath + yield * traverse(node[item], nextpath) + } } -/** - * @callback TreeCallback - * @param {?Error} error - Error if paths can't be retreived - * @param {string[] | Object.[]} result - The result depends on - * `options.values`, whether it returns only the paths, or the paths with - * the corresponding values - */ /** * Return all available paths of a block. * + * @generator * @param {Buffer} binaryBlob - Binary representation of a Zcash block - * @param {Object} [options] - Possible options - * @param {boolean} [options.values=false] - Retun only the paths by default. - * If it is `true` also return the values - * @param {TreeCallback} callback - Callback that handles the return value - * @returns {void} + * @yields {string} - A single path */ -const tree = (binaryBlob, options, callback) => { - if (typeof options === 'function') { - callback = options - options = undefined - } - options = options || {} - - util.deserialize(binaryBlob, (err, dagNode) => { - if (err) { - return callback(err) - } - - const paths = ['version', 'timestamp', 'difficulty', 'nonce', - 'solution', 'reserved', 'parent', 'tx'] - - if (options.values === true) { - const pathValues = {} - for (let path of paths) { - pathValues[path] = resolveField(dagNode, path) - } - return callback(null, pathValues) - } else { - return callback(null, paths) - } - }) -} - -// Return top-level fields. Returns `null` if field doesn't exist -const resolveField = (header, field) => { - switch (field) { - case 'version': - return header.version - case 'timestamp': - return header.time - case 'difficulty': - return header.bits - case 'nonce': - return header.nonce - case 'solution': - return header.solution - case 'reserved': - return header.reserved - case 'parent': - return { '/': util.hashToCid(header.prevHash) } - case 'tx': - return { '/': util.hashToCid(header.merkleRoot) } - default: - return null - } -} +exports.tree = function * (binaryBlob) { + const node = util.deserialize(binaryBlob) -module.exports = { - multicodec: 'zcash-block', - defaultHashAlg: 'dbl-sha2-256', - resolve: resolve, - tree: tree + yield * traverse(node) } diff --git a/src/util.js b/src/util.js index dc2a219..40eed0c 100644 --- a/src/util.js +++ b/src/util.js @@ -2,104 +2,94 @@ const ZcashBitcoreBlockHeader = require('zcash-bitcore-lib').BlockHeader const CID = require('cids') +const multicodec = require('multicodec') const multihashes = require('multihashes') const multihashing = require('multihashing-async') -const waterfall = require('async/waterfall') const ZCASH_BLOCK_HEADER_SIZE = 1487 +const CODEC = multicodec.ZCASH_BLOCK +const DEFAULT_HASH_ALG = multicodec.DBL_SHA2_256 -/** - * @callback SerializeCallback - * @param {?Error} error - Error if serialization failed - * @param {?Buffer} binaryBlob - Binary Zcash block if serialization was - * successful - */ /** * Serialize internal representation into a binary Zcash block. * * @param {ZcashBlock} dagNode - Internal representation of a Zcash block - * @param {SerializeCallback} callback - Callback that handles the - * return value - * @returns {void} + * @returns {Buffer} */ -const serialize = (dagNode, callback) => { - let err = null - let binaryBlob - try { - binaryBlob = dagNode.toBuffer() - } catch (serializeError) { - err = serializeError - } finally { - callback(err, binaryBlob) - } +const serialize = (dagNode) => { + return dagNode.toBuffer() } /** - * @callback DeserializeCallback - * @param {?Error} error - Error if deserialization failed - * @param {?ZcashBlock} dagNode - Internal representation of a Zcash block - * if deserialization was successful - */ -/** - * Deserialize Zcash block into the internal representation, + * Deserialize Zcash block into the internal representation. * * @param {Buffer} binaryBlob - Binary representation of a Zcash block - * @param {DeserializeCallback} callback - Callback that handles the - * return value - * @returns {void} + * @returns {ZcashBlock} */ -const deserialize = (binaryBlob, callback) => { +const deserialize = (binaryBlob) => { if (binaryBlob.length !== ZCASH_BLOCK_HEADER_SIZE) { - const err = new Error( + throw new Error( `Zcash block header needs to be ${ZCASH_BLOCK_HEADER_SIZE} bytes`) - return callback(err) } - const dagNode = ZcashBitcoreBlockHeader.fromBuffer(binaryBlob) - callback(null, dagNode) + const deserialized = ZcashBitcoreBlockHeader.fromBuffer(binaryBlob) + + const getters = { + difficulty: function () { + return this.bits + }, + parent: function () { + return hashToCid(this.prevHash) + }, + tx: function () { + return hashToCid(this.merkleRoot) + } + } + Object.entries(getters).forEach(([name, fun]) => { + Object.defineProperty(deserialized, name, { + enumerable: true, + get: fun + }) + }) + + const removeEnumberables = [ + 'bits', + 'merkleRoot', + 'prevHash', + 'time' + ] + removeEnumberables.forEach((field) => { + if (field in deserialized) { + Object.defineProperty(deserialized, field, { enumerable: false }) + } + }) + + return deserialized } /** - * @callback CidCallback - * @param {?Error} error - Error if getting the CID failed - * @param {?CID} cid - CID if call was successful - */ -/** - * Get the CID of the DAG-Node. + * Calculate the CID of the binary blob. * - * @param {ZcashBlock} dagNode - Internal representation of a Zcash block - * @param {Object} [options] - Options to create the CID - * @param {number} [options.version=1] - CID version number - * @param {string} [options.hashAlg='dbl-sha2-256'] - Hashing algorithm - * @param {CidCallback} callback - Callback that handles the return value - * @returns {void} + * @param {Object} binaryBlob - Encoded IPLD Node + * @param {Object} [userOptions] - Options to create the CID + * @param {number} [userOptions.cidVersion=1] - CID version number + * @param {string} [UserOptions.hashAlg] - Defaults to the defaultHashAlg of the format + * @returns {Promise.} */ -const cid = (dagNode, options, callback) => { - if (typeof options === 'function') { - callback = options - options = {} - } - options = options || {} - // avoid deadly embrace between resolver and util - const hashAlg = options.hashAlg || require('./resolver').defaultHashAlg - const version = typeof options.version === 'undefined' ? 1 : options.version - waterfall([ - (cb) => { - try { - multihashing(dagNode.toBuffer(), hashAlg, cb) - } catch (err) { - cb(err) - } - }, - (mh, cb) => cb(null, new CID(version, 'zcash-block', mh)) - ], callback) +const cid = async (binaryBlob, userOptions) => { + const defaultOptions = { cidVersion: 1, hashAlg: DEFAULT_HASH_ALG } + const options = Object.assign(defaultOptions, userOptions) + + const multihash = await multihashing(binaryBlob, options.hashAlg) + const codecName = multicodec.print[CODEC] + const cid = new CID(options.cidVersion, codecName, multihash) + + return cid } // Convert a Zcash hash (as Buffer) to a CID const hashToCid = (hash) => { - // avoid deadly embrace between resolver and util - const defaultHashAlg = require('./resolver').defaultHashAlg - const multihash = multihashes.encode(hash, defaultHashAlg) + const multihash = multihashes.encode(hash, DEFAULT_HASH_ALG) const cidVersion = 1 const cid = new CID(cidVersion, 'zcash-block', multihash) return cid @@ -108,6 +98,8 @@ const hashToCid = (hash) => { module.exports = { hashToCid: hashToCid, ZCASH_BLOCK_HEADER_SIZE: ZCASH_BLOCK_HEADER_SIZE, + codec: CODEC, + defaultHashAlg: DEFAULT_HASH_ALG, // Public API cid: cid, diff --git a/test/mod.spec.js b/test/mod.spec.js new file mode 100644 index 0000000..34c3790 --- /dev/null +++ b/test/mod.spec.js @@ -0,0 +1,20 @@ +/* eslint-env mocha */ +'use strict' + +const chai = require('chai') +const dirtyChai = require('dirty-chai') +const expect = chai.expect +chai.use(dirtyChai) +const multicodec = require('multicodec') + +const mod = require('../src') + +describe('IPLD Format', () => { + it('codec is zcash-block', () => { + expect(mod.codec).to.equal(multicodec.ZCASH_BLOCK) + }) + + it('defaultHashAlg is dbl-sha2-256', () => { + expect(mod.defaultHashAlg).to.equal(multicodec.DBL_SHA2_256) + }) +}) diff --git a/test/resolver.spec.js b/test/resolver.spec.js index 24fd007..f4d76cc 100644 --- a/test/resolver.spec.js +++ b/test/resolver.spec.js @@ -14,185 +14,128 @@ const fixtureBlockHex = loadFixture('test/fixtures/block.hex') const fixtureBlockHeader = helpers.headerFromHexBlock(fixtureBlockHex) const invalidBlock = Buffer.from('abcdef', 'hex') -describe('IPLD format resolver API resolve()', () => { - it('should return the deserialized node if no path is given', (done) => { - IpldZcash.resolver.resolve(fixtureBlockHeader, (err, value) => { - expect(err).to.not.exist() - expect(value.remainderPath).is.empty() - expect(value.value).is.not.empty() - done() - }) - }) - - it('should return the deserialized node if path is empty', (done) => { - IpldZcash.resolver.resolve(fixtureBlockHeader, '', (err, value) => { - expect(err).to.not.exist() - expect(value.remainderPath).is.empty() - expect(value.value).is.not.empty() - done() - }) +describe('IPLD format resolve API resolve()', () => { + it('should return the deserialized node if path is empty', () => { + const value = IpldZcash.resolver.resolve(fixtureBlockHeader, '') + expect(value.remainderPath).is.empty() + expect(value.value).is.not.empty() }) - it('should return the version', (done) => { - verifyPath(fixtureBlockHeader, 'version', 4, done) + it('should return the version', () => { + verifyPath(fixtureBlockHeader, 'version', 4) }) - it('should return the timestamp', (done) => { - verifyPath(fixtureBlockHeader, 'timestamp', 1481233847, done) + it('should return the timestamp', () => { + verifyPath(fixtureBlockHeader, 'timestamp', 1481233847) }) - it('should return the difficulty', (done) => { - verifyPath(fixtureBlockHeader, 'difficulty', 477875354, done) + it('should return the difficulty', () => { + verifyPath(fixtureBlockHeader, 'difficulty', 477875354) }) - it('should return the nonce', (done) => { + it('should return the nonce', () => { verifyPath( fixtureBlockHeader, 'nonce', - Buffer.from('8200000000000000d548af969ea8dceedb6bfad4000000000000000000000000', 'hex'), - done) + Buffer.from('8200000000000000d548af969ea8dceedb6bfad4000000000000000000000000', 'hex') + ) }) - it('should return the solution', (done) => { + it('should return the solution', () => { verifyPath( fixtureBlockHeader, 'solution', - Buffer.from('005836fdbc8a7a7d9cbec4f059ba17f62d0e775b19035c8e18f123d3a99f270118325eaac526ae7a68d60c9c8c5acdc3e71e987020cb55ad92e0c37af0ab200d3a19e366389bdfe53cd79f70dbc4a67ea6fdc3700f25e0b1d49cee31a54ba8cf826b34c2561c97a0c239e2872c74a33c41690a44e0de741283d60dbfb738152a90d84b1b8f4dce36c3323d35275e8c43f464e9401b757a85392335fdba2432eda2b225b9549faee001d0ebadf24c106f353a02788c386a2f6bce7d83422e8d3ba8ff5cdd85429484a67c76ce31bfacf968621f0b72d9334dfee6b430d2a811f7954548b419fb9428b6d9a09e1317774ebb628d4dd8f334fbe4fb80200f226af20f1cd089849c6207c9d87869baba2e473b0f6b07e68ada56955322d31879c5653a1a84df97a5180e0655fa8da912d5b09396dc601db16143ac00525a9f16b087b64e4fb6567822f1ed84ba723ffde6ca00f29446a54ce34ad03030e6dd55a992817ede9038436793fa72b7133fcded9443d2340b7dcfb45b02230121c5d0d2958cff63a5633db92b61ed9524f74d230a5429c76a02e12f096e611cc978893683429f89cf03a52533039ae3b7c092589aa9f60cb67b19d5849533c254986a614909ee5765097935f7b162842c09d315526f5f3d77c817eff16204fbe6c949b44e1ac1052482774279e76377431123a189d6716ddff6157c6708985f8f01277d67871e915adcc83119440c8cf6e121911b6d748a4c4b15537273379965ecb0bd89862936cfd7a45d9138b93e564596de4ae5099a371f8cf95f692dffe46523ad5bb0482891df72eac651b9c42f191841e3ad68b0459619367f0341523a03a61ecda6694a7dbcaf1f6d9d11c8c6f132fda2beca91f84cd01d78e2854b5aac4ad7219bff38f94e131e065a48961e6e5468690d0122c832f3ee5570fbed1547d91bc202151d3757d432f1edc793c5f37cf6bd34a9af42970ccb01ae1696ba75067c743b58b9ca4e81e1d7a69203c3b62609150effaab450dd4a0b20d68a31be560808c097f046924acd6e9fc18e3f5d28e698d658a96b06821737a511616bdcb4237c5d3dedd56e53d758bb2d695f52ee58cb49bff3563d38c30411c22e7393b61797d79755a4ea5f9b1232283e4b802100199633b03277e398f70f3e0ef8e7a4b7bf396aba1d55f53a2e03ef089c6720dc456715b08bb94f754d211037c15e0b2078d6226a7a31f4e8f19d885adae07244132dcf0605873a19d4dbef5a03f425975e796956827d6d66072675d10ac87a02db325559bdc9643a32a0beb93723fc3fdbb218b5c2c9d3c2ca9dec65392e1a0fbe0732e66547335f69ab4b81064a4d3fb9830d0e3c547e2a6a554f22928e8762e8941f6f5f5cc509319fb85a2cbf0e433be5a225f94c693bb0691a8ecdba58f71104e12f7cc056a10ae17856e059fb126ea1a5fa43a40f4367901212a3decbea31e0756c37587ff4fdd0271825aa48e0105f8af667977a823fe051dfaa1fb4014f50d6222fed9ccd8787c77563d83e3e52435cf19806c662596988442b39f2611fc80a8ee561bc3f944320b3f7ebaae1fc592e7a823c0967ceedf898b6f805224a3353f92121fb22fb16dbdc41cc066c1f5efaa42945ad4b6326fe73e4b3b34371c64871a99d97bec407ec53b9b01a332ada7a81f8f5f576aedd96b7ec0f51f9977c2ca8c40fbd66779a4743db1622619d23940c59f72b055674bd9ab331a20db20bbcdef4d8184929b1b6bcfc5f155ff0d263e37145f5c98cde541dda165943dec7a56deb81b8f1bd279acfcc8e16e9a968263f8d5c8793e7311a4fe2d114c9d601bf315df05317c0ad89c34e363af79ca4f0c6618f0da51cb8930f2d525779a64f3b657ff0e8b1106ce4f63f775b4cf6', 'hex'), - done) + Buffer.from('005836fdbc8a7a7d9cbec4f059ba17f62d0e775b19035c8e18f123d3a99f270118325eaac526ae7a68d60c9c8c5acdc3e71e987020cb55ad92e0c37af0ab200d3a19e366389bdfe53cd79f70dbc4a67ea6fdc3700f25e0b1d49cee31a54ba8cf826b34c2561c97a0c239e2872c74a33c41690a44e0de741283d60dbfb738152a90d84b1b8f4dce36c3323d35275e8c43f464e9401b757a85392335fdba2432eda2b225b9549faee001d0ebadf24c106f353a02788c386a2f6bce7d83422e8d3ba8ff5cdd85429484a67c76ce31bfacf968621f0b72d9334dfee6b430d2a811f7954548b419fb9428b6d9a09e1317774ebb628d4dd8f334fbe4fb80200f226af20f1cd089849c6207c9d87869baba2e473b0f6b07e68ada56955322d31879c5653a1a84df97a5180e0655fa8da912d5b09396dc601db16143ac00525a9f16b087b64e4fb6567822f1ed84ba723ffde6ca00f29446a54ce34ad03030e6dd55a992817ede9038436793fa72b7133fcded9443d2340b7dcfb45b02230121c5d0d2958cff63a5633db92b61ed9524f74d230a5429c76a02e12f096e611cc978893683429f89cf03a52533039ae3b7c092589aa9f60cb67b19d5849533c254986a614909ee5765097935f7b162842c09d315526f5f3d77c817eff16204fbe6c949b44e1ac1052482774279e76377431123a189d6716ddff6157c6708985f8f01277d67871e915adcc83119440c8cf6e121911b6d748a4c4b15537273379965ecb0bd89862936cfd7a45d9138b93e564596de4ae5099a371f8cf95f692dffe46523ad5bb0482891df72eac651b9c42f191841e3ad68b0459619367f0341523a03a61ecda6694a7dbcaf1f6d9d11c8c6f132fda2beca91f84cd01d78e2854b5aac4ad7219bff38f94e131e065a48961e6e5468690d0122c832f3ee5570fbed1547d91bc202151d3757d432f1edc793c5f37cf6bd34a9af42970ccb01ae1696ba75067c743b58b9ca4e81e1d7a69203c3b62609150effaab450dd4a0b20d68a31be560808c097f046924acd6e9fc18e3f5d28e698d658a96b06821737a511616bdcb4237c5d3dedd56e53d758bb2d695f52ee58cb49bff3563d38c30411c22e7393b61797d79755a4ea5f9b1232283e4b802100199633b03277e398f70f3e0ef8e7a4b7bf396aba1d55f53a2e03ef089c6720dc456715b08bb94f754d211037c15e0b2078d6226a7a31f4e8f19d885adae07244132dcf0605873a19d4dbef5a03f425975e796956827d6d66072675d10ac87a02db325559bdc9643a32a0beb93723fc3fdbb218b5c2c9d3c2ca9dec65392e1a0fbe0732e66547335f69ab4b81064a4d3fb9830d0e3c547e2a6a554f22928e8762e8941f6f5f5cc509319fb85a2cbf0e433be5a225f94c693bb0691a8ecdba58f71104e12f7cc056a10ae17856e059fb126ea1a5fa43a40f4367901212a3decbea31e0756c37587ff4fdd0271825aa48e0105f8af667977a823fe051dfaa1fb4014f50d6222fed9ccd8787c77563d83e3e52435cf19806c662596988442b39f2611fc80a8ee561bc3f944320b3f7ebaae1fc592e7a823c0967ceedf898b6f805224a3353f92121fb22fb16dbdc41cc066c1f5efaa42945ad4b6326fe73e4b3b34371c64871a99d97bec407ec53b9b01a332ada7a81f8f5f576aedd96b7ec0f51f9977c2ca8c40fbd66779a4743db1622619d23940c59f72b055674bd9ab331a20db20bbcdef4d8184929b1b6bcfc5f155ff0d263e37145f5c98cde541dda165943dec7a56deb81b8f1bd279acfcc8e16e9a968263f8d5c8793e7311a4fe2d114c9d601bf315df05317c0ad89c34e363af79ca4f0c6618f0da51cb8930f2d525779a64f3b657ff0e8b1106ce4f63f775b4cf6', 'hex') + ) }) - it('should return the reserved', (done) => { + it('should return the reserved', () => { verifyPath( fixtureBlockHeader, 'reserved', - Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex'), - done) + Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex') + ) }) - it('should error on non-existent path', (done) => { - verifyError(fixtureBlockHeader, 'something/random', done) + it('should error on non-existent path', () => { + verifyError( + fixtureBlockHeader, + 'something/random', + "Object has no property 'something'" + ) }) - it('should error on path starting with a slash', (done) => { - verifyError(fixtureBlockHeader, '/version', done) + it('should error on partially matching path that isn\'t a link', () => { + verifyError( + fixtureBlockHeader, + 'version/but/additional/things', + "Object has no property 'but'" + ) }) - it('should error on partially matching path that isn\'t a link', (done) => { - verifyError(fixtureBlockHeader, 'version/but/additional/things', done) + it('should return a link when parent is requested', () => { + const value = IpldZcash.resolver.resolve( + fixtureBlockHeader, 'parent') + expect(value.remainderPath).is.empty() + expect(value.value.equals( + new CID('z4QJh987XTweMqSLmNakYhbReGF55QBJY1P3WqgSYKsfWuwCvHM') + )).to.be.true() }) - it('should return a link when parent is requested', (done) => { - IpldZcash.resolver.resolve(fixtureBlockHeader, 'parent', (err, value) => { - expect(err).to.not.exist() - expect(value.remainderPath).is.empty() - expect(value.value).to.deep.equal({ - '/': new CID('z4QJh987XTweMqSLmNakYhbReGF55QBJY1P3WqgSYKsfWuwCvHM') - }) - done() - }) + it('should return a link and remaining path when parent is requested', () => { + const value = IpldZcash.resolver.resolve( + fixtureBlockHeader, 'parent/timestamp') + expect(value.remainderPath).to.equal('timestamp') + expect(value.value.equals( + new CID('z4QJh987XTweMqSLmNakYhbReGF55QBJY1P3WqgSYKsfWuwCvHM') + )).to.be.true() }) - it('should return a link and remaining path when parent is requested', - (done) => { - IpldZcash.resolver.resolve(fixtureBlockHeader, 'parent/timestamp', - (err, value) => { - expect(err).to.not.exist() - expect(value.remainderPath).to.equal('timestamp') - expect(value.value).to.deep.equal({ - '/': - new CID('z4QJh987XTweMqSLmNakYhbReGF55QBJY1P3WqgSYKsfWuwCvHM') - }) - done() - }) - }) - - it('should return a link when transactions are requested', (done) => { - IpldZcash.resolver.resolve(fixtureBlockHeader, 'tx/some/remainder', - (err, value) => { - expect(err).to.not.exist() - expect(value.remainderPath).to.equal('some/remainder') - expect(value.value).to.deep.equal({ - '/': new CID('z4QJh987RUUrqpBCCdGuhVMh6Gr21KxokFeHppiNiydiydNEut9') - }) - done() - }) + it('should return a link when transactions are requested', () => { + const value = IpldZcash.resolver.resolve( + fixtureBlockHeader, 'tx/some/remainder') + expect(value.remainderPath).to.equal('some/remainder') + expect(value.value.equals( + new CID('z4QJh987RUUrqpBCCdGuhVMh6Gr21KxokFeHppiNiydiydNEut9') + )).to.be.true() }) - it('should return an error if block is invalid', (done) => { - verifyError(invalidBlock, 'version', done) + it('should return an error if block is invalid', () => { + verifyError( + invalidBlock, 'version', 'Zcash block header needs to be 1487 bytes') }) }) describe('IPLD format resolver API tree()', () => { - it('should return only paths by default', (done) => { - IpldZcash.resolver.tree(fixtureBlockHeader, (err, value) => { - expect(err).to.not.exist() - expect(value).to.deep.equal(['version', 'timestamp', 'difficulty', - 'nonce', 'solution', 'reserved', 'parent', 'tx']) - done() - }) - }) - - it('should be able to return paths and values', (done) => { - IpldZcash.resolver.tree(fixtureBlockHeader, { - values: true - }, (err, value) => { - expect(err).to.not.exist() - expect(value).to.deep.equal({ - version: 4, - timestamp: 1481233847, - difficulty: 477875354, - nonce: Buffer.from( - '8200000000000000d548af969ea8dceedb6bfad4000000000000000000000000', - 'hex'), - reserved: Buffer.from( - '0000000000000000000000000000000000000000000000000000000000000000', - 'hex'), - solution: Buffer.from('005836fdbc8a7a7d9cbec4f059ba17f62d0e775b19035c8e18f123d3a99f270118325eaac526ae7a68d60c9c8c5acdc3e71e987020cb55ad92e0c37af0ab200d3a19e366389bdfe53cd79f70dbc4a67ea6fdc3700f25e0b1d49cee31a54ba8cf826b34c2561c97a0c239e2872c74a33c41690a44e0de741283d60dbfb738152a90d84b1b8f4dce36c3323d35275e8c43f464e9401b757a85392335fdba2432eda2b225b9549faee001d0ebadf24c106f353a02788c386a2f6bce7d83422e8d3ba8ff5cdd85429484a67c76ce31bfacf968621f0b72d9334dfee6b430d2a811f7954548b419fb9428b6d9a09e1317774ebb628d4dd8f334fbe4fb80200f226af20f1cd089849c6207c9d87869baba2e473b0f6b07e68ada56955322d31879c5653a1a84df97a5180e0655fa8da912d5b09396dc601db16143ac00525a9f16b087b64e4fb6567822f1ed84ba723ffde6ca00f29446a54ce34ad03030e6dd55a992817ede9038436793fa72b7133fcded9443d2340b7dcfb45b02230121c5d0d2958cff63a5633db92b61ed9524f74d230a5429c76a02e12f096e611cc978893683429f89cf03a52533039ae3b7c092589aa9f60cb67b19d5849533c254986a614909ee5765097935f7b162842c09d315526f5f3d77c817eff16204fbe6c949b44e1ac1052482774279e76377431123a189d6716ddff6157c6708985f8f01277d67871e915adcc83119440c8cf6e121911b6d748a4c4b15537273379965ecb0bd89862936cfd7a45d9138b93e564596de4ae5099a371f8cf95f692dffe46523ad5bb0482891df72eac651b9c42f191841e3ad68b0459619367f0341523a03a61ecda6694a7dbcaf1f6d9d11c8c6f132fda2beca91f84cd01d78e2854b5aac4ad7219bff38f94e131e065a48961e6e5468690d0122c832f3ee5570fbed1547d91bc202151d3757d432f1edc793c5f37cf6bd34a9af42970ccb01ae1696ba75067c743b58b9ca4e81e1d7a69203c3b62609150effaab450dd4a0b20d68a31be560808c097f046924acd6e9fc18e3f5d28e698d658a96b06821737a511616bdcb4237c5d3dedd56e53d758bb2d695f52ee58cb49bff3563d38c30411c22e7393b61797d79755a4ea5f9b1232283e4b802100199633b03277e398f70f3e0ef8e7a4b7bf396aba1d55f53a2e03ef089c6720dc456715b08bb94f754d211037c15e0b2078d6226a7a31f4e8f19d885adae07244132dcf0605873a19d4dbef5a03f425975e796956827d6d66072675d10ac87a02db325559bdc9643a32a0beb93723fc3fdbb218b5c2c9d3c2ca9dec65392e1a0fbe0732e66547335f69ab4b81064a4d3fb9830d0e3c547e2a6a554f22928e8762e8941f6f5f5cc509319fb85a2cbf0e433be5a225f94c693bb0691a8ecdba58f71104e12f7cc056a10ae17856e059fb126ea1a5fa43a40f4367901212a3decbea31e0756c37587ff4fdd0271825aa48e0105f8af667977a823fe051dfaa1fb4014f50d6222fed9ccd8787c77563d83e3e52435cf19806c662596988442b39f2611fc80a8ee561bc3f944320b3f7ebaae1fc592e7a823c0967ceedf898b6f805224a3353f92121fb22fb16dbdc41cc066c1f5efaa42945ad4b6326fe73e4b3b34371c64871a99d97bec407ec53b9b01a332ada7a81f8f5f576aedd96b7ec0f51f9977c2ca8c40fbd66779a4743db1622619d23940c59f72b055674bd9ab331a20db20bbcdef4d8184929b1b6bcfc5f155ff0d263e37145f5c98cde541dda165943dec7a56deb81b8f1bd279acfcc8e16e9a968263f8d5c8793e7311a4fe2d114c9d601bf315df05317c0ad89c34e363af79ca4f0c6618f0da51cb8930f2d525779a64f3b657ff0e8b1106ce4f63f775b4cf6', 'hex'), - parent: { - '/': new CID('z4QJh987XTweMqSLmNakYhbReGF55QBJY1P3WqgSYKsfWuwCvHM') - }, - tx: { - '/': new CID('z4QJh987RUUrqpBCCdGuhVMh6Gr21KxokFeHppiNiydiydNEut9') - } - }) - done() - }) - }) - - it('should return an error if block is invalid', (done) => { - IpldZcash.resolver.tree(invalidBlock, (err, value) => { - expect(value).to.not.exist() - expect(err).to.be.an('error') - done() - }) - }) -}) - -describe('IPLD format resolver API properties', () => { - it('should have `multicodec` defined correctly', (done) => { - expect(IpldZcash.resolver.multicodec).to.equal('zcash-block') - done() + it('should return only paths by default', () => { + const value = IpldZcash.resolver.tree(fixtureBlockHeader) + const paths = [...value] + expect(paths).to.have.members([ + 'version', + 'timestamp', + 'difficulty', + 'nonce', + 'solution', + 'reserved', + 'parent', + 'tx' + ]) }) - it('should have `defaultHashAlg` defined correctly', (done) => { - expect(IpldZcash.resolver.defaultHashAlg).to.equal('dbl-sha2-256') - done() + it('should return an error if block is invalid', () => { + expect(() => { + IpldZcash.resolver.tree(invalidBlock).next() + }).to.throw('Zcash block header needs to be 1487 bytes') }) }) -const verifyPath = (block, path, expected, done) => { - IpldZcash.resolver.resolve(block, path, (err, value) => { - expect(err).to.not.exist() - expect(value.remainderPath).is.empty() - expect(value.value).to.deep.equal(expected) - done() - }) +const verifyPath = (block, path, expected) => { + const value = IpldZcash.resolver.resolve(block, path) + expect(value.remainderPath).is.empty() + expect(value.value).is.deep.equal(expected) } -const verifyError = (block, path, done) => { - IpldZcash.resolver.resolve(block, path, (err, value) => { - expect(value).to.not.exist() - expect(err).to.be.an('error') - done() - }) +const verifyError = (block, path, error) => { + expect(() => + IpldZcash.resolver.resolve(block, path) + ).to.throw(error) } diff --git a/test/util.spec.js b/test/util.spec.js index a61f2eb..8b43236 100644 --- a/test/util.spec.js +++ b/test/util.spec.js @@ -3,9 +3,13 @@ const loadFixture = require('aegir/fixtures') const chai = require('chai') +const chaiAsPromised = require('chai-as-promised') const dirtyChai = require('dirty-chai') const expect = chai.expect +chai.use(chaiAsPromised) chai.use(dirtyChai) +const CID = require('cids') +const multicodec = require('multicodec') const IpldZcash = require('../src/index') const helpers = require('./helpers') @@ -14,114 +18,74 @@ const fixtureBlockHeader = helpers.headerFromHexBlock(fixtureBlockHex) const invalidDagNode = { invalid: 'dagNode' } describe('IPLD format util API deserialize()', () => { - it('should work correctly', (done) => { - IpldZcash.util.deserialize(fixtureBlockHeader, (err, dagNode) => { - expect(err).to.not.exist() - verifyBlock(dagNode, { - version: 4, - prevHash: '960143fe2c5e22cc0bf0cd5534d7f7f4347f4e75223d07379b9af71400000000', - merkleRoot: '947863a7d7a980a00ef54ce761dcb7b21f4b95fdaf4822f16f37a0e2dea8643e', - reserved: '0000000000000000000000000000000000000000000000000000000000000000', - time: 1481233847, - bits: 477875354, - nonce: '8200000000000000d548af969ea8dceedb6bfad4000000000000000000000000', - solution: '005836fdbc8a7a7d9cbec4f059ba17f62d0e775b19035c8e18f123d3a99f270118325eaac526ae7a68d60c9c8c5acdc3e71e987020cb55ad92e0c37af0ab200d3a19e366389bdfe53cd79f70dbc4a67ea6fdc3700f25e0b1d49cee31a54ba8cf826b34c2561c97a0c239e2872c74a33c41690a44e0de741283d60dbfb738152a90d84b1b8f4dce36c3323d35275e8c43f464e9401b757a85392335fdba2432eda2b225b9549faee001d0ebadf24c106f353a02788c386a2f6bce7d83422e8d3ba8ff5cdd85429484a67c76ce31bfacf968621f0b72d9334dfee6b430d2a811f7954548b419fb9428b6d9a09e1317774ebb628d4dd8f334fbe4fb80200f226af20f1cd089849c6207c9d87869baba2e473b0f6b07e68ada56955322d31879c5653a1a84df97a5180e0655fa8da912d5b09396dc601db16143ac00525a9f16b087b64e4fb6567822f1ed84ba723ffde6ca00f29446a54ce34ad03030e6dd55a992817ede9038436793fa72b7133fcded9443d2340b7dcfb45b02230121c5d0d2958cff63a5633db92b61ed9524f74d230a5429c76a02e12f096e611cc978893683429f89cf03a52533039ae3b7c092589aa9f60cb67b19d5849533c254986a614909ee5765097935f7b162842c09d315526f5f3d77c817eff16204fbe6c949b44e1ac1052482774279e76377431123a189d6716ddff6157c6708985f8f01277d67871e915adcc83119440c8cf6e121911b6d748a4c4b15537273379965ecb0bd89862936cfd7a45d9138b93e564596de4ae5099a371f8cf95f692dffe46523ad5bb0482891df72eac651b9c42f191841e3ad68b0459619367f0341523a03a61ecda6694a7dbcaf1f6d9d11c8c6f132fda2beca91f84cd01d78e2854b5aac4ad7219bff38f94e131e065a48961e6e5468690d0122c832f3ee5570fbed1547d91bc202151d3757d432f1edc793c5f37cf6bd34a9af42970ccb01ae1696ba75067c743b58b9ca4e81e1d7a69203c3b62609150effaab450dd4a0b20d68a31be560808c097f046924acd6e9fc18e3f5d28e698d658a96b06821737a511616bdcb4237c5d3dedd56e53d758bb2d695f52ee58cb49bff3563d38c30411c22e7393b61797d79755a4ea5f9b1232283e4b802100199633b03277e398f70f3e0ef8e7a4b7bf396aba1d55f53a2e03ef089c6720dc456715b08bb94f754d211037c15e0b2078d6226a7a31f4e8f19d885adae07244132dcf0605873a19d4dbef5a03f425975e796956827d6d66072675d10ac87a02db325559bdc9643a32a0beb93723fc3fdbb218b5c2c9d3c2ca9dec65392e1a0fbe0732e66547335f69ab4b81064a4d3fb9830d0e3c547e2a6a554f22928e8762e8941f6f5f5cc509319fb85a2cbf0e433be5a225f94c693bb0691a8ecdba58f71104e12f7cc056a10ae17856e059fb126ea1a5fa43a40f4367901212a3decbea31e0756c37587ff4fdd0271825aa48e0105f8af667977a823fe051dfaa1fb4014f50d6222fed9ccd8787c77563d83e3e52435cf19806c662596988442b39f2611fc80a8ee561bc3f944320b3f7ebaae1fc592e7a823c0967ceedf898b6f805224a3353f92121fb22fb16dbdc41cc066c1f5efaa42945ad4b6326fe73e4b3b34371c64871a99d97bec407ec53b9b01a332ada7a81f8f5f576aedd96b7ec0f51f9977c2ca8c40fbd66779a4743db1622619d23940c59f72b055674bd9ab331a20db20bbcdef4d8184929b1b6bcfc5f155ff0d263e37145f5c98cde541dda165943dec7a56deb81b8f1bd279acfcc8e16e9a968263f8d5c8793e7311a4fe2d114c9d601bf315df05317c0ad89c34e363af79ca4f0c6618f0da51cb8930f2d525779a64f3b657ff0e8b1106ce4f63f775b4cf6' - }) - done() + it('should work correctly', () => { + const dagNode = IpldZcash.util.deserialize(fixtureBlockHeader) + verifyBlock(dagNode, { + version: 4, + prevHash: '960143fe2c5e22cc0bf0cd5534d7f7f4347f4e75223d07379b9af71400000000', + merkleRoot: '947863a7d7a980a00ef54ce761dcb7b21f4b95fdaf4822f16f37a0e2dea8643e', + reserved: '0000000000000000000000000000000000000000000000000000000000000000', + time: 1481233847, + bits: 477875354, + nonce: '8200000000000000d548af969ea8dceedb6bfad4000000000000000000000000', + solution: '005836fdbc8a7a7d9cbec4f059ba17f62d0e775b19035c8e18f123d3a99f270118325eaac526ae7a68d60c9c8c5acdc3e71e987020cb55ad92e0c37af0ab200d3a19e366389bdfe53cd79f70dbc4a67ea6fdc3700f25e0b1d49cee31a54ba8cf826b34c2561c97a0c239e2872c74a33c41690a44e0de741283d60dbfb738152a90d84b1b8f4dce36c3323d35275e8c43f464e9401b757a85392335fdba2432eda2b225b9549faee001d0ebadf24c106f353a02788c386a2f6bce7d83422e8d3ba8ff5cdd85429484a67c76ce31bfacf968621f0b72d9334dfee6b430d2a811f7954548b419fb9428b6d9a09e1317774ebb628d4dd8f334fbe4fb80200f226af20f1cd089849c6207c9d87869baba2e473b0f6b07e68ada56955322d31879c5653a1a84df97a5180e0655fa8da912d5b09396dc601db16143ac00525a9f16b087b64e4fb6567822f1ed84ba723ffde6ca00f29446a54ce34ad03030e6dd55a992817ede9038436793fa72b7133fcded9443d2340b7dcfb45b02230121c5d0d2958cff63a5633db92b61ed9524f74d230a5429c76a02e12f096e611cc978893683429f89cf03a52533039ae3b7c092589aa9f60cb67b19d5849533c254986a614909ee5765097935f7b162842c09d315526f5f3d77c817eff16204fbe6c949b44e1ac1052482774279e76377431123a189d6716ddff6157c6708985f8f01277d67871e915adcc83119440c8cf6e121911b6d748a4c4b15537273379965ecb0bd89862936cfd7a45d9138b93e564596de4ae5099a371f8cf95f692dffe46523ad5bb0482891df72eac651b9c42f191841e3ad68b0459619367f0341523a03a61ecda6694a7dbcaf1f6d9d11c8c6f132fda2beca91f84cd01d78e2854b5aac4ad7219bff38f94e131e065a48961e6e5468690d0122c832f3ee5570fbed1547d91bc202151d3757d432f1edc793c5f37cf6bd34a9af42970ccb01ae1696ba75067c743b58b9ca4e81e1d7a69203c3b62609150effaab450dd4a0b20d68a31be560808c097f046924acd6e9fc18e3f5d28e698d658a96b06821737a511616bdcb4237c5d3dedd56e53d758bb2d695f52ee58cb49bff3563d38c30411c22e7393b61797d79755a4ea5f9b1232283e4b802100199633b03277e398f70f3e0ef8e7a4b7bf396aba1d55f53a2e03ef089c6720dc456715b08bb94f754d211037c15e0b2078d6226a7a31f4e8f19d885adae07244132dcf0605873a19d4dbef5a03f425975e796956827d6d66072675d10ac87a02db325559bdc9643a32a0beb93723fc3fdbb218b5c2c9d3c2ca9dec65392e1a0fbe0732e66547335f69ab4b81064a4d3fb9830d0e3c547e2a6a554f22928e8762e8941f6f5f5cc509319fb85a2cbf0e433be5a225f94c693bb0691a8ecdba58f71104e12f7cc056a10ae17856e059fb126ea1a5fa43a40f4367901212a3decbea31e0756c37587ff4fdd0271825aa48e0105f8af667977a823fe051dfaa1fb4014f50d6222fed9ccd8787c77563d83e3e52435cf19806c662596988442b39f2611fc80a8ee561bc3f944320b3f7ebaae1fc592e7a823c0967ceedf898b6f805224a3353f92121fb22fb16dbdc41cc066c1f5efaa42945ad4b6326fe73e4b3b34371c64871a99d97bec407ec53b9b01a332ada7a81f8f5f576aedd96b7ec0f51f9977c2ca8c40fbd66779a4743db1622619d23940c59f72b055674bd9ab331a20db20bbcdef4d8184929b1b6bcfc5f155ff0d263e37145f5c98cde541dda165943dec7a56deb81b8f1bd279acfcc8e16e9a968263f8d5c8793e7311a4fe2d114c9d601bf315df05317c0ad89c34e363af79ca4f0c6618f0da51cb8930f2d525779a64f3b657ff0e8b1106ce4f63f775b4cf6' }) }) - it('should error on an invalid block', (done) => { + it('should error on an invalid block', () => { const invalidBlock = Buffer.from('abcdef', 'hex') - IpldZcash.util.deserialize(invalidBlock, (err, dagNode) => { - expect(dagNode).to.not.exist() - expect(err).to.be.an('error') - done() - }) + expect(() => { + IpldZcash.util.deserialize(invalidBlock) + }).to.throw('Zcash block header needs to be 1487 bytes') }) }) describe('IPLD format util API serialize()', () => { - it('should round-trip (de)serialization correctly', (done) => { - IpldZcash.util.deserialize(fixtureBlockHeader, (err, dagNode) => { - expect(err).to.not.exist() - IpldZcash.util.serialize(dagNode, (err, binaryBlob) => { - expect(err).to.not.exist() - expect(binaryBlob).to.deep.equal(fixtureBlockHeader) - done() - }) - }) + it('should round-trip (de)serialization correctly', () => { + const dagNode = IpldZcash.util.deserialize(fixtureBlockHeader) + const binaryBlob = IpldZcash.util.serialize(dagNode) + expect(binaryBlob).to.deep.equal(fixtureBlockHeader) }) - it('should error on an invalid internal representation', (done) => { - IpldZcash.util.serialize(invalidDagNode, (err, binaryBlob) => { - expect(binaryBlob).to.not.exist() - expect(err).to.be.an('error') - done() - }) + it('should error on an invalid internal representation', () => { + expect(() => { + IpldZcash.util.serialize(invalidDagNode) + }).to.throw() }) }) describe('IPLD format util API cid()', () => { - it('should encode the CID correctly', (done) => { - IpldZcash.util.deserialize(fixtureBlockHeader, (err, dagNode) => { - expect(err).to.not.exist() - verifyCid( - dagNode, - '5620e1451fd8fecefdd9d443f294bc5ae918301922088ba51d35a2a4672c00000000', - done) - }) - }) - - it('should encode the CID correctly with default options specified', (done) => { - IpldZcash.util.deserialize(fixtureBlockHeader, (err, dagNode) => { - expect(err).to.not.exist() - verifyCid1( - dagNode, - { version: 1, hashAlg: 'dbl-sha2-256' }, - '5620e1451fd8fecefdd9d443f294bc5ae918301922088ba51d35a2a4672c00000000', - done) - }) - }) + const expectedCid = new CID(1, 'zcash-block', Buffer.from( + '5620e1451fd8fecefdd9d443f294bc5ae918301922088ba51d35a2a4672c00000000', + 'hex')) - it('should encode the CID correctly with options', (done) => { - IpldZcash.util.deserialize(fixtureBlockHeader, (err, dagNode) => { - expect(err).to.not.exist() - verifyCid1( - dagNode, - { hashAlg: 'sha3-256' }, - '1620426585d4624b64080d96788c8199562e73fc60f32fde54a82b36f4204c046ce6', - done) - }) + it('should encode the CID correctly', async () => { + const cid = await IpldZcash.util.cid(fixtureBlockHeader) + expect(cid.equals(expectedCid)).to.be.true() }) - it('should error unknown hash algorithm', (done) => { - IpldZcash.util.deserialize(fixtureBlockHeader, (err, dagNode) => { - expect(err).to.not.exist() - IpldZcash.util.cid(dagNode, { hashAlg: 'unknown' }, (err, cid) => { - expect(err).to.exist() - done() - }) + it('should encode the CID correctly with default options specified', async () => { + const cid = await IpldZcash.util.cid(fixtureBlockHeader, { + cidVersion: 1, + hashAlg: multicodec.DBL_SHA2_256 }) + expect(cid.equals(expectedCid)).to.be.true() }) - it('should encode the CID correctly and ignore undefined options', (done) => { - IpldZcash.util.deserialize(fixtureBlockHeader, (err, dagNode) => { - expect(err).to.not.exist() - verifyCid1( - dagNode, - undefined, - '5620e1451fd8fecefdd9d443f294bc5ae918301922088ba51d35a2a4672c00000000', - done) + it('should encode the CID correctly with options', async () => { + const cid = await IpldZcash.util.cid(fixtureBlockHeader, { + hashAlg: multicodec.SHA3_256 }) + expect(cid.equals(new CID(1, 'zcash-block', Buffer.from( + '1620426585d4624b64080d96788c8199562e73fc60f32fde54a82b36f4204c046ce6', + 'hex' + )))).to.be.true() }) - it('should error on an invalid internal representation', (done) => { - IpldZcash.util.cid(invalidDagNode, (err, cid) => { - expect(cid).to.not.exist() - expect(err).to.be.an('error') - done() - }) + it('should error unknown hash algorithm', async () => { + await expect( + IpldZcash.util.cid(fixtureBlockHeader, { hashAlg: 0xffffff }) + ).to.be.rejectedWith('Unrecognized function code: 16777215') }) }) @@ -135,19 +99,3 @@ const verifyBlock = (header, expected) => { expect(header.nonce.toString('hex')).to.equal(expected.nonce) expect(header.solution.toString('hex')).to.equal(expected.solution) } - -const verifyCid = (dagNode, expectedCid, doneCb) => { - IpldZcash.util.cid(dagNode, (err, cid) => { - expect(err).to.not.exist() - expect(cid.multihash.toString('hex')).to.equal(expectedCid) - doneCb() - }) -} - -const verifyCid1 = (dagNode, options, expectedCid, doneCb) => { - IpldZcash.util.cid(dagNode, options, (err, cid) => { - expect(err).to.not.exist() - expect(cid.multihash.toString('hex')).to.equal(expectedCid) - doneCb() - }) -}