diff --git a/lib/crypto/aes.js b/lib/crypto/aes.js index dd579bc3..1bec1729 100644 --- a/lib/crypto/aes.js +++ b/lib/crypto/aes.js @@ -11,7 +11,6 @@ */ const crypto = require('crypto'); -const util = require('../utils/util'); const native = require('../native').binding; /** @@ -24,7 +23,7 @@ const native = require('../native').binding; exports.encipher = function encipher(data, key, iv) { let cipher = crypto.createCipheriv('aes-256-cbc', key, iv); - return util.concat(cipher.update(data), cipher.final()); + return Buffer.concat([cipher.update(data), cipher.final()]); }; /** @@ -38,7 +37,7 @@ exports.encipher = function encipher(data, key, iv) { exports.decipher = function _decipher(data, key, iv) { let decipher = crypto.createDecipheriv('aes-256-cbc', key, iv); try { - return util.concat(decipher.update(data), decipher.final()); + return Buffer.concat([decipher.update(data), decipher.final()]); } catch (e) { throw new Error('Bad key for decryption.'); } diff --git a/lib/crypto/digest-browser.js b/lib/crypto/digest-browser.js index e27bc2cb..95a94e45 100644 --- a/lib/crypto/digest-browser.js +++ b/lib/crypto/digest-browser.js @@ -14,6 +14,7 @@ const assert = require('assert'); const hashjs = require('hash.js'); const sha256 = require('./sha256'); +const POOL64 = Buffer.allocUnsafe(64); /** * Hash with chosen algorithm. @@ -85,6 +86,25 @@ exports.hash256 = function hash256(data) { return sha256.hash256(data); }; +/** + * Hash left and right hashes with hash256. + * @param {Buffer} left + * @param {Buffer} right + * @returns {Buffer} + */ + +exports.root256 = function root256(left, right) { + let data = POOL64; + + assert(left.length === 32); + assert(right.length === 32); + + left.copy(data, 0); + right.copy(data, 32); + + return exports.hash256(data); +}; + /** * Create an HMAC. * @param {String} alg diff --git a/lib/crypto/digest.js b/lib/crypto/digest.js index ef0d8dd2..9a23cb6f 100644 --- a/lib/crypto/digest.js +++ b/lib/crypto/digest.js @@ -10,8 +10,10 @@ * @module crypto.digest */ +const assert = require('assert'); const crypto = require('crypto'); const native = require('../native').binding; +const POOL64 = Buffer.allocUnsafe(64); /** * Hash with chosen algorithm. @@ -74,6 +76,25 @@ exports.hash256 = function hash256(data) { return exports.sha256(exports.sha256(data)); }; +/** + * Hash left and right hashes with hash256. + * @param {Buffer} left + * @param {Buffer} right + * @returns {Buffer} + */ + +exports.root256 = function root256(left, right) { + let data = POOL64; + + assert(left.length === 32); + assert(right.length === 32); + + left.copy(data, 0); + right.copy(data, 32); + + return exports.hash256(data); +}; + /** * Create an HMAC. * @param {String} alg @@ -95,4 +116,5 @@ if (native) { exports.sha256 = native.sha256; exports.hash160 = native.hash160; exports.hash256 = native.hash256; + exports.root256 = native.root256; } diff --git a/lib/crypto/merkle.js b/lib/crypto/merkle.js index b25b6674..89e0fe2b 100644 --- a/lib/crypto/merkle.js +++ b/lib/crypto/merkle.js @@ -25,7 +25,6 @@ exports.createTree = function createTree(leaves) { let nodes = leaves; let size = leaves.length; let malleated = false; - let data; if (size === 0) { let hash = Buffer.allocUnsafe(32); @@ -34,8 +33,6 @@ exports.createTree = function createTree(leaves) { return [nodes, malleated]; } - data = Buffer.allocUnsafe(64); - for (let j = 0; size > 1; size = (size + 1) >>> 1) { for (let i = 0; i < size; i += 2) { let k = Math.min(i + 1, size - 1); @@ -48,10 +45,7 @@ exports.createTree = function createTree(leaves) { malleated = true; } - left.copy(data, 0); - right.copy(data, 32); - - hash = digest.hash256(data); + hash = digest.root256(left, right); nodes.push(hash); } @@ -108,25 +102,17 @@ exports.createBranch = function createBranch(index, leaves) { */ exports.verifyBranch = function verifyBranch(hash, branch, index) { - let data; - if (branch.length === 0) return hash; - data = Buffer.allocUnsafe(64); - for (let i = 0; i < branch.length; i++) { let otherside = branch[i]; - if (index & 1) { - otherside.copy(data, 0); - hash.copy(data, 32); - } else { - hash.copy(data, 0); - otherside.copy(data, 32); - } + if (index & 1) + hash = digest.root256(otherside, hash); + else + hash = digest.root256(hash, otherside); - hash = digest.hash256(data); index >>>= 1; } diff --git a/lib/mining/miner.js b/lib/mining/miner.js index 88aae366..fc40bd3c 100644 --- a/lib/mining/miner.js +++ b/lib/mining/miner.js @@ -276,18 +276,18 @@ Miner.prototype.assemble = function assemble(attempt) { if (tx.isCoinbase()) throw new Error('Cannot add coinbase to block.'); - for (let input of tx.inputs) { - let prev = input.prevout.hash; + for (let {prevout} of tx.inputs) { + let hash = prevout.hash; - if (!this.mempool.hasEntry(prev)) + if (!this.mempool.hasEntry(hash)) continue; item.depCount += 1; - if (!depMap[prev]) - depMap[prev] = []; + if (!depMap[hash]) + depMap[hash] = []; - depMap[prev].push(item); + depMap[hash].push(item); } if (item.depCount > 0) @@ -344,7 +344,7 @@ Miner.prototype.assemble = function assemble(attempt) { if (!deps) continue; - for (item of deps) { + for (let item of deps) { if (--item.depCount === 0) queue.insert(item); } diff --git a/lib/mining/template.js b/lib/mining/template.js index e106c997..6dd5e7a1 100644 --- a/lib/mining/template.js +++ b/lib/mining/template.js @@ -173,7 +173,7 @@ BlockTemplate.fromOptions = function fromOptions(options) { BlockTemplate.prototype.getWitnessHash = function getWitnessHash() { let nonce = encoding.ZERO_HASH; let leaves = []; - let root, malleated, data; + let root, malleated; leaves.push(encoding.ZERO_HASH); @@ -184,9 +184,7 @@ BlockTemplate.prototype.getWitnessHash = function getWitnessHash() { assert(!malleated); - data = util.concat(root, nonce); - - return digest.hash256(data); + return digest.root256(root, nonce); }; /** @@ -697,10 +695,8 @@ function MerkleTree() { } MerkleTree.prototype.withFirst = function withFirst(hash) { - for (let step of this.steps) { - let data = util.concat(hash, step); - hash = digest.hash256(data); - } + for (let step of this.steps) + hash = digest.root256(hash, step); return hash; }; @@ -757,8 +753,7 @@ MerkleTree.prototype.fromLeaves = function fromLeaves(leaves) { leaves.push(leaves[len - 1]); for (let i = 2; i < len; i += 2) { - let data = util.concat(leaves[i], leaves[i + 1]); - let hash = digest.hash256(data); + let hash = digest.root256(leaves[i], leaves[i + 1]); hashes.push(hash); } diff --git a/lib/net/bip152.js b/lib/net/bip152.js index ccf1e369..949ef7a5 100644 --- a/lib/net/bip152.js +++ b/lib/net/bip152.js @@ -400,7 +400,7 @@ CompactBlock.prototype.hasIndex = function hasIndex(index) { */ CompactBlock.prototype.initKey = function initKey() { - let data = util.concat(this.abbr(), this.keyNonce); + let data = Buffer.concat([this.abbr(), this.keyNonce]); let hash = digest.sha256(data); this.sipKey = hash.slice(0, 16); }; diff --git a/lib/net/hostlist.js b/lib/net/hostlist.js index 71293708..075c23a5 100644 --- a/lib/net/hostlist.js +++ b/lib/net/hostlist.js @@ -20,6 +20,7 @@ const seeds = require('./seeds'); const dns = require('./dns'); const Logger = require('../node/logger'); const fs = require('../utils/fs'); +const POOL32 = Buffer.allocUnsafe(32); /** * Host List @@ -459,7 +460,7 @@ HostList.prototype.getHost = function getHost() { HostList.prototype.freshBucket = function freshBucket(entry) { let addr = entry.addr; let src = entry.src; - let data = util.concat(addr.raw, src.raw); + let data = concat32(addr.raw, src.raw); let hash = murmur3(data, 0xfba4c795); let index = hash % this.fresh.length; return this.fresh[index]; @@ -1588,6 +1589,17 @@ HostListOptions.prototype.fromOptions = function fromOptions(options) { return this; }; +/* + * Helpers + */ + +function concat32(left, right) { + let data = POOL32; + left.copy(data, 0); + right.copy(data, 32); + return data; +} + /* * Expose */ diff --git a/lib/primitives/block.js b/lib/primitives/block.js index f80e4dbb..955aa22f 100644 --- a/lib/primitives/block.js +++ b/lib/primitives/block.js @@ -298,7 +298,7 @@ Block.prototype.createMerkleRoot = function createMerkleRoot(enc) { */ Block.prototype.createWitnessNonce = function createWitnessNonce() { - return util.copy(encoding.ZERO_HASH); + return Buffer.from(encoding.ZERO_HASH); }; /** @@ -311,7 +311,7 @@ Block.prototype.createWitnessNonce = function createWitnessNonce() { Block.prototype.createCommitmentHash = function createCommitmentHash(enc) { let nonce = this.getWitnessNonce(); let leaves = []; - let root, data, hash; + let root, hash; assert(nonce, 'No witness nonce present.'); @@ -327,9 +327,7 @@ Block.prototype.createCommitmentHash = function createCommitmentHash(enc) { // Note: malleation check ignored here. // assert(!malleated); - data = util.concat(root, nonce); - - hash = digest.hash256(data); + hash = digest.root256(root, nonce); return enc === 'hex' ? hash.toString('hex') diff --git a/lib/primitives/merkleblock.js b/lib/primitives/merkleblock.js index 8bf09227..5ac28db6 100644 --- a/lib/primitives/merkleblock.js +++ b/lib/primitives/merkleblock.js @@ -17,7 +17,6 @@ const consensus = require('../protocol/consensus'); const AbstractBlock = require('./abstractblock'); const Headers = require('./headers'); const DUMMY = Buffer.from([0]); -const POOL = Buffer.allocUnsafe(64); /** * Represents a merkle (filtered) block. @@ -200,7 +199,6 @@ MerkleBlock.prototype.extractTree = function extractTree() { let flags = this.flags; let totalTX = this.totalTX; let height = 0; - let data = POOL; let root; let width = (height) => { @@ -246,10 +244,7 @@ MerkleBlock.prototype.extractTree = function extractTree() { right = left; } - left.copy(data, 0); - right.copy(data, 32); - - return digest.hash256(data); + return digest.root256(left, right); }; if (totalTX === 0) @@ -566,7 +561,6 @@ MerkleBlock.fromMatches = function fromMatches(block, matches) { let hashes = []; let totalTX = block.txs.length; let height = 0; - let data = POOL; let flags, merkle; let width = (height) => { @@ -586,10 +580,7 @@ MerkleBlock.fromMatches = function fromMatches(block, matches) { else right = left; - left.copy(data, 0); - right.copy(data, 32); - - return digest.hash256(data); + return digest.root256(left, right); }; let traverse = (height, pos, leaves, matches) => { diff --git a/lib/primitives/tx.js b/lib/primitives/tx.js index 71a76661..8924ba25 100644 --- a/lib/primitives/tx.js +++ b/lib/primitives/tx.js @@ -451,7 +451,7 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, prev, type) { // Bitcoind used to return 1 as an error code: // it ended up being treated like a hash. if (index >= this.outputs.length) - return util.copy(encoding.ONE_HASH); + return Buffer.from(encoding.ONE_HASH); } // Remove all code separators. diff --git a/lib/script/sigcache.js b/lib/script/sigcache.js index 61490c7a..c9940f82 100644 --- a/lib/script/sigcache.js +++ b/lib/script/sigcache.js @@ -131,8 +131,8 @@ SigCache.prototype.verify = function verify(msg, sig, key) { */ function SigCacheEntry(sig, key) { - this.sig = util.copy(sig); - this.key = util.copy(key); + this.sig = Buffer.from(sig); + this.key = Buffer.from(key); } /** diff --git a/lib/utils/util.js b/lib/utils/util.js index 881e694b..447c2194 100644 --- a/lib/utils/util.js +++ b/lib/utils/util.js @@ -16,32 +16,6 @@ const nodeUtil = require('util'); const util = exports; -/** - * Clone a buffer. - * @param {Buffer} data - * @returns {Buffer} - */ - -util.copy = function copy(data) { - let clone = Buffer.allocUnsafe(data.length); - data.copy(clone, 0, 0, data.length); - return clone; -}; - -/** - * Concatenate two buffers. - * @param {Buffer} a - * @param {Buffer} b - * @returns {Buffer} - */ - -util.concat = function concat(a, b) { - let data = Buffer.allocUnsafe(a.length + b.length); - a.copy(data, 0); - b.copy(data, a.length); - return data; -}; - /** * Return hrtime (shim for browser). * @param {Array} time @@ -108,6 +82,8 @@ util.revHex = function revHex(data) { let out = ''; assert(typeof data === 'string'); + assert(data.length > 0); + assert(data.length % 2 === 0); for (let i = 0; i < data.length; i += 2) out = data.slice(i, i + 2) + out; @@ -769,15 +745,6 @@ util.binaryRemove = function binaryRemove(items, item, compare) { return true; }; -/** - * Ensure hidden-class mode for object. - * @param {Object} obj - */ - -util.fastProp = function fastProp(obj) { - ({ __proto__: obj }); -}; - /** * Quick test to see if a string is uppercase. * @param {String} str diff --git a/package.json b/package.json index 69f96c91..d5305901 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "n64": "0.0.11" }, "optionalDependencies": { - "bcoin-native": "0.0.20", + "bcoin-native": "0.0.21", "leveldown": "1.7.0-0", "secp256k1": "3.2.5", "socket.io": "2.0.1", diff --git a/test/chain-test.js b/test/chain-test.js index dac47e64..94808c98 100644 --- a/test/chain-test.js +++ b/test/chain-test.js @@ -12,7 +12,6 @@ const MTX = require('../lib/primitives/mtx'); const MemWallet = require('./util/memwallet'); const Network = require('../lib/protocol/network'); const Output = require('../lib/primitives/output'); -const util = require('../lib/utils/util'); const common = require('../lib/blockchain/common'); const opcodes = Script.opcodes; @@ -547,7 +546,7 @@ describe('Chain', function() { assert(output.script.isCommitment()); - commit = util.copy(output.script.get(1)); + commit = Buffer.from(output.script.get(1)); commit.fill(0, 10); output.script.set(1, commit); output.script.compile();