miner: compare cumulative descendant fee rate.
This commit is contained in:
parent
dcf7e7a9f4
commit
cb7af959ce
@ -1160,10 +1160,10 @@ RPC.prototype._entryToJSON = function _entryToJSON(entry) {
|
||||
height: entry.height,
|
||||
startingpriority: entry.priority,
|
||||
currentpriority: entry.getPriority(this.chain.height),
|
||||
descendantcount: this.mempool.countDescendants(tx),
|
||||
descendantcount: this.mempool.countDescendants(entry),
|
||||
descendantsize: entry.sizes,
|
||||
descendantfees: Amount.btc(entry.fee, true),
|
||||
ancestorcount: this.mempool.countAncestors(tx),
|
||||
ancestorcount: this.mempool.countAncestors(entry),
|
||||
ancestorsize: entry.sizes,
|
||||
ancestorfees: Amount.btc(entry.fee, true),
|
||||
depends: this.mempool.getDepends(tx).map(util.revHex)
|
||||
|
||||
@ -860,7 +860,7 @@ Mempool.prototype.verify = co(function* verify(entry, view) {
|
||||
throw new VerifyError(tx, 'highfee', 'absurdly-high-fee', 0);
|
||||
|
||||
// Why do we have this here? Nested transactions are cool.
|
||||
if (this.countAncestors(tx) > this.options.maxAncestors) {
|
||||
if (this.countAncestors(entry, true) > this.options.maxAncestors) {
|
||||
throw new VerifyError(tx,
|
||||
'nonstandard',
|
||||
'too-long-mempool-chain',
|
||||
@ -1027,8 +1027,8 @@ Mempool.prototype.removeEntry = function removeEntry(entry, limit) {
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
Mempool.prototype.countAncestors = function countAncestors(tx) {
|
||||
return this._countAncestors(tx, 0, {});
|
||||
Mempool.prototype.countAncestors = function countAncestors(entry, update) {
|
||||
return this._countAncestors(entry, 0, {}, true);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1040,15 +1040,16 @@ Mempool.prototype.countAncestors = function countAncestors(tx) {
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
Mempool.prototype._countAncestors = function countAncestors(tx, count, set) {
|
||||
var i, input, hash, prev;
|
||||
Mempool.prototype._countAncestors = function countAncestors(entry, count, set, update) {
|
||||
var tx = entry.tx;
|
||||
var i, input, hash, pentry;
|
||||
|
||||
for (i = 0; i < tx.inputs.length; i++) {
|
||||
input = tx.inputs[i];
|
||||
hash = input.prevout.hash;
|
||||
prev = this.getTX(hash);
|
||||
pentry = this.getEntry(hash);
|
||||
|
||||
if (!prev)
|
||||
if (!pentry)
|
||||
continue;
|
||||
|
||||
if (set[hash])
|
||||
@ -1057,10 +1058,15 @@ Mempool.prototype._countAncestors = function countAncestors(tx, count, set) {
|
||||
set[hash] = true;
|
||||
count += 1;
|
||||
|
||||
if (update) {
|
||||
pentry.descFee += entry.fee;
|
||||
pentry.descSize += entry.size;
|
||||
}
|
||||
|
||||
if (count > this.options.maxAncestors)
|
||||
break;
|
||||
|
||||
count = this._countAncestors(prev, count, set);
|
||||
count = this._countAncestors(pentry, count, set);
|
||||
|
||||
if (count > this.options.maxAncestors)
|
||||
break;
|
||||
@ -1076,8 +1082,8 @@ Mempool.prototype._countAncestors = function countAncestors(tx, count, set) {
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
Mempool.prototype.countDescendants = function countDescendants(tx) {
|
||||
return this._countDescendants(tx, 0, {});
|
||||
Mempool.prototype.countDescendants = function countDescendants(entry) {
|
||||
return this._countDescendants(entry, 0, {});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1090,17 +1096,18 @@ Mempool.prototype.countDescendants = function countDescendants(tx) {
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
Mempool.prototype._countDescendants = function countDescendants(tx, count, set) {
|
||||
var hash = tx.hash('hex');
|
||||
Mempool.prototype._countDescendants = function countDescendants(entry, count, set) {
|
||||
var tx = entry.tx;
|
||||
var hash = entry.hash;
|
||||
var i, next, nhash;
|
||||
|
||||
for (i = 0; i < tx.outputs.length; i++) {
|
||||
next = this.getSpentTX(hash, i);
|
||||
next = this.getSpent(hash, i);
|
||||
|
||||
if (!next)
|
||||
continue;
|
||||
|
||||
nhash = next.hash('hex');
|
||||
nhash = next.hash;
|
||||
|
||||
if (set[nhash])
|
||||
continue;
|
||||
|
||||
@ -40,6 +40,8 @@ function MempoolEntry(options) {
|
||||
this.ts = 0;
|
||||
this.value = 0;
|
||||
this.dependencies = false;
|
||||
this.descFee = 0;
|
||||
this.descSize = 0;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
@ -61,6 +63,8 @@ MempoolEntry.prototype.fromOptions = function fromOptions(options) {
|
||||
this.ts = options.ts;
|
||||
this.value = options.value;
|
||||
this.dependencies = options.dependencies;
|
||||
this.descFee = options.descFee;
|
||||
this.descSize = options.descSize;
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -108,6 +112,8 @@ MempoolEntry.prototype.fromTX = function fromTX(tx, view, height) {
|
||||
this.ts = util.now();
|
||||
this.value = value;
|
||||
this.dependencies = dependencies;
|
||||
this.descFee = fee;
|
||||
this.descSize = size;
|
||||
|
||||
return this;
|
||||
};
|
||||
@ -159,6 +165,15 @@ MempoolEntry.prototype.getRate = function getRate() {
|
||||
return policy.getRate(this.size, this.fee);
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate fee cumulative descendant rate.
|
||||
* @returns {Rate}
|
||||
*/
|
||||
|
||||
MempoolEntry.prototype.getDescRate = function getDescRate() {
|
||||
return policy.getRate(this.descSize, this.descFee);
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether the entry is free with
|
||||
* the current priority (calculated by
|
||||
|
||||
@ -374,7 +374,7 @@ Miner.prototype.build = function build(attempt) {
|
||||
var prev, deps, hashes, weight, sigops;
|
||||
|
||||
if (priority)
|
||||
queue.sort(cmpPriority);
|
||||
queue.set(cmpPriority);
|
||||
|
||||
if (!this.mempool)
|
||||
return [];
|
||||
@ -437,9 +437,8 @@ Miner.prototype.build = function build(attempt) {
|
||||
if (priority) {
|
||||
if (weight > this.options.priorityWeight
|
||||
|| item.priority < this.options.priorityThreshold) {
|
||||
// Todo: Compare descendant rate with
|
||||
// cumulative fees and cumulative vsize.
|
||||
queue.sort(cmpRate);
|
||||
queue.set(cmpRate);
|
||||
queue.sort();
|
||||
priority = false;
|
||||
queue.push(item);
|
||||
continue;
|
||||
@ -623,8 +622,12 @@ MinerOptions.fromOptions = function fromOptions(options) {
|
||||
*/
|
||||
|
||||
function Queue(cmp) {
|
||||
this.cmp = cmp || null;
|
||||
if (!(this instanceof Queue))
|
||||
return new Queue(cmp);
|
||||
|
||||
this.cmp = null;
|
||||
this.items = [];
|
||||
this.set(cmp);
|
||||
}
|
||||
|
||||
Queue.prototype.size = function size() {
|
||||
@ -640,10 +643,15 @@ Queue.prototype.pop = function pop() {
|
||||
return this.items.pop();
|
||||
};
|
||||
|
||||
Queue.prototype.sort = function sort(cmp) {
|
||||
assert(cmp === null || typeof cmp === 'function',
|
||||
Queue.prototype.set = function set(cmp) {
|
||||
assert(cmp == null || typeof cmp === 'function',
|
||||
'Comparator must be a function.');
|
||||
this.cmp = cmp;
|
||||
this.cmp = cmp || null;
|
||||
};
|
||||
|
||||
Queue.prototype.sort = function sort() {
|
||||
assert(this.cmp, 'No comparator for queue.');
|
||||
this.items.sort(this.cmp);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -655,7 +663,7 @@ function cmpPriority(a, b) {
|
||||
}
|
||||
|
||||
function cmpRate(a, b) {
|
||||
return a.rate - b.rate;
|
||||
return a.descRate - b.descRate;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -584,6 +584,7 @@ function BlockEntry(tx) {
|
||||
this.free = false;
|
||||
this.sigops = 0;
|
||||
this.depCount = 0;
|
||||
this.descRate = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -601,6 +602,7 @@ BlockEntry.fromTX = function fromTX(tx, view, attempt) {
|
||||
entry.priority = tx.getPriority(view, attempt.height);
|
||||
entry.free = false;
|
||||
entry.sigops = tx.getSigopsCost(view, attempt.flags);
|
||||
entry.descRate = entry.rate;
|
||||
return entry;
|
||||
};
|
||||
|
||||
@ -618,6 +620,7 @@ BlockEntry.fromEntry = function fromEntry(entry, attempt) {
|
||||
item.priority = entry.getPriority(attempt.height);
|
||||
item.free = entry.isFree(attempt.height);
|
||||
item.sigops = entry.sigops;
|
||||
item.descRate = entry.getDescRate();
|
||||
return item;
|
||||
};
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user