From 2ee6cea969b233bc2d9412fa5c87147bf4568daf Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Wed, 18 Jan 2017 21:42:48 -0800 Subject: [PATCH] net: better dos protection for merkleblocks. --- lib/net/peer.js | 18 +++++++++++++++++- lib/primitives/merkleblock.js | 10 +++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/lib/net/peer.js b/lib/net/peer.js index e8e648a2..ca41187c 100644 --- a/lib/net/peer.js +++ b/lib/net/peer.js @@ -1649,6 +1649,7 @@ Peer.prototype.handleFilterClear = co(function* handleFilterClear(packet) { Peer.prototype.handleMerkleBlock = co(function* handleMerkleBlock(packet) { var block = packet.block; + var ret = new VerifyResult(); // Potential DoS. if (!this.options.spv) { @@ -1659,7 +1660,21 @@ Peer.prototype.handleMerkleBlock = co(function* handleMerkleBlock(packet) { 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.waitingTX = block.matches.length; @@ -2467,6 +2482,7 @@ Peer.prototype.handleTX = co(function* handleTX(packet) { var tx = packet.tx; if (this.lastMerkle) { + assert(this.waitingTX > 0); if (this.lastMerkle.hasTX(tx)) { this.lastMerkle.addTX(tx); if (--this.waitingTX === 0) diff --git a/lib/primitives/merkleblock.js b/lib/primitives/merkleblock.js index 9ea0f8b3..724f5ca6 100644 --- a/lib/primitives/merkleblock.js +++ b/lib/primitives/merkleblock.js @@ -247,21 +247,21 @@ MerkleBlock.prototype.extractTree = function extractTree() { return crypto.hash256(buf); } - for (p = 0; p < this.hashes.length; p++) - hashes.push(this.hashes[p]); - if (totalTX === 0) throw new Error('Zero transactions.'); if (totalTX > consensus.MAX_BLOCK_SIZE / 60) throw new Error('Too many transactions.'); - if (hashes.length > totalTX) + if (this.hashes.length > totalTX) 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.'); + for (p = 0; p < this.hashes.length; p++) + hashes.push(this.hashes[p]); + while (width(height) > 1) height++;