pool: refactor and add compact block mode 1 support.
This commit is contained in:
parent
7543049180
commit
18c4a83ed3
@ -1678,10 +1678,10 @@ RejectPacket.fromRaw = function fromRaw(data, enc) {
|
||||
* @private
|
||||
* @param {Number} code
|
||||
* @param {String} reason
|
||||
* @param {(TX|Block)?} obj
|
||||
* @param {(TX|Block)?} msg
|
||||
*/
|
||||
|
||||
RejectPacket.prototype.fromReason = function fromReason(code, reason, obj) {
|
||||
RejectPacket.prototype.fromReason = function fromReason(code, reason, msg) {
|
||||
if (typeof code === 'string')
|
||||
code = RejectPacket.codes[code.toUpperCase()];
|
||||
|
||||
@ -1695,9 +1695,9 @@ RejectPacket.prototype.fromReason = function fromReason(code, reason, obj) {
|
||||
this.code = code;
|
||||
this.reason = reason;
|
||||
|
||||
if (obj) {
|
||||
this.message = (obj instanceof TX) ? 'tx' : 'block';
|
||||
this.hash = obj.hash('hex');
|
||||
if (msg) {
|
||||
this.message = (msg instanceof TX) ? 'tx' : 'block';
|
||||
this.hash = msg.hash('hex');
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
107
lib/net/peer.js
107
lib/net/peer.js
@ -26,7 +26,6 @@ var BIP152 = require('./bip152');
|
||||
var Block = require('../primitives/block');
|
||||
var TX = require('../primitives/tx');
|
||||
var encoding = require('../utils/encoding');
|
||||
var errors = require('../protocol/errors');
|
||||
var NetAddress = require('../primitives/netaddress');
|
||||
var services = common.services;
|
||||
var invTypes = InvItem.types;
|
||||
@ -115,8 +114,9 @@ function Peer(pool) {
|
||||
this.bip150 = null;
|
||||
this.compactMode = -1;
|
||||
this.compactWitness = false;
|
||||
this.lastMerkle = null;
|
||||
this.waitingTX = 0;
|
||||
this.merkleBlock = null;
|
||||
this.merkleTime = -1;
|
||||
this.merkleMatches = 0;
|
||||
this.syncSent = false;
|
||||
this.sentAddr = false;
|
||||
this.sentGetAddr = false;
|
||||
@ -270,13 +270,14 @@ Peer.prototype._init = function init() {
|
||||
|
||||
this.parser.on('error', function(err) {
|
||||
self.error(err);
|
||||
self.reject(null, 'malformed', 'error parsing message', 10);
|
||||
self.sendReject('malformed', 'error parsing message');
|
||||
self.increaseBan(10);
|
||||
});
|
||||
|
||||
if (this.bip151) {
|
||||
this.bip151.on('error', function(err) {
|
||||
self.error(err);
|
||||
self.reject(null, 'malformed', 'error parsing message', 10);
|
||||
self.destroy();
|
||||
});
|
||||
this.bip151.on('rekey', function() {
|
||||
self.logger.debug('Rekeying with peer (%s).', self.hostname);
|
||||
@ -649,7 +650,7 @@ Peer.prototype.announceBlock = function announceBlock(blocks) {
|
||||
// they're using compact block mode 1.
|
||||
if (this.compactMode === 1) {
|
||||
this.invFilter.add(block.hash());
|
||||
this.sendCompactBlock(block, this.compactWitness);
|
||||
this.sendCompactBlock(block);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -824,11 +825,12 @@ Peer.prototype.sendHeaders = function sendHeaders(items) {
|
||||
* Send a compact block.
|
||||
* @private
|
||||
* @param {Block} block
|
||||
* @param {Boolean} witness
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
Peer.prototype.sendCompactBlock = function sendCompactBlock(block, witness) {
|
||||
Peer.prototype.sendCompactBlock = function sendCompactBlock(block) {
|
||||
var witness = this.compactWitness;
|
||||
|
||||
// Try again with a new nonce
|
||||
// if we get a siphash collision.
|
||||
for (;;) {
|
||||
@ -1122,6 +1124,15 @@ Peer.prototype.maybeTimeout = function maybeTimeout() {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.merkleBlock) {
|
||||
assert(this.merkleTime !== -1);
|
||||
if (now > this.merkleTime + 60000) {
|
||||
this.error('Peer is stalling (merkleblock).');
|
||||
this.destroy();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.pool.syncing || this.chain.synced)
|
||||
return;
|
||||
|
||||
@ -1509,26 +1520,10 @@ Peer.prototype.handlePacket = co(function* handlePacket(packet) {
|
||||
this.emit(packet.cmd, packet);
|
||||
});
|
||||
|
||||
/**
|
||||
* Flush merkle block once all matched
|
||||
* txs have been received.
|
||||
* @private
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Peer.prototype.flushMerkle = co(function* flushMerkle() {
|
||||
assert(this.lastMerkle);
|
||||
|
||||
yield this.pool.addBlock(this, this.lastMerkle);
|
||||
|
||||
this.lastMerkle = null;
|
||||
this.waitingTX = 0;
|
||||
});
|
||||
|
||||
/**
|
||||
* Handle `filterload` packet.
|
||||
* @private
|
||||
* @param {FilterLoadPacket}
|
||||
* @param {FilterLoadPacket} packet
|
||||
*/
|
||||
|
||||
Peer.prototype.handleFilterLoad = co(function* handleFilterLoad(packet) {
|
||||
@ -1546,7 +1541,7 @@ Peer.prototype.handleFilterLoad = co(function* handleFilterLoad(packet) {
|
||||
/**
|
||||
* Handle `filteradd` packet.
|
||||
* @private
|
||||
* @param {FilterAddPacket}
|
||||
* @param {FilterAddPacket} packet
|
||||
*/
|
||||
|
||||
Peer.prototype.handleFilterAdd = co(function* handleFilterAdd(packet) {
|
||||
@ -2025,7 +2020,7 @@ Peer.prototype.handleGetBlockTxn = co(function* handleGetBlockTxn(packet) {
|
||||
*/
|
||||
|
||||
Peer.prototype.handleBlockTxn = co(function* handleBlockTxn(packet) {
|
||||
yield this.pool.handleGetBlockTxn(this, packet);
|
||||
yield this.pool.handleBlockTxn(this, packet);
|
||||
});
|
||||
|
||||
/**
|
||||
@ -2037,24 +2032,22 @@ Peer.prototype.handleBlockTxn = co(function* handleBlockTxn(packet) {
|
||||
|
||||
Peer.prototype.sendGetHeaders = function sendGetHeaders(locator, stop) {
|
||||
var packet = new packets.GetHeadersPacket(locator, stop);
|
||||
var height = -1;
|
||||
var hash = null;
|
||||
var end = null;
|
||||
|
||||
if (packet.locator.length > 0)
|
||||
hash = util.revHex(packet.locator[0]);
|
||||
|
||||
if (stop)
|
||||
end = util.revHex(stop);
|
||||
|
||||
this.logger.debug(
|
||||
'Requesting headers packet from peer with getheaders (%s).',
|
||||
this.hostname);
|
||||
|
||||
if (packet.locator.length > 0) {
|
||||
height = this.chain.checkHeight(packet.locator[0]);
|
||||
hash = util.revHex(packet.locator[0]);
|
||||
}
|
||||
|
||||
if (stop)
|
||||
stop = util.revHex(stop);
|
||||
|
||||
this.logger.debug(
|
||||
'Height: %d, Hash: %s, Stop: %s',
|
||||
height, hash, stop || null);
|
||||
'Sending getheaders (hash=%s, stop=%s).',
|
||||
hash, end);
|
||||
|
||||
this.send(packet);
|
||||
};
|
||||
@ -2069,10 +2062,7 @@ Peer.prototype.sendGetBlocks = function getBlocks(locator, stop) {
|
||||
var packet = new packets.GetBlocksPacket(locator, stop);
|
||||
var height = -1;
|
||||
var hash = null;
|
||||
|
||||
this.logger.debug(
|
||||
'Requesting inv packet from peer with getblocks (%s).',
|
||||
this.hostname);
|
||||
var end = null;
|
||||
|
||||
if (packet.locator.length > 0) {
|
||||
height = this.chain.checkHeight(packet.locator[0]);
|
||||
@ -2080,11 +2070,15 @@ Peer.prototype.sendGetBlocks = function getBlocks(locator, stop) {
|
||||
}
|
||||
|
||||
if (stop)
|
||||
stop = util.revHex(stop);
|
||||
end = util.revHex(stop);
|
||||
|
||||
this.logger.debug(
|
||||
'Height: %d, Hash: %s, Stop: %s',
|
||||
height, hash, stop || null);
|
||||
'Requesting inv packet from peer with getblocks (%s).',
|
||||
this.hostname);
|
||||
|
||||
this.logger.debug(
|
||||
'Sending getblocks (height=%d, hash=%s, stop=%s).',
|
||||
height, hash, end);
|
||||
|
||||
this.send(packet);
|
||||
};
|
||||
@ -2115,15 +2109,15 @@ Peer.prototype.sendMempool = function sendMempool() {
|
||||
* Send `reject` to peer.
|
||||
* @param {Number} code
|
||||
* @param {String} reason
|
||||
* @param {TX|Block} obj
|
||||
* @param {TX|Block} msg
|
||||
*/
|
||||
|
||||
Peer.prototype.sendReject = function sendReject(code, reason, obj) {
|
||||
var reject = packets.RejectPacket.fromReason(code, reason, obj);
|
||||
Peer.prototype.sendReject = function sendReject(code, reason, msg) {
|
||||
var reject = packets.RejectPacket.fromReason(code, reason, msg);
|
||||
|
||||
if (obj) {
|
||||
if (msg) {
|
||||
this.logger.debug('Rejecting %s %s (%s): ccode=%s reason=%s.',
|
||||
reject.message, obj.rhash(), this.hostname, code, reason);
|
||||
reject.message, msg.rhash(), this.hostname, code, reason);
|
||||
} else {
|
||||
this.logger.debug('Rejecting packet from %s: ccode=%s reason=%s.',
|
||||
this.hostname, code, reason);
|
||||
@ -2138,12 +2132,13 @@ Peer.prototype.sendReject = function sendReject(code, reason, obj) {
|
||||
|
||||
/**
|
||||
* Send a `sendcmpct` packet.
|
||||
* @param {Number} mode
|
||||
*/
|
||||
|
||||
Peer.prototype.sendCompact = function sendCompact() {
|
||||
Peer.prototype.sendCompact = function sendCompact(mode) {
|
||||
var version = this.options.witness ? 2 : 1;
|
||||
this.logger.info('Initializing compact blocks (%s).', this.hostname);
|
||||
this.send(new packets.SendCmpctPacket(0, version));
|
||||
this.send(new packets.SendCmpctPacket(mode, version));
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2174,14 +2169,14 @@ Peer.prototype.ban = function ban() {
|
||||
/**
|
||||
* Send a `reject` packet to peer.
|
||||
* @see Framer.reject
|
||||
* @param {(TX|Block)?} obj
|
||||
* @param {String} code - cccode.
|
||||
* @param {(TX|Block)?} msg
|
||||
* @param {String} code
|
||||
* @param {String} reason
|
||||
* @param {Number} score
|
||||
*/
|
||||
|
||||
Peer.prototype.reject = function reject(obj, code, reason, score) {
|
||||
this.sendReject(code, reason, obj);
|
||||
Peer.prototype.reject = function reject(msg, code, reason, score) {
|
||||
this.sendReject(code, reason, msg);
|
||||
this.increaseBan(score);
|
||||
};
|
||||
|
||||
|
||||
226
lib/net/pool.js
226
lib/net/pool.js
@ -34,7 +34,6 @@ var Map = require('../utils/map');
|
||||
var packets = require('./packets');
|
||||
var invTypes = InvItem.types;
|
||||
var VerifyError = errors.VerifyError;
|
||||
var VerifyResult = errors.VerifyResult;
|
||||
|
||||
/**
|
||||
* A pool of peers for handling all network activity.
|
||||
@ -104,7 +103,6 @@ function Pool(options) {
|
||||
|
||||
this.connected = false;
|
||||
this.syncing = false;
|
||||
this.feeRate = this.options.feeRate;
|
||||
this.nonce = util.nonce();
|
||||
this.spvFilter = null;
|
||||
this.txFilter = null;
|
||||
@ -180,26 +178,6 @@ Pool.prototype._init = function _init() {
|
||||
self.emit('block', block, entry);
|
||||
});
|
||||
|
||||
this.chain.on('competitor', function(block, entry) {
|
||||
self.emit('competitor', block, entry);
|
||||
});
|
||||
|
||||
this.chain.on('fork', function(block, height, expected) {
|
||||
self.emit('fork', block, height, expected);
|
||||
});
|
||||
|
||||
this.chain.on('invalid', function(block, height) {
|
||||
self.emit('invalid', block, height);
|
||||
});
|
||||
|
||||
this.chain.on('exists', function(block, height) {
|
||||
self.emit('exists', block, height);
|
||||
});
|
||||
|
||||
this.chain.on('orphan', function(block, height) {
|
||||
self.emit('orphan', block, height);
|
||||
});
|
||||
|
||||
this.chain.on('reset', function() {
|
||||
self.resetChain();
|
||||
self.forceSync();
|
||||
@ -896,7 +874,7 @@ Pool.prototype.handleOpen = function handleOpen(peer) {
|
||||
// We want compact blocks!
|
||||
if (this.options.compact) {
|
||||
if (peer.version >= common.COMPACT_VERSION)
|
||||
peer.sendCompact();
|
||||
peer.sendCompact(this.options.blockMode);
|
||||
}
|
||||
|
||||
// Find some more peers.
|
||||
@ -911,8 +889,8 @@ Pool.prototype.handleOpen = function handleOpen(peer) {
|
||||
this.announceList(peer);
|
||||
|
||||
// Set a fee rate filter.
|
||||
if (this.feeRate !== -1)
|
||||
peer.sendFeeRate(this.feeRate);
|
||||
if (this.options.feeRate !== -1)
|
||||
peer.sendFeeRate(this.options.feeRate);
|
||||
|
||||
// Start syncing the chain.
|
||||
peer.sync();
|
||||
@ -982,7 +960,7 @@ Pool.prototype.handleVersion = co(function* handleVersion(peer, packet) {
|
||||
*/
|
||||
|
||||
Pool.prototype.handleVerack = co(function* handleVerack(peer, packet) {
|
||||
;
|
||||
this.emit('verack', packet, peer);
|
||||
});
|
||||
|
||||
/**
|
||||
@ -993,7 +971,7 @@ Pool.prototype.handleVerack = co(function* handleVerack(peer, packet) {
|
||||
*/
|
||||
|
||||
Pool.prototype.handlePing = co(function* handlePing(peer, packet) {
|
||||
;
|
||||
this.emit('ping', packet, peer);
|
||||
});
|
||||
|
||||
/**
|
||||
@ -1004,7 +982,7 @@ Pool.prototype.handlePing = co(function* handlePing(peer, packet) {
|
||||
*/
|
||||
|
||||
Pool.prototype.handlePong = co(function* handlePong(peer, packet) {
|
||||
;
|
||||
this.emit('pong', packet, peer);
|
||||
});
|
||||
|
||||
/**
|
||||
@ -1051,6 +1029,8 @@ Pool.prototype.handleGetAddr = co(function* handleGetAddr(peer, packet) {
|
||||
peer.hostname);
|
||||
|
||||
peer.send(new packets.AddrPacket(items));
|
||||
|
||||
this.emit('getaddr', packet, peer);
|
||||
});
|
||||
|
||||
/**
|
||||
@ -1066,8 +1046,6 @@ Pool.prototype.handleAddr = co(function* handleAddr(peer, packet) {
|
||||
var services = this.options.requiredServices;
|
||||
var i, addr;
|
||||
|
||||
this.emit('addr', addrs, peer);
|
||||
|
||||
for (i = 0; i < addrs.length; i++) {
|
||||
addr = addrs[i];
|
||||
|
||||
@ -1096,6 +1074,8 @@ Pool.prototype.handleAddr = co(function* handleAddr(peer, packet) {
|
||||
peer.hostname);
|
||||
|
||||
this.fillOutbound();
|
||||
|
||||
this.emit('addr', packet, peer);
|
||||
});
|
||||
|
||||
/**
|
||||
@ -1159,13 +1139,13 @@ Pool.prototype._handleInv = co(function* handleInv(peer, packet) {
|
||||
unknown, peer.hostname);
|
||||
}
|
||||
|
||||
this.emit('inv', items, peer);
|
||||
|
||||
if (blocks.length > 0)
|
||||
yield this.handleBlockInv(peer, blocks);
|
||||
|
||||
if (txs.length > 0)
|
||||
yield this.handleTXInv(peer, txs);
|
||||
|
||||
this.emit('inv', packet, peer);
|
||||
});
|
||||
|
||||
/**
|
||||
@ -1361,7 +1341,7 @@ Pool.prototype.handleGetData = co(function* handleGetData(peer, packet) {
|
||||
continue;
|
||||
}
|
||||
|
||||
peer.sendCompactBlock(block, peer.compactWitness);
|
||||
peer.sendCompactBlock(block);
|
||||
|
||||
blocks++;
|
||||
|
||||
@ -1399,7 +1379,7 @@ Pool.prototype.handleGetData = co(function* handleGetData(peer, packet) {
|
||||
unknown, peer.hostname);
|
||||
}
|
||||
|
||||
this.emit('getdata', items, peer);
|
||||
this.emit('getdata', packet, peer);
|
||||
});
|
||||
|
||||
/**
|
||||
@ -1417,6 +1397,8 @@ Pool.prototype.handleNotFound = co(function* handleNotFound(peer, packet) {
|
||||
item = items[i];
|
||||
this.fulfill(peer, item.hash);
|
||||
}
|
||||
|
||||
this.emit('notfound', packet, peer);
|
||||
});
|
||||
|
||||
/**
|
||||
@ -1462,6 +1444,8 @@ Pool.prototype.handleGetBlocks = co(function* handleGetBlocks(peer, packet) {
|
||||
}
|
||||
|
||||
peer.sendInv(blocks);
|
||||
|
||||
this.emit('getblocks', packet, peer);
|
||||
});
|
||||
|
||||
/**
|
||||
@ -1511,6 +1495,8 @@ Pool.prototype.handleGetHeaders = co(function* handleGetHeaders(peer, packet) {
|
||||
}
|
||||
|
||||
peer.sendHeaders(headers);
|
||||
|
||||
this.emit('getheaders', packet, peer);
|
||||
});
|
||||
|
||||
/**
|
||||
@ -1595,13 +1581,13 @@ Pool.prototype._handleHeaders = co(function* handleHeaders(peer, packet) {
|
||||
this.headerChain.push(node);
|
||||
}
|
||||
|
||||
this.emit('headers', headers, peer);
|
||||
|
||||
this.logger.debug(
|
||||
'Received %s headers from peer (%s).',
|
||||
headers.length,
|
||||
peer.hostname);
|
||||
|
||||
this.emit('headers', packet, peer);
|
||||
|
||||
// Request the hashes we just added.
|
||||
if (isCheckpoint) {
|
||||
this.headerChain.shift();
|
||||
@ -1622,7 +1608,7 @@ Pool.prototype._handleHeaders = co(function* handleHeaders(peer, packet) {
|
||||
*/
|
||||
|
||||
Pool.prototype.handleSendHeaders = co(function* handleSendHeaders(peer, packet) {
|
||||
this.emit('sendheader', packet, peer);
|
||||
this.emit('sendheaders', packet, peer);
|
||||
});
|
||||
|
||||
/**
|
||||
@ -1645,7 +1631,7 @@ Pool.prototype.handleBlock = co(function* handleBlock(peer, packet) {
|
||||
});
|
||||
|
||||
/**
|
||||
* Handle `block` packet. Attempt to add to chain.
|
||||
* Attempt to add block to chain.
|
||||
* @private
|
||||
* @param {Peer} peer
|
||||
* @param {Block} block
|
||||
@ -1663,7 +1649,7 @@ Pool.prototype.addBlock = co(function* addBlock(peer, block) {
|
||||
});
|
||||
|
||||
/**
|
||||
* Handle `block` packet. Attempt to add to chain (without a lock).
|
||||
* Attempt to add block to chain (without a lock).
|
||||
* @private
|
||||
* @param {Peer} peer
|
||||
* @param {Block} block
|
||||
@ -1673,16 +1659,12 @@ Pool.prototype.addBlock = co(function* addBlock(peer, block) {
|
||||
Pool.prototype._addBlock = co(function* addBlock(peer, block) {
|
||||
var hash = block.hash('hex');
|
||||
var isCheckpoint = false;
|
||||
var requested, node, checkpoint;
|
||||
var node, checkpoint;
|
||||
|
||||
if (!this.syncing)
|
||||
return;
|
||||
|
||||
requested = this.fulfill(peer, hash);
|
||||
|
||||
// Someone is sending us blocks without
|
||||
// us requesting them.
|
||||
if (!requested) {
|
||||
if (!this.fulfill(peer, hash)) {
|
||||
peer.invFilter.add(block.hash());
|
||||
this.logger.warning(
|
||||
'Received unrequested block: %s (%s).',
|
||||
@ -1817,23 +1799,28 @@ Pool.prototype.handleTX = co(function* handleTX(peer, packet) {
|
||||
|
||||
Pool.prototype._handleTX = co(function* handleTX(peer, packet) {
|
||||
var tx = packet.tx;
|
||||
var hash = tx.hash('hex');
|
||||
var requested, missing;
|
||||
|
||||
if (peer.lastMerkle) {
|
||||
assert(peer.waitingTX > 0);
|
||||
if (peer.lastMerkle.hasTX(tx)) {
|
||||
peer.lastMerkle.addTX(tx);
|
||||
if (--peer.waitingTX === 0)
|
||||
yield peer.flushMerkle();
|
||||
if (peer.merkleBlock) {
|
||||
assert(peer.merkleMatches > 0);
|
||||
if (peer.merkleBlock.hasTX(tx)) {
|
||||
peer.merkleBlock.addTX(tx);
|
||||
if (--peer.merkleMatches === 0) {
|
||||
yield this.addBlock(peer, peer.merkleBlock);
|
||||
peer.merkleTime = -1;
|
||||
peer.merkleBlock = null;
|
||||
peer.merkleMatches = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var hash = tx.hash('hex');
|
||||
var requested = this.fulfill(peer, hash);
|
||||
var missing;
|
||||
requested = this.fulfill(peer, hash);
|
||||
|
||||
if (!requested) {
|
||||
this.logger.warning('Peer sent unrequested tx: %s (%s).',
|
||||
this.logger.warning(
|
||||
'Peer sent unrequested tx: %s (%s).',
|
||||
tx.txid(), peer.hostname);
|
||||
|
||||
peer.invFilter.add(tx.hash());
|
||||
@ -1917,7 +1904,7 @@ Pool.prototype.handleReject = co(function* handleReject(peer, packet) {
|
||||
|
||||
Pool.prototype.handleMempool = co(function* handleMempool(peer, packet) {
|
||||
var items = [];
|
||||
var i, hashes;
|
||||
var i, hash, hashes;
|
||||
|
||||
if (!this.mempool)
|
||||
return;
|
||||
@ -1930,14 +1917,16 @@ Pool.prototype.handleMempool = co(function* handleMempool(peer, packet) {
|
||||
|
||||
hashes = this.mempool.getSnapshot();
|
||||
|
||||
for (i = 0; i < hashes.length; i++)
|
||||
items.push(new InvItem(invTypes.TX, hashes[i]));
|
||||
for (i = 0; i < hashes.length; i++) {
|
||||
hash = hashes[i];
|
||||
items.push(new InvItem(invTypes.TX, hash));
|
||||
}
|
||||
|
||||
this.logger.debug('Sending mempool snapshot (%s).', peer.hostname);
|
||||
|
||||
this.emit('mempool', peer);
|
||||
|
||||
peer.sendInv(items);
|
||||
|
||||
this.emit('mempool', packet, peer);
|
||||
});
|
||||
|
||||
/**
|
||||
@ -1970,7 +1959,7 @@ Pool.prototype.handleFilterAdd = co(function* handleFilterAdd(peer, packet) {
|
||||
*/
|
||||
|
||||
Pool.prototype.handleFilterClear = co(function* handleFilterClear(peer, packet) {
|
||||
this.emit('filterclear', peer, packet);
|
||||
this.emit('filterclear', packet, peer);
|
||||
});
|
||||
|
||||
/**
|
||||
@ -1982,7 +1971,10 @@ Pool.prototype.handleFilterClear = co(function* handleFilterClear(peer, packet)
|
||||
|
||||
Pool.prototype.handleMerkleBlock = co(function* handleMerkleBlock(peer, packet) {
|
||||
var block = packet.block;
|
||||
var ret = new VerifyResult();
|
||||
var hash = block.hash('hex');
|
||||
|
||||
if (!this.syncing)
|
||||
return;
|
||||
|
||||
// Potential DoS.
|
||||
if (!this.options.spv) {
|
||||
@ -1993,7 +1985,15 @@ Pool.prototype.handleMerkleBlock = co(function* handleMerkleBlock(peer, packet)
|
||||
return;
|
||||
}
|
||||
|
||||
if (peer.lastMerkle) {
|
||||
if (!peer.requestMap.has(hash)) {
|
||||
this.logger.warning(
|
||||
'Peer sent an unrequested merkleblock (%s).',
|
||||
peer.hostname);
|
||||
peer.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
if (peer.merkleBlock) {
|
||||
this.logger.warning(
|
||||
'Peer sent a merkleblock prematurely (%s).',
|
||||
peer.hostname);
|
||||
@ -2001,19 +2001,24 @@ Pool.prototype.handleMerkleBlock = co(function* handleMerkleBlock(peer, packet)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!block.verify(ret)) {
|
||||
if (!block.verify()) {
|
||||
this.logger.warning(
|
||||
'Peer sent an invalid merkleblock (%s).',
|
||||
peer.hostname);
|
||||
peer.reject(block, 'invalid', ret.reason, ret.score);
|
||||
peer.increaseBan(100);
|
||||
return;
|
||||
}
|
||||
|
||||
peer.lastMerkle = block;
|
||||
peer.waitingTX = block.matches.length;
|
||||
if (block.matches.length === 0) {
|
||||
yield this.addBlock(peer, block);
|
||||
return;
|
||||
}
|
||||
|
||||
if (peer.waitingTX === 0)
|
||||
yield peer.flushMerkle();
|
||||
peer.merkleTime = util.ms();
|
||||
peer.merkleBlock = block;
|
||||
peer.merkleMatches = block.matches.length;
|
||||
|
||||
this.emit('merkleblock', packet, peer);
|
||||
});
|
||||
|
||||
/**
|
||||
@ -2051,6 +2056,9 @@ Pool.prototype.handleCmpctBlock = co(function* handleCmpctBlock(peer, packet) {
|
||||
var witness = this.options.witness;
|
||||
var result;
|
||||
|
||||
if (!this.syncing)
|
||||
return;
|
||||
|
||||
if (!this.options.compact) {
|
||||
this.logger.info('Peer sent unsolicited cmpctblock (%s).', peer.hostname);
|
||||
return;
|
||||
@ -2061,13 +2069,33 @@ Pool.prototype.handleCmpctBlock = co(function* handleCmpctBlock(peer, packet) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.compactBlocks.has(hash)) {
|
||||
if (peer.compactBlocks.has(hash)) {
|
||||
this.logger.debug(
|
||||
'Peer sent us a duplicate compact block (%s).',
|
||||
peer.hostname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.compactBlocks.has(hash)) {
|
||||
this.logger.debug(
|
||||
'Already waiting for compact block %s (%s).',
|
||||
hash, peer.hostname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!peer.requestMap.has(hash)) {
|
||||
if (this.options.blockMode !== 1) {
|
||||
this.logger.warning(
|
||||
'Peer sent us an unrequested compact block (%s).',
|
||||
peer.hostname);
|
||||
peer.destroy();
|
||||
return;
|
||||
}
|
||||
peer.requestMap.insert(hash);
|
||||
assert(!this.requestMap.has(hash));
|
||||
this.requestMap.insert(hash);
|
||||
}
|
||||
|
||||
if (!block.verify()) {
|
||||
this.logger.debug(
|
||||
'Peer sent an invalid compact block (%s).',
|
||||
@ -2086,10 +2114,12 @@ Pool.prototype.handleCmpctBlock = co(function* handleCmpctBlock(peer, packet) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (peer.compactBlocks.size >= 10) {
|
||||
this.logger.warning('Compact block DoS attempt (%s).', peer.hostname);
|
||||
peer.destroy();
|
||||
return;
|
||||
if (this.options.blockMode === 1) {
|
||||
if (peer.compactBlocks.size >= 10) {
|
||||
this.logger.warning('Compact block DoS attempt (%s).', peer.hostname);
|
||||
peer.destroy();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
assert(!peer.compactBlocks.has(hash));
|
||||
@ -2101,9 +2131,9 @@ Pool.prototype.handleCmpctBlock = co(function* handleCmpctBlock(peer, packet) {
|
||||
'Received semi-full compact block %s (%s).',
|
||||
block.rhash(), peer.hostname);
|
||||
|
||||
this.emit('cmpctblock', block, peer);
|
||||
|
||||
peer.send(new packets.GetBlockTxnPacket(block.toRequest()));
|
||||
|
||||
this.emit('cmpctblock', packet, peer);
|
||||
});
|
||||
|
||||
/**
|
||||
@ -2147,11 +2177,11 @@ Pool.prototype.handleGetBlockTxn = co(function* handleGetBlockTxn(peer, packet)
|
||||
return;
|
||||
}
|
||||
|
||||
this.emit('getblocktxn', req, peer);
|
||||
|
||||
res = BIP152.TXResponse.fromBlock(block, req);
|
||||
|
||||
peer.send(new packets.BlockTxnPacket(res, peer.compactWitness));
|
||||
|
||||
this.emit('getblocktxn', packet, peer);
|
||||
});
|
||||
|
||||
/**
|
||||
@ -2161,7 +2191,7 @@ Pool.prototype.handleGetBlockTxn = co(function* handleGetBlockTxn(peer, packet)
|
||||
* @param {BlockTxnPacket} packet
|
||||
*/
|
||||
|
||||
Peer.prototype.handleBlockTxn = co(function* handleBlockTxn(peer, packet) {
|
||||
Pool.prototype.handleBlockTxn = co(function* handleBlockTxn(peer, packet) {
|
||||
var res = packet.response;
|
||||
var block = peer.compactBlocks.get(res.hash);
|
||||
|
||||
@ -2185,9 +2215,9 @@ Peer.prototype.handleBlockTxn = co(function* handleBlockTxn(peer, packet) {
|
||||
'Filled compact block %s (%s).',
|
||||
block.rhash(), peer.hostname);
|
||||
|
||||
this.emit('blocktxn', res, peer);
|
||||
|
||||
yield this.addBlock(peer, block.toBlock());
|
||||
|
||||
this.emit('blocktxn', packet, peer);
|
||||
});
|
||||
|
||||
/**
|
||||
@ -2197,7 +2227,7 @@ Peer.prototype.handleBlockTxn = co(function* handleBlockTxn(peer, packet) {
|
||||
* @param {EncinitPacket} packet
|
||||
*/
|
||||
|
||||
Peer.prototype.handleEncinit = co(function* handleEncinit(peer, packet) {
|
||||
Pool.prototype.handleEncinit = co(function* handleEncinit(peer, packet) {
|
||||
this.emit('encinit', packet, peer);
|
||||
});
|
||||
|
||||
@ -2208,7 +2238,7 @@ Peer.prototype.handleEncinit = co(function* handleEncinit(peer, packet) {
|
||||
* @param {EncackPacket} packet
|
||||
*/
|
||||
|
||||
Peer.prototype.handleEncack = co(function* handleEncack(peer, packet) {
|
||||
Pool.prototype.handleEncack = co(function* handleEncack(peer, packet) {
|
||||
this.emit('encack', packet, peer);
|
||||
});
|
||||
|
||||
@ -2219,7 +2249,7 @@ Peer.prototype.handleEncack = co(function* handleEncack(peer, packet) {
|
||||
* @param {AuthChallengePacket} packet
|
||||
*/
|
||||
|
||||
Peer.prototype.handleAuthChallenge = co(function* handleAuthChallenge(peer, packet) {
|
||||
Pool.prototype.handleAuthChallenge = co(function* handleAuthChallenge(peer, packet) {
|
||||
this.emit('authchallenge', packet, peer);
|
||||
});
|
||||
|
||||
@ -2230,7 +2260,7 @@ Peer.prototype.handleAuthChallenge = co(function* handleAuthChallenge(peer, pack
|
||||
* @param {AuthReplyPacket} packet
|
||||
*/
|
||||
|
||||
Peer.prototype.handleAuthReply = co(function* handleAuthReply(peer, packet) {
|
||||
Pool.prototype.handleAuthReply = co(function* handleAuthReply(peer, packet) {
|
||||
this.emit('authreply', packet, peer);
|
||||
});
|
||||
|
||||
@ -2241,7 +2271,7 @@ Peer.prototype.handleAuthReply = co(function* handleAuthReply(peer, packet) {
|
||||
* @param {AuthProposePacket} packet
|
||||
*/
|
||||
|
||||
Peer.prototype.handleAuthPropose = co(function* handleAuthPropose(peer, packet) {
|
||||
Pool.prototype.handleAuthPropose = co(function* handleAuthPropose(peer, packet) {
|
||||
this.emit('authpropose', packet, peer);
|
||||
});
|
||||
|
||||
@ -2252,8 +2282,8 @@ Peer.prototype.handleAuthPropose = co(function* handleAuthPropose(peer, packet)
|
||||
* @param {UnknownPacket} packet
|
||||
*/
|
||||
|
||||
Peer.prototype.handleUnknown = co(function* handleUnknown(peer, packet) {
|
||||
this.logger.warning('Unknown packet: %s.', packet.cmd);
|
||||
Pool.prototype.handleUnknown = co(function* handleUnknown(peer, packet) {
|
||||
this.logger.warning('Unknown packet: %s (%s).', packet.cmd, peer.hostname);
|
||||
this.emit('unknown', packet, peer);
|
||||
});
|
||||
|
||||
@ -2780,20 +2810,6 @@ Pool.prototype.announceTX = function announceTX(msg) {
|
||||
peer.announceTX(msg);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set a fee rate filter for all peers.
|
||||
* @param {Rate} rate
|
||||
*/
|
||||
|
||||
Pool.prototype.setFeeRate = function setFeeRate(rate) {
|
||||
var peer;
|
||||
|
||||
this.feeRate = rate;
|
||||
|
||||
for (peer = this.peers.head(); peer; peer = peer.next)
|
||||
peer.sendFeeRate(rate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Attempt to retrieve external IP from icanhazip.com.
|
||||
* @returns {Promise}
|
||||
@ -2898,6 +2914,7 @@ function PoolOptions(options) {
|
||||
this.seeds = this.network.seeds;
|
||||
this.nodes = [];
|
||||
this.invTimeout = 60000;
|
||||
this.blockMode = 0;
|
||||
this.services = common.LOCAL_SERVICES;
|
||||
this.requiredServices = common.REQUIRED_SERVICES;
|
||||
|
||||
@ -3091,6 +3108,11 @@ PoolOptions.prototype.fromOptions = function fromOptions(options) {
|
||||
this.invTimeout = options.invTimeout;
|
||||
}
|
||||
|
||||
if (options.blockMode != null) {
|
||||
assert(typeof options.blockMode === 'number');
|
||||
this.blockMode = options.blockMode;
|
||||
}
|
||||
|
||||
if (!this.witness) {
|
||||
this.services &= ~common.services.WITNESS;
|
||||
this.requiredServices &= ~common.services.WITNESS;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user