net: refactor framer and parser.
This commit is contained in:
parent
40e028f182
commit
d663eef37e
1044
lib/net/framer.js
1044
lib/net/framer.js
File diff suppressed because it is too large
Load Diff
@ -997,6 +997,240 @@ NetworkAddress.prototype.toRaw = function toRaw(full, writer) {
|
||||
return p;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a `getutxos` packet.
|
||||
* @exports GetUTXOsPacket
|
||||
* @constructor
|
||||
* @param {Boolean} mempool
|
||||
* @param {Outpoint[]} prevout
|
||||
* @property {Boolean} mempool
|
||||
* @property {Outpoint[]} prevout
|
||||
*/
|
||||
|
||||
function GetUTXOsPacket(mempool, prevout) {
|
||||
if (!(this instanceof GetUTXOsPacket))
|
||||
return new GetUTXOsPacket(mempool, prevout);
|
||||
|
||||
this.mempool = mempool || false;
|
||||
this.prevout = prevout || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize getutxos packet.
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
GetUTXOsPacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var i;
|
||||
|
||||
p.writeU8(this.mempool ? 1 : 0);
|
||||
p.writeVarint(this.prevout.length);
|
||||
|
||||
for (i = 0; i < this.prevout.length; i++)
|
||||
this.prevout[i].toRaw(p);
|
||||
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
|
||||
return p;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject properties from serialized data.
|
||||
* @private
|
||||
* @param {Buffer} data
|
||||
*/
|
||||
|
||||
GetUTXOsPacket.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var i, count;
|
||||
|
||||
this.mempool = p.readU8() === 1;
|
||||
|
||||
count = p.readVarint();
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
this.prevout.push(bcoin.outpoint.fromRaw(p));
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate getutxos packet from serialized data.
|
||||
* @param {Buffer} data
|
||||
* @param {String?} enc
|
||||
* @returns {GetBlocksPacket}
|
||||
*/
|
||||
|
||||
GetUTXOsPacket.fromRaw = function fromRaw(data, enc) {
|
||||
if (typeof data === 'string')
|
||||
data = new Buffer(data, enc);
|
||||
return new GetUTXOsPacket().fromRaw(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a `utxos` packet.
|
||||
* @exports UTXOsPacket
|
||||
* @constructor
|
||||
* @param {Object} options
|
||||
* @property {Number} height
|
||||
* @property {Hash} tip
|
||||
* @property {Boolean[]} hits
|
||||
* @property {Coin[]} coins
|
||||
*/
|
||||
|
||||
function UTXOsPacket(options) {
|
||||
if (!(this instanceof UTXOsPacket))
|
||||
return new UTXOsPacket(options);
|
||||
|
||||
this.height = -1;
|
||||
this.tip = constants.NULL_HASH;
|
||||
this.hits = [];
|
||||
this.coins = [];
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject properties from options.
|
||||
* @private
|
||||
* @param {Buffer} data
|
||||
*/
|
||||
|
||||
UTXOsPacket.prototype.fromOptions = function fromOptions(options) {
|
||||
if (options.height != null) {
|
||||
assert(utils.isNumber(options.height));
|
||||
this.height = options.height;
|
||||
}
|
||||
|
||||
if (options.tip) {
|
||||
assert(typeof options.tip === 'string');
|
||||
this.tip = options.tip;
|
||||
}
|
||||
|
||||
if (options.hits) {
|
||||
assert(Array.isArray(options.hits));
|
||||
this.hits = options.hits;
|
||||
}
|
||||
|
||||
if (options.coins) {
|
||||
assert(Array.isArray(options.coins));
|
||||
this.coins = options.coins;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate utxos packet from options.
|
||||
* @param {Buffer} data
|
||||
* @param {String?} enc
|
||||
* @returns {GetBlocksPacket}
|
||||
*/
|
||||
|
||||
UTXOsPacket.fromOptions = function fromOptions(options) {
|
||||
return new UTXOsPacket().fromOptions(options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize utxos packet.
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
UTXOsPacket.prototype.toRaw = function toRaw(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
var map = new Buffer((this.hits.length + 7) / 8 | 0);
|
||||
var i, bit, oct, coin, height;
|
||||
|
||||
for (i = 0; i < this.hits.length; i++) {
|
||||
bit = i % 8;
|
||||
oct = (i - bit) / 8;
|
||||
map[oct] |= +this.hits[i] << (7 - bit);
|
||||
}
|
||||
|
||||
p.writeU32(this.height);
|
||||
p.writeHash(this.tip);
|
||||
p.writeVarBytes(map);
|
||||
p.writeVarInt(this.coins.length);
|
||||
|
||||
for (i = 0; i < this.coins.length; i++) {
|
||||
coin = this.coins[i];
|
||||
height = coin.height;
|
||||
|
||||
if (height === -1)
|
||||
height = 0x7fffffff;
|
||||
|
||||
p.writeU32(coin.version);
|
||||
p.writeU32(height);
|
||||
p.write64(coin.value);
|
||||
p.writeVarBytes(coin.script.toRaw());
|
||||
}
|
||||
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
|
||||
return p;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject properties from serialized data.
|
||||
* @private
|
||||
* @param {Buffer} data
|
||||
*/
|
||||
|
||||
UTXOsPacket.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var i, bit, oct, coin, output;
|
||||
var version, height, map, count;
|
||||
|
||||
this.height = p.readU32();
|
||||
this.tip = p.readHash('hex');
|
||||
|
||||
map = p.readVarBytes();
|
||||
count = p.readVarint();
|
||||
|
||||
for (i = 0; i < map.length * 8; i++) {
|
||||
bit = i % 8;
|
||||
oct = (i - bit) / 8;
|
||||
this.hits.push((map[oct] >> (7 - bit)) & 1);
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
version = p.readU32();
|
||||
height = p.readU32();
|
||||
coin = new bcoin.coin();
|
||||
|
||||
if (height === 0x7fffffff)
|
||||
height = -1;
|
||||
|
||||
output = bcoin.output.fromRaw(p);
|
||||
|
||||
coin.version = version;
|
||||
coin.height = height;
|
||||
coin.script = output.script;
|
||||
coin.value = output.value;
|
||||
|
||||
this.coins.push(coin);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate utxos packet from serialized data.
|
||||
* @param {Buffer} data
|
||||
* @param {String?} enc
|
||||
* @returns {GetBlocksPacket}
|
||||
*/
|
||||
|
||||
UTXOsPacket.fromRaw = function fromRaw(data, enc) {
|
||||
if (typeof data === 'string')
|
||||
data = new Buffer(data, enc);
|
||||
return new UTXOsPacket().fromRaw(data);
|
||||
};
|
||||
|
||||
/*
|
||||
* Expose
|
||||
*/
|
||||
@ -1005,4 +1239,6 @@ exports.VersionPacket = VersionPacket;
|
||||
exports.GetBlocksPacket = GetBlocksPacket;
|
||||
exports.AlertPacket = AlertPacket;
|
||||
exports.RejectPacket = RejectPacket;
|
||||
exports.GetUTXOsPacket = GetUTXOsPacket;
|
||||
exports.UTXOsPacket = UTXOsPacket;
|
||||
exports.NetworkAddress = NetworkAddress;
|
||||
|
||||
@ -13,6 +13,7 @@ var utils = require('../utils/utils');
|
||||
var assert = utils.assert;
|
||||
var constants = require('../protocol/constants');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var packets = require('./packets');
|
||||
|
||||
/**
|
||||
* Protocol packet parser
|
||||
@ -191,378 +192,109 @@ Parser.prototype.parseHeader = function parseHeader(h) {
|
||||
return new Packet(cmd, this.waiting, chk);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse mempool packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
Parser.parseMempool = function parseMempool(p) {
|
||||
return {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse submitorder packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {SubmitOrderPacket}
|
||||
*/
|
||||
|
||||
Parser.parseSubmitOrder = function parseSubmitOrder(p) {
|
||||
p = new BufferReader(p);
|
||||
return {
|
||||
hash: p.readHash('hex'),
|
||||
tx: Parser.parseTX(p)
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse checkorder packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {SubmitOrderPacket}
|
||||
*/
|
||||
|
||||
Parser.parseCheckOrder = function parseCheckOrder(p) {
|
||||
return Parser.parseSubmitOrder(p);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse reply packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {ReplyPacket}
|
||||
*/
|
||||
|
||||
Parser.parseReply = function parseReply(p) {
|
||||
p = new BufferReader(p);
|
||||
return {
|
||||
hash: p.readHash('hex'),
|
||||
code: p.readU32(),
|
||||
publicKey: p.readVarBytes()
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse sendheaders packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
Parser.parseSendHeaders = function parseSendHeaders(p) {
|
||||
return {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse havewitness packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
Parser.parseHaveWitness = function parseHaveWitness(p) {
|
||||
return {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse getaddr packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
Parser.parseGetAddr = function parseGetAddr(p) {
|
||||
return {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse filterload packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {Bloom}
|
||||
*/
|
||||
|
||||
Parser.parseFilterLoad = function parseFilterLoad(p) {
|
||||
return bcoin.bloom.fromRaw(p);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse filteradd packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {FilterAddPacket}
|
||||
*/
|
||||
|
||||
Parser.parseFilterAdd = function parseFilterAdd(p) {
|
||||
p = new BufferReader(p);
|
||||
return {
|
||||
data: p.readVarBytes()
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse filterclear packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
Parser.parseFilterClear = function parseFilterClear(p) {
|
||||
return {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse a payload.
|
||||
* @param {String} cmd - Packet type.
|
||||
* @param {Buffer} p - Payload.
|
||||
* @param {Buffer} data - Payload.
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
Parser.prototype.parsePayload = function parsePayload(cmd, p) {
|
||||
Parser.prototype.parsePayload = function parsePayload(cmd, data) {
|
||||
switch (cmd) {
|
||||
case 'version':
|
||||
return Parser.parseVersion(p);
|
||||
return packets.VersionPacket.fromRaw(data);
|
||||
case 'verack':
|
||||
return Parser.parseVerack(p);
|
||||
case 'mempool':
|
||||
return Parser.parseMempool(p);
|
||||
case 'getaddr':
|
||||
return Parser.parseGetAddr(p);
|
||||
case 'submitorder':
|
||||
return Parser.parseSubmitOrder(p);
|
||||
case 'checkorder':
|
||||
return Parser.parseCheckOrder(p);
|
||||
case 'reply':
|
||||
return Parser.parseReply(p);
|
||||
case 'sendheaders':
|
||||
return Parser.parseSendHeaders(p);
|
||||
case 'havewitness':
|
||||
return Parser.parseHaveWitness(p);
|
||||
case 'filterload':
|
||||
return Parser.parseFilterLoad(p);
|
||||
case 'filteradd':
|
||||
return Parser.parseFilterAdd(p);
|
||||
case 'filterclear':
|
||||
return Parser.parseFilterClear(p);
|
||||
case 'inv':
|
||||
return Parser.parseInv(p);
|
||||
case 'getdata':
|
||||
return Parser.parseGetData(p);
|
||||
case 'notfound':
|
||||
return Parser.parseNotFound(p);
|
||||
case 'getheaders':
|
||||
return Parser.parseGetHeaders(p);
|
||||
case 'getblocks':
|
||||
return Parser.parseGetBlocks(p);
|
||||
case 'merkleblock':
|
||||
return Parser.parseMerkleBlock(p);
|
||||
case 'headers':
|
||||
return Parser.parseHeaders(p);
|
||||
case 'block':
|
||||
return Parser.parseMemBlock(p);
|
||||
case 'tx':
|
||||
return Parser.parseTX(p);
|
||||
case 'reject':
|
||||
return Parser.parseReject(p);
|
||||
case 'addr':
|
||||
return Parser.parseAddr(p);
|
||||
return null;
|
||||
case 'ping':
|
||||
return Parser.parsePing(p);
|
||||
return parsePing(data);
|
||||
case 'pong':
|
||||
return Parser.parsePong(p);
|
||||
return parsePing(data);
|
||||
case 'alert':
|
||||
return Parser.parseAlert(p);
|
||||
return packets.AlertPacket.fromRaw(data);
|
||||
case 'getaddr':
|
||||
return null;
|
||||
case 'addr':
|
||||
return parseAddr(data);
|
||||
case 'inv':
|
||||
return parseInv(data);
|
||||
case 'getdata':
|
||||
return parseInv(data);
|
||||
case 'notfound':
|
||||
return parseInv(data);
|
||||
case 'getblocks':
|
||||
return packets.GetBlocksPacket.fromRaw(data);
|
||||
case 'getheaders':
|
||||
return packets.GetBlocksPacket.fromRaw(data);
|
||||
case 'headers':
|
||||
return parseHeaders(data);
|
||||
case 'sendheaders':
|
||||
return null;
|
||||
case 'block':
|
||||
return bcoin.memblock.fromRaw(data);
|
||||
case 'tx':
|
||||
return bcoin.tx.fromRaw(data);
|
||||
case 'reject':
|
||||
return packets.RejectPacket.fromRaw(data);
|
||||
case 'mempool':
|
||||
return null;
|
||||
case 'filterload':
|
||||
return bcoin.bloom.fromRaw(data);
|
||||
case 'filteradd':
|
||||
return parseFilterAdd(data);
|
||||
case 'filterclear':
|
||||
return null;
|
||||
case 'merkleblock':
|
||||
return bcoin.merkleblock.fromRaw(data);
|
||||
case 'getutxos':
|
||||
return Parser.parseGetUTXOs(p);
|
||||
return packets.GetUTXOsPacket.fromRaw(data);
|
||||
case 'utxos':
|
||||
return Parser.parseUTXOs(p);
|
||||
return packets.UTXOsPacket.fromRaw(data);
|
||||
case 'havewitness':
|
||||
return null;
|
||||
case 'feefilter':
|
||||
return Parser.parseFeeFilter(p);
|
||||
case 'encinit':
|
||||
return Parser.parseEncinit(p);
|
||||
case 'encack':
|
||||
return Parser.parseEncack(p);
|
||||
return parseFeeFilter(data);
|
||||
case 'sendcmpct':
|
||||
return Parser.parseSendCmpct(p);
|
||||
return bcoin.bip152.SendCompact.fromRaw(data);
|
||||
case 'cmpctblock':
|
||||
return Parser.parseCmpctBlock(p);
|
||||
return bcoin.bip152.CompactBlock.fromRaw(data);
|
||||
case 'getblocktxn':
|
||||
return Parser.parseGetBlockTxn(p);
|
||||
return bcoin.bip152.TXRequest.fromRaw(data);
|
||||
case 'blocktxn':
|
||||
return Parser.parseBlockTxn(p);
|
||||
return bcoin.bip152.TXResponse.fromRaw(data);
|
||||
case 'encinit':
|
||||
assert(data.length >= 34);
|
||||
return data;
|
||||
case 'encack':
|
||||
assert(data.length >= 33);
|
||||
return data;
|
||||
case 'authchallenge':
|
||||
return Parser.parseAuthChallenge(p);
|
||||
assert(data.length >= 32);
|
||||
return data;
|
||||
case 'authreply':
|
||||
return Parser.parseAuthReply(p);
|
||||
assert(data.length >= 64);
|
||||
return data;
|
||||
case 'authpropose':
|
||||
return Parser.parseAuthPropose(p);
|
||||
assert(data.length >= 32);
|
||||
return data;
|
||||
default:
|
||||
return p;
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse getutxos packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {GetUTXOsPacket}
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
Parser.parseGetUTXOs = function parseGetUTXOs(p) {
|
||||
var mempool, prevout, count, i;
|
||||
function parsePing(data) {
|
||||
var p = new BufferReader(data);
|
||||
return p.readU64();
|
||||
}
|
||||
|
||||
p = new BufferReader(p);
|
||||
|
||||
mempool = p.readU8() === 1;
|
||||
prevout = [];
|
||||
count = p.readVarint();
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
prevout.push(bcoin.outpoint.fromRaw(p));
|
||||
|
||||
return {
|
||||
mempool: mempool,
|
||||
prevout: prevout
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse utxos packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {UTXOsPacket}
|
||||
*/
|
||||
|
||||
Parser.parseUTXOs = function parseUTXOs(p) {
|
||||
var chainHeight, tip, map, count, coins;
|
||||
var coin, version, height, i, hits, j;
|
||||
|
||||
p = new BufferReader(p);
|
||||
|
||||
chainHeight = p.readU32();
|
||||
tip = p.readHash('hex');
|
||||
map = p.readVarBytes();
|
||||
count = p.readVarint();
|
||||
coins = [];
|
||||
hits = [];
|
||||
|
||||
for (i = 0; i < map.length; i++) {
|
||||
for (j = 0; j < 8; j++)
|
||||
hits.push((map[i] >> j) & 1);
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
version = p.readU32();
|
||||
height = p.readU32();
|
||||
|
||||
if (height === 0x7fffffff)
|
||||
height = -1;
|
||||
|
||||
coin = bcoin.output.fromRaw(p);
|
||||
coin.version = version;
|
||||
coin.height = height;
|
||||
coins.push(new bcoin.coin(coin));
|
||||
}
|
||||
|
||||
return {
|
||||
height: chainHeight,
|
||||
tip: tip,
|
||||
map: map,
|
||||
coins: coins,
|
||||
hits: hits
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse ping packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {PingPacket}
|
||||
*/
|
||||
|
||||
Parser.parsePing = function parsePing(p) {
|
||||
p = new BufferReader(p);
|
||||
|
||||
return {
|
||||
nonce: p.readU64()
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse pong packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {PingPacket}
|
||||
*/
|
||||
|
||||
Parser.parsePong = function parsePong(p) {
|
||||
p = new BufferReader(p);
|
||||
|
||||
return {
|
||||
nonce: p.readU64()
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse version packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {VersionPacket}
|
||||
*/
|
||||
|
||||
Parser.parseVersion = function parseVersion(p) {
|
||||
return bcoin.packets.VersionPacket.fromRaw(p);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse verack packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
Parser.parseVerack = function parseVerack(p) {
|
||||
return {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse notfound packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {InvItem[]}
|
||||
*/
|
||||
|
||||
Parser.parseNotFound = function parseNotFound(p) {
|
||||
return Parser.parseInv(p);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse getdata packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {InvItem[]}
|
||||
*/
|
||||
|
||||
Parser.parseGetData = function parseGetData(p) {
|
||||
return Parser.parseInv(p);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse getblocks packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {GetBlocksPacket}
|
||||
*/
|
||||
|
||||
Parser.parseGetBlocks = function parseGetBlocks(p) {
|
||||
return bcoin.packets.GetBlocksPacket.fromRaw(p);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse getheaders packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {GetBlocksPacket}
|
||||
*/
|
||||
|
||||
Parser.parseGetHeaders = function parseGetHeaders(p) {
|
||||
return bcoin.packets.GetBlocksPacket.fromRaw(p);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse inv packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {InvItem[]}
|
||||
*/
|
||||
|
||||
Parser.parseInv = function parseInv(p) {
|
||||
function parseInv(data) {
|
||||
var p = new BufferReader(data);
|
||||
var items = [];
|
||||
var i, count;
|
||||
|
||||
p = new BufferReader(p);
|
||||
|
||||
count = p.readVarint();
|
||||
|
||||
assert(count <= 50000, 'Item count too high.');
|
||||
@ -571,174 +303,45 @@ Parser.parseInv = function parseInv(p) {
|
||||
items.push(bcoin.invitem.fromRaw(p));
|
||||
|
||||
return items;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse merkleblock packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {Block}
|
||||
*/
|
||||
|
||||
Parser.parseMerkleBlock = function parseMerkleBlock(p) {
|
||||
return bcoin.merkleblock.fromRaw(p);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse headers packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {Headers[]}
|
||||
*/
|
||||
|
||||
Parser.parseHeaders = function parseHeaders(p) {
|
||||
function parseHeaders(data) {
|
||||
var p = new BufferReader(data);
|
||||
var headers = [];
|
||||
var i, count;
|
||||
|
||||
p = new BufferReader(p);
|
||||
|
||||
count = p.readVarint();
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
headers.push(bcoin.headers.fromRaw(p));
|
||||
|
||||
return headers;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse block packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {Block}
|
||||
*/
|
||||
|
||||
Parser.parseBlock = function parseBlock(p) {
|
||||
return bcoin.block.fromRaw(p);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse block packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {Block}
|
||||
*/
|
||||
|
||||
Parser.parseMemBlock = function parseMemBlock(p) {
|
||||
return bcoin.memblock.fromRaw(p);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse tx packet (will automatically switch to witness
|
||||
* parsing if a witness transaction is detected).
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {TX}
|
||||
*/
|
||||
|
||||
Parser.parseTX = function parseTX(p) {
|
||||
return bcoin.tx.fromRaw(p);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse reject packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {RejectPacket}
|
||||
*/
|
||||
|
||||
Parser.parseReject = function parseReject(p) {
|
||||
return bcoin.packets.RejectPacket.fromRaw(p);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse addr packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {NetworkAddress[]}
|
||||
*/
|
||||
|
||||
Parser.parseAddr = function parseAddr(p) {
|
||||
function parseAddr(data) {
|
||||
var p = new BufferReader(data);
|
||||
var addrs = [];
|
||||
var i, count;
|
||||
|
||||
p = new BufferReader(p);
|
||||
|
||||
count = p.readVarint();
|
||||
|
||||
assert(count <= 10000, 'Too many addresses.');
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
addrs.push(bcoin.packets.NetworkAddress.fromRaw(p, true));
|
||||
addrs.push(packets.NetworkAddress.fromRaw(p, true));
|
||||
|
||||
return addrs;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse mempool packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {Object}
|
||||
*/
|
||||
function parseFeeFilter(data) {
|
||||
var p = new BufferReader(data);
|
||||
return p.read64N();
|
||||
}
|
||||
|
||||
Parser.parseMempool = function parseMempool(p) {
|
||||
return {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse alert packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {AlertPacket}
|
||||
*/
|
||||
|
||||
Parser.parseAlert = function parseAlert(p) {
|
||||
return bcoin.packets.AlertPacket.fromRaw(p);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse feefilter packet.
|
||||
* @param {Buffer|BufferReader} p
|
||||
* @returns {FeeFilterPacket}
|
||||
*/
|
||||
|
||||
Parser.parseFeeFilter = function parseFeeFilter(p) {
|
||||
p = new BufferReader(p);
|
||||
return {
|
||||
rate: p.read64N()
|
||||
};
|
||||
};
|
||||
|
||||
Parser.parseEncinit = function parseEncinit(p) {
|
||||
// Handled elsewhere.
|
||||
return p;
|
||||
};
|
||||
|
||||
Parser.parseEncack = function parseEncack(p) {
|
||||
// Handled elsewhere.
|
||||
return p;
|
||||
};
|
||||
|
||||
Parser.parseSendCmpct = function parseSendCmpct(p) {
|
||||
return bcoin.bip152.SendCompact.fromRaw(p);
|
||||
};
|
||||
|
||||
Parser.parseCmpctBlock = function parseCmpctBlock(p) {
|
||||
return bcoin.bip152.CompactBlock.fromRaw(p);
|
||||
};
|
||||
|
||||
Parser.parseGetBlockTxn = function parseGetBlockTxn(p) {
|
||||
return bcoin.bip152.TXRequest.fromRaw(p);
|
||||
};
|
||||
|
||||
Parser.parseBlockTxn = function parseBlockTxn(p) {
|
||||
return bcoin.bip152.TXResponse.fromRaw(p);
|
||||
};
|
||||
|
||||
Parser.parseAuthChallenge = function parseAuthChallenge(p) {
|
||||
// Handled elsewhere.
|
||||
return p;
|
||||
};
|
||||
|
||||
Parser.parseAuthReply = function parseAuthReply(p) {
|
||||
// Handled elsewhere.
|
||||
return p;
|
||||
};
|
||||
|
||||
Parser.parseAuthPropose = function parseAuthPropose(p) {
|
||||
// Handled elsewhere.
|
||||
return p;
|
||||
};
|
||||
function parseFilterAdd(data) {
|
||||
var p = new BufferReader(data);
|
||||
return p.readVarBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Packet
|
||||
|
||||
333
lib/net/peer.js
333
lib/net/peer.js
@ -20,6 +20,7 @@ var VersionPacket = bcoin.packets.VersionPacket;
|
||||
var GetBlocksPacket = bcoin.packets.GetBlocksPacket;
|
||||
var RejectPacket = bcoin.packets.RejectPacket;
|
||||
var NetworkAddress = bcoin.packets.NetworkAddress;
|
||||
var GetUTXOsPacket = bcoin.packets.GetUTXOsPacket;
|
||||
|
||||
/**
|
||||
* Represents a remote peer.
|
||||
@ -648,9 +649,7 @@ Peer.prototype.sendPing = function sendPing() {
|
||||
this.lastPing = utils.ms();
|
||||
this.challenge = utils.nonce();
|
||||
|
||||
this.write(this.framer.ping({
|
||||
nonce: this.challenge
|
||||
}));
|
||||
this.write(this.framer.ping(this.challenge));
|
||||
};
|
||||
|
||||
/**
|
||||
@ -692,9 +691,7 @@ Peer.prototype.updateWatch = function updateWatch() {
|
||||
*/
|
||||
|
||||
Peer.prototype.sendFeeRate = function sendFeeRate(rate) {
|
||||
this.write(this.framer.feeFilter({
|
||||
rate: rate
|
||||
}));
|
||||
this.write(this.framer.feeFilter(rate));
|
||||
};
|
||||
|
||||
/**
|
||||
@ -892,52 +889,39 @@ Peer.prototype._onPacket = function onPacket(packet) {
|
||||
switch (cmd) {
|
||||
case 'version':
|
||||
return this._handleVersion(payload);
|
||||
case 'inv':
|
||||
return this._handleInv(payload);
|
||||
case 'headers':
|
||||
return this._handleHeaders(payload);
|
||||
case 'getdata':
|
||||
return this._handleGetData(payload);
|
||||
case 'addr':
|
||||
return this._handleAddr(payload);
|
||||
case 'verack':
|
||||
this.fire(cmd);
|
||||
break;
|
||||
case 'ping':
|
||||
return this._handlePing(payload);
|
||||
case 'pong':
|
||||
return this._handlePong(payload);
|
||||
case 'getaddr':
|
||||
return this._handleGetAddr(payload);
|
||||
case 'reject':
|
||||
return this._handleReject(payload);
|
||||
case 'alert':
|
||||
return this._handleAlert(payload);
|
||||
case 'getutxos':
|
||||
return this._handleGetUTXOs(payload);
|
||||
case 'utxos':
|
||||
return this._handleUTXOs(payload);
|
||||
case 'feefilter':
|
||||
return this._handleFeeFilter(payload);
|
||||
case 'getaddr':
|
||||
return this._handleGetAddr();
|
||||
case 'addr':
|
||||
return this._handleAddr(payload);
|
||||
case 'inv':
|
||||
return this._handleInv(payload);
|
||||
case 'getdata':
|
||||
return this._handleGetData(payload);
|
||||
case 'notfound':
|
||||
this.fire(cmd, payload);
|
||||
break;
|
||||
case 'getblocks':
|
||||
return this._handleGetBlocks(payload);
|
||||
case 'getheaders':
|
||||
return this._handleGetHeaders(payload);
|
||||
case 'mempool':
|
||||
return this._handleMempool(payload);
|
||||
case 'filterload':
|
||||
return this._handleFilterLoad(payload);
|
||||
case 'filteradd':
|
||||
return this._handleFilterAdd(payload);
|
||||
case 'filterclear':
|
||||
return this._handleFilterClear(payload);
|
||||
case 'headers':
|
||||
return this._handleHeaders(payload);
|
||||
case 'sendheaders':
|
||||
this.preferHeaders = true;
|
||||
this.fire(cmd);
|
||||
break;
|
||||
case 'block':
|
||||
this.fire(cmd, payload);
|
||||
break;
|
||||
case 'merkleblock':
|
||||
payload.verifyPartial();
|
||||
this.lastBlock = payload;
|
||||
this.waiting = payload.matches.length;
|
||||
if (this.waiting === 0)
|
||||
this._flushMerkle();
|
||||
break;
|
||||
case 'tx':
|
||||
if (this.lastBlock) {
|
||||
if (this.lastBlock.hasTX(payload)) {
|
||||
@ -949,20 +933,41 @@ Peer.prototype._onPacket = function onPacket(packet) {
|
||||
}
|
||||
this.fire(cmd, payload);
|
||||
break;
|
||||
case 'sendheaders':
|
||||
this.preferHeaders = true;
|
||||
this.fire(cmd, payload);
|
||||
case 'reject':
|
||||
return this._handleReject(payload);
|
||||
case 'mempool':
|
||||
return this._handleMempool();
|
||||
case 'filterload':
|
||||
return this._handleFilterLoad(payload);
|
||||
case 'filteradd':
|
||||
return this._handleFilterAdd(payload);
|
||||
case 'filterclear':
|
||||
return this._handleFilterClear();
|
||||
case 'merkleblock':
|
||||
payload.verifyPartial();
|
||||
this.lastBlock = payload;
|
||||
this.waiting = payload.matches.length;
|
||||
if (this.waiting === 0)
|
||||
this._flushMerkle();
|
||||
break;
|
||||
case 'getutxos':
|
||||
return this._handleGetUTXOs(payload);
|
||||
case 'utxos':
|
||||
return this._handleUTXOs(payload);
|
||||
case 'havewitness':
|
||||
this.haveWitness = true;
|
||||
this.fire(cmd, payload);
|
||||
break;
|
||||
case 'verack':
|
||||
this.fire(cmd, payload);
|
||||
break;
|
||||
case 'notfound':
|
||||
this.fire(cmd, payload);
|
||||
this.fire(cmd);
|
||||
break;
|
||||
case 'feefilter':
|
||||
return this._handleFeeFilter(payload);
|
||||
case 'sendcmpct':
|
||||
return this._handleSendCmpct(payload);
|
||||
case 'cmpctblock':
|
||||
return this._handleCmpctBlock(payload);
|
||||
case 'getblocktxn':
|
||||
return this._handleGetBlockTxn(payload);
|
||||
case 'blocktxn':
|
||||
return this._handleBlockTxn(payload);
|
||||
case 'encinit':
|
||||
return this._handleEncinit(payload);
|
||||
case 'encack':
|
||||
@ -973,14 +978,6 @@ Peer.prototype._onPacket = function onPacket(packet) {
|
||||
return this._handleAuthReply(payload);
|
||||
case 'authpropose':
|
||||
return this._handleAuthPropose(payload);
|
||||
case 'sendcmpct':
|
||||
return this._handleSendCmpct(payload);
|
||||
case 'cmpctblock':
|
||||
return this._handleCmpctBlock(payload);
|
||||
case 'getblocktxn':
|
||||
return this._handleGetBlockTxn(payload);
|
||||
case 'blocktxn':
|
||||
return this._handleBlockTxn(payload);
|
||||
default:
|
||||
this.logger.warning('Unknown packet: %s.', cmd);
|
||||
this.fire(cmd, payload);
|
||||
@ -1018,13 +1015,13 @@ Peer.prototype.fire = function fire(cmd, payload) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleFilterLoad = function _handleFilterLoad(payload) {
|
||||
if (!payload.isWithinConstraints()) {
|
||||
Peer.prototype._handleFilterLoad = function _handleFilterLoad(filter) {
|
||||
if (!filter.isWithinConstraints()) {
|
||||
this.setMisbehavior(100);
|
||||
return;
|
||||
}
|
||||
|
||||
this.spvFilter = payload;
|
||||
this.spvFilter = filter;
|
||||
this.relay = true;
|
||||
};
|
||||
|
||||
@ -1034,14 +1031,14 @@ Peer.prototype._handleFilterLoad = function _handleFilterLoad(payload) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleFilterAdd = function _handleFilterAdd(payload) {
|
||||
if (payload.data.length > constants.script.MAX_PUSH) {
|
||||
Peer.prototype._handleFilterAdd = function _handleFilterAdd(data) {
|
||||
if (data.length > constants.script.MAX_PUSH) {
|
||||
this.setMisbehavior(100);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.spvFilter)
|
||||
this.spvFilter.add(payload.data);
|
||||
this.spvFilter.add(data);
|
||||
|
||||
this.relay = true;
|
||||
};
|
||||
@ -1052,109 +1049,40 @@ Peer.prototype._handleFilterAdd = function _handleFilterAdd(payload) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleFilterClear = function _handleFilterClear(payload) {
|
||||
Peer.prototype._handleFilterClear = function _handleFilterClear() {
|
||||
if (this.spvFilter)
|
||||
this.spvFilter.reset();
|
||||
|
||||
this.relay = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle `utxos` packet.
|
||||
* @private
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleUTXOs = function _handleUTXOs(payload) {
|
||||
this.logger.debug('Received %d utxos (%s).',
|
||||
payload.coins.length, this.hostname);
|
||||
this.fire('utxos', payload);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle `feefilter` packet.
|
||||
* @private
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleFeeFilter = function _handleFeeFilter(payload) {
|
||||
if (!(payload.rate >= 0 && payload.rate <= constants.MAX_MONEY)) {
|
||||
Peer.prototype._handleFeeFilter = function _handleFeeFilter(rate) {
|
||||
if (!(rate >= 0 && rate <= constants.MAX_MONEY)) {
|
||||
this.setMisbehavior(100);
|
||||
return;
|
||||
}
|
||||
|
||||
this.feeRate = payload.rate;
|
||||
this.feeRate = rate;
|
||||
|
||||
this.fire('feefilter', payload);
|
||||
this.fire('feefilter', rate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Request UTXOs from peer.
|
||||
* @param {Outpoint[]} outpoints
|
||||
* @param {Function} callback - Returns [Error, {@link Coin}[]].
|
||||
*/
|
||||
|
||||
Peer.prototype.getUTXOs = function getUTXOs(outpoints, callback) {
|
||||
var self = this;
|
||||
var reqs = [];
|
||||
var coins = [];
|
||||
var i;
|
||||
|
||||
for (i = 0; i < outpoints.length; i += 15)
|
||||
reqs.push(outpoints.slice(i, i + 15));
|
||||
|
||||
utils.forEachSerial(reqs, function(outpoints, next) {
|
||||
self._getUTXOs(outpoints, function(err, coin) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
coins = coins.concat(coin);
|
||||
|
||||
next();
|
||||
});
|
||||
}, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
callback(null, coins);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Send non-chunked getuxos to peer.
|
||||
* Handle `utxos` packet.
|
||||
* @private
|
||||
* @param {Outpoint[]} outpoints
|
||||
* @param {Function} callback
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._getUTXOs = function _getUTXOs(outpoints, callback) {
|
||||
var index = 0;
|
||||
var i, prevout, coin;
|
||||
|
||||
this.request('utxos', function(err, payload) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
for (i = 0; i < payload.hits.length; i++) {
|
||||
if (payload.hits[i]) {
|
||||
prevout = outpoints[i];
|
||||
coin = payload.coins[index++];
|
||||
|
||||
if (!prevout || !coin)
|
||||
return callback(new Error('Malformed utxos message.'));
|
||||
|
||||
coin.hash = prevout.hash;
|
||||
coin.index = prevout.index;
|
||||
}
|
||||
}
|
||||
|
||||
callback(null, payload.coins);
|
||||
});
|
||||
|
||||
this.write(this.framer.getUTXOs({
|
||||
mempool: true,
|
||||
prevout: outpoints
|
||||
}));
|
||||
Peer.prototype._handleUTXOs = function _handleUTXOs(utxos) {
|
||||
this.logger.debug('Received %d utxos (%s).',
|
||||
utxos.coins.length, this.hostname);
|
||||
this.fire('utxos', utxos);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1164,9 +1092,8 @@ Peer.prototype._getUTXOs = function _getUTXOs(outpoints, callback) {
|
||||
|
||||
Peer.prototype._handleGetUTXOs = function _handleGetUTXOs(payload) {
|
||||
var self = this;
|
||||
var coins = [];
|
||||
var hits = [];
|
||||
var unlock = this._lock(_handleGetUTXOs, [payload, utils.nop]);
|
||||
var utxos;
|
||||
|
||||
if (!unlock)
|
||||
return;
|
||||
@ -1191,6 +1118,8 @@ Peer.prototype._handleGetUTXOs = function _handleGetUTXOs(payload) {
|
||||
if (payload.prevout.length > 15)
|
||||
return done();
|
||||
|
||||
utxos = new GetUTXOsPacket();
|
||||
|
||||
utils.forEachSerial(payload.prevout, function(prevout, next) {
|
||||
var hash = prevout.hash;
|
||||
var index = prevout.index;
|
||||
@ -1200,13 +1129,13 @@ Peer.prototype._handleGetUTXOs = function _handleGetUTXOs(payload) {
|
||||
coin = self.mempool.getCoin(hash, index);
|
||||
|
||||
if (coin) {
|
||||
hits.push(1);
|
||||
coins.push(coin);
|
||||
utxos.hits.push(1);
|
||||
utxos.coins.push(coin);
|
||||
return next();
|
||||
}
|
||||
|
||||
if (self.mempool.isSpent(hash, index)) {
|
||||
hits.push(0);
|
||||
utxos.hits.push(0);
|
||||
return next();
|
||||
}
|
||||
}
|
||||
@ -1216,12 +1145,12 @@ Peer.prototype._handleGetUTXOs = function _handleGetUTXOs(payload) {
|
||||
return next(err);
|
||||
|
||||
if (!coin) {
|
||||
hits.push(0);
|
||||
utxos.hits.push(0);
|
||||
return next();
|
||||
}
|
||||
|
||||
hits.push(1);
|
||||
coins.push(coin);
|
||||
utxos.hits.push(1);
|
||||
utxos.coins.push(coin);
|
||||
|
||||
next();
|
||||
});
|
||||
@ -1229,12 +1158,10 @@ Peer.prototype._handleGetUTXOs = function _handleGetUTXOs(payload) {
|
||||
if (err)
|
||||
return done(err);
|
||||
|
||||
self.write(self.framer.UTXOs({
|
||||
height: self.chain.height,
|
||||
tip: self.chain.tip.hash,
|
||||
hits: hits,
|
||||
coins: coins
|
||||
}));
|
||||
utxos.height = self.chain.height;
|
||||
utxos.tip = self.chain.tip.hash;
|
||||
|
||||
self.write(self.framer.UTXOs(utxos));
|
||||
|
||||
done();
|
||||
});
|
||||
@ -1726,8 +1653,8 @@ Peer.prototype._handleAddr = function _handleAddr(addrs) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handlePing = function _handlePing(data) {
|
||||
this.write(this.framer.pong(data));
|
||||
Peer.prototype._handlePing = function _handlePing(nonce) {
|
||||
this.write(this.framer.pong(nonce));
|
||||
this.fire('ping', this.minPing);
|
||||
};
|
||||
|
||||
@ -1737,7 +1664,7 @@ Peer.prototype._handlePing = function _handlePing(data) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handlePong = function _handlePong(data) {
|
||||
Peer.prototype._handlePong = function _handlePong(nonce) {
|
||||
var now = utils.ms();
|
||||
|
||||
if (!this.challenge) {
|
||||
@ -1745,8 +1672,8 @@ Peer.prototype._handlePong = function _handlePong(data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.nonce.cmp(this.challenge) !== 0) {
|
||||
if (data.nonce.cmpn(0) === 0) {
|
||||
if (nonce.cmp(this.challenge) !== 0) {
|
||||
if (nonce.cmpn(0) === 0) {
|
||||
this.logger.debug('Peer sent a zero nonce (%s).', this.hostname);
|
||||
this.challenge = null;
|
||||
return;
|
||||
@ -1879,15 +1806,15 @@ Peer.prototype._handleHeaders = function _handleHeaders(headers) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleReject = function _handleReject(payload) {
|
||||
Peer.prototype._handleReject = function _handleReject(details) {
|
||||
var hash, entry;
|
||||
|
||||
this.fire('reject', payload);
|
||||
this.fire('reject', details);
|
||||
|
||||
if (!payload.data)
|
||||
if (!details.data)
|
||||
return;
|
||||
|
||||
hash = payload.data;
|
||||
hash = details.data;
|
||||
entry = this.pool.invMap[hash];
|
||||
|
||||
if (!entry)
|
||||
@ -1913,12 +1840,12 @@ Peer.prototype._handleAlert = function _handleAlert(alert) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleEncinit = function _handleEncinit(payload) {
|
||||
Peer.prototype._handleEncinit = function _handleEncinit(data) {
|
||||
if (!this.bip151)
|
||||
return;
|
||||
|
||||
try {
|
||||
this.bip151.encinit(payload);
|
||||
this.bip151.encinit(data);
|
||||
} catch (e) {
|
||||
this._error(e);
|
||||
return;
|
||||
@ -1926,7 +1853,7 @@ Peer.prototype._handleEncinit = function _handleEncinit(payload) {
|
||||
|
||||
this.write(this.framer.encack(this.bip151.toEncack()));
|
||||
|
||||
this.fire('encinit', payload);
|
||||
this.fire('encinit', data);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1935,18 +1862,18 @@ Peer.prototype._handleEncinit = function _handleEncinit(payload) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleEncack = function _handleEncack(payload) {
|
||||
Peer.prototype._handleEncack = function _handleEncack(data) {
|
||||
if (!this.bip151)
|
||||
return;
|
||||
|
||||
try {
|
||||
this.bip151.encack(payload);
|
||||
this.bip151.encack(data);
|
||||
} catch (e) {
|
||||
this._error(e);
|
||||
return;
|
||||
}
|
||||
|
||||
this.fire('encack', payload);
|
||||
this.fire('encack', data);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1955,14 +1882,14 @@ Peer.prototype._handleEncack = function _handleEncack(payload) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleAuthChallenge = function _handleAuthChallenge(payload) {
|
||||
Peer.prototype._handleAuthChallenge = function _handleAuthChallenge(data) {
|
||||
var result;
|
||||
|
||||
if (!this.bip150)
|
||||
return;
|
||||
|
||||
try {
|
||||
result = this.bip150.challenge(payload);
|
||||
result = this.bip150.challenge(data);
|
||||
} catch (e) {
|
||||
this._error(e);
|
||||
return;
|
||||
@ -1970,7 +1897,7 @@ Peer.prototype._handleAuthChallenge = function _handleAuthChallenge(payload) {
|
||||
|
||||
this.write(this.framer.authReply(result));
|
||||
|
||||
this.fire('authchallenge', payload);
|
||||
this.fire('authchallenge', data);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1979,14 +1906,14 @@ Peer.prototype._handleAuthChallenge = function _handleAuthChallenge(payload) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleAuthReply = function _handleAuthReply(payload) {
|
||||
Peer.prototype._handleAuthReply = function _handleAuthReply(data) {
|
||||
var result;
|
||||
|
||||
if (!this.bip150)
|
||||
return;
|
||||
|
||||
try {
|
||||
result = this.bip150.reply(payload);
|
||||
result = this.bip150.reply(data);
|
||||
} catch (e) {
|
||||
this._error(e);
|
||||
return;
|
||||
@ -1995,7 +1922,7 @@ Peer.prototype._handleAuthReply = function _handleAuthReply(payload) {
|
||||
if (result)
|
||||
this.write(this.framer.authPropose(result));
|
||||
|
||||
this.fire('authreply', payload);
|
||||
this.fire('authreply', data);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2004,14 +1931,14 @@ Peer.prototype._handleAuthReply = function _handleAuthReply(payload) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleAuthPropose = function _handleAuthPropose(payload) {
|
||||
Peer.prototype._handleAuthPropose = function _handleAuthPropose(data) {
|
||||
var result;
|
||||
|
||||
if (!this.bip150)
|
||||
return;
|
||||
|
||||
try {
|
||||
result = this.bip150.propose(payload);
|
||||
result = this.bip150.propose(data);
|
||||
} catch (e) {
|
||||
this._error(e);
|
||||
return;
|
||||
@ -2019,7 +1946,7 @@ Peer.prototype._handleAuthPropose = function _handleAuthPropose(payload) {
|
||||
|
||||
this.write(this.framer.authChallenge(result));
|
||||
|
||||
this.fire('authpropose', payload);
|
||||
this.fire('authpropose', data);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2028,21 +1955,25 @@ Peer.prototype._handleAuthPropose = function _handleAuthPropose(payload) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleSendCmpct = function _handleSendCmpct(payload) {
|
||||
if (payload.version !== 1) {
|
||||
Peer.prototype._handleSendCmpct = function _handleSendCmpct(cmpct) {
|
||||
if (cmpct.version !== 1) {
|
||||
// Ignore
|
||||
this.logger.info('Peer request compact blocks version %d (%s).',
|
||||
cmpct.version, this.hostname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (payload.mode !== 0) {
|
||||
if (cmpct.mode !== 0) {
|
||||
// Ignore (we can't do mode 1 yet).
|
||||
this.logger.info('Peer request compact blocks mode %d (%s).',
|
||||
cmpct.mode, this.hostname);
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.info('Peer initialized compact blocks (%s).', this.hostname);
|
||||
|
||||
this.compactMode = payload;
|
||||
this.fire('sendcmpct', payload);
|
||||
this.compactMode = cmpct;
|
||||
this.fire('sendcmpct', cmpct);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2210,15 +2141,22 @@ Peer.prototype.sendAlert = function sendAlert(alert) {
|
||||
|
||||
Peer.prototype.sendGetHeaders = function sendGetHeaders(locator, stop) {
|
||||
var packet = new GetBlocksPacket(locator, stop);
|
||||
var height = -1;
|
||||
var hash = null;
|
||||
|
||||
this.logger.debug(
|
||||
'Requesting headers packet from peer with getheaders (%s).',
|
||||
this.hostname);
|
||||
|
||||
this.logger.debug('Height: %d, Hash: %s, Stop: %s',
|
||||
locator && locator.length ? this.chain._getCachedHeight(locator[0]) : -1,
|
||||
locator && locator.length ? utils.revHex(locator[0]) : 0,
|
||||
stop ? utils.revHex(stop) : 0);
|
||||
if (packet.locator.length > 0) {
|
||||
height = this.chain._getCachedHeight(packet.locator[0]);
|
||||
hash = utils.revHex(packet.locator[0]);
|
||||
}
|
||||
|
||||
if (stop)
|
||||
stop = utils.revHex(stop);
|
||||
|
||||
this.logger.debug('Height: %d, Hash: %s, Stop: %s', height, hash, stop);
|
||||
|
||||
this.write(this.framer.getHeaders(packet));
|
||||
};
|
||||
@ -2231,15 +2169,22 @@ Peer.prototype.sendGetHeaders = function sendGetHeaders(locator, stop) {
|
||||
|
||||
Peer.prototype.sendGetBlocks = function getBlocks(locator, stop) {
|
||||
var packet = new GetBlocksPacket(locator, stop);
|
||||
var height = -1;
|
||||
var hash = null;
|
||||
|
||||
this.logger.debug(
|
||||
'Requesting inv packet from peer with getblocks (%s).',
|
||||
this.hostname);
|
||||
|
||||
this.logger.debug('Height: %d, Hash: %s, Stop: %s',
|
||||
locator && locator.length ? this.chain._getCachedHeight(locator[0]) : -1,
|
||||
locator && locator.length ? utils.revHex(locator[0]) : 0,
|
||||
stop ? utils.revHex(stop) : 0);
|
||||
if (packet.locator.length > 0) {
|
||||
height = this.chain._getCachedHeight(packet.locator[0]);
|
||||
hash = utils.revHex(packet.locator[0]);
|
||||
}
|
||||
|
||||
if (stop)
|
||||
stop = utils.revHex(stop);
|
||||
|
||||
this.logger.debug('Height: %d, Hash: %s, Stop: %s', height, hash, stop);
|
||||
|
||||
this.write(this.framer.getBlocks(packet));
|
||||
};
|
||||
|
||||
@ -1709,60 +1709,6 @@ Pool.prototype.setFeeRate = function setFeeRate(rate) {
|
||||
this.peers.regular[i].sendFeeRate(rate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Request UTXOs from peer.
|
||||
* @param {Outpoint[]} outpoints
|
||||
* @param {Function} callback - Returns [Error, {@link Coin}[]].
|
||||
*/
|
||||
|
||||
Pool.prototype.getUTXOs = function getUTXOs(outpoints, callback) {
|
||||
var i, peer;
|
||||
|
||||
for (i = 0; i < this.peers.all.length; i++) {
|
||||
peer = this.peers.all[i];
|
||||
|
||||
if (!peer.version)
|
||||
continue;
|
||||
|
||||
if (peer.version.services & constants.services.GETUXO)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i === this.peers.regular.length)
|
||||
return utils.asyncify(callback)(new Error('No peer available.'));
|
||||
|
||||
peer.getUTXOs(outpoints, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Attempt to fill transaction using getutxos (note: unreliable).
|
||||
* @param {TX} tx
|
||||
* @param {Function} callback - Returns [Error, {@link TX}].
|
||||
*/
|
||||
|
||||
Pool.prototype.fillCoins = function fillCoins(tx, callback) {
|
||||
var outpoints = [];
|
||||
var i, input;
|
||||
|
||||
for (i = 0; i < tx.inputs.length; i++) {
|
||||
input = tx.inputs[i];
|
||||
if (!input.coin)
|
||||
outpoints.push(input.prevout);
|
||||
}
|
||||
|
||||
if (outpoints.length === 0)
|
||||
return utils.asyncify(callback)(null, tx);
|
||||
|
||||
this.getUTXOs(outpoints, function(err, coins) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
tx.fillCoins(coins);
|
||||
|
||||
callback(null, tx);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Allocate a new loader host.
|
||||
* @returns {NetworkAddress}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user