mempool: better ancestor and descendant traversal.
This commit is contained in:
parent
f625013548
commit
9e1428a8d5
@ -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;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user