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) {
|
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];
|
return this.spents[hash + index];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1076,24 +1087,44 @@ Mempool.prototype.checkInputs = co(function* checkInputs(tx, flags) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Mempool.prototype.countAncestors = function countAncestors(tx) {
|
Mempool.prototype.countAncestors = function countAncestors(tx) {
|
||||||
var max = 0;
|
return this._countAncestors(tx, {}, 0);
|
||||||
var i, input, count, prev;
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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++) {
|
for (i = 0; i < tx.inputs.length; i++) {
|
||||||
input = tx.inputs[i];
|
input = tx.inputs[i];
|
||||||
prev = this.getTX(input.prevout.hash);
|
hash = input.prevout.hash;
|
||||||
|
prev = this.getTX(hash);
|
||||||
|
|
||||||
if (!prev)
|
if (!prev)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
count = 1;
|
if (set[hash])
|
||||||
count += this.countAncestors(prev);
|
continue;
|
||||||
|
|
||||||
if (count > max)
|
set[hash] = true;
|
||||||
max = count;
|
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) {
|
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 hash = tx.hash('hex');
|
||||||
var i, count, next;
|
var i, entry, next, nhash;
|
||||||
|
|
||||||
for (i = 0; i < tx.outputs.length; i++) {
|
for (i = 0; i < tx.outputs.length; i++) {
|
||||||
next = this.isSpent(hash, i);
|
entry = this.getSpent(hash, i);
|
||||||
|
|
||||||
if (!next)
|
if (!entry)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
count = 1;
|
next = entry.tx;
|
||||||
count += this.countDescendants(next.tx);
|
nhash = next.hash('hex');
|
||||||
|
|
||||||
if (count > max)
|
if (set[nhash])
|
||||||
max = count;
|
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) {
|
Mempool.prototype.getAncestors = function getAncestors(tx) {
|
||||||
var self = this;
|
return this._getAncestors(tx, [], {});
|
||||||
var entries = [];
|
};
|
||||||
|
|
||||||
(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++) {
|
Mempool.prototype._getAncestors = function getAncestors(tx, entries, set) {
|
||||||
input = tx.inputs[i];
|
var i, hash, input, prev;
|
||||||
prev = self.getTX(input.prevout.hash);
|
|
||||||
|
|
||||||
if (!prev)
|
for (i = 0; i < tx.inputs.length; i++) {
|
||||||
continue;
|
input = tx.inputs[i];
|
||||||
|
hash = input.prevout.hash;
|
||||||
|
prev = this.getTX(hash);
|
||||||
|
|
||||||
entries.push(prev);
|
if (!prev)
|
||||||
traverse(prev);
|
continue;
|
||||||
}
|
|
||||||
})(tx);
|
if (set[hash])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
set[hash] = true;
|
||||||
|
entries.push(prev);
|
||||||
|
|
||||||
|
this._getAncestors(prev, entries, set);
|
||||||
|
}
|
||||||
|
|
||||||
return entries;
|
return entries;
|
||||||
};
|
};
|
||||||
@ -1159,23 +1218,36 @@ Mempool.prototype.getAncestors = function getAncestors(tx) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Mempool.prototype.getDescendants = function getDescendants(tx) {
|
Mempool.prototype.getDescendants = function getDescendants(tx) {
|
||||||
var self = this;
|
return this._getDescendants(tx, [], {});
|
||||||
var entries = [];
|
};
|
||||||
|
|
||||||
(function traverse(tx) {
|
/**
|
||||||
var hash = tx.hash('hex');
|
* Get all a transaction descendants.
|
||||||
var i, next;
|
* @param {TX} tx
|
||||||
|
* @returns {MempoolEntry[]}
|
||||||
|
*/
|
||||||
|
|
||||||
for (i = 0; i < tx.outputs.length; i++) {
|
Mempool.prototype._getDescendants = function getDescendants(tx, entries, set) {
|
||||||
next = self.isSpent(hash, i);
|
var hash = tx.hash('hex');
|
||||||
|
var i, entry, next, nhash;
|
||||||
|
|
||||||
if (!next)
|
for (i = 0; i < tx.outputs.length; i++) {
|
||||||
continue;
|
entry = this.getSpent(hash, i);
|
||||||
|
|
||||||
entries.push(next);
|
if (!entry)
|
||||||
traverse(next.tx);
|
continue;
|
||||||
}
|
|
||||||
})(tx);
|
next = entry.tx;
|
||||||
|
nhash = next.hash('hex');
|
||||||
|
|
||||||
|
if (set[nhash])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
set[nhash] = true;
|
||||||
|
entries.push(next);
|
||||||
|
|
||||||
|
this._getDescendants(next, entries, set);
|
||||||
|
}
|
||||||
|
|
||||||
return entries;
|
return entries;
|
||||||
};
|
};
|
||||||
@ -1671,7 +1743,7 @@ Mempool.prototype.removeSpenders = function removeSpenders(entry) {
|
|||||||
var i, spender;
|
var i, spender;
|
||||||
|
|
||||||
for (i = 0; i < tx.outputs.length; i++) {
|
for (i = 0; i < tx.outputs.length; i++) {
|
||||||
spender = this.isSpent(hash, i);
|
spender = this.getSpent(hash, i);
|
||||||
|
|
||||||
if (!spender)
|
if (!spender)
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user