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