priority. checkInputs. chainValue.

This commit is contained in:
Christopher Jeffrey 2016-07-01 23:49:52 -07:00
parent 4bf962638e
commit 27a8a83969
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
4 changed files with 76 additions and 46 deletions

View File

@ -7,8 +7,7 @@
'use strict'; 'use strict';
var utils = require('./utils'); var assert = require('assert');
var assert = utils.assert;
/** /**
* An LRU cache, used for caching {@link ChainEntry}s. * An LRU cache, used for caching {@link ChainEntry}s.
@ -22,15 +21,22 @@ function LRU(maxSize, getSize) {
if (!(this instanceof LRU)) if (!(this instanceof LRU))
return new LRU(maxSize, getSize); return new LRU(maxSize, getSize);
this.data = {};
this.size = 0;
this.maxSize = maxSize; this.maxSize = maxSize;
this.getSize = this._createGetSize(getSize); this.getSize = this._createGetSize(getSize);
this.data = {};
this.size = 0;
this.head = null; this.head = null;
this.tail = null; this.tail = null;
} }
/**
* Create a getSize callback.
* @private
* @param {Number} size
* @returns {Function}
*/
LRU.prototype._createGetSize = function _createGetSize(size) { LRU.prototype._createGetSize = function _createGetSize(size) {
if (!size) if (!size)
return; return;

View File

@ -1914,7 +1914,8 @@ MempoolEntry.fromOptions = function fromOptions(options) {
*/ */
MempoolEntry.prototype.fromTX = function fromTX(tx, height) { MempoolEntry.prototype.fromTX = function fromTX(tx, height) {
var data = tx.getPriority(height); var priority = tx.getPriority(height);
var value = tx.getChainValue(height);
var dependencies = false; var dependencies = false;
var size = tx.getVirtualSize(); var size = tx.getVirtualSize();
var fee = tx.getFee(); var fee = tx.getFee();
@ -1930,9 +1931,9 @@ MempoolEntry.prototype.fromTX = function fromTX(tx, height) {
this.tx = tx; this.tx = tx;
this.height = height; this.height = height;
this.size = size; this.size = size;
this.priority = data.priority; this.priority = priority;
this.fee = fee; this.fee = fee;
this.chainValue = data.value; this.chainValue = value;
this.ts = utils.now(); this.ts = utils.now();
this.count = 1; this.count = 1;
this.sizes = size; this.sizes = size;

View File

@ -1266,9 +1266,9 @@ MTX.prototype.avoidFeeSniping = function avoidFeeSniping(height) {
height = 0; height = 0;
if ((Math.random() * 10 | 0) === 0) if ((Math.random() * 10 | 0) === 0)
this.setLocktime(Math.max(0, height - (Math.random() * 100 | 0))); height = Math.max(0, height - (Math.random() * 100 | 0));
else
this.setLocktime(height); this.setLocktime(height);
}; };
/** /**

View File

@ -1447,6 +1447,13 @@ TX.prototype.checkInputs = function checkInputs(spendHeight, ret) {
input = this.inputs[i]; input = this.inputs[i];
coin = input.coin; coin = input.coin;
if (!coin) {
// Note: don't trigger dos score here.
ret.reason = 'bad-txns-inputs-missingorspent';
ret.score = 0;
return false;
}
if (coin.coinbase && spendHeight != null) { if (coin.coinbase && spendHeight != null) {
if (spendHeight - coin.height < constants.tx.COINBASE_MATURITY) { if (spendHeight - coin.height < constants.tx.COINBASE_MATURITY) {
ret.reason = 'bad-txns-premature-spend-of-coinbase'; ret.reason = 'bad-txns-premature-spend-of-coinbase';
@ -1462,17 +1469,18 @@ TX.prototype.checkInputs = function checkInputs(spendHeight, ret) {
} }
total += coin.value; total += coin.value;
if (total < 0 || total > constants.MAX_MONEY) {
ret.reason = 'bad-txns-inputvalues-outofrange';
ret.score = 100;
return false;
}
} }
if (total < 0 || total > constants.MAX_MONEY) { // Overflows already checked in `isSane()`.
ret.reason = 'bad-txns-inputvalues-outofrange';
ret.score = 100;
return false;
}
value = this.getOutputValue(); value = this.getOutputValue();
if (value > total) { if (total < value) {
ret.reason = 'bad-txns-in-belowout'; ret.reason = 'bad-txns-in-belowout';
ret.score = 100; ret.score = 100;
return false; return false;
@ -1532,32 +1540,28 @@ TX.prototype.getModifiedSize = function getModifiedSize(size) {
/** /**
* Calculate the transaction priority. * Calculate the transaction priority.
* @param {Number?} height - If not present, tx height * @param {Number?} height - If not present, tx height
* or mempool height will be used. * or network height will be used.
* @param {Number?} size - Size to calculate priority * @param {Number?} size - Size to calculate priority
* based on. If not present, modified size will be * based on. If not present, virtual size will be used.
* calculated and used. * @returns {Number}
* @returns {Object} data - Object containing
* `priority` and `value`.
*/ */
TX.prototype.getPriority = function getPriority(height, size) { TX.prototype.getPriority = function getPriority(height, size) {
var sum, i, input, age, value; var sum = 0;
var i, input, age;
if (this.isCoinbase()) if (this.isCoinbase())
return { value: 0, priority: 0 }; return sum;
if (height == null) { if (height == null) {
height = this.height; height = this.height;
if (height === -1) if (height === -1)
height = bcoin.network.get().height + 1; height = bcoin.network.get().height;
} }
if (size == null) if (size == null)
size = this.maxSize(); size = this.maxSize();
sum = 0;
value = 0;
for (i = 0; i < this.inputs.length; i++) { for (i = 0; i < this.inputs.length; i++) {
input = this.inputs[i]; input = this.inputs[i];
@ -1570,14 +1574,42 @@ TX.prototype.getPriority = function getPriority(height, size) {
if (input.coin.height <= height) { if (input.coin.height <= height) {
age = height - input.coin.height; age = height - input.coin.height;
sum += input.coin.value * age; sum += input.coin.value * age;
value += input.coin.value;
} }
} }
return { return Math.floor(sum / size);
value: value, };
priority: Math.floor(sum / size)
}; /**
* Calculate the transaction's on-chain value.
* @param {Number?} height
* @returns {Number}
*/
TX.prototype.getChainValue = function getChainValue(height) {
var value = 0;
var i, input;
if (this.isCoinbase())
return value;
if (height == null)
height = Infinity;
for (i = 0; i < this.inputs.length; i++) {
input = this.inputs[i];
if (!input.coin)
continue;
if (input.coin.height === -1)
continue;
if (input.coin.height <= height)
value += input.coin.value;
}
return value;
}; };
/** /**
@ -1586,24 +1618,15 @@ TX.prototype.getPriority = function getPriority(height, size) {
* passed this test is most likely relayable * passed this test is most likely relayable
* without a fee. * without a fee.
* @param {Number?} height - If not present, tx * @param {Number?} height - If not present, tx
* height or mempool height will be used. * height or network height will be used.
* @param {Number?} size - If not present, modified * @param {Number?} size - If not present, modified
* size will be calculated and used. * size will be calculated and used.
* @returns {Boolean} * @returns {Boolean}
*/ */
TX.prototype.isFree = function isFree(height, size) { TX.prototype.isFree = function isFree(height, size) {
var data; var priority = this.getPriority(height, size);
return priority > constants.tx.FREE_THRESHOLD;
if (height == null) {
height = this.height;
if (height === -1)
height = bcoin.network.get().height + 1;
}
data = this.getPriority(height, size);
return data.priority > constants.tx.FREE_THRESHOLD;
}; };
/** /**
@ -1852,7 +1875,7 @@ TX.prototype.inspect = function inspect() {
minFee: utils.btc(this.getMinFee()), minFee: utils.btc(this.getMinFee()),
rate: utils.btc(this.getRate()), rate: utils.btc(this.getRate()),
confirmations: this.getConfirmations(), confirmations: this.getConfirmations(),
priority: this.getPriority().priority.toString(10), priority: this.getPriority(),
date: utils.date(this.ts || this.ps), date: utils.date(this.ts || this.ps),
block: this.block ? utils.revHex(this.block) : null, block: this.block ? utils.revHex(this.block) : null,
ts: this.ts, ts: this.ts,