diff --git a/lib/net/peer.js b/lib/net/peer.js index 582de881..3a99bc11 100644 --- a/lib/net/peer.js +++ b/lib/net/peer.js @@ -117,6 +117,7 @@ function Peer(options) { this.merkleBlock = null; this.merkleTime = -1; this.merkleMatches = 0; + this.merkleMap = null; this.syncing = false; this.sentAddr = false; this.sentGetAddr = false; diff --git a/lib/net/pool.js b/lib/net/pool.js index ea31dcbb..4a02a5aa 100644 --- a/lib/net/pool.js +++ b/lib/net/pool.js @@ -736,6 +736,7 @@ Pool.prototype.stopSync = function stopSync() { peer.merkleBlock = null; peer.merkleTime = -1; peer.merkleMatches = 0; + peer.merkleMap = null; peer.blockTime = -1; peer.blockMap.reset(); peer.compactBlocks.reset(); @@ -2454,18 +2455,34 @@ Pool.prototype._handleTX = co(function* handleTX(peer, packet) { var tx = packet.tx; var hash = tx.hash('hex'); var flags = chainCommon.flags.VERIFY_NONE; + var block = peer.merkleBlock; var missing; - if (peer.merkleBlock) { + if (block) { assert(peer.merkleMatches > 0); - if (peer.merkleBlock.hasTX(hash)) { - peer.merkleBlock.addTX(tx); - if (--peer.merkleMatches === 0) { - yield this._addBlock(peer, peer.merkleBlock, flags); - peer.merkleTime = -1; - peer.merkleBlock = null; - peer.merkleMatches = 0; + assert(peer.merkleMap); + + if (block.hasTX(hash)) { + if (peer.merkleMap.has(hash)) { + this.logger.warning( + 'Peer sent duplicate merkle tx: %s (%s).', + tx.txid(), peer.hostname()); + peer.increaseBan(100); + return; } + + peer.merkleMap.insert(hash); + + block.addTX(tx); + + if (--peer.merkleMatches === 0) { + peer.merkleBlock = null; + peer.merkleTime = -1; + peer.merkleMatches = 0; + peer.merkleMap = null; + yield this._addBlock(peer, block, flags); + } + return; } } @@ -2684,9 +2701,10 @@ Pool.prototype._handleMerkleBlock = co(function* handleMerkleBlock(peer, packet) return; } - peer.merkleTime = util.ms(); peer.merkleBlock = block; + peer.merkleTime = util.ms(); peer.merkleMatches = block.tree.matches.length; + peer.merkleMap = new Map(); }); /**