mempool: better ancestor and descendant traversal.

This commit is contained in:
Christopher Jeffrey 2016-11-17 23:21:01 -08:00
parent f625013548
commit 9e1428a8d5
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD

View File

@ -384,6 +384,17 @@ Mempool.prototype.getCoin = function getCoin(hash, index) {
*/
Mempool.prototype.isSpent = function isSpent(hash, index) {
return this.spents[hash + index] != null;
};
/**
* Get an output's spender transaction.
* @param {Hash} hash
* @param {Number} index
* @returns {MempoolEntry}
*/
Mempool.prototype.getSpent = function getSpent(hash, index) {
return this.spents[hash + index];
};
@ -1076,24 +1087,44 @@ Mempool.prototype.checkInputs = co(function* checkInputs(tx, flags) {
*/
Mempool.prototype.countAncestors = function countAncestors(tx) {
var max = 0;
var i, input, count, prev;
return this._countAncestors(tx, {}, 0);
};
/**
* Traverse ancestors and count.
* @private
* @param {TX} tx
* @param {Object} set
* @param {Number} count
*/
Mempool.prototype._countAncestors = function countAncestors(tx, set, count) {
var i, input, hash, prev;
for (i = 0; i < tx.inputs.length; i++) {
input = tx.inputs[i];
prev = this.getTX(input.prevout.hash);
hash = input.prevout.hash;
prev = this.getTX(hash);
if (!prev)
continue;
count = 1;
count += this.countAncestors(prev);
if (set[hash])
continue;
if (count > max)
max = count;
set[hash] = true;
count += 1;
if (count > constants.mempool.ANCESTOR_LIMIT)
break;
count = this._countAncestors(prev, set, count);
if (count > constants.mempool.ANCESTOR_LIMIT)
break;
}
return max;
return count;
};
/**
@ -1104,24 +1135,40 @@ Mempool.prototype.countAncestors = function countAncestors(tx) {
*/
Mempool.prototype.countDescendants = function countDescendants(tx) {
var max = 0;
return this._countDescendants(tx, {}, 0);
};
/**
* Count the highest number of
* descendants a transaction may have.
* @private
* @param {TX} tx
* @returns {Number}
*/
Mempool.prototype._countDescendants = function countDescendants(tx, set, count) {
var hash = tx.hash('hex');
var i, count, next;
var i, entry, next, nhash;
for (i = 0; i < tx.outputs.length; i++) {
next = this.isSpent(hash, i);
entry = this.getSpent(hash, i);
if (!next)
if (!entry)
continue;
count = 1;
count += this.countDescendants(next.tx);
next = entry.tx;
nhash = next.hash('hex');
if (count > max)
max = count;
if (set[nhash])
continue;
set[nhash] = true;
count += 1;
count = this._countDescendants(next, set, count);
}
return max;
return count;
};
/**
@ -1131,23 +1178,35 @@ Mempool.prototype.countDescendants = function countDescendants(tx) {
*/
Mempool.prototype.getAncestors = function getAncestors(tx) {
var self = this;
var entries = [];
return this._getAncestors(tx, [], {});
};
(function traverse(tx) {
var i, input, prev;
/**
* Get all transaction ancestors.
* @private
* @param {TX} tx
* @returns {MempoolEntry[]}
*/
for (i = 0; i < tx.inputs.length; i++) {
input = tx.inputs[i];
prev = self.getTX(input.prevout.hash);
Mempool.prototype._getAncestors = function getAncestors(tx, entries, set) {
var i, hash, input, prev;
if (!prev)
continue;
for (i = 0; i < tx.inputs.length; i++) {
input = tx.inputs[i];
hash = input.prevout.hash;
prev = this.getTX(hash);
entries.push(prev);
traverse(prev);
}
})(tx);
if (!prev)
continue;
if (set[hash])
continue;
set[hash] = true;
entries.push(prev);
this._getAncestors(prev, entries, set);
}
return entries;
};
@ -1159,23 +1218,36 @@ Mempool.prototype.getAncestors = function getAncestors(tx) {
*/
Mempool.prototype.getDescendants = function getDescendants(tx) {
var self = this;
var entries = [];
return this._getDescendants(tx, [], {});
};
(function traverse(tx) {
var hash = tx.hash('hex');
var i, next;
/**
* Get all a transaction descendants.
* @param {TX} tx
* @returns {MempoolEntry[]}
*/
for (i = 0; i < tx.outputs.length; i++) {
next = self.isSpent(hash, i);
Mempool.prototype._getDescendants = function getDescendants(tx, entries, set) {
var hash = tx.hash('hex');
var i, entry, next, nhash;
if (!next)
continue;
for (i = 0; i < tx.outputs.length; i++) {
entry = this.getSpent(hash, i);
entries.push(next);
traverse(next.tx);
}
})(tx);
if (!entry)
continue;
next = entry.tx;
nhash = next.hash('hex');
if (set[nhash])
continue;
set[nhash] = true;
entries.push(next);
this._getDescendants(next, entries, set);
}
return entries;
};
@ -1671,7 +1743,7 @@ Mempool.prototype.removeSpenders = function removeSpenders(entry) {
var i, spender;
for (i = 0; i < tx.outputs.length; i++) {
spender = this.isSpent(hash, i);
spender = this.getSpent(hash, i);
if (!spender)
continue;