From 73d3291ee984873506684d89f171699d9e5c3af1 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Mon, 22 Feb 2016 21:25:01 -0800 Subject: [PATCH] more buffer work. --- lib/bcoin/address.js | 2 +- lib/bcoin/ec.js | 2 - lib/bcoin/hd.js | 8 +- lib/bcoin/miner.js | 4 +- lib/bcoin/protocol/framer.js | 156 +++++++++++++++++++++++++---------- lib/bcoin/protocol/parser.js | 10 +-- lib/bcoin/script.js | 6 +- lib/bcoin/tx.js | 2 +- lib/bcoin/utils.js | 98 +--------------------- 9 files changed, 132 insertions(+), 156 deletions(-) diff --git a/lib/bcoin/address.js b/lib/bcoin/address.js index d85de67e..c05207c2 100644 --- a/lib/bcoin/address.js +++ b/lib/bcoin/address.js @@ -601,7 +601,7 @@ Address.fromJSON = function fromJSON(json, passphrase) { path: json.path, key: bcoin.keypair.fromJSON(json.key, passphrase), type: json.type, - redeem: json.redeem ? utils.toArray(json.redeem, 'hex') : null, + redeem: json.redeem ? new Buffer(json.redeem, 'hex') : null, keys: json.keys.map(utils.fromBase58), m: json.m, n: json.n diff --git a/lib/bcoin/ec.js b/lib/bcoin/ec.js index 93928f1f..b28ed656 100644 --- a/lib/bcoin/ec.js +++ b/lib/bcoin/ec.js @@ -22,8 +22,6 @@ ec.generate = function generate(options) { priv = bcoin.crypto.randomBytes(32); } while (!bcoin.secp256k1.privateKeyVerify(priv)); pub = bcoin.secp256k1.publicKeyCreate(priv, true); - priv = utils.toArray(priv); - pub = utils.toArray(pub); return bcoin.keypair({ priv: priv, pub: pub }); } diff --git a/lib/bcoin/hd.js b/lib/bcoin/hd.js index 8654d971..5057dc2e 100644 --- a/lib/bcoin/hd.js +++ b/lib/bcoin/hd.js @@ -679,7 +679,7 @@ HDPrivateKey.prototype._build = function _build(data) { off += utils.copy(data.parentFingerPrint, sequence, off); off += utils.copy(data.childIndex, sequence, off); off += utils.copy(data.chainCode, sequence, off); - off += utils.copy([0], sequence, off); + off += utils.writeU8(sequence, 0, off); off += utils.copy(data.privateKey, sequence, off); assert(off === 78, off); checksum = utils.dsha256(sequence.slice(0, off)).slice(0, 4); @@ -744,11 +744,11 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) { 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.copy(this.privateKey, data, off); 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.copy(this.publicKey, data, off); off += utils.writeU32BE(data, index, off); } @@ -1081,7 +1081,7 @@ HDPublicKey.prototype.derive = function derive(index, hardened) { throw new Error('invalid path'); data = new Buffer(this.publicKey.length + 4); - off += this.publicKey.copy(data, off, 0, this.publicKey.length); + off += utils.copy(this.publicKey, data, off); off += utils.writeU32BE(data, index, off); hash = utils.sha512hmac(data, this.chainCode); diff --git a/lib/bcoin/miner.js b/lib/bcoin/miner.js index ced90739..e899443b 100644 --- a/lib/bcoin/miner.js +++ b/lib/bcoin/miner.js @@ -220,7 +220,7 @@ Miner.prototype.createBlock = function createBlock(tx) { bcoin.script.array(this.last.height + 1), // extraNonce - incremented when // the nonce overflows. - [], + new Buffer([]), // Add a nonce to ensure we don't // collide with a previous coinbase // of ours. This isn't really @@ -229,7 +229,7 @@ Miner.prototype.createBlock = function createBlock(tx) { new Buffer(utils.nonce().toArray()), // Let the world know this little // miner succeeded. - utils.ascii2array(this.msg || 'mined by bcoin') + new Buffer(this.msg || 'mined by bcoin', 'ascii') ], seq: 0xffffffff }); diff --git a/lib/bcoin/protocol/framer.js b/lib/bcoin/protocol/framer.js index 7eb33328..199f794c 100644 --- a/lib/bcoin/protocol/framer.js +++ b/lib/bcoin/protocol/framer.js @@ -30,6 +30,8 @@ Framer.prototype.header = function header(cmd, payload) { var h = new Buffer(24); var len, i; + cmd = new Buffer(cmd, 'ascii'); + assert(cmd.length < 12); assert(payload.length <= 0xffffffff); @@ -37,7 +39,7 @@ Framer.prototype.header = function header(cmd, payload) { utils.writeU32(h, network.magic, 0); // Command - len = utils.writeAscii(h, cmd, 4); + len = utils.copy(cmd, h, 4); for (i = 4 + len; i < 4 + 12; i++) h[i] = 0; @@ -120,11 +122,11 @@ Framer.prototype.version = function version(packet) { // Their address (recv) remote = this._addr(packet.remote || {}); - off += remote.copy(p, off, 0, remote.length); + off += utils.copy(remote, p, off); // Our address (from) local = this._addr(packet.local || {}); - off += local.copy(p, off, 0, local.length); + off += utils.copy(local, p, off); // Nonce, very dramatic off += utils.writeU64(p, utils.nonce(), off); @@ -172,7 +174,7 @@ Framer.prototype._inv = function _inv(command, items) { if (typeof hash === 'string') hash = new Buffer(hash, 'hex'); assert.equal(hash.length, 32); - off += hash.copy(res, off, 0, hash.length); + off += utils.copy(hash, res, off); } return this.packet(command, res); @@ -275,40 +277,82 @@ Framer.prototype._getBlocks = function _getBlocks(cmd, hashes, stop) { return this.packet(cmd, p); }; -Framer.tx = function tx(tx) { - var p = []; - var off, i, input, s, output, value, j; +Framer.txIn = function txIn(input) { + var off = 0; + var s, p; - off = utils.write32(p, tx.version, 0); - off += utils.writeIntv(p, tx.inputs.length, off); + s = bcoin.script.encode(input.script); + p = new Buffer(32 + 4 + utils.sizeIntv(s.length) + s.length + 4); + + off += utils.copy(new Buffer(input.prevout.hash, 'hex'), p, off); + off += utils.writeU32(p, input.prevout.index, off); + + off += utils.writeIntv(p, s.length, off); + off += utils.copy(s, p, off); + + off += utils.writeU32(p, input.sequence, off); + + return p; +}; + +Framer.txOut = function txOut(output) { + var off = 0; + var s, p; + + s = bcoin.script.encode(output.script); + p = new Buffer(8 + utils.sizeIntv(s.length) + s.length); + + off += utils.write64(p, output.value, off); + assert(output.value.byteLength() <= 8); + + off += utils.writeIntv(p, s.length, off); + off += utils.copy(s, p, off); + + return p; +}; + +Framer.tx = function tx(tx) { + var inputs = []; + var outputs = []; + var inputSize = 0; + var outputSize = 0; + var off = 0; + var p, i, input, output; for (i = 0; i < tx.inputs.length; i++) { - input = tx.inputs[i]; + input = Framer.txIn(tx.inputs[i]); + inputs.push(input); + inputSize += input.length; + } - off += utils.copy(new Buffer(input.prevout.hash, 'hex'), p, off, true); - off += utils.writeU32(p, input.prevout.index, off); + for (i = 0; i < tx.outputs.length; i++) { + output = Framer.txOut(tx.outputs[i]); + outputs.push(output); + outputSize += output.length; + } - s = bcoin.script.encode(input.script); - off += utils.writeIntv(p, s.length, off); - off += utils.copy(s, p, off, true); + p = new Buffer(4 + + utils.sizeIntv(tx.inputs.length) + inputSize + + utils.sizeIntv(tx.outputs.length) + outputSize + + 4); - off += utils.writeU32(p, input.sequence, off); + off += utils.write32(p, tx.version, off); + + off += utils.writeIntv(p, tx.inputs.length, off); + for (i = 0; i < inputs.length; i++) { + input = inputs[i]; + off += utils.copy(input, p, off); } off += utils.writeIntv(p, tx.outputs.length, off); - for (i = 0; i < tx.outputs.length; i++) { - output = tx.outputs[i]; - - off += utils.write64(p, output.value, off); - assert(output.value.byteLength() <= 8); - - s = bcoin.script.encode(output.script); - off += utils.writeIntv(p, s.length, off); - off += utils.copy(s, p, off, true); + for (i = 0; i < outputs.length; i++) { + output = outputs[i]; + off += utils.copy(output, p, off); } + off += utils.writeU32(p, tx.locktime, off); - return new Buffer(p); + return p; }; Framer.prototype.tx = function tx(tx) { @@ -316,21 +360,37 @@ Framer.prototype.tx = function tx(tx) { }; Framer.block = function _block(block, type) { - var p = []; var off = 0; - var i; + var txSize = 0; + var txs = []; + var i, tx; if (!type) type = block.subtype; + if (type === 'merkleblock') { + p = new Buffer(80 + 4 + + utils.sizeIntv(block.hashes.length) + (block.hashes.length * 32) + + utils.sizeIntv(block.flags.length) + block.flags.length); + } else if (type === 'header') { + p = new Buffer(80 + utils.sizeIntv(block.txs.length)); + } else { + for (i = 0; i < block.txs.length; i++) { + tx = block.txs[i].render(); + txs.push(tx); + txSize += tx.length; + } + p = new Buffer(80 + utils.sizeIntv(block.txs.length) + txSize); + } + // version off += utils.write32(p, block.version, off); // prev_block - off += utils.copy(new Buffer(block.prevBlock, 'hex'), p, off, true); + off += utils.copy(new Buffer(block.prevBlock, 'hex'), p, off); // merkle_root - off += utils.copy(new Buffer(block.merkleRoot, 'hex'), p, off, true); + off += utils.copy(new Buffer(block.merkleRoot, 'hex'), p, off); // timestamp off += utils.writeU32(p, block.ts, off); @@ -346,13 +406,17 @@ Framer.block = function _block(block, type) { if (type === 'merkleblock') { // txn_count off += utils.writeU32(p, block.totalTX, off); + // hash count off += utils.writeIntv(p, block.hashes.length, off); + // hashes for (i = 0; i < block.hashes.length; i++) - off += utils.copy(new Buffer(block.hashes[i], 'hex'), p, off, true); + off += utils.copy(new Buffer(block.hashes[i], 'hex'), p, off); + // flag count off += utils.writeIntv(p, block.flags.length, off); + // flags for (i = 0; i < block.flags.length; i++) p[off++] = block.flags[i]; @@ -362,12 +426,13 @@ Framer.block = function _block(block, type) { } else { // txn_count off += utils.writeIntv(p, block.txs.length, off); + // txs - for (i = 0; i < block.txs.length; i++) - off += utils.copy(block.txs[i].render(), p, off, true); + for (i = 0; i < txs.length; i++) + off += utils.copy(txs[i], p, off); } - return new Buffer(p); + return p; }; Framer.prototype.block = function _block(block) { @@ -379,25 +444,28 @@ Framer.prototype.merkleBlock = function merkleBlock(block) { }; Framer.prototype.reject = function reject(details) { - var p = []; + var message = new Buffer(details.message || '', 'ascii'); + var ccode = constants.reject[details.ccode] || constants.reject.malformed; + var reason = new Buffer(details.reason || '', 'ascii'); + var data = details.data || new Buffer([]); + var p = new Buffer( + utils.sizeIntv(message.length) + message.length + + 1 + + utils.sizeIntv(reason.length) + reason.length + + data.length); var off = 0; - var message = details.message || ''; - var ccode = constants.reject[details.ccode] || constants.reject.malformed; - var reason = details.reason || ''; - var data = details.data || []; - off += utils.writeIntv(p, message.length, off); - off += utils.writeAscii(p, message, off); + off += utils.copy(message, p, off); off += utils.writeU8(p, ccode, off); off += utils.writeIntv(p, reason.length, off); - off += utils.writeAscii(p, reason, off); + off += utils.copy(reason, p, off); - off += utils.copy(data, p, off, true); + off += utils.copy(data, p, off); - return this.packet('reject', new Buffer(p)); + return this.packet('reject', p); }; Framer.prototype.addr = function addr(peers) { diff --git a/lib/bcoin/protocol/parser.js b/lib/bcoin/protocol/parser.js index 9c84a4dc..6ece088f 100644 --- a/lib/bcoin/protocol/parser.js +++ b/lib/bcoin/protocol/parser.js @@ -50,7 +50,7 @@ Parser.prototype.feed = function feed(data) { len = 0; for (; off < chunk.length; i++) { - len = this.pending[0].copy(chunk, off, 0, this.pending[0].length); + len = utils.copy(this.pending[0], chunk, off); if (len === this.pending[0].length) this.pending.shift(); else @@ -100,7 +100,7 @@ Parser.prototype.parseHeader = function parseHeader(h) { if (i === 12) return this._error('Not NULL-terminated cmd'); - cmd = utils.stringify(h.slice(4, 4 + i)); + cmd = h.slice(4, 4 + i).toString('ascii'); this.waiting = utils.readU32(h, 16); return { @@ -215,7 +215,7 @@ Parser.prototype.parseVersion = function parseVersion(p) { local: recv, remote: from, nonce: nonce, - agent: utils.stringify(agent), + agent: agent.toString('ascii'), height: height, relay: relay }; @@ -481,7 +481,7 @@ Parser.prototype.parseReject = function parseReject(p) { if (off + messageLen + 2 > p.length) return this._error('Invalid reject message'); - message = utils.stringify(p.slice(off, off + messageLen)); + message = p.slice(off, off + messageLen).toString('ascii'); off += messageLen; ccode = utils.readU8(p, off); @@ -494,7 +494,7 @@ Parser.prototype.parseReject = function parseReject(p) { if (off + reasonLen > p.length) return this._error('Invalid reject reason'); - reason = utils.stringify(p.slice(off, off + reasonLen)); + reason = p.slice(off, off + reasonLen).toString('ascii'); off += reasonLen; diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index 368b6c88..f4631566 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -1552,7 +1552,7 @@ script.getOutputData = function getOutputData(s, inScriptHash) { type: 'nulldata', side: 'output', nulldata: s[1], - text: utils.array2utf8(s[1]) + text: s[1].toString('utf8') }; } @@ -2055,7 +2055,9 @@ script.getCoinbaseData = function getCoinbaseData(s) { coinbase.flags = flags; coinbase.text = - flags.map(utils.array2utf8).join('') + flags.map(function(flag) { + return flag.toString('utf8'); + }).join('') .replace(/[\u0000-\u0019\u007f-\u00ff]/g, ''); return coinbase; diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index 77301b1e..75dad79c 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -765,7 +765,7 @@ TX.prototype.scriptOutput = function scriptOutput(index, options) { // return [data] flags = options.flags; if (typeof flags === 'string') - flags = utils.ascii2array(flags); + flags = new Buffer(flags, 'ascii'); assert(Buffer.isBuffer(flags)); assert(flags.length <= constants.script.maxOpReturn); script = bcoin.script.createNulldata(flags); diff --git a/lib/bcoin/utils.js b/lib/bcoin/utils.js index 00d3e599..084337db 100644 --- a/lib/bcoin/utils.js +++ b/lib/bcoin/utils.js @@ -280,107 +280,15 @@ utils.decrypt = function decrypt(data, passphrase) { return out; }; -utils.writeAscii = function writeAscii(dst, str, off) { - var i = 0; - var c; - - for (; i < str.length; i++) { - c = str.charCodeAt(i); - dst[off + i] = c & 0xff; - } - - return i; -}; - -utils.readAscii = function readAscii(arr, off, len, printable) { - var str = ''; - var i = off; - var c; - - for (i = off; i < off + len; i++) { - if (printable) { - c = arr[i] & 0xff; - if (c === 0x09 || c === 0x0a || c === 0x0d || (c > 0x1f && c < 0x7f)) - c = String.fromCharCode(c); - else - c = ''; - } else { - c = String.fromCharCode(arr[i] & 0xff); - } - str += c; - } - - return str; -}; - -utils.ascii2array = function ascii2array(str) { - var dst = []; - utils.writeAscii(dst, str, 0); - return dst; -}; - -utils.array2ascii = function array2ascii(arr, printable) { - return utils.readAscii(arr, 0, arr.length, true); -}; - -utils.array2utf8 = function array2utf8(arr) { - if (Buffer.isBuffer(arr)) - return arr.toString('utf8'); - return new Buffer(arr).toString('utf8'); -}; - -utils.copy = function copy(src, dst, off, force) { - if (Buffer.isBuffer(src) && Buffer.isBuffer(dst)) { - utils.assert(!force); - return src.copy(dst, off, 0, src.length); - } - - var len = src.length; - var i = 0; - - if (!force) - len = Math.min(dst.length - off, len); - - for (; i < len; i++) - dst[i + off] = src[i]; - - return i; -}; - -utils.stringify = function stringify(arr) { - var res = ''; - var i = 0; - - if (Buffer.isBuffer(arr)) - return arr.toString('ascii'); - - for (; i < arr.length; i++) - res += String.fromCharCode(arr[i]); - - return res; +utils.copy = function copy(src, dst, off) { + return src.copy(dst, off, 0, src.length); }; utils.toHex = function toHex(msg) { - var res = ''; - var i = 0; - var word; - - if (Buffer.isBuffer(msg)) - return msg.toString('hex'); - if (typeof msg === 'string') return msg; - res = new Buffer(msg).toString('hex'); - - // for (; i < msg.length; i++) { - // word = msg[i].toString(16); - // if (word.length === 1) - // word = '0' + word; - // res += word; - // } - - return res; + return new Buffer(msg).toString('hex'); }; utils.isHex = function isHex(msg) {