no slices.

This commit is contained in:
Christopher Jeffrey 2016-03-14 13:51:04 -07:00
parent 00dfad25da
commit d0a5ae7aa4

View File

@ -54,7 +54,6 @@ Parser.prototype.feed = function feed(data) {
this.pending.shift(); this.pending.shift();
else else
this.pending[0] = this.pending[0].slice(len); this.pending[0] = this.pending[0].slice(len);
//this.pending[0] = this.pending[0].slice(len);
off += len; off += len;
} }
@ -154,47 +153,57 @@ Parser.prototype.parsePayload = function parsePayload(cmd, p) {
return p; return p;
}; };
Parser.parsePing = function parsePing(p) { Parser.parsePing = function parsePing(p, off) {
if (p.length < 8) off = off || 0;
if (p.length - off < 8)
throw new Error('pong packet is too small'); throw new Error('pong packet is too small');
return { return {
nonce: utils.readU64(p, 0) nonce: utils.readU64(p, off)
}; };
}; };
Parser.parsePong = function parsePong(p) { Parser.parsePong = function parsePong(p, off) {
if (p.length < 8) off = off || 0;
if (p.length - off < 8)
throw new Error('ping packet is too small'); throw new Error('ping packet is too small');
return { return {
nonce: utils.readU64(p, 0) nonce: utils.readU64(p, off)
}; };
}; };
Parser.parseVersion = function parseVersion(p) { Parser.parseVersion = function parseVersion(p, off) {
var v, services, ts, recv, from, nonce, result, off, agent, height, relay; var v, services, ts, recv, from, nonce, result, off, agent, height, relay;
off = off || 0;
if (p.length < 85) if (p.length < 85)
throw new Error('version packet is too small'); throw new Error('version packet is too small');
v = utils.readU32(p, 0); v = utils.readU32(p, off);
services = utils.readU64(p, 4); off += 4;
services = utils.readU64(p, off);
off += 8;
// Timestamp // Timestamp
ts = utils.read64(p, 12); ts = utils.read64(p, off);
off += 8;
// Our address (recv) // Our address (recv)
recv = Parser.parseAddress(p, 20); recv = Parser.parseAddress(p, off);
off += 26;
// Their Address (from) // Their Address (from)
from = Parser.parseAddress(p, 46); from = Parser.parseAddress(p, off);
off += 26;
// Nonce, very dramatic // Nonce, very dramatic
nonce = utils.readU64(p, 72); nonce = utils.readU64(p, off);
off += 8;
// User agent length // User agent length
result = utils.readIntv(p, 80); result = utils.readIntv(p, off);
off = result.off; off = result.off;
agent = p.toString('ascii', off, off + result.r); agent = p.toString('ascii', off, off + result.r);
off += result.r; off += result.r;
@ -205,6 +214,8 @@ Parser.parseVersion = function parseVersion(p) {
// Relay // Relay
relay = p.length > off ? p[off] === 1 : true; relay = p.length > off ? p[off] === 1 : true;
if (p.length > off)
off += 1;
try { try {
ts = ts.toNumber(); ts = ts.toNumber();
@ -235,18 +246,19 @@ Parser.parseVersion = function parseVersion(p) {
}; };
}; };
Parser.parseInvList = function parseInvList(p) { Parser.parseInvList = function parseInvList(p, off) {
var items = []; var items = [];
var i, off, count; var i, count;
off = off || 0;
count = utils.readIntv(p, 0); count = utils.readIntv(p, off);
p = p.slice(count.off); off = count.off;
count = count.r; count = count.r;
if (p.length < count * 36) if (p.length < count * 36)
throw new Error('Invalid getdata size'); throw new Error('Invalid getdata size');
for (i = 0, off = 0; i < count; i++, off += 36) { for (i = 0; i < count; i++, off += 36) {
items.push({ items.push({
type: constants.invByVal[utils.readU32(p, off)], type: constants.invByVal[utils.readU32(p, off)],
hash: utils.slice(p, off + 4, off + 36) hash: utils.slice(p, off + 4, off + 36)
@ -256,13 +268,30 @@ Parser.parseInvList = function parseInvList(p) {
return items; return items;
}; };
Parser.parseMerkleBlock = function parseMerkleBlock(p) { Parser.parseMerkleBlock = function parseMerkleBlock(p, off) {
var i, hashCount, off, hashes, flagCount, flags; var i, hashCount, hashes, flagCount, flags;
off = off || 0;
var start = off;
if (p.length < 86) if (p.length - off < 86)
throw new Error('Invalid merkleblock size'); throw new Error('Invalid merkleblock size');
hashCount = utils.readIntv(p, 84); var version = utils.read32(p, off);
off += 4;
var prevBlock = utils.slice(p, off, off + 32);
off += 32;
var merkleRoot = utils.slice(p, off, off + 32);
off += 32;
var ts = utils.readU32(p, off);
off += 4;
var bits = utils.readU32(p, off);
off += 4;
var nonce = utils.readU32(p, off);
off += 4;
var totalTX = utils.readU32(p, off);
off += 4;
hashCount = utils.readIntv(p, off);
off = hashCount.off; off = hashCount.off;
hashCount = hashCount.r; hashCount = hashCount.r;
@ -285,27 +314,28 @@ Parser.parseMerkleBlock = function parseMerkleBlock(p) {
flags = utils.slice(p, off, off + flagCount); flags = utils.slice(p, off, off + flagCount);
return { return {
version: utils.read32(p, 0), version: version,
prevBlock: utils.slice(p, 4, 36), prevBlock: prevBlock,
merkleRoot: utils.slice(p, 36, 68), merkleRoot: merkleRoot,
ts: utils.readU32(p, 68), ts: ts,
bits: utils.readU32(p, 72), bits: bits,
nonce: utils.readU32(p, 76), nonce: nonce,
totalTX: utils.readU32(p, 80), totalTX: totalTX,
hashes: hashes, hashes: hashes,
flags: flags, flags: flags,
_size: p.length _size: off - start
}; };
}; };
Parser.parseHeaders = function parseHeaders(p) { Parser.parseHeaders = function parseHeaders(p, off) {
var headers = []; var headers = [];
var i, result, off, count, header, start, r; var i, result, count, header, start, r;
off = off || 0;
if (p.length < 81) if (p.length - off < 81)
throw new Error('Invalid headers size'); throw new Error('Invalid headers size');
result = utils.readIntv(p, 0); result = utils.readIntv(p, off);
off = result.off; off = result.off;
count = result.r; count = result.r;
@ -336,20 +366,35 @@ Parser.parseHeaders = function parseHeaders(p) {
return headers; return headers;
}; };
Parser.parseBlock = function parseBlock(p) { Parser.parseBlock = function parseBlock(p, off) {
var txs = []; var txs = [];
var witnessSize = 0; var witnessSize = 0;
var i, result, off, totalTX, tx; var i, result, off, totalTX, tx;
off = off || 0;
var start = off;
if (p.length < 81) if (p.length - off < 81)
throw new Error('Invalid block size'); throw new Error('Invalid block size');
result = utils.readIntv(p, 80); var version = utils.read32(p, off);
off += 4;
var prevBlock = utils.slice(p, off, off + 32);
off += 32;
var merkleRoot = utils.slice(p, off, off + 32);
off += 32;
var ts = utils.readU32(p, off);
off += 4;
var bits = utils.readU32(p, off);
off += 4;
var nonce = utils.readU32(p, off);
off += 4;
result = utils.readIntv(p, off);
off = result.off; off = result.off;
totalTX = result.r; totalTX = result.r;
for (i = 0; i < totalTX; i++) { for (i = 0; i < totalTX; i++) {
tx = Parser.parseTX(p.slice(off), true); tx = Parser.parseTX(p, off);
if (!tx) if (!tx)
throw new Error('Invalid tx count for block'); throw new Error('Invalid tx count for block');
tx._offset = off; tx._offset = off;
@ -359,30 +404,43 @@ Parser.parseBlock = function parseBlock(p) {
} }
return { return {
version: utils.read32(p, 0), version: version,
prevBlock: utils.slice(p, 4, 36), prevBlock: prevBlock,
merkleRoot: utils.slice(p, 36, 68), merkleRoot: merkleRoot,
ts: utils.readU32(p, 68), ts: ts,
bits: utils.readU32(p, 72), bits: bits,
nonce: utils.readU32(p, 76), nonce: nonce,
totalTX: totalTX,
txs: txs, txs: txs,
_size: p.length, _size: off - start,
_witnessSize: witnessSize _witnessSize: witnessSize
}; };
}; };
Parser.parseBlockCompact = function parseBlockCompact(p) { Parser.parseBlockCompact = function parseBlockCompact(p, off) {
var height = -1; var height = -1;
var i, result, off, totalTX, tx; var i, result, off, totalTX, tx;
var inCount, input, s, version; var inCount, input, s, version;
off = off || 0;
var start = off;
if (p.length < 81) if (p.length - off < 81)
throw new Error('Invalid block size'); throw new Error('Invalid block size');
version = utils.read32(p, 0); version = utils.read32(p, off);
off += 4;
result = utils.readIntv(p, 80); var prevBlock = utils.slice(p, off, off + 32);
off += 32;
var merkleRoot = utils.slice(p, off, off + 32);
off += 32;
var ts = utils.readU32(p, off);
off += 4;
var bits = utils.readU32(p, off);
off += 4;
var nonce = utils.readU32(p, off);
off += 4;
result = utils.readIntv(p, off);
off = result.off; off = result.off;
totalTX = result.r; totalTX = result.r;
@ -395,7 +453,7 @@ Parser.parseBlockCompact = function parseBlockCompact(p) {
inCount = inCount.r; inCount = inCount.r;
if (inCount > 0) { if (inCount > 0) {
input = Parser.parseInput(p.slice(off)); input = Parser.parseInput(p, off);
if (!input) if (!input)
throw new Error('Invalid tx count for block'); throw new Error('Invalid tx count for block');
} }
@ -409,66 +467,87 @@ Parser.parseBlockCompact = function parseBlockCompact(p) {
return { return {
version: version, version: version,
prevBlock: utils.slice(p, 4, 36), prevBlock: prevBlock,
merkleRoot: utils.slice(p, 36, 68), merkleRoot: merkleRoot,
ts: utils.readU32(p, 68), ts: ts,
bits: utils.readU32(p, 72), bits: bits,
nonce: utils.readU32(p, 76), nonce: nonce,
totalTX: totalTX, totalTX: totalTX,
coinbaseHeight: height, coinbaseHeight: height,
txs: [], txs: [],
_raw: p, _raw: p,
_size: p.length _size: off - start
}; };
}; };
Parser.parseInput = function parseInput(p) { Parser.parseInput = function parseInput(p, off) {
var scriptLen, off; var scriptLen;
if (p.length < 41) off = off || 0;
var start = off;
if (p.length - off < 41)
throw new Error('Invalid tx_in size'); throw new Error('Invalid tx_in size');
scriptLen = utils.readIntv(p, 36); var hash = utils.slice(p, off, off + 32);
off += 32;
var index = utils.readU32(p, off);
off += 4;
scriptLen = utils.readIntv(p, off);
off = scriptLen.off; off = scriptLen.off;
scriptLen = scriptLen.r; scriptLen = scriptLen.r;
if (off + scriptLen + 4 > p.length) if (off + scriptLen + 4 > p.length)
throw new Error('Invalid tx_in script length'); throw new Error('Invalid tx_in script length');
var script = bcoin.script.decode(utils.slice(p, off, off + scriptLen));
off += scriptLen;
var sequence = utils.readU32(p, off);
off += 4;
return { return {
_size: off + scriptLen + 4, _size: off - start,
prevout: { prevout: {
hash: utils.slice(p, 0, 32), hash: hash,
index: utils.readU32(p, 32) index: index
}, },
script: bcoin.script.decode(utils.slice(p, off, off + scriptLen)), script: script,
sequence: utils.readU32(p, off + scriptLen) sequence: sequence
}; };
}; };
Parser.parseOutput = function parseOutput(p) { Parser.parseOutput = function parseOutput(p, off) {
var scriptLen, off; var scriptLen;
off = off || 0;
var start = off;
if (p.length < 9) if (p.length - off < 9)
throw new Error('Invalid tx_out size'); throw new Error('Invalid tx_out size');
scriptLen = utils.readIntv(p, 8); var value = utils.read64(p, off);
off += 8;
scriptLen = utils.readIntv(p, off);
off = scriptLen.off; off = scriptLen.off;
scriptLen = scriptLen.r; scriptLen = scriptLen.r;
if (off + scriptLen > p.length) if (off + scriptLen > p.length)
throw new Error('Invalid tx_out script length'); throw new Error('Invalid tx_out script length');
var script = bcoin.script.decode(utils.slice(p, off, off + scriptLen));
off += scriptLen;
return { return {
_size: off + scriptLen, _size: off - start,
value: utils.read64(p, 0), value: value,
script: bcoin.script.decode(utils.slice(p, off, off + scriptLen)) script: script
}; };
}; };
Parser.parseCoin = function parseCoin(p, extended) { Parser.parseCoin = function parseCoin(p, extended, off) {
var off = 0;
var version, height, value, script, hash, index, spent, scriptLen; var version, height, value, script, hash, index, spent, scriptLen;
off = off || 0;
if (p.length < 17 + (extended ? 37 : 0)) if (p.length < 17 + (extended ? 37 : 0))
throw new Error('Invalid utxo size'); throw new Error('Invalid utxo size');
@ -520,18 +599,20 @@ Parser.parseCoin = function parseCoin(p, extended) {
}; };
}; };
Parser.parseTX = function parseTX(p, block) { Parser.parseTX = function parseTX(p, off) {
var off = 0;
var inCount, txIn, tx; var inCount, txIn, tx;
var outCount, txOut; var outCount, txOut;
var version, locktime, i; var version, locktime, i;
var raw; var raw;
off = off || 0;
var start = off;
var block = off !== 0;
if (p.length < 10) if (p.length - off < 10)
throw new Error('Invalid tx size'); throw new Error('Invalid tx size');
if (Parser.isWitnessTX(p)) if (Parser.isWitnessTX(p, off))
return Parser.parseWitnessTX(p, block); return Parser.parseWitnessTX(p, off);
version = utils.readU32(p, off); version = utils.readU32(p, off);
off += 4; off += 4;
@ -548,7 +629,7 @@ Parser.parseTX = function parseTX(p, block) {
txIn = new Array(inCount); txIn = new Array(inCount);
for (i = 0; i < inCount; i++) { for (i = 0; i < inCount; i++) {
tx = Parser.parseInput(p.slice(off)); tx = Parser.parseInput(p, off);
if (!tx) if (!tx)
return; return;
@ -572,7 +653,7 @@ Parser.parseTX = function parseTX(p, block) {
txOut = new Array(outCount); txOut = new Array(outCount);
for (i = 0; i < outCount; i++) { for (i = 0; i < outCount; i++) {
tx = Parser.parseOutput(p.slice(off)); tx = Parser.parseOutput(p, off);
if (!tx) if (!tx)
return; return;
@ -600,27 +681,31 @@ Parser.parseTX = function parseTX(p, block) {
locktime: locktime, locktime: locktime,
_witnessSize: 0, _witnessSize: 0,
// _raw: raw, // _raw: raw,
_size: off _size: off - start
}; };
}; };
Parser.isWitnessTX = function isWitnessTX(p) { Parser.isWitnessTX = function isWitnessTX(p, off) {
if (p.length < 12) off = off || 0;
if (p.length - off < 12)
return false; return false;
return p[4] === 0 && p[5] !== 0; return p[off + 4] === 0 && p[off + 5] !== 0;
}; };
Parser.parseWitnessTX = function parseWitnessTX(p, block) { Parser.parseWitnessTX = function parseWitnessTX(p, off) {
var off = 0;
var inCount, txIn, tx; var inCount, txIn, tx;
var outCount, txOut; var outCount, txOut;
var marker, flag; var marker, flag;
var version, locktime, i; var version, locktime, i;
var witnessSize = 0; var witnessSize = 0;
var raw; var raw;
off = off || 0;
var start = off;
var block = off !== 0;
if (p.length < 12) if (p.length - off < 12)
throw new Error('Invalid witness tx size'); throw new Error('Invalid witness tx size');
version = utils.readU32(p, off); version = utils.readU32(p, off);
@ -648,7 +733,7 @@ Parser.parseWitnessTX = function parseWitnessTX(p, block) {
txIn = new Array(inCount); txIn = new Array(inCount);
for (i = 0; i < inCount; i++) { for (i = 0; i < inCount; i++) {
tx = Parser.parseInput(p.slice(off)); tx = Parser.parseInput(p, off);
if (!tx) if (!tx)
return; return;
@ -671,7 +756,7 @@ Parser.parseWitnessTX = function parseWitnessTX(p, block) {
txOut = new Array(outCount); txOut = new Array(outCount);
for (i = 0; i < outCount; i++) { for (i = 0; i < outCount; i++) {
tx = Parser.parseOutput(p.slice(off)); tx = Parser.parseOutput(p, off);
if (!tx) if (!tx)
return; return;
@ -685,7 +770,7 @@ Parser.parseWitnessTX = function parseWitnessTX(p, block) {
} }
for (i = 0; i < inCount; i++) { for (i = 0; i < inCount; i++) {
tx = Parser.parseWitness(p.slice(off)); tx = Parser.parseWitness(p, off);
if (!tx) if (!tx)
return; return;
@ -716,15 +801,16 @@ Parser.parseWitnessTX = function parseWitnessTX(p, block) {
outputs: txOut, outputs: txOut,
locktime: locktime, locktime: locktime,
// _raw: raw, // _raw: raw,
_size: off, _size: off - start,
_witnessSize: witnessSize + 2 _witnessSize: witnessSize + 2
}; };
}; };
Parser.parseWitness = function parseWitness(p) { Parser.parseWitness = function parseWitness(p, off) {
var witness = []; var witness = [];
var off = 0;
var chunkCount, chunkSize, item, i; var chunkCount, chunkSize, item, i;
off = off || 0;
var start = off;
chunkCount = utils.readIntv(p, off); chunkCount = utils.readIntv(p, off);
off = chunkCount.off; off = chunkCount.off;
@ -742,25 +828,26 @@ Parser.parseWitness = function parseWitness(p) {
} }
return { return {
_size: off, _size: off - start,
witness: witness witness: witness
}; };
}; };
Parser.parseReject = function parseReject(p) { Parser.parseReject = function parseReject(p, off) {
var messageLen, off, message, ccode, reasonLen, reason, data; var messageLen, off, message, ccode, reasonLen, reason, data;
off = off || 0;
if (p.length < 3) if (p.length < 3)
throw new Error('Invalid reject size'); throw new Error('Invalid reject size');
messageLen = utils.readIntv(p, 0); messageLen = utils.readIntv(p, off);
off = messageLen.off; off = messageLen.off;
messageLen = messageLen.r; messageLen = messageLen.r;
if (off + messageLen + 2 > p.length) if (off + messageLen + 2 > p.length)
throw new Error('Invalid reject message'); throw new Error('Invalid reject message');
message = p.slice(off, off + messageLen).toString('ascii'); message = p.toString('ascii', off, off + messageLen);
off += messageLen; off += messageLen;
ccode = utils.readU8(p, off); ccode = utils.readU8(p, off);
@ -773,7 +860,7 @@ Parser.parseReject = function parseReject(p) {
if (off + reasonLen > p.length) if (off + reasonLen > p.length)
throw new Error('Invalid reject reason'); throw new Error('Invalid reject reason');
reason = p.slice(off, off + reasonLen).toString('ascii'); reason = p.toString('ascii', off, off + reasonLen);
off += reasonLen; off += reasonLen;
@ -828,14 +915,15 @@ Parser.parseAddress = function parseAddress(p, off, full) {
}; };
}; };
Parser.parseAddr = function parseAddr(p) { Parser.parseAddr = function parseAddr(p, off) {
if (p.length < 31) if (p.length < 31)
throw new Error('Invalid addr size'); throw new Error('Invalid addr size');
var addrs = []; var addrs = [];
var i, off, count; var i, count;
off = off || 0;
count = utils.readIntv(p, 0); count = utils.readIntv(p, off);
off = count.off; off = count.off;
count = count.r; count = count.r;
@ -847,13 +935,116 @@ Parser.parseAddr = function parseAddr(p) {
return addrs; return addrs;
}; };
Parser.parseMempool = function parseMempool(p) { Parser.parseMempool = function parseMempool(p, off) {
if (p.length > 0) off = off || 0;
if (p.length - off > 0)
throw new Error('Invalid mempool size'); throw new Error('Invalid mempool size');
return {}; return {};
}; };
function BufferReader(data, offset) {
this.data = data;
this.offset = offset || 0;
}
BufferReader.prototype.readU8 = function readU8() {
var ret = utils.readU8(this.data, this.offset);
this.offset += 1;
return ret;
};
BufferReader.prototype.readU16 = function readU16() {
var ret = utils.readU16(this.data, this.offset);
this.offset += 2;
return ret;
};
BufferReader.prototype.readU16BE = function readU16BE() {
var ret = utils.readU16BE(this.data, this.offset);
this.offset += 2;
return ret;
};
BufferReader.prototype.readU32 = function readU32() {
var ret = utils.readU32(this.data, this.offset);
this.offset += 4;
return ret;
};
BufferReader.prototype.readU32BE = function readU32BE() {
var ret = utils.readU32BE(this.data, this.offset);
this.offset += 4;
return ret;
};
BufferReader.prototype.readU64 = function readU64() {
var ret = utils.readU64(this.data, this.offset);
this.offset += 8;
return ret;
};
BufferReader.prototype.readU64BE = function readU64BE() {
var ret = utils.readU64BE(this.data, this.offset);
this.offset += 8;
return ret;
};
BufferReader.prototype.read8 = function read8() {
var ret = utils.read8(this.data, this.offset);
this.offset += 1;
return ret;
};
BufferReader.prototype.read16 = function read16() {
var ret = utils.read16(this.data, this.offset);
this.offset += 2;
return ret;
};
BufferReader.prototype.read16BE = function read16BE() {
var ret = utils.read16BE(this.data, this.offset);
this.offset += 2;
return ret;
};
BufferReader.prototype.read32 = function read32() {
var ret = utils.read32(this.data, this.offset);
this.offset += 4;
return ret;
};
BufferReader.prototype.read32BE = function read32BE() {
var ret = utils.read32BE(this.data, this.offset);
this.offset += 4;
return ret;
};
BufferReader.prototype.read64 = function read64() {
var ret = utils.read64(this.data, this.offset);
this.offset += 8;
return ret;
};
BufferReader.prototype.read64BE = function read64BE() {
var ret = utils.read64BE(this.data, this.offset);
this.offset += 8;
return ret;
};
BufferReader.prototype.slice = function slice(size) {
if (size == null)
size = this.data.length - this.offset;
var ret = utils.slice(this.data, this.offset, this.offset + size);
this.offset += size;
return ret;
};
BufferReader.prototype.readHash = function readHash() {
return this.slice(32);
};
/** /**
* Expose * Expose
*/ */