Skip to content
This repository has been archived by the owner on Dec 6, 2022. It is now read-only.

Commit

Permalink
fix: replace node buffers with uint8array (#65)
Browse files Browse the repository at this point in the history
Accepts and emits `Uint8Array`s instead of node `Buffer`s but converts
them internally because `bitcoinjs-lib` only understands `Buffer`s.

BREAKING CHANGE:

- `util.serialize` returns `Uint8Array`s
- `util.cid` returns `CID`s with a breaking API change - see multiformats/js-cid#117 for changes
  • Loading branch information
achingbrain authored Aug 4, 2020
1 parent 7d9d6f3 commit f9d3c7e
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 36 deletions.
13 changes: 6 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,14 @@
"dependencies": {
"bitcoinjs-lib": "^5.0.0",
"buffer": "^5.6.0",
"cids": "^0.8.3",
"multicodec": "^1.0.0",
"multihashes": "^1.0.1",
"multihashing-async": "^1.0.0"
"cids": "^1.0.0",
"multicodec": "^2.0.0",
"multihashes": "^3.0.0",
"multihashing-async": "^2.0.0",
"uint8arrays": "^1.0.0"
},
"devDependencies": {
"aegir": "^25.0.0",
"chai": "^4.2.0",
"dirty-chai": "^2.0.1"
"aegir": "^25.0.0"
},
"contributors": [
"Volker Mische <volker.mische@gmail.com>",
Expand Down
7 changes: 3 additions & 4 deletions src/resolver.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use strict'

const CID = require('cids')
const { Buffer } = require('buffer')

const util = require('./util')

Expand All @@ -11,7 +10,7 @@ const util = require('./util')
* 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 Bitcoin block
* @param {Uint8Array} binaryBlob - Binary representation of a Bitcoin block
* @param {string} [path='/'] - Path that should be resolved
* @returns {Object} result - Result of the path it it was resolved successfully
* @returns {*} result.value - Value the path resolves to
Expand Down Expand Up @@ -46,7 +45,7 @@ exports.resolve = (binaryBlob, path) => {

const traverse = function * (node, path) {
// Traverse only objects and arrays
if (Buffer.isBuffer(node) || CID.isCID(node) || typeof node === 'string' ||
if (node instanceof Uint8Array || CID.isCID(node) || typeof node === 'string' ||
node === null) {
return
}
Expand All @@ -61,7 +60,7 @@ const traverse = function * (node, path) {
* Return all available paths of a block.
*
* @generator
* @param {Buffer} binaryBlob - Binary representation of a Bitcoin block
* @param {Uint8Array} binaryBlob - Binary representation of a Bitcoin block
* @yields {string} - A single path
*/
exports.tree = function * (binaryBlob) {
Expand Down
11 changes: 8 additions & 3 deletions src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const CID = require('cids')
const multicodec = require('multicodec')
const multihashes = require('multihashes')
const multihashing = require('multihashing-async')
const { Buffer } = require('buffer')

const BITCOIN_BLOCK_HEADER_SIZE = 80
const CODEC = multicodec.BITCOIN_BLOCK
Expand All @@ -14,7 +15,7 @@ const DEFAULT_HASH_ALG = multicodec.DBL_SHA2_256
* Serialize internal representation into a binary Bitcoin block.
*
* @param {BitcoinBlock} dagNode - Internal representation of a Bitcoin block
* @returns {Buffer}
* @returns {Uint8Array}
*/
const serialize = (dagNode) => {
return dagNode.toBuffer(true)
Expand All @@ -23,7 +24,7 @@ const serialize = (dagNode) => {
/**
* Deserialize Bitcoin block into the internal representation.
*
* @param {Buffer} binaryBlob - Binary representation of a Bitcoin block
* @param {Uint8Array} binaryBlob - Binary representation of a Bitcoin block
* @returns {BitcoinBlock}
*/
const deserialize = (binaryBlob) => {
Expand All @@ -32,6 +33,10 @@ const deserialize = (binaryBlob) => {
`Bitcoin block header needs to be ${BITCOIN_BLOCK_HEADER_SIZE} bytes`)
}

if (!Buffer.isBuffer(binaryBlob)) {
binaryBlob = Buffer.from(binaryBlob, binaryBlob.byteOffset, binaryBlob.byteLength)
}

const deserialized = BitcoinjsBlock.fromBuffer(binaryBlob)

const getters = {
Expand Down Expand Up @@ -88,7 +93,7 @@ const cid = async (binaryBlob, userOptions) => {
return cid
}

// Convert a Bitcoin hash (as Buffer) to a CID
// Convert a Bitcoin hash (as Uint8Array) to a CID
const hashToCid = (hash) => {
const multihash = multihashes.encode(hash, DEFAULT_HASH_ALG)
const cidVersion = 1
Expand Down
4 changes: 2 additions & 2 deletions test/helpers.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
'use strict'

const { Buffer } = require('buffer')
const uint8ArrayFromString = require('uint8arrays/from-string')

const BITCOIN_BLOCK_HEADER_SIZE = require('../src/index')
.util.BITCOIN_BLOCK_HEADER_SIZE

const headerFromHexBlock = (hex) => {
return Buffer.from(hex.toString(), 'hex').slice(0, BITCOIN_BLOCK_HEADER_SIZE)
return uint8ArrayFromString(hex.toString(), 'base16').slice(0, BITCOIN_BLOCK_HEADER_SIZE)
}

module.exports = {
Expand Down
5 changes: 1 addition & 4 deletions test/mod.spec.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
/* eslint-env mocha */
'use strict'

const chai = require('chai')
const dirtyChai = require('dirty-chai')
const expect = chai.expect
chai.use(dirtyChai)
const { expect } = require('aegir/utils/chai')
const multicodec = require('multicodec')

const mod = require('../src')
Expand Down
9 changes: 3 additions & 6 deletions test/resolver.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,15 @@
'use strict'

const loadFixture = require('aegir/fixtures')
const chai = require('chai')
const dirtyChai = require('dirty-chai')
const expect = chai.expect
chai.use(dirtyChai)
const { expect } = require('aegir/utils/chai')
const CID = require('cids')
const { Buffer } = require('buffer')
const uint8ArrayFromString = require('uint8arrays/from-string')
const IpldBitcoin = require('../src/index')
const helpers = require('./helpers')

const fixtureBlockHex = loadFixture('test/fixtures/block.hex')
const fixtureBlockHeader = helpers.headerFromHexBlock(fixtureBlockHex)
const invalidBlock = Buffer.from('abcdef', 'hex')
const invalidBlock = uint8ArrayFromString('abcdef', 'base16')

describe('IPLD format resolve API resolve()', () => {
it('should return the deserialized node if path is empty', () => {
Expand Down
29 changes: 19 additions & 10 deletions test/util.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@
'use strict'

const loadFixture = require('aegir/fixtures')
const chai = require('chai')
const dirtyChai = require('dirty-chai')
const expect = chai.expect
chai.use(dirtyChai)
const { expect } = require('aegir/utils/chai')
const CID = require('cids')
const multicodec = require('multicodec')
const { Buffer } = require('buffer')
const uint8ArrayFromString = require('uint8arrays/from-string')
const IpldBitcoin = require('../src/index')
const helpers = require('./helpers')

Expand All @@ -29,6 +26,18 @@ describe('IPLD format util API deserialize()', () => {
})
})

it('should work correctly with Uint8Arrays', () => {
const dagNode = IpldBitcoin.util.deserialize(Uint8Array.from(fixtureBlockHeader))
verifyBlock(dagNode, {
version: 2,
prevHash: '87d6242b27d248a9e145fe764a0bcef03a403883a2e4c8590200000000000000',
merkleRoot: '11a5b9a70acebedbbf71ef8ca341e8a98cf279c49eee8f92e10a2227743b6aeb',
timestamp: 1386981279,
bits: 419740270,
nonce: 3159344128
})
})

it('should deserialize Segwit correctly (a)', () => {
const segwitBlockHex = loadFixture('test/fixtures/segwit.hex')
const segwitBlockHeader = helpers.headerFromHexBlock(segwitBlockHex)
Expand Down Expand Up @@ -72,7 +81,7 @@ describe('IPLD format util API deserialize()', () => {
})

it('should error on an invalid block', () => {
const invalidBlock = Buffer.from('abcdef', 'hex')
const invalidBlock = uint8ArrayFromString('abcdef', 'base16')
expect(() => {
IpldBitcoin.util.deserialize(invalidBlock)
}).to.throw('Bitcoin block header needs to be 80 bytes')
Expand All @@ -94,9 +103,9 @@ describe('IPLD format util API serialize()', () => {
})

describe('IPLD format util API cid()', () => {
const expectedCid = new CID(1, 'bitcoin-block', Buffer.from(
const expectedCid = new CID(1, 'bitcoin-block', uint8ArrayFromString(
'56203ec2c691d447b2fd0d6a94742345af1f351037dab1ab9e900200000000000000',
'hex'))
'base16'))

it('should encode the CID correctly', async () => {
const cid = await IpldBitcoin.util.cid(fixtureBlockHeader)
Expand All @@ -107,9 +116,9 @@ describe('IPLD format util API cid()', () => {
const cid = await IpldBitcoin.util.cid(fixtureBlockHeader, {
hashAlg: multicodec.SHA3_256
})
expect(cid.equals(new CID(1, 'bitcoin-block', Buffer.from(
expect(cid.equals(new CID(1, 'bitcoin-block', uint8ArrayFromString(
'16208fd2802e0304c79c08a1ff2afb706ce64b78f3b94fd1c9142946c2e715589cfb',
'hex'
'base16'
)))).to.be.true()
})

Expand Down

0 comments on commit f9d3c7e

Please sign in to comment.