net: better dos protection for merkleblocks.

This commit is contained in:
Christopher Jeffrey 2017-01-18 21:42:48 -08:00
parent 4cba97a0a8
commit 2ee6cea969
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
2 changed files with 22 additions and 6 deletions

View File

@ -1649,6 +1649,7 @@ Peer.prototype.handleFilterClear = co(function* handleFilterClear(packet) {
Peer.prototype.handleMerkleBlock = co(function* handleMerkleBlock(packet) { Peer.prototype.handleMerkleBlock = co(function* handleMerkleBlock(packet) {
var block = packet.block; var block = packet.block;
var ret = new VerifyResult();
// Potential DoS. // Potential DoS.
if (!this.options.spv) { if (!this.options.spv) {
@ -1659,7 +1660,21 @@ Peer.prototype.handleMerkleBlock = co(function* handleMerkleBlock(packet) {
return; return;
} }
block.verifyPartial(); if (this.lastMerkle) {
this.logger.warning(
'Peer sent a merkleblock prematurely (%s).',
this.hostname);
this.increaseBan(100);
return;
}
if (!block.verify(ret)) {
this.logger.warning(
'Peer sent an invalid merkleblock (%s).',
this.hostname);
this.reject(block, 'invalid', ret.reason, ret.score);
return;
}
this.lastMerkle = block; this.lastMerkle = block;
this.waitingTX = block.matches.length; this.waitingTX = block.matches.length;
@ -2467,6 +2482,7 @@ Peer.prototype.handleTX = co(function* handleTX(packet) {
var tx = packet.tx; var tx = packet.tx;
if (this.lastMerkle) { if (this.lastMerkle) {
assert(this.waitingTX > 0);
if (this.lastMerkle.hasTX(tx)) { if (this.lastMerkle.hasTX(tx)) {
this.lastMerkle.addTX(tx); this.lastMerkle.addTX(tx);
if (--this.waitingTX === 0) if (--this.waitingTX === 0)

View File

@ -247,21 +247,21 @@ MerkleBlock.prototype.extractTree = function extractTree() {
return crypto.hash256(buf); return crypto.hash256(buf);
} }
for (p = 0; p < this.hashes.length; p++)
hashes.push(this.hashes[p]);
if (totalTX === 0) if (totalTX === 0)
throw new Error('Zero transactions.'); throw new Error('Zero transactions.');
if (totalTX > consensus.MAX_BLOCK_SIZE / 60) if (totalTX > consensus.MAX_BLOCK_SIZE / 60)
throw new Error('Too many transactions.'); throw new Error('Too many transactions.');
if (hashes.length > totalTX) if (this.hashes.length > totalTX)
throw new Error('Too many hashes.'); throw new Error('Too many hashes.');
if (flags.length * 8 < hashes.length) if (flags.length * 8 < this.hashes.length)
throw new Error('Flags too small.'); throw new Error('Flags too small.');
for (p = 0; p < this.hashes.length; p++)
hashes.push(this.hashes[p]);
while (width(height) > 1) while (width(height) > 1)
height++; height++;