diff --git a/lib/bcoin/address.js b/lib/bcoin/address.js index d56781ba..d85de67e 100644 --- a/lib/bcoin/address.js +++ b/lib/bcoin/address.js @@ -103,7 +103,7 @@ Address.prototype.getBalance = function getBalance() { Address.prototype.setRedeem = function setRedeem(redeem) { var old = this.getScriptAddress(); - if (!utils.isBytes(redeem)) + if (!Buffer.isBuffer(redeem)) redeem = bcoin.script.encode(redeem); this.type = 'multisig'; @@ -116,7 +116,7 @@ Address.prototype.addKey = function addKey(key) { var old = this.getScriptAddress(); var cur; - key = utils.toBuffer(key); + key = utils.ensureBuffer(key); var has = this.keys.some(function(k) { return utils.isEqual(k, key); @@ -144,7 +144,7 @@ Address.prototype.removeKey = function removeKey(key) { var old = this.getScriptAddress(); var cur; - key = utils.toBuffer(key); + key = utils.ensureBuffer(key); var index = this.keys.map(function(k, i) { return utils.isEqual(k, key) ? i : null; @@ -192,8 +192,8 @@ Address.prototype.getScript = function getScript() { return this._script; if (this.redeem) { - redeem = this.redeem.slice(); - assert(utils.isBytes(redeem)); + redeem = this.redeem; + assert(Buffer.isBuffer(redeem)); } else if (this.keys.length < this.n) { redeem = bcoin.script.createPubkeyhash(this.getKeyHash()); redeem = bcoin.script.encode(redeem); @@ -472,19 +472,23 @@ Address.prototype.toExplore = function toExplore() { }; Address.hash160 = function hash160(key) { - key = utils.toBuffer(key); + key = utils.ensureBuffer(key); return utils.ripesha(key); }; Address.toAddress = function toAddress(hash, prefix) { var addr; - hash = utils.toArray(hash, 'hex'); + if (!Buffer.isBuffer(hash)) + hash = new Buffer(hash, 'hex'); + + addr = new Buffer(1 + hash.length + 4); prefix = network.prefixes[prefix || 'pubkeyhash']; - hash = [prefix].concat(hash); - addr = hash.concat(utils.checksum(hash)); + utils.writeU8(addr, prefix, 0); + utils.copy(hash, addr, 1); + utils.copy(utils.checksum(addr.slice(0, 21)), addr, 21); return utils.toBase58(addr); }; @@ -499,21 +503,27 @@ Address.toHash = function toHash(addr, prefix) { if (prefix == null && typeof addr === 'string') prefix = Address.prefixes[addr[0]]; - if (!utils.isBuffer(addr)) + if (!Buffer.isBuffer(addr)) addr = utils.fromBase58(addr); prefix = network.prefixes[prefix || 'pubkeyhash']; - if (addr.length !== 25) - return []; + if (addr.length !== 25) { + utils.debug('Address is not the right length.'); + return new Buffer([]); + } - if (addr[0] !== prefix) - return []; + if (addr[0] !== prefix) { + utils.debug('Address is not the right prefix.'); + return new Buffer([]); + } chk = utils.checksum(addr.slice(0, -4)); - if (utils.readU32(chk, 0) !== utils.readU32(addr, 21)) - return []; + if (utils.readU32(chk, 0) !== utils.readU32(addr, 21)) { + utils.debug('Address checksum failed.'); + return new Buffer([]); + } return addr.slice(1, -4); }; @@ -523,7 +533,7 @@ Address.__defineGetter__('prefixes', function() { return Address._prefixes; Address._prefixes = ['pubkeyhash', 'scripthash'].reduce(function(out, prefix) { - var ch = Address.compile([], prefix)[0]; + var ch = Address.compile(new Buffer([]), prefix)[0]; out[ch] = prefix; return out; }, {}); diff --git a/lib/bcoin/block.js b/lib/bcoin/block.js index c7b6ade7..00638d3d 100644 --- a/lib/bcoin/block.js +++ b/lib/bcoin/block.js @@ -96,18 +96,18 @@ function Block(data, subtype) { Block.prototype.hash = function hash(enc) { // Hash it if (!this._hash) - this._hash = utils.toHex(utils.dsha256(this.abbr())); - return enc === 'hex' ? this._hash : utils.toArray(this._hash, 'hex'); + this._hash = utils.dsha256(this.abbr()); + return enc === 'hex' ? this._hash.toString('hex') : this._hash; }; Block.prototype.abbr = function abbr() { if (this.network && this._raw) - return utils.toArray(this._raw.slice(0, 80)); + return this._raw.slice(0, 80); - var res = new Array(80); + var res = new Buffer(80); utils.write32(res, this.version, 0); - utils.copy(utils.toArray(this.prevBlock, 'hex'), res, 4); - utils.copy(utils.toArray(this.merkleRoot, 'hex'), res, 36); + utils.copy(new Buffer(this.prevBlock, 'hex'), res, 4); + utils.copy(new Buffer(this.merkleRoot, 'hex'), res, 36); utils.writeU32(res, this.ts, 68); utils.writeU32(res, this.bits, 72); utils.writeU32(res, this.nonce, 76); @@ -128,7 +128,7 @@ Block.verify = function verify(data, subtype) { Block.prototype.render = function render() { if (this.network && this._raw && this._raw.length > 80) - return utils.toArray(this._raw); + return this._raw; return bcoin.protocol.framer.block(this, this.subtype); }; @@ -337,7 +337,7 @@ Block.prototype.getCoinbaseHeight = function getCoinbaseHeight() { s = coinbase.inputs[0].script; - if (Array.isArray(s[0])) + if (Buffer.isBuffer(s[0])) height = bcoin.script.num(s[0], true); else height = -1; @@ -502,7 +502,7 @@ Block.fromJSON = function fromJSON(json) { assert.equal(json.v, 1); assert.equal(json.type, 'block'); - raw = utils.toArray(json.block, 'hex'); + raw = new Buffer(json.block, 'hex'); parser = new bcoin.protocol.parser(); @@ -578,9 +578,6 @@ Block.fromRaw = function fromRaw(data, enc) { if (enc === 'hex') data = new Buffer(data, 'hex'); - if (Array.isArray(data)) - data = new Buffer(data); - return new Block(parser.parseBlock(data), 'block'); }; diff --git a/lib/bcoin/bloom.js b/lib/bcoin/bloom.js index 2964bcc9..6c6eede5 100644 --- a/lib/bcoin/bloom.js +++ b/lib/bcoin/bloom.js @@ -35,7 +35,7 @@ Bloom.prototype.reset = function reset() { Bloom.prototype.add = function add(val, enc) { var i, bit, pos, shift; - val = utils.toArray(val, enc); + val = utils.toBuffer(val, enc); for (i = 0; i < this.n; i++) { bit = this.hash(val, i); @@ -49,7 +49,7 @@ Bloom.prototype.add = function add(val, enc) { Bloom.prototype.test = function test(val, enc) { var i, bit, pos, shift; - val = utils.toArray(val, enc); + val = utils.toBuffer(val, enc); for (i = 0; i < this.n; i++) { bit = this.hash(val, i); @@ -63,11 +63,13 @@ Bloom.prototype.test = function test(val, enc) { return true; }; -Bloom.prototype.toArray = function toArray() { +Bloom.prototype.toBuffer = function toBuffer() { var bytes = Math.ceil(this.size / 8); - var res = new Array(this.filter.length * 4); + var res = new Buffer(this.filter.length * 4); var i, w; + res.fill(0); + for (i = 0; i < this.filter.length; i++) { w = this.filter[i]; res[i * 4] = w & 0xff; @@ -76,7 +78,8 @@ Bloom.prototype.toArray = function toArray() { res[i * 4 + 3] = (w >> 24) & 0xff; } - return res.slice(0, bytes); + // return res.slice(0, bytes); + return res; }; function mul32(a, b) { @@ -112,7 +115,7 @@ function rotl32(w, b) { } function hash(data, seed) { - data = utils.toArray(data); + data = utils.toBuffer(data); var c1 = 0xcc9e2d51; var c2 = 0x1b873593; diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index 8d0d839d..7fbf8262 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -1487,7 +1487,7 @@ Chain.prototype.hasBlock = function hasBlock(hash) { if (typeof hash === 'number') return this.db.has(hash); - if (utils.isBuffer(hash)) + if (Buffer.isBuffer(hash)) hash = utils.toHex(hash); else if (hash.hash) hash = hash.hash('hex'); @@ -1500,7 +1500,7 @@ Chain.prototype.hasOrphan = function hasOrphan(hash) { }; Chain.prototype.hasPending = function hasPending(hash) { - if (utils.isBuffer(hash)) + if (Buffer.isBuffer(hash)) hash = utils.toHex(hash); else if (hash.hash) hash = hash.hash('hex'); @@ -1512,7 +1512,7 @@ Chain.prototype.getEntry = function getEntry(hash) { if (typeof hash === 'number') return this.db.getSync(hash); - if (utils.isBuffer(hash)) + if (Buffer.isBuffer(hash)) hash = utils.toHex(hash); else if (hash.hash) hash = hash.hash('hex'); @@ -1524,7 +1524,7 @@ Chain.prototype.getEntryAsync = function getEntryAsync(hash, callback) { if (typeof hash === 'number') return this.db.getAsync(hash, callback); - if (utils.isBuffer(hash)) + if (Buffer.isBuffer(hash)) hash = utils.toHex(hash); else if (hash.hash) hash = hash.hash('hex'); @@ -1533,7 +1533,7 @@ Chain.prototype.getEntryAsync = function getEntryAsync(hash, callback) { }; Chain.prototype.getOrphan = function getOrphan(hash) { - if (utils.isBuffer(hash)) + if (Buffer.isBuffer(hash)) hash = utils.toHex(hash); else if (hash.hash) hash = hash.hash('hex'); @@ -1637,7 +1637,7 @@ Chain.prototype.getLocator = function getLocator(start) { var i, existing; if (start) { - if (utils.isBuffer(start)) + if (Buffer.isBuffer(start)) start = utils.toHex(start); else if (start.hash) start = start.hash('hex'); @@ -1690,7 +1690,7 @@ Chain.prototype.getLocatorAsync = function getLocatorAsync(start, callback, forc return; if (start) { - if (utils.isBuffer(start)) + if (Buffer.isBuffer(start)) start = utils.toHex(start); else if (start.hash) start = start.hash('hex'); @@ -1754,7 +1754,7 @@ Chain.prototype.getOrphanRoot = function getOrphanRoot(hash) { var self = this; var root; - if (utils.isBuffer(hash)) + if (Buffer.isBuffer(hash)) hash = utils.toHex(hash); else if (hash.hash) hash = hash.hash('hex'); diff --git a/lib/bcoin/chainblock.js b/lib/bcoin/chainblock.js index 3d2d11e5..4ba6a379 100644 --- a/lib/bcoin/chainblock.js +++ b/lib/bcoin/chainblock.js @@ -126,12 +126,12 @@ ChainBlock.prototype.toRaw = function toRaw() { var res = new Buffer(ChainBlock.BLOCK_SIZE); utils.write32(res, this.version, 0); - utils.copy(utils.toArray(this.prevBlock, 'hex'), res, 4); - utils.copy(utils.toArray(this.merkleRoot, 'hex'), res, 36); + utils.copy(new Buffer(this.prevBlock, 'hex'), res, 4); + utils.copy(new Buffer(this.merkleRoot, 'hex'), res, 36); utils.writeU32(res, this.ts, 68); utils.writeU32(res, this.bits, 72); utils.writeU32(res, this.nonce, 76); - utils.copy(this.chainwork.toArray('be', 32), res, 80); + utils.copy(new Buffer(this.chainwork.toArray('be', 32)), res, 80); return res; }; diff --git a/lib/bcoin/coin.js b/lib/bcoin/coin.js index 707506a1..af2b290d 100644 --- a/lib/bcoin/coin.js +++ b/lib/bcoin/coin.js @@ -51,7 +51,7 @@ function Coin(tx, index) { this._offset = options._offset || 0; } - if (utils.isBuffer(this.hash)) + if (Buffer.isBuffer(this.hash)) this.hash = utils.toHex(this.hash); this.rhash = utils.revHex(this.hash); @@ -136,7 +136,7 @@ Coin.fromJSON = function fromJSON(json) { version: json.version, height: json.height, value: utils.satoshi(json.value), - script: bcoin.script.decode(utils.toArray(json.script, 'hex')), + script: bcoin.script.decode(new Buffer(json.script, 'hex')), hash: json.hash, index: json.index, spent: json.spent, @@ -162,7 +162,7 @@ Coin.fromFullJSON = function fromFullJSON(json) { version: json.version, height: json.height, value: utils.satoshi(json.value), - script: bcoin.script.decode(utils.toArray(json.script, 'hex')), + script: bcoin.script.decode(new Buffer(json.script, 'hex')), hash: utils.revHex(json.hash), index: json.index, spent: json.spent, @@ -190,7 +190,7 @@ Coin.prototype.toRaw = function toRaw(enc, strict) { off += utils.copy(script, data, off); if (!strict) { - off += utils.copy(utils.toArray(this.hash, 'hex'), data, off); + off += utils.copy(new Buffer(this.hash, 'hex'), data, off); off += utils.writeU32(data, this.index, off); off += utils.writeU8(data, this.spent ? 1 : 0, off); } @@ -206,7 +206,7 @@ Coin.fromRaw = function fromRaw(data, enc, strict) { var version, height, value, script, hash, index, spent, scriptLen; if (enc === 'hex') - data = utils.toArray(data, 'hex'); + data = new Buffer(data, 'hex'); if (data.length < 17 + (!strict ? 37 : 0)) throw new Error('Invalid utxo size'); @@ -229,7 +229,7 @@ Coin.fromRaw = function fromRaw(data, enc, strict) { if (off + scriptLen > data.length - (!strict ? 37 : 0)) throw new Error('Invalid utxo script length'); - script = bcoin.script.decode(utils.toArray(data.slice(off, off + scriptLen))); + script = bcoin.script.decode(data.slice(off, off + scriptLen)); off += scriptLen; if (!strict) { diff --git a/lib/bcoin/ec.js b/lib/bcoin/ec.js index 3f80646f..93928f1f 100644 --- a/lib/bcoin/ec.js +++ b/lib/bcoin/ec.js @@ -24,17 +24,17 @@ ec.generate = function generate(options) { pub = bcoin.secp256k1.publicKeyCreate(priv, true); priv = utils.toArray(priv); pub = utils.toArray(pub); - return bcoin.ecdsa.keyPair({ priv: priv, pub: pub }); + return bcoin.keypair({ priv: priv, pub: pub }); } - return bcoin.ecdsa.genKeyPair(options); + return bcoin.keypair(options); }; ec.verify = function verify(msg, sig, key, historical) { - if (key.getPublic) - key = key.getPublic(true, 'array'); + if (key.getPublicKey) + key = key.getPublicKey(); - if (!utils.isBuffer(sig)) + if (!Buffer.isBuffer(sig)) return false; if (sig.length === 0) @@ -54,10 +54,6 @@ ec.verify = function verify(msg, sig, key, historical) { if (historical) sig = ec.toLowS(sig); - msg = new Buffer(msg); - sig = new Buffer(sig); - key = new Buffer(key) - // Import from DER. sig = bcoin.secp256k1.signatureImport(sig); @@ -85,8 +81,7 @@ ec.sign = function sign(msg, key) { var sig; if (bcoin.secp256k1) { - msg = new Buffer(msg); - key = new Buffer(key.getPrivate().toArray('be', 32)); + key = key.getPrivateKey(); // Sign message sig = bcoin.secp256k1.sign(msg, key); @@ -96,14 +91,12 @@ ec.sign = function sign(msg, key) { // Convert to DER array sig = bcoin.secp256k1.signatureExport(sig); - - sig = utils.toArray(sig); } else { // Sign message and ensure low S value - sig = bcoin.ecdsa.sign(msg, key.priv, { canonical: true }); + sig = bcoin.ecdsa.sign(msg, key.privatePoint, { canonical: true }); // Convert to DER array - sig = sig.toDER(); + sig = new Buffer(sig.toDER()); } return sig; @@ -156,7 +149,7 @@ function getLength(buf, p) { ec.isLowS = function isLowS(sig) { if (!sig.s) { - if (!utils.isBuffer(sig)) + if (!Buffer.isBuffer(sig)) return false; try { @@ -182,7 +175,7 @@ ec.isLowS = function isLowS(sig) { ec.toLowS = function toLowS(sig) { if (!sig.s) { - assert(utils.isBuffer(sig)); + assert(Buffer.isBuffer(sig)); try { sig = new bcoin.ecdsa.signature(sig); @@ -196,5 +189,5 @@ ec.toLowS = function toLowS(sig) { if (sig.s.cmp(bcoin.ecdsa.nh) > 0) sig.s = bcoin.ecdsa.n.sub(sig.s); - return sig.toDER(); + return new Buffer(sig.toDER()); }; diff --git a/lib/bcoin/hd.js b/lib/bcoin/hd.js index 638bac36..8654d971 100644 --- a/lib/bcoin/hd.js +++ b/lib/bcoin/hd.js @@ -75,7 +75,7 @@ function HDSeed(options) { options = options || {}; this.bits = options.bits || 128; - this.entropy = options.entropy || elliptic.rand(this.bits / 8); + this.entropy = options.entropy || new Buffer(elliptic.rand(this.bits / 8)); this.mnemonic = options.mnemonic || HDSeed._mnemonic(this.entropy); this.seed = this.createSeed(options.passphrase); } @@ -149,7 +149,7 @@ function HDPrivateKey(options) { if (options.seed && typeof options.seed === 'object' - && !utils.isBuffer(options.seed) + && !Buffer.isBuffer(options.seed) && !(options.seed instanceof bcoin.hd.seed)) { options.seed = bcoin.hd.seed(options.seed); } @@ -531,54 +531,54 @@ HDPrivateKey.prototype._normalize = function _normalize(data) { // version = uint_32be if (typeof data.version === 'string') - data.version = utils.toArray(data.version, 'hex'); + data.version = new Buffer(data.version, 'hex'); else if (typeof data.version === 'number') data.version = array32(data.version); // depth = unsigned char if (typeof data.depth === 'string') - data.depth = utils.toArray(data.depth, 'hex'); + data.depth = new Buffer(data.depth, 'hex'); else if (typeof data.depth === 'number') - data.depth = [data.depth]; + data.depth = new Buffer([data.depth]); if (new bn(data.depth).toNumber() > 0xff) throw new Error('Depth is too high'); // parent finger print = uint_32be if (typeof data.parentFingerPrint === 'string') - data.parentFingerPrint = utils.toArray(data.parentFingerPrint, 'hex'); + data.parentFingerPrint = new Buffer(data.parentFingerPrint, 'hex'); else if (typeof data.parentFingerPrint === 'number') data.parentFingerPrint = array32(data.parentFingerPrint); // child index = uint_32be if (typeof data.childIndex === 'string') - data.childIndex = utils.toArray(data.childIndex, 'hex'); + data.childIndex = new Buffer(data.childIndex, 'hex'); else if (typeof data.childIndex === 'number') data.childIndex = array32(data.childIndex); // chain code = 32 bytes if (typeof data.chainCode === 'string') - data.chainCode = utils.toArray(data.chainCode, 'hex'); + data.chainCode = new Buffer(data.chainCode, 'hex'); // private key = 32 bytes if (data.privateKey) { - if (data.privateKey.getPrivate) - data.privateKey = data.privateKey.getPrivate().toArray('be', 32); + if (data.privateKey.getPrivateKey) + data.privateKey = data.privateKey.getPrivateKey(); else if (typeof data.privateKey === 'string') - data.privateKey = utils.toBuffer(data.privateKey); + data.privateKey = utils.ensureBuffer(data.privateKey); } // public key = 33 bytes if (data.publicKey) { - if (data.publicKey.getPublic) - data.publicKey = data.privateKey.getPublic(true, 'array'); + if (data.publicKey.getPublicKey) + data.publicKey = data.privateKey.getPublicKey(); else if (typeof data.publicKey === 'string') - data.publicKey = utils.toBuffer(data.publicKey); + data.publicKey = utils.ensureBuffer(data.publicKey); } // checksum = 4 bytes if (typeof data.checksum === 'string') - data.checksum = utils.toArray(data.checksum, 'hex'); + data.checksum = new Buffer(data.checksum, 'hex'); else if (typeof data.checksum === 'number') data.checksum = array32(data.checksum); @@ -592,7 +592,7 @@ HDPrivateKey.prototype._seed = function _seed(seed) { seed = seed.seed; if (utils.isHex(seed)) - seed = utils.toArray(seed, 'hex'); + seed = new Buffer(seed, 'hex'); if (seed.length < constants.hd.minEntropy || seed.length > constants.hd.maxEntropy) { @@ -614,15 +614,15 @@ HDPrivateKey.prototype._seed = function _seed(seed) { HDPrivateKey.prototype._generate = function _generate(privateKey, entropy) { if (!privateKey) - privateKey = bcoin.ec.generate().getPrivate().toArray('be', 32); + privateKey = bcoin.ec.generate().getPrivateKey(); if (utils.isHex(privateKey)) - privateKey = utils.toArray(privateKey, 'hex'); + privateKey = new Buffer(privateKey, 'hex'); else if (utils.isBase58(privateKey)) - privateKey = bcoin.keypair.fromSecret(privateKey).getPrivate().toArray('be', 32); + privateKey = bcoin.keypair.fromSecret(privateKey).getPrivateKey(); if (!entropy) - entropy = elliptic.rand(32); + entropy = new Buffer(elliptic.rand(32)); return { version: network[this.network].prefixes.xprivkey, @@ -670,7 +670,7 @@ HDPrivateKey.prototype._unbuild = function _unbuild(xkey) { }; HDPrivateKey.prototype._build = function _build(data) { - var sequence = new Array(82); + var sequence = new Buffer(82); var off = 0; var checksum, xprivkey, pair, privateKey, publicKey, size, fingerPrint; @@ -688,9 +688,9 @@ HDPrivateKey.prototype._build = function _build(data) { xprivkey = utils.toBase58(sequence); - pair = bcoin.ecdsa.keyPair({ priv: data.privateKey }); - privateKey = pair.getPrivate().toArray('be', 32); - publicKey = pair.getPublic(true, 'array'); + pair = bcoin.keypair({ privateKey: data.privateKey }); + privateKey = pair.getPrivateKey(); + publicKey = pair.getPublicKey(); size = constants.hd.parentFingerPrintSize; fingerPrint = utils.ripesha(publicKey).slice(0, size); @@ -722,11 +722,12 @@ HDPrivateKey.prototype._build = function _build(data) { this.hdPrivateKey = this; this.xpubkey = this.hdPublicKey.xpubkey; - this.pair = bcoin.ecdsa.keyPair({ priv: this.privateKey }); + this.pair = bcoin.keypair({ privateKey: this.privateKey }); }; HDPrivateKey.prototype.derive = function derive(index, hardened) { var cached, data, hash, leftPart, chainCode, privateKey, child; + var off = 0; if (typeof index === 'string') return this.deriveString(index); @@ -740,18 +741,25 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) { if (index < constants.hd.hardened && hardened) index += constants.hd.hardened; - data = hardened - ? [0].concat(this.privateKey).concat(array32(index)) - : data = [].concat(this.publicKey).concat(array32(index)); + if (hardened) { + data = new Buffer(1 + this.privateKey.length + 4); + off += utils.writeU8(data, 0, off); + off += this.privateKey.copy(data, off, 0, this.privateKey.length); + off += utils.writeU32BE(data, index, off); + } else { + data = new Buffer(this.publicKey.length + 4); + off += this.publicKey.copy(data, off, 0, this.publicKey.length); + off += utils.writeU32BE(data, index, off); + } hash = utils.sha512hmac(data, this.chainCode); leftPart = new bn(hash.slice(0, 32)); chainCode = hash.slice(32, 64); - privateKey = leftPart + privateKey = new Buffer(leftPart .add(new bn(this.privateKey)) .mod(ec.curve.n) - .toArray('be', 32); + .toArray('be', 32)); child = new HDPrivateKey({ network: this.network, @@ -1012,7 +1020,7 @@ HDPublicKey.prototype._unbuild = function _unbuild(xkey) { }; HDPublicKey.prototype._build = function _build(data) { - var sequence = new Array(82); + var sequence = new Buffer(82); var off = 0; var checksum, xpubkey, publicKey, size, fingerPrint; @@ -1051,11 +1059,12 @@ HDPublicKey.prototype._build = function _build(data) { this.fingerPrint = fingerPrint; this.xprivkey = data.xprivkey; - this.pair = bcoin.ecdsa.keyPair({ pub: this.publicKey }); + this.pair = bcoin.keypair({ publicKey: this.publicKey }); }; HDPublicKey.prototype.derive = function derive(index, hardened) { var cached, data, hash, leftPart, chainCode, pair, point, publicKey, child; + var off = 0; if (typeof index === 'string') return this.deriveString(index); @@ -1071,14 +1080,17 @@ HDPublicKey.prototype.derive = function derive(index, hardened) { if (index < 0) throw new Error('invalid path'); - data = [].concat(this.publicKey).concat(array32(index)); + data = new Buffer(this.publicKey.length + 4); + off += this.publicKey.copy(data, off, 0, this.publicKey.length); + off += utils.writeU32BE(data, index, off); + hash = utils.sha512hmac(data, this.chainCode); leftPart = new bn(hash.slice(0, 32)); chainCode = hash.slice(32, 64); - pair = bcoin.ecdsa.keyPair({ pub: this.publicKey }); - point = ec.curve.g.mul(leftPart).add(pair.pub); - publicKey = bcoin.ecdsa.keyPair({ pub: point }).getPublic(true, 'array'); + pair = bcoin.keypair({ publicKey: this.publicKey }); + point = ec.curve.g.mul(leftPart).add(pair.publicPoint); + publicKey = bcoin.keypair({ publicKey: point }).getPublicKey(); child = new HDPublicKey({ network: this.network, @@ -1132,14 +1144,6 @@ HDPublicKey.prototype.deriveString = function deriveString(path) { return this.pair.validate.apply(this.pair, arguments); }; - HD.prototype.getPublic = function getPublic() { - return this.pair.getPublic.apply(this.pair, arguments); - }; - - HD.prototype.getPrivate = function getPrivate() { - return this.pair.getPrivate.apply(this.pair, arguments); - }; - HD.prototype.getPublicKey = function getPublicKey() { return bcoin.keypair.prototype.getPublicKey.apply(this, arguments); }; @@ -1156,12 +1160,12 @@ HDPublicKey.prototype.deriveString = function deriveString(path) { return this.pair.verify.apply(this.pair, arguments); }; - HD.prototype.__defineGetter__('pub', function() { - return this.pair.pub; + HD.prototype.__defineGetter__('publicPoint', function() { + return this.pair.publicPoint; }); - HD.prototype.__defineGetter__('priv', function() { - return this.pair.priv; + HD.prototype.__defineGetter__('privatePoint', function() { + return this.pair.privatePoint; }); HD.prototype.compressed = true; @@ -1180,7 +1184,7 @@ HDPrivateKey.fromSecret = function fromSecret(privateKey) { */ function array32(data) { - var b = []; + var b = new Buffer(4); utils.writeU32BE(b, data, 0); return b; } @@ -1211,13 +1215,9 @@ function pbkdf2(key, salt, iterations, dkLen) { if (typeof key === 'string') key = new Buffer(key, 'ascii'); - else if (Array.isArray(key)) - key = new Buffer(key); if (typeof salt === 'string') salt = new Buffer(salt, 'ascii'); - else if (Array.isArray(key)) - salt = new Buffer(salt); var DK = new Buffer(dkLen); var U = new Buffer(hLen); diff --git a/lib/bcoin/input.js b/lib/bcoin/input.js index 1818c75a..1fde2ee4 100644 --- a/lib/bcoin/input.js +++ b/lib/bcoin/input.js @@ -31,7 +31,7 @@ function Input(options) { if (options.output) this.output = bcoin.coin(options.output); - if (utils.isBuffer(this.prevout.hash)) + if (Buffer.isBuffer(this.prevout.hash)) this.prevout.hash = utils.toHex(this.prevout.hash); if (!this.prevout.rhash) @@ -384,7 +384,7 @@ Input.fromFullJSON = function fromFullJSON(json) { index: json.prevout.index }, output: json.output ? bcoin.coin.fromFullJSON(json.output) : null, - script: bcoin.script.decode(utils.toArray(json.script, 'hex')), + script: bcoin.script.decode(new Buffer(json.script, 'hex')), sequence: json.sequence }); }; diff --git a/lib/bcoin/keypair.js b/lib/bcoin/keypair.js index 5efed4ce..49321aa8 100644 --- a/lib/bcoin/keypair.js +++ b/lib/bcoin/keypair.js @@ -71,12 +71,12 @@ function KeyPair(options) { } } -KeyPair.prototype.__defineGetter__('priv', function() { - return this.pair.priv; +KeyPair.prototype.__defineGetter__('privatePoint', function() { + return this.pair.getPrivate(); }); -KeyPair.prototype.__defineGetter__('pub', function() { - return this.pair.pub; +KeyPair.prototype.__defineGetter__('publicPoint', function() { + return this.pair.getPublic(); }); KeyPair.prototype.__defineGetter__('privateKey', function() { @@ -99,21 +99,21 @@ KeyPair.prototype.verify = function verify(msg, signature) { return this.pair.verify.apply(this.pair, arguments); }; -KeyPair.prototype.getPrivate = function getPrivate(enc) { - return this.pair.getPrivate.apply(this.pair, arguments); -}; - -KeyPair.prototype.getPublic = function getPublic(enc) { - return this.pair.getPublic.apply(this.pair, arguments); -}; - KeyPair.prototype.getPrivateKey = function getPrivateKey(enc) { - var privateKey = this.pair.getPrivate(); + var privateKey; - if (!privateKey) - return; + if (!this._privateKey) { + privateKey = this.pair.getPrivate(); - privateKey = privateKey.toArray('be', 32); + if (!privateKey) + return; + + privateKey = new Buffer(privateKey.toArray('be', 32)); + + this._privateKey = privateKey; + } + + privateKey = this._privateKey; if (enc === 'base58') return KeyPair.toSecret(privateKey, this.compressed); @@ -125,7 +125,12 @@ KeyPair.prototype.getPrivateKey = function getPrivateKey(enc) { }; KeyPair.prototype.getPublicKey = function getPublicKey(enc) { - var publicKey = this.pair.getPublic(this.compressed, 'array'); + var publicKey; + + if (!this._publicKey) + this._publicKey = new Buffer(this.pair.getPublic(this.compressed, 'array')); + + publicKey = this._publicKey; if (enc === 'base58') return utils.toBase58(publicKey); @@ -141,23 +146,19 @@ KeyPair.prototype.toSecret = function toSecret() { }; KeyPair.toSecret = function toSecret(privateKey, compressed) { - var arr, chk; + var buf = new Buffer(1 + privateKey.length + (compressed ? 1 : 0) + 4); + var off = 0; + var chk; - // We'll be using ncompressed public key as an address - arr = [network.prefixes.privkey]; - - // 0-pad key - while (arr.length + privateKey.length < 33) - arr.push(0); - - arr = arr.concat(privateKey); + off += utils.writeU8(buf, network.prefixes.privkey, 0); + off += utils.copy(privateKey, buf, off); if (compressed !== false) - arr.push(1); + off += utils.writeU8(buf, 1, off); - chk = utils.checksum(arr); + utils.copy(utils.checksum(buf.slice(0, off)), buf, off); - return utils.toBase58(arr.concat(chk)); + return utils.toBase58(buf); }; KeyPair.fromSecret = function fromSecret(privateKey) { @@ -185,14 +186,14 @@ KeyPair.fromSecret = function fromSecret(privateKey) { KeyPair.verify = function verify(msg, sig, key) { try { - return bcoin.ecdsa.verify(msg, sig, key); + return bcoin.ec.verify(msg, sig, key); } catch (e) { return false; } }; KeyPair.sign = function sign(msg, key) { - return bcoin.ecdsa.sign(msg, key.priv); + return bcoin.ec.sign(msg, key.priv); }; KeyPair.prototype.toJSON = function toJSON(passphrase) { diff --git a/lib/bcoin/miner.js b/lib/bcoin/miner.js index c66807b5..ced90739 100644 --- a/lib/bcoin/miner.js +++ b/lib/bcoin/miner.js @@ -226,7 +226,7 @@ Miner.prototype.createBlock = function createBlock(tx) { // of ours. This isn't really // necessary nowdays due to bip34 // (used above). - utils.nonce().toArray(), + new Buffer(utils.nonce().toArray()), // Let the world know this little // miner succeeded. utils.ascii2array(this.msg || 'mined by bcoin') @@ -279,7 +279,7 @@ Miner.prototype.updateCoinbase = function updateCoinbase(block) { if (!block) block = this.block; - coinbase.inputs[0].script[1] = block.extraNonce.toArray(); + coinbase.inputs[0].script[1] = new Buffer(block.extraNonce.toArray()); coinbase.outputs[0].value = reward.add(this.fee); }; diff --git a/lib/bcoin/output.js b/lib/bcoin/output.js index 0ec496d4..7d7f2a6e 100644 --- a/lib/bcoin/output.js +++ b/lib/bcoin/output.js @@ -269,7 +269,7 @@ Output.prototype.toFullJSON = function toFullJSON() { Output.fromFullJSON = function fromFullJSON(json) { return new Output({ value: utils.satoshi(json.value), - script: bcoin.script.decode(utils.toArray(json.script, 'hex')) + script: bcoin.script.decode(new Buffer(json.script, 'hex')) }); }; diff --git a/lib/bcoin/peer.js b/lib/bcoin/peer.js index dfc3f33c..d54a80dc 100644 --- a/lib/bcoin/peer.js +++ b/lib/bcoin/peer.js @@ -166,10 +166,10 @@ Peer.prototype._init = function init() { self.ack = true; self.emit('ack'); self.ts = utils.now(); - self._write(self.framer.packet('getaddr', [])); + self._write(self.framer.packet('getaddr', new Buffer([]))); // if (self.pool.options.headers) { // if (self.version && self.version.v > 70012) - // self._write(self.framer.packet('sendheaders', [])); + // self._write(self.framer.packet('sendheaders', new Buffer([]))); // } }); @@ -219,7 +219,7 @@ Peer.prototype.broadcast = function broadcast(items) { return; if (!Array.isArray(items)) - items = [ items ]; + items = [items]; result = items.map(function(item) { var key = item.hash('hex'); @@ -305,7 +305,7 @@ Peer.prototype._write = function write(chunk) { if (this.destroyed) return; - this.socket.write(new Buffer(chunk)); + this.socket.write(chunk); }; Peer.prototype._error = function error(err) { diff --git a/lib/bcoin/pool.js b/lib/bcoin/pool.js index fb19b00f..71ed95e8 100644 --- a/lib/bcoin/pool.js +++ b/lib/bcoin/pool.js @@ -993,7 +993,7 @@ Pool.prototype._addPeer = function _addPeer() { }; Pool.prototype.markTX = function(hash, state) { - if (utils.isBuffer(hash)) + if (Buffer.isBuffer(hash)) hash = utils.toHex(hash); else if (hash.hash) hash = hash.hash('hex'); @@ -1138,7 +1138,7 @@ Pool.prototype.isWatched = function(tx, bloom) { function testScript(script) { return script.some(function(chunk) { - if (!Array.isArray(chunk) || chunk.length === 0) + if (!Buffer.isBuffer(chunk) || chunk.length === 0) return false; return bloom.test(chunk); }); @@ -1164,7 +1164,7 @@ Pool.prototype.isWatched = function(tx, bloom) { prev = input.prevout.hash; if (typeof prev === 'string') - prev = utils.toArray(prev, 'hex'); + prev = new Buffer(prev, 'hex'); // Test the prev_out tx hash if (bloom.test(prev)) @@ -1387,7 +1387,7 @@ Pool.prototype.search = function search(id, range, callback) { } if (typeof id === 'string') - id = utils.toArray(id, 'hex'); + id = new Buffer(id, 'hex'); if (typeof range === 'number') range = { start: range, end: null }; @@ -1449,7 +1449,7 @@ Pool.prototype.getData = function getData(peer, type, hash, options, callback) { if (!options) options = {}; - if (utils.isBuffer(hash)) + if (Buffer.isBuffer(hash)) hash = utils.toHex(hash); if (this.request.map[hash]) { @@ -1541,7 +1541,7 @@ Pool.prototype.scheduleRequests = function scheduleRequests(peer) { Pool.prototype.fulfill = function fulfill(hash) { var hash; - if (utils.isBuffer(hash)) + if (Buffer.isBuffer(hash)) hash = utils.toHex(hash); else if (hash.hash) hash = hash.hash('hex'); diff --git a/lib/bcoin/protocol/constants.js b/lib/bcoin/protocol/constants.js index 9870dde7..3b0a7f2f 100644 --- a/lib/bcoin/protocol/constants.js +++ b/lib/bcoin/protocol/constants.js @@ -258,12 +258,12 @@ exports.hd = { exports.locktimeThreshold = 500000000; // Tue Nov 5 00:53:20 1985 UTC -exports.oneHash = utils.toArray( +exports.oneHash = new Buffer( '0000000000000000000000000000000000000000000000000000000000000001', 'hex' ); -exports.zeroHash = utils.toArray( +exports.zeroHash = new Buffer( '0000000000000000000000000000000000000000000000000000000000000000', 'hex' ); diff --git a/lib/bcoin/protocol/framer.js b/lib/bcoin/protocol/framer.js index f2441786..7eb33328 100644 --- a/lib/bcoin/protocol/framer.js +++ b/lib/bcoin/protocol/framer.js @@ -22,12 +22,12 @@ function Framer(options) { this.options = options; - this.agent = utils.toArray(options.userAgent || constants.userAgent); + this.agent = new Buffer(options.userAgent || constants.userAgent, 'ascii'); this.agent = this.agent.slice(0, 0xfc); } Framer.prototype.header = function header(cmd, payload) { - var h = new Array(24); + var h = new Buffer(24); var len, i; assert(cmd.length < 12); @@ -52,11 +52,12 @@ Framer.prototype.header = function header(cmd, payload) { Framer.prototype.packet = function packet(cmd, payload) { var h = this.header(cmd, payload); - return h.concat(payload); + return Buffer.concat([h, payload]); }; -Framer.prototype._addr = function addr(p, off, data, full) { - var start = off; +Framer.prototype._addr = function addr(data, full) { + var p = new Buffer(26 + (full ? 4 : 0)); + var off = 0; if (!data) data = {}; @@ -68,7 +69,7 @@ Framer.prototype._addr = function addr(p, off, data, full) { data.services = constants.services.network; if (!data.ipv4) - data.ipv4 = []; + data.ipv4 = new Buffer([]); if (!data.port) data.port = network.port; @@ -97,13 +98,13 @@ Framer.prototype._addr = function addr(p, off, data, full) { // port off += utils.writeU16BE(p, data.port, off); - return off - start; + return p; }; Framer.prototype.version = function version(packet) { - var p = new Array(86 + this.agent.length); + var p = new Buffer(86 + this.agent.length); var off = 0; - var i; + var i, remote, local; if (!packet) packet = {}; @@ -118,10 +119,12 @@ Framer.prototype.version = function version(packet) { off += utils.write64(p, utils.now(), off); // Their address (recv) - off += this._addr(p, off, packet.remote || {}); + remote = this._addr(packet.remote || {}); + off += remote.copy(p, off, 0, remote.length); // Our address (from) - off += this._addr(p, off, packet.local || {}); + local = this._addr(packet.local || {}); + off += local.copy(p, off, 0, local.length); // Nonce, very dramatic off += utils.writeU64(p, utils.nonce(), off); @@ -142,19 +145,22 @@ Framer.prototype.version = function version(packet) { // Relay p[off++] = packet.relay ? 1 : 0; + assert(off === p.length); + return this.packet('version', p); }; Framer.prototype.verack = function verack() { - return this.packet('verack', []); + return this.packet('verack', new Buffer([])); }; Framer.prototype._inv = function _inv(command, items) { - var res = []; - var off, i, hash; + var res, off, i, hash; assert(items.length <= 50000); + res = new Buffer(utils.sizeIntv(items.length) + items.length * 36); + off = utils.writeIntv(res, items.length, 0); for (i = 0; i < items.length; i++) { @@ -164,11 +170,9 @@ Framer.prototype._inv = function _inv(command, items) { // Hash hash = items[i].hash; if (typeof hash === 'string') - hash = utils.toArray(hash, 'hex'); + hash = new Buffer(hash, 'hex'); assert.equal(hash.length, 32); - res = res.concat(hash); - - off += hash.length; + off += hash.copy(res, off, 0, hash.length); } return this.packet(command, res); @@ -187,21 +191,21 @@ Framer.prototype.notFound = function notFound(items) { }; Framer.prototype.ping = function ping(data) { - var p = []; + var p = new Buffer(8); utils.writeU64(p, data.nonce, 0); return this.packet('ping', p); }; Framer.prototype.pong = function pong(data) { - var p = []; + var p = new Buffer(8); utils.writeU64(p, data.nonce, 0); return this.packet('pong', p); }; Framer.prototype.filterLoad = function filterLoad(bloom, update) { - var filter = bloom.toArray(); - var before = []; - var after = new Array(9); + var filter = bloom.toBuffer(); + var before = new Buffer(utils.sizeIntv(filter.length)); + var after = new Buffer(9); utils.writeIntv(before, filter.length, 0); @@ -214,11 +218,11 @@ Framer.prototype.filterLoad = function filterLoad(bloom, update) { // nFlags after[8] = constants.filterFlags[update]; - return this.packet('filterload', before.concat(filter, after)); + return this.packet('filterload', Buffer.concat([before, filter, after])); }; Framer.prototype.filterClear = function filterClear() { - return this.packet('filterclear', []); + return this.packet('filterclear', new Buffer([])); }; Framer.prototype.getHeaders = function getHeaders(hashes, stop) { @@ -230,22 +234,22 @@ Framer.prototype.getBlocks = function getBlocks(hashes, stop) { }; Framer.prototype._getBlocks = function _getBlocks(cmd, hashes, stop) { - var p = []; - var off, i, hash, len; + var p = new Buffer(4 + utils.sizeIntv(hashes.length) + 32 * (hashes.length + 1)); + var i, hash, len; + var off = 0; // getheaders can have a null hash if (cmd === 'getheaders' && !hashes) hashes = []; - utils.writeU32(p, constants.version, 0); - off = 4 + utils.writeIntv(p, hashes.length, 4); - p.length = off + 32 * (hashes.length + 1); + off += utils.writeU32(p, constants.version, 0); + off += utils.writeIntv(p, hashes.length, 4); for (i = 0; i < hashes.length; i++) { hash = hashes[i]; if (typeof hash === 'string') - hash = utils.toArray(hash, 'hex'); + hash = new Buffer(hash, 'hex'); len = utils.copy(hash, p, off); @@ -256,7 +260,8 @@ Framer.prototype._getBlocks = function _getBlocks(cmd, hashes, stop) { } if (stop) { - stop = utils.toArray(stop, 'hex'); + if (typeof hash === 'string') + stop = new Buffer(stop, 'hex'); len = utils.copy(stop, p, off); } else { len = 0; @@ -280,7 +285,7 @@ Framer.tx = function tx(tx) { for (i = 0; i < tx.inputs.length; i++) { input = tx.inputs[i]; - off += utils.copy(utils.toArray(input.prevout.hash, 'hex'), p, off, true); + off += utils.copy(new Buffer(input.prevout.hash, 'hex'), p, off, true); off += utils.writeU32(p, input.prevout.index, off); s = bcoin.script.encode(input.script); @@ -303,7 +308,7 @@ Framer.tx = function tx(tx) { } off += utils.writeU32(p, tx.locktime, off); - return p; + return new Buffer(p); }; Framer.prototype.tx = function tx(tx) { @@ -322,10 +327,10 @@ Framer.block = function _block(block, type) { off += utils.write32(p, block.version, off); // prev_block - off += utils.copy(utils.toArray(block.prevBlock, 'hex'), p, off, true); + off += utils.copy(new Buffer(block.prevBlock, 'hex'), p, off, true); // merkle_root - off += utils.copy(utils.toArray(block.merkleRoot, 'hex'), p, off, true); + off += utils.copy(new Buffer(block.merkleRoot, 'hex'), p, off, true); // timestamp off += utils.writeU32(p, block.ts, off); @@ -345,7 +350,7 @@ Framer.block = function _block(block, type) { off += utils.writeIntv(p, block.hashes.length, off); // hashes for (i = 0; i < block.hashes.length; i++) - off += utils.copy(utils.toArray(block.hashes[i], 'hex'), p, off, true); + off += utils.copy(new Buffer(block.hashes[i], 'hex'), p, off, true); // flag count off += utils.writeIntv(p, block.flags.length, off); // flags @@ -362,7 +367,7 @@ Framer.block = function _block(block, type) { off += utils.copy(block.txs[i].render(), p, off, true); } - return p; + return new Buffer(p); }; Framer.prototype.block = function _block(block) { @@ -392,12 +397,14 @@ Framer.prototype.reject = function reject(details) { off += utils.copy(data, p, off, true); - return this.packet('reject', p); + return this.packet('reject', new Buffer(p)); }; Framer.prototype.addr = function addr(peers) { - var p = []; + var p = new Buffer(utils.sizeIntv(peers.length) + peers.length * 30); var off = 0; + var addrs = []; + var addr; var i, peer; off += utils.writeIntv(p, peers.length, off); @@ -405,20 +412,22 @@ Framer.prototype.addr = function addr(peers) { for (i = 0; i < peers.length; i++) { peer = peers[i]; - off += this._addr(p, off, { + addr = this._addr({ ts: peer.ts, services: peer.services, ipv6: peer.ipv6, ipv4: peer.ipv4, port: peer.port }, true); + + off += addr.copy(p, off, 0, addr.length); } return this.packet('addr', p); }; Framer.prototype.mempool = function mempool() { - return this.packet('mempool', []); + return this.packet('mempool', new Buffer([])); }; /** diff --git a/lib/bcoin/protocol/network.js b/lib/bcoin/protocol/network.js index 2a8bf757..56211c3b 100644 --- a/lib/bcoin/protocol/network.js +++ b/lib/bcoin/protocol/network.js @@ -48,7 +48,7 @@ main.seeds = [ main.port = 8333; -main.alertKey = utils.toArray('' +main.alertKey = new Buffer('' + '04fc9702847840aaf195de8442ebecedf5b095c' + 'dbb9bc716bda9110971b28a49e0ead8564ff0db' + '22209e0374782c093bb899692d524e9d6a6956e' @@ -149,7 +149,7 @@ testnet.seeds = [ testnet.port = 18333; -testnet.alertKey = utils.toArray('' +testnet.alertKey = new Buffer('' + '04302390343f91cc401d56d68b123028bf52e5f' + 'ca1939df127f63c6467cdf9c8e2c14b61104cf8' + '17d0b780da337893ecc4aaff1309e536162dabb' @@ -234,8 +234,8 @@ regtest.seeds = [ regtest.port = 18444; -regtest._alertKey = bcoin.ec.generate(); -regtest.alertKey = regtest._alertKey.getPublic(true, 'array'); +// regtest._alertKey = bcoin.ec.generate(); +// regtest.alertKey = regtest._alertKey.getPublic(true, 'array'); regtest.checkpoints = {}; regtest.checkpoints.tsLastCheckpoint = 0; diff --git a/lib/bcoin/protocol/parser.js b/lib/bcoin/protocol/parser.js index 96687572..9c84a4dc 100644 --- a/lib/bcoin/protocol/parser.js +++ b/lib/bcoin/protocol/parser.js @@ -235,7 +235,7 @@ Parser.prototype.parseInvList = function parseInvList(p) { for (i = 0, off = 0; i < count; i++, off += 36) { items.push({ type: constants.invByVal[utils.readU32(p, off)], - hash: utils.toArray(p.slice(off + 4, off + 36)) + hash: p.slice(off + 4, off + 36) }); } @@ -258,7 +258,7 @@ Parser.prototype.parseMerkleBlock = function parseMerkleBlock(p) { hashes = new Array(hashCount); for (i = 0; i < hashCount; i++) - hashes[i] = utils.toArray(p.slice(off + i * 32, off + (i + 1) * 32)); + hashes[i] = p.slice(off + i * 32, off + (i + 1) * 32); off = off + 32 * hashCount; flagCount = utils.readIntv(p, off); @@ -268,12 +268,12 @@ Parser.prototype.parseMerkleBlock = function parseMerkleBlock(p) { if (off + flagCount > p.length) return this._error('Invalid flag count'); - flags = utils.toArray(p.slice(off, off + flagCount)); + flags = p.slice(off, off + flagCount); return { version: utils.read32(p, 0), - prevBlock: utils.toArray(p.slice(4, 36)), - merkleRoot: utils.toArray(p.slice(36, 68)), + prevBlock: p.slice(4, 36), + merkleRoot: p.slice(36, 68), ts: utils.readU32(p, 68), bits: utils.readU32(p, 72), nonce: utils.readU32(p, 76), @@ -304,9 +304,9 @@ Parser.prototype.parseHeaders = function parseHeaders(p) { start = off; header.version = utils.read32(p, off); off += 4; - header.prevBlock = utils.toArray(p.slice(off, off + 32)); + header.prevBlock = p.slice(off, off + 32); off += 32; - header.merkleRoot = utils.toArray(p.slice(off, off + 32)); + header.merkleRoot = p.slice(off, off + 32); off += 32; header.ts = utils.readU32(p, off); off += 4; @@ -346,8 +346,8 @@ Parser.prototype.parseBlock = function parseBlock(p) { return { version: utils.read32(p, 0), - prevBlock: utils.toArray(p.slice(4, 36)), - merkleRoot: utils.toArray(p.slice(36, 68)), + prevBlock: p.slice(4, 36), + merkleRoot: p.slice(36, 68), ts: utils.readU32(p, 68), bits: utils.readU32(p, 72), nonce: utils.readU32(p, 76), @@ -374,10 +374,10 @@ Parser.prototype.parseTXIn = function parseTXIn(p) { return { _size: off + scriptLen + 4, prevout: { - hash: utils.toArray(p.slice(0, 32)), + hash: p.slice(0, 32), index: utils.readU32(p, 32) }, - script: bcoin.script.decode(utils.toArray(p.slice(off, off + scriptLen))), + script: bcoin.script.decode(p.slice(off, off + scriptLen)), sequence: utils.readU32(p, off + scriptLen) }; }; @@ -398,7 +398,7 @@ Parser.prototype.parseTXOut = function parseTXOut(p) { return { _size: off + scriptLen, value: utils.read64(p, 0), - script: bcoin.script.decode(utils.toArray(p.slice(off, off + scriptLen))) + script: bcoin.script.decode(p.slice(off, off + scriptLen)) }; }; @@ -498,7 +498,7 @@ Parser.prototype.parseReject = function parseReject(p) { off += reasonLen; - data = utils.toArray(p.slice(off, off + 32)); + data = p.slice(off, off + 32); return { message: message, @@ -524,7 +524,7 @@ Parser.prototype._parseAddr = function _parseAddr(p, off, full) { services = utils.readU64(p, off); off += 8; - ip = utils.toArray(p.slice(off, off + 16)); + ip = p.slice(off, off + 16); off += 16; port = utils.readU16BE(p, off); diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index dc359677..368b6c88 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -41,7 +41,7 @@ script.decode = function decode(s) { // Special case: this is an empty array // because it can be seen as an empty pushdata. if (b === 0x00) { - opcodes.push([]); + opcodes.push(new Buffer([])); continue; } @@ -99,57 +99,107 @@ script.decode = function decode(s) { script.encode = function encode(s) { if (!s) - return []; + return new Buffer([]); var opcodes = constants.opcodes; - var res = []; var i = 0; var instr; + var total = 0; + var off = 0; + var res; for (i = 0; i < s.length; i++) { instr = s[i]; - // Push value to stack - if (Array.isArray(instr)) { - // Check for nonstandard pushdatas that - // may have been decoded from before. + if (Array.isArray(instr)) + instr = s[i] = new Buffer(instr); + + if (Buffer.isBuffer(instr)) { if (instr.pushdata) { if (instr.pushdata.opcode === null) { - res = res.concat(instr.pushdata.len, instr); + total += 1 + instr.length; } else if (instr.pushdata.opcode === 'pushdata1') { - res = res.concat(opcodes.pushdata1, instr.pushdata.len, instr); + total += 1 + 1 + instr.length; } else if (instr.pushdata.opcode === 'pushdata2') { - res.push(opcodes.pushdata2); - utils.writeU16(res, instr.pushdata.len, res.length); - res = res.concat(instr); + total += 1 + 2 + instr.length; } else if (instr.pushdata.opcode === 'pushdata4') { - res.push(opcodes.pushdata4); - utils.writeU32(res, instr.pushdata.len, res.length); - res = res.concat(instr); + total += 1 + 4 + instr.length; } continue; } if (instr.length === 0) { - res.push(opcodes['0']); + total += 1; } else if (1 <= instr.length && instr.length <= 0x4b) { - res = res.concat(instr.length, instr); + total += 1 + instr.length; } else if (instr.length <= 0xff) { - res = res.concat(opcodes.pushdata1, instr.length, instr); + total += 1 + 1 + instr.length; } else if (instr.length <= 0xffff) { - res.push(opcodes.pushdata2); - utils.writeU16(res, instr.length, res.length); - res = res.concat(instr); + total += 1 + 2 + instr.length; } else { - res.push(opcodes.pushdata4); - utils.writeU32(res, instr.length, res.length); - res = res.concat(instr); + total += 1 + 4 + instr.length; } continue; } - res.push(opcodes[instr] || instr); + total += 1; } + res = new Buffer(total); + + for (i = 0; i < s.length; i++) { + instr = s[i]; + + assert(!Array.isArray(instr)); + + // Push value to stack + if (Buffer.isBuffer(instr)) { + // Check for nonstandard pushdatas that + // may have been decoded from before. + if (instr.pushdata) { + if (instr.pushdata.opcode === null) { + res[off++] = instr.pushdata.len; + off += instr.copy(res, off, 0, instr.length); + } else if (instr.pushdata.opcode === 'pushdata1') { + res[off++] = opcodes.pushdata1; + res[off++] = instr.pushdata.len; + off += instr.copy(res, off, 0, instr.length); + } else if (instr.pushdata.opcode === 'pushdata2') { + res[off++] = opcodes.pushdata2; + off += utils.writeU16(res, instr.pushdata.len, off); + off += instr.copy(res, off, 0, instr.length); + } else if (instr.pushdata.opcode === 'pushdata4') { + res[off++] = opcodes.pushdata4; + off += utils.writeU32(res, instr.pushdata.len, off); + off += instr.copy(res, off, 0, instr.length); + } + continue; + } + if (instr.length === 0) { + res[off++] = opcodes['0']; + } else if (1 <= instr.length && instr.length <= 0x4b) { + res[off++] = instr.length; + off += instr.copy(res, off, 0, instr.length); + } else if (instr.length <= 0xff) { + res[off++] = opcodes.pushdata1; + res[off++] = instr.length; + off += instr.copy(res, off, 0, instr.length); + } else if (instr.length <= 0xffff) { + res[off++] = opcodes.pushdata2; + off += utils.writeU16(res, instr.length, off); + off += instr.copy(res, off, 0, instr.length); + } else { + res[off++] = opcodes.pushdata4; + off += utils.writeU32(res, instr.length, off); + off += instr.copy(res, off, 0, instr.length); + } + continue; + } + + res[off++] = opcodes[instr] || instr; + } + + assert(off === res.length); + return res; }; @@ -185,7 +235,7 @@ script.normalize = function normalize(s) { if (typeof op === 'string' && constants.opcodes[op] == null) { if (op[0] === '[') op = op.slice(1, -1); - op = utils.toArray(op, 'hex'); + op = new Buffer(op, 'hex'); } s[i] = op; @@ -236,7 +286,7 @@ script.verify = function verify(input, output, tx, i, flags) { // Grab the real redeem script redeem = stack.pop(); - if (!Array.isArray(redeem)) + if (!Buffer.isBuffer(redeem)) return false; redeem = script.decode(redeem); @@ -275,6 +325,9 @@ script.getSubscript = function getSubscript(s, lastSep) { res.push(s[i]); } + if (res.length === s.length) + return s; + return res; }; @@ -298,7 +351,7 @@ script.checksig = function checksig(msg, sig, key, flags) { if (flags == null) flags = constants.flags.STANDARD_VERIFY_FLAGS; - if (!utils.isBuffer(sig)) + if (!Buffer.isBuffer(sig)) return false; if (sig.length === 0) @@ -322,7 +375,7 @@ script.sign = function sign(msg, key, type) { // Add the sighash type as a single byte // to the signature. - sig = sig.concat(type); + sig = Buffer.concat([sig, new Buffer([type])]); return sig; }; @@ -383,7 +436,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) { for (pc = 0; pc < s.length; pc++) { o = s[pc]; - if (Array.isArray(o)) { + if (Buffer.isBuffer(o)) { if (o.length > constants.script.maxPush) return false; if (!script.checkPush(o, flags)) @@ -393,7 +446,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) { } if (o >= 1 && o <= 16) { - stack.push([o]); + stack.push(new Buffer([o])); continue; } @@ -412,7 +465,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) { break; } case '1negate': { - stack.push([-1]); + stack.push(new Buffer([0x80, 0xff])); break; } case 'if': @@ -751,7 +804,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) { n2 = script.num(stack.pop()); n1 = script.num(stack.pop()); val = n2.cmp(n1) <= 0 && n1.cmp(n3) < 0; - stack.push(val.cmpn(0) !== 0 ? [1] : []); + stack.push(val.cmpn(0) !== 0 ? new Buffer([1]) : new Buffer([])); break; } @@ -800,7 +853,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) { if (!res) return false; } else { - stack.push(res ? [1] : []); + stack.push(res ? new Buffer([1]) : new Buffer([])); } break; } @@ -830,7 +883,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) { if (!res) return false; } else { - stack.push(res ? [1] : []); + stack.push(res ? new Buffer([1]) : new Buffer([])); } break; @@ -907,7 +960,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) { if (!res) return false; } else { - stack.push(res ? [1] : []); + stack.push(res ? new Buffer([1]) : new Buffer([])); } break; @@ -925,7 +978,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) { locktime = stack[stack.length - 1]; - if (!Array.isArray(locktime)) + if (!Buffer.isBuffer(locktime)) return false; if (locktime.length > 6) { @@ -969,7 +1022,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) { evalScript = stack.pop(); - if (!Array.isArray(evalScript)) + if (!Buffer.isBuffer(evalScript)) return false; evalScript = script.decode(evalScript); @@ -1015,7 +1068,7 @@ script.bool = function bool(value) { if (value instanceof bn) return value.cmpn(0) !== 0; - assert(utils.isBuffer(value)); + assert(Buffer.isBuffer(value)); for (i = 0; i < value.length; i++) { if (value[i] !== 0) { @@ -1037,7 +1090,7 @@ script.num = function num(value, useNum, minimaldata) { // if (value instanceof bn) // return useNum ? value.toNumber() : value; - assert(utils.isBuffer(value)); + assert(Buffer.isBuffer(value)); if (minimaldata && value.length > 0) { // If the low bits on the last byte are unset, @@ -1086,7 +1139,7 @@ script.num = function num(value, useNum, minimaldata) { }; script.array = function(value) { - if (Array.isArray(value)) + if (Buffer.isBuffer(value)) return value.slice(); if (utils.isFinite(value)) @@ -1106,7 +1159,7 @@ script.array = function(value) { if (value.cmpn(0) === 0) return []; - return value.toArray('le'); + return new Buffer(value.toArray('le')); }; script.removeData = function removeData(s, data) { @@ -1199,7 +1252,7 @@ script.getRedeem = function getRedeem(s) { raw = s[s.length - 1]; - if (!Array.isArray(raw)) + if (!Buffer.isBuffer(raw)) return; if (raw._redeem) @@ -1256,7 +1309,7 @@ script.size = script.getSize; script.isEncoded = function isEncoded(s) { var i, b; - if (!Array.isArray(s)) + if (!s) return false; for (i = 0; i < s.length; i++) { @@ -1279,7 +1332,7 @@ script._locktime = function _locktime(s) { if (s.length < 2) return; - if (!utils.isBuffer(s[0])) + if (!Buffer.isBuffer(s[0])) return; if (s[1] !== 'checklocktimeverify') @@ -1671,7 +1724,7 @@ script.recoverKey = function recoverKey(sig, msg) { return; } - return bcoin.ecdsa.keyPair({ pub: key }).getPublic(true, 'array'); + return new Buffer(bcoin.ecdsa.keyPair({ pub: key }).getPublic(true, 'array')); }; script.guessKey = function guessKey(sig, prev, tx, i) { @@ -1733,7 +1786,7 @@ script.isMultisig = function isMultisig(s, keys) { n = s[s.length - 2]; - if (Array.isArray(n)) { + if (Buffer.isBuffer(n)) { if (n.length !== 0) return false; n = 0; @@ -1750,7 +1803,7 @@ script.isMultisig = function isMultisig(s, keys) { m = s[0]; - if (Array.isArray(m)) { + if (Buffer.isBuffer(m)) { if (m.length !== 0) return false; m = 0; @@ -1890,7 +1943,7 @@ script.isMultisigInput = function isMultisigInput(s, keys, tx, index) { if (s.length < 3) return false; - if (!Array.isArray(s[0]) || s[0].length !== 0) + if (!Buffer.isBuffer(s[0]) || s[0].length !== 0) return false; for (i = 1; i < s.length; i++) { @@ -1947,7 +2000,7 @@ script.isScripthashInput = function isScripthashInput(s, redeem) { // Last data element should be an array // for the redeem script. - if (!Array.isArray(raw)) + if (!Buffer.isBuffer(raw)) return false; // Check data against last array in case @@ -1986,18 +2039,18 @@ script.getCoinbaseData = function getCoinbaseData(s) { script: s }; - if (Array.isArray(s[0])) + if (Buffer.isBuffer(s[0])) coinbase.height = script.num(s[0], true); else coinbase.height = -1; - if (Array.isArray(s[1])) + if (Buffer.isBuffer(s[1])) coinbase.extraNonce = script.num(s[1]); else coinbase.extraNonce = script.num(0); flags = s.slice(2).filter(function(chunk) { - return Array.isArray(chunk) && chunk.length !== 0; + return Buffer.isBuffer(chunk) && chunk.length !== 0; }); coinbase.flags = flags; @@ -2013,35 +2066,35 @@ script.getCoinbaseData = function getCoinbaseData(s) { // verification, not detection. script.isHash = function isHash(hash) { - if (!utils.isBuffer(hash)) + if (!Buffer.isBuffer(hash)) return false; return hash.length === 20; }; script.isKey = function isKey(key) { - if (!utils.isBuffer(key)) + if (!Buffer.isBuffer(key)) return false; return key.length >= 33 && key.length <= 65; }; script.isSignature = function isSignature(sig) { - if (!utils.isBuffer(sig)) + if (!Buffer.isBuffer(sig)) return false; return sig.length >= 9 && sig.length <= 73; }; script.isDummy = function isDummy(data) { - if (!utils.isBuffer(data)) + if (!Buffer.isBuffer(data)) return false; return data.length === 0; }; script.isData = function isData(data) { - if (!utils.isBuffer(data)) + if (!Buffer.isBuffer(data)) return false; return data.length <= constants.script.maxOpReturn; @@ -2051,7 +2104,7 @@ script.isValidKey = function isValidKey(key, flags) { if (flags == null) flags = constants.flags.STANDARD_VERIFY_FLAGS; - if (!utils.isBuffer(key)) + if (!Buffer.isBuffer(key)) return false; if (flags & constants.flags.VERIFY_STRICTENC) { @@ -2065,7 +2118,7 @@ script.isValidKey = function isValidKey(key, flags) { }; script.isKeyEncoding = function isKeyEncoding(key) { - if (!utils.isBuffer(key)) + if (!Buffer.isBuffer(key)) return false; if (key.length < 33) @@ -2088,7 +2141,7 @@ script.isValidSignature = function isValidSignature(sig, flags) { if (flags == null) flags = constants.flags.STANDARD_VERIFY_FLAGS; - if (!utils.isBuffer(sig)) + if (!Buffer.isBuffer(sig)) return false; // Allow empty sigs @@ -2135,7 +2188,7 @@ script.isValidSignature = function isValidSignature(sig, flags) { script.isSignatureEncoding = function isSignatureEncoding(sig) { var lenR, lenS; - if (!utils.isBuffer(sig)) + if (!Buffer.isBuffer(sig)) return false; // Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S] [sighash] @@ -2218,7 +2271,7 @@ script.isSignatureEncoding = function isSignatureEncoding(sig) { }; script.isHashType = function isHashType(sig) { - if (!utils.isBuffer(sig)) + if (!Buffer.isBuffer(sig)) return false; if (sig.length === 0) @@ -2234,7 +2287,7 @@ script.isHashType = function isHashType(sig) { script.isLowDER = function isLowDER(sig) { if (!sig.s) { - if (!utils.isBuffer(sig)) + if (!Buffer.isBuffer(sig)) return false; if (!script.isSignatureEncoding(sig)) @@ -2263,7 +2316,7 @@ script.format = function format(s) { } return script.concat(scripts).map(function(chunk) { - if (Array.isArray(chunk)) { + if (Buffer.isBuffer(chunk)) { if (chunk.length === 0) return 0 + ''; return '[' + utils.toHex(chunk) + ']'; @@ -2278,7 +2331,7 @@ script.isPushOnly = function isPushOnly(s) { var i, op; for (i = 0; i < s.length; i++) { op = s[i]; - if (Array.isArray(op) || op === '1negate' || (op >= 1 && op <= 16)) + if (Buffer.isBuffer(op) || op === '1negate' || (op >= 1 && op <= 16)) continue; return false; } @@ -2292,7 +2345,7 @@ script.getSigops = function getSigops(s, accurate) { for (i = 0; i < s.length; i++) { op = s[i]; - if (Array.isArray(op)) + if (Buffer.isBuffer(op)) continue; if (constants.opcodes[op] == null) return 0; diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index 99c3d397..77301b1e 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -125,7 +125,7 @@ TX.prototype.hash = function hash(enc, force) { TX.prototype.render = function render(force) { if (!force && this.isStatic() && this._raw) - return utils.toArray(this._raw); + return this._raw; return bcoin.protocol.framer.tx(this); }; @@ -152,7 +152,7 @@ TX.prototype._addInput = function _addInput(options, index) { if (options instanceof TX) { options = { tx: options, index: index }; - } else if (typeof options === 'string' || utils.isBuffer(options)) { + } else if (typeof options === 'string' || Buffer.isBuffer(options)) { options = { hash: options, index: index }; } @@ -270,7 +270,7 @@ TX.prototype.scriptInput = function scriptInput(index, publicKey, redeem) { // Already has a script template (at least) if (input.script.length) return true; - input.script = [[]]; + input.script = [new Buffer([])]; } else if (bcoin.script.isPubkeyhash(s)) { // P2PKH if (!utils.isEqual(s[2], bcoin.address.hash160(publicKey))) @@ -278,7 +278,7 @@ TX.prototype.scriptInput = function scriptInput(index, publicKey, redeem) { // Already has a script template (at least) if (input.script.length) return true; - input.script = [[], publicKey]; + input.script = [new Buffer([]), publicKey]; } else if (bcoin.script.isMultisig(s)) { // Multisig for (i = 0; i < s.length; i++) { @@ -296,14 +296,14 @@ TX.prototype.scriptInput = function scriptInput(index, publicKey, redeem) { // Technically we should create m signature slots, // but we create n signature slots so we can order // the signatures properly. - input.script = [[]]; + input.script = [new Buffer([])]; // Grab `n` value (number of keys). n = s[s.length - 2]; // Fill script with `n` signature slots. for (i = 0; i < n; i++) - input.script[i + 1] = []; + input.script[i + 1] = new Buffer([]); } else { for (i = 0; i < s.length; i++) { if (utils.isEqual(s[i], publicKey)) @@ -322,11 +322,11 @@ TX.prototype.scriptInput = function scriptInput(index, publicKey, redeem) { // Also, only allow nonstandard types for // scripthash. if (redeem) { - input.script = [[]]; + input.script = [new Buffer([])]; // Fill script with `n` signature slots. for (i = 0; i < s.length; i++) { if (bcoin.script.isKey(s[i])) - input.script.push([]); + input.script.push(new Buffer([])); } } } @@ -414,14 +414,14 @@ TX.prototype.signInput = function signInput(index, key, type) { } // Get pubkey. - publicKey = key.getPublic(true, 'array'); + publicKey = key.getPublicKey(); // Add signatures. if (bcoin.script.isPubkey(s)) { // P2PK // Something is wrong. Abort. - if (!Array.isArray(input.script[0])) + if (!Buffer.isBuffer(input.script[0])) return false; // Already signed. @@ -441,7 +441,7 @@ TX.prototype.signInput = function signInput(index, key, type) { // P2PKH // Something is wrong. Abort. - if (!Array.isArray(input.script[0])) + if (!Buffer.isBuffer(input.script[0])) return false; // Already signed. @@ -507,7 +507,7 @@ TX.prototype.signInput = function signInput(index, key, type) { // or by `m`. Add some signature slots for // us to use. while (len - 1 < n) { - input.script.splice(len, 0, []); + input.script.splice(len, 0, new Buffer([])); len++; } @@ -568,7 +568,7 @@ TX.prototype.signInput = function signInput(index, key, type) { }; TX.prototype.sign = function sign(index, key, redeem, type) { - var publicKey = key.getPublic(true, 'array'); + var publicKey = key.getPublicKey(); var input; if (index && typeof index === 'object') @@ -642,7 +642,7 @@ TX.prototype.isSigned = function isSigned(index, required) { if (bcoin.script.isMultisig(s)) { // Grab `m` value (number of required sigs). m = s[0]; - if (Array.isArray(m)) + if (Buffer.isBuffer(m)) m = m[0] || 0; // Ensure all members are signatures. @@ -728,7 +728,7 @@ TX.prototype.scriptOutput = function scriptOutput(index, options) { // https://github.com/bitcoin/bips/blob/master/bip-0011.mediawiki // https://github.com/bitcoin/bips/blob/master/bip-0019.mediawiki // m [key1] [key2] ... n checkmultisig - keys = options.keys.map(utils.toBuffer); + keys = options.keys.map(utils.ensureBuffer); m = options.m; n = options.n || keys.length; @@ -757,7 +757,7 @@ TX.prototype.scriptOutput = function scriptOutput(index, options) { // P2PK Transaction // [pubkey] checksig script = [ - utils.toBuffer(options.key), + utils.ensureBuffer(options.key), 'checksig' ]; } else if (options.flags) { @@ -766,7 +766,7 @@ TX.prototype.scriptOutput = function scriptOutput(index, options) { flags = options.flags; if (typeof flags === 'string') flags = utils.ascii2array(flags); - assert(utils.isBuffer(flags)); + assert(Buffer.isBuffer(flags)); assert(flags.length <= constants.script.maxOpReturn); script = bcoin.script.createNulldata(flags); } @@ -866,9 +866,11 @@ TX.prototype.signatureHash = function signatureHash(index, s, type) { copy.inputs.length = 1; } - msg = copy.render(true); + copy = copy.render(true); - utils.writeU32(msg, type, msg.length); + msg = new Buffer(copy.length + 4); + utils.copy(copy, msg, 0); + utils.writeU32(msg, type, copy.length); hash = utils.dsha256(msg); @@ -1214,8 +1216,8 @@ TX.prototype.sortMembers = function sortMembers() { } this.inputs = this.inputs.slice().sort(function(a, b) { - var h1 = utils.toArray(a.prevout.hash, 'hex'); - var h2 = utils.toArray(b.prevout.hash, 'hex'); + var h1 = new Buffer(a.prevout.hash, 'hex'); + var h2 = new Buffer(b.prevout.hash, 'hex'); var res = utils.cmp(h1, h2); if (res !== 0) @@ -1871,7 +1873,7 @@ TX.fromJSON = function fromJSON(json) { assert.equal(json.v, 1); assert.equal(json.type, 'tx'); - raw = utils.toArray(json.tx, 'hex'); + raw = new Buffer(json.tx, 'hex'); data = new bcoin.protocol.parser().parseTX(raw); data.network = json.network; @@ -1920,9 +1922,6 @@ TX.fromRaw = function fromRaw(data, enc) { if (enc === 'hex') data = new Buffer(data, 'hex'); - if (Array.isArray(data)) - data = new Buffer(data); - return new bcoin.tx(parser.parseTX(data)); }; diff --git a/lib/bcoin/utils.js b/lib/bcoin/utils.js index afcab5af..00d3e599 100644 --- a/lib/bcoin/utils.js +++ b/lib/bcoin/utils.js @@ -14,6 +14,29 @@ var util = require('util'); * Utils */ +utils.toBuffer = function toBuffer(msg, enc) { + if (Buffer.isBuffer(msg)) + return msg; + + if (Array.isArray(msg)) + return new Buffer(msg); + + if (!msg) + return new Buffer([]); + + if (typeof msg === 'string') { + if (!enc) + return new Buffer(msg, 'ascii'); + + if (enc === 'base58') + return utils.fromBase58(msg); + + return new Buffer(msg, enc); + } + + assert(false); +}; + utils.toArray = function toArray(msg, enc) { if (Buffer.isBuffer(msg)) return Array.prototype.slice.call(msg); @@ -140,7 +163,7 @@ utils.fromBase58 = function fromBase58(str) { for (i = 0; i < zeroes; i++) z.push(0); - return z.concat(res.toArray()); + return new Buffer(z.concat(res.toArray())); }; utils.isBase58 = function isBase58(msg) { @@ -151,28 +174,22 @@ utils.ripemd160 = function ripemd160(data, enc) { var result; if (!bcoin.crypto) - return bcoin.hash.ripemd160().update(data, enc).digest(); - - if (Array.isArray(data)) - data = new Buffer(data); + return new Buffer(bcoin.hash.ripemd160().update(data, enc).digest()); result = bcoin.crypto.createHash('ripemd160').update(data, enc).digest(); - return utils.toArray(result); + return result; }; utils.sha1 = function sha1(data, enc) { var result; if (!bcoin.crypto) - return bcoin.hash.sha1().update(data, enc).digest(); - - if (Array.isArray(data)) - data = new Buffer(data); + return new Buffer(bcoin.hash.sha1().update(data, enc).digest()); result = bcoin.crypto.createHash('sha1').update(data, enc).digest(); - return utils.toArray(result); + return result; }; utils.ripesha = function ripesha(data, enc) { @@ -187,14 +204,11 @@ utils.sha256 = function sha256(data, enc) { var result; if (!bcoin.crypto) - return bcoin.hash.sha256().update(data, enc).digest(); - - if (Array.isArray(data)) - data = new Buffer(data); + return new Buffer(bcoin.hash.sha256().update(data, enc).digest()); result = bcoin.crypto.createHash('sha256').update(data, enc).digest(); - return utils.toArray(result); + return result; }; utils.dsha256 = function dsha256(data, enc) { @@ -205,14 +219,14 @@ utils.sha512hmac = function sha512hmac(data, salt) { var hmac, result; if (!bcoin.crypto) { - hmac = bcoin.hash.hmac(hash.sha512, utils.toArray(salt)); - return hmac.update(utils.toArray(data)).digest(); + hmac = bcoin.hash.hmac(hash.sha512, salt); + return new Buffer(hmac.update(data).digest()); } - hmac = bcoin.crypto.createHmac('sha512', new Buffer(salt)); - result = hmac.update(new Buffer(data)).digest(); + hmac = bcoin.crypto.createHmac('sha512', salt); + result = hmac.update(data).digest(); - return utils.toArray(result); + return result; }; utils.salt = 'bcoin:'; @@ -647,48 +661,74 @@ utils.isIP = function isIP(ip) { }; utils.ip2version = function ip2version(ip, version) { - utils.assert(Array.isArray(ip)); - utils.assert(version === 4 || version === 6); + var b, i, j; - ip = ip.slice(); + utils.assert(Buffer.isBuffer(ip)); + utils.assert(version === 4 || version === 6); if (version === 4) { // Check to see if this an // ipv4-mapped ipv6 address. if (ip.length > 4) { while (ip[0] === 0) - ip.shift(); + ip = ip.slice(1); // Found an ipv4 address if (ip.length === 6 && ip[0] === 0xff && ip[1] === 0xff) return ip.slice(-4); // No ipv4 address - return [0, 0, 0, 0]; + return new Buffer([0, 0, 0, 0]); } // Pad to 4 bytes - while (ip.length < 4) - ip.unshift(0); + if (ip.length < 4) { + b = new Buffer(4); + i = ip.length; + j = b.length; + b.fill(0); + while (i) + b[--j] = ip[--i]; + ip = b; + } return ip; } if (version === 6) { // Pad to 4 bytes - while (ip.length < 4) - ip.unshift(0); + if (ip.length < 4) { + b = new Buffer(4); + i = ip.length; + j = b.length; + b.fill(0); + while (i) + b[--j] = ip[--i]; + ip = b; + } // Try to convert ipv4 address to // ipv4-mapped ipv6 address. if (ip.length === 4) { - while (ip.length < 6) - ip.unshift(0xff); + b = new Buffer(6); + i = ip.length; + j = b.length; + b.fill(0xff); + while (i) + b[--j] = ip[--i]; + ip = b; } // Pad to 16 bytes - while (ip.length < 16) - ip.unshift(0); + if (ip.length < 16) { + b = new Buffer(16); + i = ip.length; + j = b.length; + b.fill(0); + while (i) + b[--j] = ip[--i]; + ip = b; + } return ip; } @@ -700,15 +740,15 @@ utils.ip2array = function ip2array(ip, version) { utils.assert(version === 4 || version === 6); if (type === 0) { - if (!Array.isArray(ip)) - ip = [0, 0, 0, 0]; + if (!Buffer.isBuffer(ip)) + ip = new Buffer([0, 0, 0, 0]); } else if (type === 4) { - ip = ip.split('.').map(function(n) { + ip = new Buffer(ip.split('.').map(function(n) { return +n; - }); + })); utils.assert(ip.length <= 4); } else if (type === 6) { - ip = utils.toArray(ip.replace(/:/g, ''), 'hex'); + ip = new Buffer(ip.replace(/:/g, ''), 'hex'); utils.assert(ip.length <= 16); } @@ -718,11 +758,11 @@ utils.ip2array = function ip2array(ip, version) { utils.array2ip = function array2ip(ip, version) { var out, i, hi, lo; - if (!Array.isArray(ip)) { + if (!Buffer.isBuffer(ip)) { if (utils.isIP(ip)) ip = utils.ip2array(ip, version); else - ip = [0, 0, 0, 0]; + ip = new Buffer([0, 0, 0, 0]); } utils.assert(version === 4 || version === 6); @@ -731,7 +771,7 @@ utils.array2ip = function array2ip(ip, version) { ip = utils.ip2version(ip, version); if (version === 4) - return ip.join('.'); + return Array.prototype.slice.call(ip).join('.'); if (version === 6) { out = []; @@ -762,19 +802,18 @@ utils.isArray = function isArray(msg) { }; utils.isBuffer = function isBuffer(msg) { - utils.assert(!Buffer.isBuffer(msg)); - return Array.isArray(msg); + return Buffer.isBuffer(msg); }; -utils.toBuffer = function toBuffer(msg) { - if (Array.isArray(msg)) +utils.ensureBuffer = function ensureBuffer(msg) { + if (Buffer.isBuffer(msg)) return msg; - if (utils.isArrayLike(msg)) - return Array.prototype.slice.call(msg); + if (Array.isArray(msg)) + return new Buffer(msg); if (utils.isHex(msg)) - return utils.toArray(msg, 'hex'); + return new Buffer(msg, 'hex'); if (utils.isBase58(msg)) return utils.fromBase58(msg); @@ -785,6 +824,9 @@ utils.toBuffer = function toBuffer(msg) { utils.isBytes = function isBytes(data) { var i; + if (Buffer.isBuffer(data)) + return true; + if (!Array.isArray(data)) return false; @@ -941,7 +983,9 @@ utils.testTarget = function testTarget(target, hash) { target = utils.fromCompact(target); if (typeof hash === 'string') - hash = utils.toArray(hash, 'hex'); + hash = new Buffer(hash, 'hex'); + + hash = Array.prototype.slice.call(hash); return new bn(hash.slice().reverse()).cmp(target) < 0; }; @@ -959,9 +1003,9 @@ utils.hash = function hash(obj, enc) { throw new Error('Cannot get hash of null'); if (typeof obj === 'string') - return enc === 'hex' ? obj : utils.toArray(obj, 'hex'); + return enc === 'hex' ? obj : new Buffer(obj, 'hex'); - if (utils.isBuffer(obj)) + if (Buffer.isBuffer(obj)) return enc === 'hex' ? utils.toHex(obj) : obj; if (typeof obj.hash === 'function') diff --git a/test/block-test.js b/test/block-test.js index 0aa3a600..990efb53 100644 --- a/test/block-test.js +++ b/test/block-test.js @@ -40,12 +40,12 @@ describe('Block', function() { }); it('should decode/encode with parser/framer', function() { - var b = bcoin.block(parser.parseMerkleBlock(bcoin.utils.toArray(raw, 'hex')), 'merkleblock'); + var b = bcoin.block(parser.parseMerkleBlock(new Buffer(raw, 'hex')), 'merkleblock'); assert.equal(bcoin.utils.toHex(b.render()), raw); }); it('should be verifiable', function() { - var b = bcoin.block(parser.parseMerkleBlock(bcoin.utils.toArray(raw, 'hex')), 'merkleblock'); + var b = bcoin.block(parser.parseMerkleBlock(new Buffer(raw, 'hex')), 'merkleblock'); assert(b.verify()); }); diff --git a/test/protocol-test.js b/test/protocol-test.js index 0c8e41fc..600dd325 100644 --- a/test/protocol-test.js +++ b/test/protocol-test.js @@ -64,7 +64,7 @@ describe('Protocol', function() { return +n; }); addr._ipv6 = addr.ipv6; - addr.ipv6 = utils.toArray(addr.ipv6, 'hex'); + addr.ipv6 = new Buffer(addr.ipv6.replace(/:/g, ''), 'hex'); }); packetTest('addr', peers, function(payload) { @@ -86,7 +86,7 @@ describe('Protocol', function() { it('should include the raw data of only one transaction in a ' + 'parsed transaction', function() { - var rawTwoTxs = utils.toArray( + var rawTwoTxs = new Buffer( '0100000004b124cca7e9686375380c845d0fd002ed704aef4472f4cc193' + 'fca4aa1b3404da400000000b400493046022100d3c9ba786488323c975f' + 'e61593df6a8041c5442736f361887abfe5c97175c72b022100ca61688f4' + @@ -137,7 +137,7 @@ describe('Protocol', function() { '0001976a9146167aeaeec59836b22447b8af2c5e61fb4f1b7b088ac00a3' + 'dc5c0500000017a9149eb21980dc9d413d8eac27314938b9da920ee53e8' + '700000000', 'hex'); - var rawFirstTx = utils.toArray( + var rawFirstTx = new Buffer( '0100000004b124cca7e9686375380c845d0fd002ed704aef4472f4cc193' + 'fca4aa1b3404da400000000b400493046022100d3c9ba786488323c975f' + 'e61593df6a8041c5442736f361887abfe5c97175c72b022100ca61688f4' + diff --git a/test/script-test.js b/test/script-test.js index db5d4a09..008edc57 100644 --- a/test/script-test.js +++ b/test/script-test.js @@ -9,7 +9,7 @@ describe('Script', function() { '101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f' + 'ac'; - var decoded = bcoin.script.decode(bcoin.utils.toArray(src, 'hex')); + var decoded = bcoin.script.decode(new Buffer(src, 'hex')); assert.equal(decoded.length, 3); assert.equal( bcoin.utils.toHex(decoded[0]), @@ -33,14 +33,14 @@ describe('Script', function() { it('should recognize a P2SH output', function () { var hex = 'a91419a7d869032368fd1f1e26e5e73a4ad0e474960e87' - var encoded = bcoin.utils.toArray(hex, 'hex') + var encoded = new Buffer(hex, 'hex') var decoded = bcoin.script.decode(encoded); assert(bcoin.script.isScripthash(decoded)) }) it('should recognize a Null Data output', function () { var hex = '6a28590c080112220a1b353930632e6f7267282a5f5e294f7665726c6179404f7261636c65103b1a010c' - var encoded = bcoin.utils.toArray(hex, 'hex') + var encoded = new Buffer(hex, 'hex') var decoded = bcoin.script.decode(encoded); assert(bcoin.script.isNulldata(decoded)) }) diff --git a/test/tx-test.js b/test/tx-test.js index 1d741e80..e4eff4d8 100644 --- a/test/tx-test.js +++ b/test/tx-test.js @@ -42,14 +42,15 @@ describe('TX', function() { '2e88ac00000000'; it('should decode/encode with parser/framer', function() { - var tx = bcoin.tx(parser.parseTX(bcoin.utils.toArray(raw, 'hex'))); + var tx = bcoin.tx(parser.parseTX(new Buffer(raw, 'hex'))); assert.equal(bcoin.utils.toHex(tx.render()), raw); }); it('should be verifiable', function() { - var tx = bcoin.tx(parser.parseTX(bcoin.utils.toArray(raw, 'hex'))); - var p = bcoin.tx(parser.parseTX(bcoin.utils.toArray(inp, 'hex'))); + var tx = bcoin.tx(parser.parseTX(new Buffer(raw, 'hex'))); + var p = bcoin.tx(parser.parseTX(new Buffer(inp, 'hex'))); tx.input(p, 1); + bcoin.utils.print(tx); assert(tx.verify()); }); diff --git a/test/utils-test.js b/test/utils-test.js index 95ae2c4d..472a54a6 100644 --- a/test/utils-test.js +++ b/test/utils-test.js @@ -5,7 +5,7 @@ var utils = bcoin.utils; describe('Utils', function() { it('should encode/decode base58', function() { - var arr = [ 0, 0, 0, 0xde, 0xad, 0xbe, 0xef ]; + var arr = new Buffer([ 0, 0, 0, 0xde, 0xad, 0xbe, 0xef ]); var b = utils.toBase58(arr); assert.equal(b, '1116h8cQN'); assert.deepEqual(utils.fromBase58(b), arr); @@ -13,7 +13,7 @@ describe('Utils', function() { it('should translate bits to target', function() { var bits = 0x1900896c; - var hash = utils.toArray( + var hash = new Buffer( '672b3f1bb11a994267ea4171069ba0aa4448a840f38e8f340000000000000000', 'hex' ); @@ -28,7 +28,7 @@ describe('Utils', function() { assert.equal(btc, '546.78'); btc = utils.toBTC(new bn(5460).mul(new bn(10000000))); assert.equal(btc, '546.0'); - btc = utils.toBTC(new bn(5460).mul(new bn(10000000)).toArray()); + btc = utils.toBTC(new Buffer(new bn(5460).mul(new bn(10000000)).toArray())); assert.equal(btc, '546.0'); btc = utils.toBTC(new bn(5460).mul(new bn(10000000)).toString('hex')); assert.equal(btc, '546.0'); @@ -45,12 +45,12 @@ describe('Utils', function() { it('should convert objects to hashes', function() { var b1 = '00'; - var b2 = [0]; - var b3 = { hash: function(enc) { return enc === 'hex' ? '00' : [0]; } }; + var b2 = new Buffer([0]); + var b3 = { hash: function(enc) { return enc === 'hex' ? '00' : new Buffer([0]); } }; var b4 = { hash: '00' }; var b5 = { _hash: '00' }; - var b6 = { hash: [0] }; - var b7 = { _hash: [0] }; + var b6 = { hash: new Buffer([0]) }; + var b7 = { _hash: new Buffer([0]) }; [b1, b2, b3, b4, b5, b6, b7].forEach(function(b, i) { utils.assert.equal(utils.hash(b, 'hex'), '00'); utils.assert(utils.isEqual(utils.hash(b), [0]));