diff --git a/lib/mempool/mempool.js b/lib/mempool/mempool.js index 741182ad..3d2b64c7 100644 --- a/lib/mempool/mempool.js +++ b/lib/mempool/mempool.js @@ -724,7 +724,7 @@ Mempool.prototype.removeUnchecked = function removeUnchecked(entry, limit) { // are still spending valid coins (which // now exist on the blockchain). if (limit) { - this._removeSpenders(entry); + this.removeSpenders(entry); this.logger.debug('Evicting %s from the mempool.', entry.tx.rhash); } @@ -976,6 +976,58 @@ Mempool.prototype.countDescendants = function countDescendants(tx) { return max; }; +/** + * Get all transaction ancestors. + * @param {TX} tx + * @returns {MempoolEntry[]} + */ + +Mempool.prototype.getAncestors = function getAncestors(tx) { + var self = this; + var entries = []; + + (function traverse(tx) { + var i, input, prev; + + for (i = 0; i < tx.inputs.length; i++) { + input = tx.inputs[i]; + prev = self.getTX(input.prevout.hash); + if (!prev) + continue; + entries.push(prev); + traverse(prev); + } + })(tx); + + return entries; +}; + +/** + * Get all a transaction descendants. + * @param {TX} tx + * @returns {MempoolEntry[]} + */ + +Mempool.prototype.getDescendants = function getDescendants(tx) { + var self = this; + var entries = []; + + (function traverse(tx) { + var hash = tx.hash('hex'); + var i, next; + + for (i = 0; i < tx.outputs.length; i++) { + next = self.isSpent(hash, i); + if (!next) + continue; + entries.push(next); + traverse(next.tx); + } + })(tx); + + return entries; +}; + /** * Find a unconfirmed transactions that * this transaction depends on. @@ -1387,7 +1439,7 @@ Mempool.prototype.trackEntry = function trackEntry(entry) { assert(input.coin); if (this.options.indexAddress) - this.coinIndex.removeCoin(input.coin); + this.coinIndex.removeCoin(input.prevout); this.spents[key] = entry; } @@ -1430,12 +1482,10 @@ Mempool.prototype.untrackEntry = function untrackEntry(entry) { input = tx.inputs[i]; key = input.prevout.hash + input.prevout.index; - delete this.spents[key]; - - assert(input.coin); - if (this.options.indexAddress) - this.coinIndex.removeCoin(input.coin); + this.coinIndex.removeCoin(input.prevout); + + delete this.spents[key]; } if (this.options.indexAddress) { @@ -1462,7 +1512,7 @@ Mempool.prototype.untrackEntry = function untrackEntry(entry) { * @param {Function} callback */ -Mempool.prototype._removeSpenders = function _removeSpenders(entry) { +Mempool.prototype.removeSpenders = function removeSpenders(entry) { var tx = entry.tx; var hash = tx.hash('hex'); var i, spender; @@ -1855,6 +1905,7 @@ AddressIndex.prototype.getTX = function getTX(address) { }; AddressIndex.prototype.addTX = function addTX(tx) { + var key = tx.hash('hex'); var hashes = tx.getHashes('hex'); var i, hash, items; @@ -1869,12 +1920,18 @@ AddressIndex.prototype.addTX = function addTX(tx) { utils.binaryInsert(items, tx.hash(), utils.cmp); } + + this.map[key] = hashes; }; AddressIndex.prototype.removeTX = function removeTX(tx) { - var hashes = tx.getHashes('hex'); + var key = tx.hash('hex'); + var hashes = this.map[key]; var i, hash, items; + if (!hashes) + return; + for (i = 0; i < hashes.length; i++) { hash = hashes[i]; items = this.map[hash]; @@ -1887,9 +1944,12 @@ AddressIndex.prototype.removeTX = function removeTX(tx) { if (items.length === 0) delete this.map[hash]; } + + delete this.map[key]; }; AddressIndex.prototype.addCoin = function addCoin(coin) { + var key = coin.hash + coin.index; var hash = coin.getHash('hex'); var outpoint, items; @@ -1905,10 +1965,13 @@ AddressIndex.prototype.addCoin = function addCoin(coin) { outpoint = bcoin.outpoint(coin.hash, coin.index).toRaw(); utils.binaryInsert(items, outpoint, utils.cmp); + + this.map[key] = hash; }; AddressIndex.prototype.removeCoin = function removeCoin(coin) { - var hash = coin.getHash('hex'); + var key = coin.hash + coin.index; + var hash = this.map[key]; var outpoint, items; if (!hash) @@ -1924,6 +1987,8 @@ AddressIndex.prototype.removeCoin = function removeCoin(coin) { if (items.length === 0) delete this.map[hash]; + + delete this.map[key]; }; /*