diff --git a/lib/bcoin/protocol/framer.js b/lib/bcoin/protocol/framer.js index 953d001b..788aff31 100644 --- a/lib/bcoin/protocol/framer.js +++ b/lib/bcoin/protocol/framer.js @@ -103,7 +103,7 @@ Framer.prototype.version = function version(packet) { if (!this.agent) { p[off++] = 0; } else { - off += varint(p, this.agent.length, off); + off += utils.writeIntv(p, this.agent.length, off); for (i = 0; i < this.agent.length; i++) p[off++] = this.agent[i]; } @@ -121,39 +121,9 @@ Framer.prototype.verack = function verack() { return this.packet('verack', []); }; -function varint(arr, value, off) { - if (!off) - off = 0; - - if (value < 0xfd) { - arr[off] = value; - return 1; - } - - if (value <= 0xffff) { - arr[off] = 0xfd; - arr[off + 1] = value & 0xff; - arr[off + 2] = value >>> 8; - return 3; - } - - if (value <= 0xffffffff) { - arr[off] = 0xfe; - arr[off + 1] = value & 0xff; - arr[off + 2] = (value >>> 8) & 0xff; - arr[off + 3] = (value >>> 16) & 0xff; - arr[off + 4] = value >>> 24; - return 5; - } - - arr[off] = 0xff; - utils.writeU64(arr, value, off + 1); - return 9; -} - Framer.prototype._inv = function _inv(command, items) { var res = []; - var off = varint(res, items.length, 0); + var off = utils.writeIntv(res, items.length, 0); var i, hash; assert(items.length <= 50000); @@ -200,7 +170,7 @@ Framer.prototype.filterLoad = function filterLoad(bloom, update) { var before = []; var after = new Array(9); - varint(before, filter.length, 0); + utils.writeIntv(before, filter.length, 0); // Number of hash functions writeU32(after, bloom.n, 0); @@ -231,7 +201,7 @@ Framer.prototype._getBlocks = function _getBlocks(cmd, hashes, stop) { var off, i, hash, len; writeU32(p, constants.version, 0); - off = 4 + varint(p, hashes.length, 4); + off = 4 + utils.writeIntv(p, hashes.length, 4); p.length = off + 32 * (hashes.length + 1); for (i = 0; i < hashes.length; i++) { @@ -268,7 +238,7 @@ Framer.tx = function tx(tx) { var off, i, input, s, output, value, j; off = writeU32(p, tx.version, 0); - off += varint(p, tx.inputs.length, off); + off += utils.writeIntv(p, tx.inputs.length, off); for (i = 0; i < tx.inputs.length; i++) { input = tx.inputs[i]; @@ -277,13 +247,13 @@ Framer.tx = function tx(tx) { off += writeU32(p, input.out.index, off); s = bcoin.script.encode(input.script); - off += varint(p, s.length, off); + off += utils.writeIntv(p, s.length, off); off += utils.copy(s, p, off, true); off += writeU32(p, input.seq, off); } - off += varint(p, tx.outputs.length, off); + off += utils.writeIntv(p, tx.outputs.length, off); for (i = 0; i < tx.outputs.length; i++) { output = tx.outputs[i]; @@ -297,7 +267,7 @@ Framer.tx = function tx(tx) { p[off] = 0; s = bcoin.script.encode(output.script); - off += varint(p, s.length, off); + off += utils.writeIntv(p, s.length, off); off += utils.copy(s, p, off, true); } off += writeU32(p, tx.lock, off); @@ -344,7 +314,7 @@ Framer.block = function _block(block, type) { // txn_count off += writeU32(p, block.totalTX, off); // hash count - off += varint(p, block.hashes.length, off); + off += utils.writeIntv(p, block.hashes.length, off); // hashes block.hashes.forEach(function(hash) { utils.toArray(hash, 'hex').forEach(function(ch) { @@ -352,14 +322,14 @@ Framer.block = function _block(block, type) { }); }); // flag count - off += varint(p, block.flags.length, off); + off += utils.writeIntv(p, block.flags.length, off); // flags block.flags.forEach(function(flag) { p[off++] = flag; }); } else if (type === 'block') { // txn_count - off += varint(p, block.totalTX, off); + off += utils.writeIntv(p, block.totalTX, off); // txs block.txs.forEach(function(tx) { var raw = tx._raw || tx.render(); @@ -391,7 +361,7 @@ Framer.prototype.addr = function addr(peers) { var i; // count - off += varint(p, peers.length, off); + off += utils.writeIntv(p, peers.length, off); for (; i < peers.length; i++) { peer = peers[i]; diff --git a/lib/bcoin/protocol/parser.js b/lib/bcoin/protocol/parser.js index 1465296e..82187d38 100644 --- a/lib/bcoin/protocol/parser.js +++ b/lib/bcoin/protocol/parser.js @@ -158,7 +158,7 @@ Parser.prototype.parseVersion = function parseVersion(p) { nonce = { lo: readU32(p, 72), hi: readU32(p, 76) }; // User agent length - result = readIntv(p, 80); + result = utils.readIntv(p, 80); off = result.off; agent = p.slice(off, off + result.r); off += result.r; @@ -181,34 +181,11 @@ Parser.prototype.parseVersion = function parseVersion(p) { }; }; -function readIntv(p, off) { - var r, bytes; - - if (!off) - off = 0; - - if (p[off] < 0xfd) { - r = p[off]; - bytes = 1; - } else if (p[off] === 0xfd) { - r = p[off + 1] | (p[off + 2] << 8); - bytes = 3; - } else if (p[off] === 0xfe) { - r = readU32(p, off + 1); - bytes = 5; - } else { - r = 0; - bytes = 9; - } - - return { off: off + bytes, r: r }; -} - Parser.prototype.parseInvList = function parseInvList(p) { var items = []; var i, off, count; - count = readIntv(p, 0); + count = utils.readIntv(p, 0); p = p.slice(count.off); count = count.r; @@ -231,7 +208,7 @@ Parser.prototype.parseMerkleBlock = function parseMerkleBlock(p) { if (p.length < 86) return this._error('Invalid merkleblock size'); - hashCount = readIntv(p, 84); + hashCount = utils.readIntv(p, 84); off = hashCount.off; hashCount = hashCount.r; @@ -244,7 +221,7 @@ Parser.prototype.parseMerkleBlock = function parseMerkleBlock(p) { hashes[i] = p.slice(off + i * 32, off + (i + 1) * 32); off = off + 32 * hashCount; - flagCount = readIntv(p, off); + flagCount = utils.readIntv(p, off); off = flagCount.off; flagCount = flagCount.r; @@ -275,7 +252,7 @@ Parser.prototype.parseHeaders = function parseHeaders(p) { if (p.length < 81) return this._error('Invalid headers size'); - result = readIntv(p, 0); + result = utils.readIntv(p, 0); off = result.off; count = result.r; @@ -295,7 +272,7 @@ Parser.prototype.parseHeaders = function parseHeaders(p) { off += 4; header.nonce = readU32(p, off); off += 4; - r = readIntv(p, off); + r = utils.readIntv(p, off); header.totalTX = r.r; off = r.off; header._raw = p.slice(start, start + 80); @@ -313,7 +290,7 @@ Parser.prototype.parseBlock = function parseBlock(p) { if (p.length < 81) return this._error('Invalid block size'); - result = readIntv(p, 80); + result = utils.readIntv(p, 80); off = result.off; totalTX = result.r; @@ -345,7 +322,7 @@ Parser.prototype.parseTXIn = function parseTXIn(p) { if (p.length < 41) return this._error('Invalid tx_in size'); - scriptLen = readIntv(p, 36); + scriptLen = utils.readIntv(p, 36); off = scriptLen.off; scriptLen = scriptLen.r; @@ -369,7 +346,7 @@ Parser.prototype.parseTXOut = function parseTXOut(p) { if (p.length < 9) return this._error('Invalid tx_out size'); - scriptLen = readIntv(p, 8); + scriptLen = utils.readIntv(p, 8); off = scriptLen.off; scriptLen = scriptLen.r; @@ -391,7 +368,7 @@ Parser.prototype.parseTX = function parseTX(p) { if (p.length < 10) return this._error('Invalid tx size'); - inCount = readIntv(p, 4); + inCount = utils.readIntv(p, 4); off = inCount.off; inCount = inCount.r; @@ -415,7 +392,7 @@ Parser.prototype.parseTX = function parseTX(p) { return this._error('Invalid tx_in offset'); } - outCount = readIntv(p, off); + outCount = utils.readIntv(p, off); off = outCount.off; outCount = outCount.r; if (outCount < 0) @@ -454,7 +431,7 @@ Parser.prototype.parseReject = function parseReject(p) { if (p.length < 3) return this._error('Invalid reject size'); - messageLen = readIntv(p, 0); + messageLen = utils.readIntv(p, 0); off = messageLen.off; messageLen = messageLen.r; @@ -467,7 +444,7 @@ Parser.prototype.parseReject = function parseReject(p) { ccode = p[off]; off++; - reasonLen = readIntv(p, off); + reasonLen = utils.readIntv(p, off); off = reasonLen.off; reasonLen = reasonLen.r; @@ -496,7 +473,7 @@ Parser.prototype.parseAddr = function parseAddr(p) { var i, len, off, count, ts, service, ipv6, ipv4, port; // count - len = readIntv(p, 0); + len = utils.readIntv(p, 0); off = len.off; count = len.r; diff --git a/lib/bcoin/utils.js b/lib/bcoin/utils.js index de712e31..1dce48e6 100644 --- a/lib/bcoin/utils.js +++ b/lib/bcoin/utils.js @@ -665,3 +665,56 @@ utils.sortKeys = function sortKeys(keys) { return new bn(a).cmp(new bn(b)) > 0; }); }; + +utils.readIntv = function readIntv(p, off) { + var r, bytes; + + if (!off) + off = 0; + + if (p[off] < 0xfd) { + r = p[off]; + bytes = 1; + } else if (p[off] === 0xfd) { + r = p[off + 1] | (p[off + 2] << 8); + bytes = 3; + } else if (p[off] === 0xfe) { + r = utils.readU32(p, off + 1); + bytes = 5; + } else { + r = 0; + bytes = 9; + } + + return { off: off + bytes, r: r }; +}; + +utils.writeIntv = function writeIntv(arr, value, off) { + if (!off) + off = 0; + + if (value < 0xfd) { + arr[off] = value; + return 1; + } + + if (value <= 0xffff) { + arr[off] = 0xfd; + arr[off + 1] = value & 0xff; + arr[off + 2] = value >>> 8; + return 3; + } + + if (value <= 0xffffffff) { + arr[off] = 0xfe; + arr[off + 1] = value & 0xff; + arr[off + 2] = (value >>> 8) & 0xff; + arr[off + 3] = (value >>> 16) & 0xff; + arr[off + 4] = value >>> 24; + return 5; + } + + arr[off] = 0xff; + utils.writeU64(arr, value, off + 1); + return 9; +};