diff --git a/lib/mempool/mempool.js b/lib/mempool/mempool.js index 89f581e8..a1d8c899 100644 --- a/lib/mempool/mempool.js +++ b/lib/mempool/mempool.js @@ -366,39 +366,43 @@ Mempool.prototype._reset = co(function* reset() { Mempool.prototype.limitSize = function limitSize(added) { var maxSize = this.options.maxSize; + var threshold = maxSize - (maxSize / 10); var expiryTime = this.options.expiryTime; var now = util.now(); - var trimmed = false; - var i, queue, entry, keys, hash, start; + var i, queue, hashes, hash, entry, start; if (this.size <= maxSize) - return trimmed; + return false; queue = new Heap(cmpRate); - keys = this.getSnapshot(); + hashes = this.getSnapshot(); start = util.hrtime(); - for (i = 0; i < keys.length; i++) { - hash = keys[i]; + for (i = 0; i < hashes.length; i++) { + hash = hashes[i]; entry = this.getEntry(hash); if (!entry) continue; + if (this.hasDepends(entry.tx)) + continue; + if (now < entry.ts + expiryTime) { queue.insert(entry); continue; } - if (entry === added) - trimmed = true; + this.logger.debug( + 'Removing package %s from mempool (too old).', + entry.txid()); this.evictEntry(entry); } - if (this.size <= maxSize) - return trimmed; + if (this.size <= threshold) + return !this.hasEntry(added); this.logger.debug( '(bench) Heap mempool traversal: %d.', @@ -406,19 +410,23 @@ Mempool.prototype.limitSize = function limitSize(added) { start = util.hrtime(); + this.logger.debug( + '(bench) Heap mempool queue size: %d.', + queue.size()); + while (queue.size() > 0) { entry = queue.shift(); hash = entry.hash('hex'); - if (!this.hasEntry(hash)) - continue; + assert(this.hasEntry(hash)); + + this.logger.debug( + 'Removing package %s from mempool (low fee).', + entry.txid()); this.evictEntry(entry); - if (entry === added) - trimmed = true; - - if (this.size <= maxSize - (maxSize / 10)) + if (this.size <= threshold) break; } @@ -426,7 +434,7 @@ Mempool.prototype.limitSize = function limitSize(added) { '(bench) Heap mempool map removal: %d.', util.hrtime(start)); - return trimmed; + return !this.hasEntry(added); }; /** @@ -877,7 +885,7 @@ Mempool.prototype.insertTX = co(function* insertTX(tx) { yield this.addEntry(entry, view); // Trim size if we're too big. - if (this.limitSize(entry)) { + if (this.limitSize(hash)) { throw new VerifyError(tx, 'insufficientfee', 'mempool full', @@ -1132,19 +1140,14 @@ Mempool.prototype.removeEntry = function removeEntry(entry) { }; /** - * Evict a transaction from the mempool. + * Remove a transaction from the mempool. * Recursively remove its spenders. * @param {MempoolEntry} entry */ Mempool.prototype.evictEntry = function evictEntry(entry) { - var tx = entry.tx; - - this.logger.debug('Evicting %s from the mempool.', tx.txid()); - this.removeSpenders(entry); this.updateAncestors(entry, removeFee); - this.removeEntry(entry); }; @@ -1388,6 +1391,25 @@ Mempool.prototype.getDepends = function getDepends(tx) { return depends; }; +/** + * Test whether a transaction has dependencies. + * @param {TX} tx + * @returns {Boolean} + */ + +Mempool.prototype.hasDepends = function hasDepends(tx) { + var i, input, hash; + + for (i = 0; i < tx.inputs.length; i++) { + input = tx.inputs[i]; + hash = input.prevout.hash; + if (this.hasEntry(hash)) + return true; + } + + return false; +}; + /** * Return the full balance of all unspents in the mempool * (not very useful in practice, only used for testing). @@ -1900,7 +1922,7 @@ Mempool.prototype.removeDoubleSpends = function removeDoubleSpends(tx) { this.logger.debug( 'Removing double spender from mempool: %s.', - spent.tx.rhash()); + spent.txid()); this.evictEntry(spent); diff --git a/lib/mempool/mempoolentry.js b/lib/mempool/mempoolentry.js index 00679d52..09ab312f 100644 --- a/lib/mempool/mempoolentry.js +++ b/lib/mempool/mempoolentry.js @@ -142,6 +142,15 @@ MempoolEntry.prototype.hash = function hash(enc) { return this.tx.hash(enc); }; +/** + * Calculate reverse transaction hash. + * @returns {Hash} + */ + +MempoolEntry.prototype.txid = function txid() { + return this.tx.txid(); +}; + /** * Calculate priority, taking into account * the entry height delta, modified size,