mempool: refactor fee estimation.
This commit is contained in:
parent
161fe6e2a1
commit
a11344db0e
@ -15,8 +15,8 @@ var policy = require('../protocol/policy');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var StaticWriter = require('../utils/staticwriter');
|
||||
var encoding = require('../utils/encoding');
|
||||
var Map = require('../utils/map');
|
||||
var Logger = require('../node/logger');
|
||||
var Network = require('../protocol/network');
|
||||
var global = util.global;
|
||||
var Float64Array = global.Float64Array || Array;
|
||||
var Int32Array = global.Int32Array || Array;
|
||||
@ -52,7 +52,7 @@ function ConfirmStats(type, logger) {
|
||||
if (!(this instanceof ConfirmStats))
|
||||
return new ConfirmStats(type, logger);
|
||||
|
||||
this.logger = logger || Logger.global;
|
||||
this.logger = Logger.global;
|
||||
|
||||
this.type = type;
|
||||
this.decay = 0;
|
||||
@ -70,6 +70,11 @@ function ConfirmStats(type, logger) {
|
||||
this.txAvg = new Float64Array(0);
|
||||
this.curBlockVal = new Float64Array(0);
|
||||
this.avg = new Float64Array(0);
|
||||
|
||||
if (logger) {
|
||||
assert(typeof logger === 'object');
|
||||
this.logger = logger;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -409,36 +414,41 @@ ConfirmStats.fromRaw = function fromRaw(data, type, logger) {
|
||||
* Estimator for fees and priority.
|
||||
* @alias module:mempool.PolicyEstimator
|
||||
* @constructor
|
||||
* @param {Network|NetworkType} network
|
||||
* @param {Logger?} logger
|
||||
*/
|
||||
|
||||
function PolicyEstimator(network, logger) {
|
||||
function PolicyEstimator(logger) {
|
||||
if (!(this instanceof PolicyEstimator))
|
||||
return new PolicyEstimator(network, logger);
|
||||
return new PolicyEstimator(logger);
|
||||
|
||||
this.network = Network.get(network);
|
||||
this.logger = logger || Logger.global;
|
||||
this.logger = Logger.global;
|
||||
|
||||
this.minTrackedFee = policy.MIN_RELAY >= MIN_FEERATE
|
||||
? policy.MIN_RELAY
|
||||
: MIN_FEERATE;
|
||||
this.minTrackedFee = MIN_FEERATE;
|
||||
this.minTrackedPri = MIN_PRIORITY;
|
||||
|
||||
this.minTrackedPri = policy.FREE_THRESHOLD >= MIN_PRIORITY
|
||||
? policy.FREE_THRESHOLD
|
||||
: MIN_PRIORITY;
|
||||
|
||||
this.feeStats = new ConfirmStats('FeeRate', this.logger);
|
||||
this.priStats = new ConfirmStats('Priority', this.logger);
|
||||
this.feeStats = new ConfirmStats('FeeRate');
|
||||
this.priStats = new ConfirmStats('Priority');
|
||||
|
||||
this.feeUnlikely = 0;
|
||||
this.feeLikely = INF_FEERATE;
|
||||
this.priUnlikely = 0;
|
||||
this.priLikely = INF_PRIORITY;
|
||||
|
||||
this.map = {};
|
||||
this.mapSize = 0;
|
||||
this.map = new Map();
|
||||
this.bestHeight = 0;
|
||||
|
||||
if (policy.MIN_RELAY >= MIN_FEERATE)
|
||||
this.minTrackedFee = policy.MIN_RELAY;
|
||||
|
||||
if (policy.FREE_THRESHOLD >= MIN_PRIORITY)
|
||||
this.minTrackedPri = policy.FREE_THRESHOLD;
|
||||
|
||||
if (logger) {
|
||||
assert(typeof logger === 'object');
|
||||
this.logger = logger;
|
||||
this.feeStats.logger = logger;
|
||||
this.priStats.logger = logger;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -481,8 +491,7 @@ PolicyEstimator.prototype.reset = function reset() {
|
||||
this.priUnlikely = 0;
|
||||
this.priLikely = INF_PRIORITY;
|
||||
|
||||
this.map = {};
|
||||
this.mapSize = 0;
|
||||
this.map.reset();
|
||||
this.bestHeight = 0;
|
||||
|
||||
this.init();
|
||||
@ -494,7 +503,7 @@ PolicyEstimator.prototype.reset = function reset() {
|
||||
*/
|
||||
|
||||
PolicyEstimator.prototype.removeTX = function removeTX(hash) {
|
||||
var item = this.map[hash];
|
||||
var item = this.map.get(hash);
|
||||
|
||||
if (!item) {
|
||||
this.logger.spam(
|
||||
@ -505,8 +514,7 @@ PolicyEstimator.prototype.removeTX = function removeTX(hash) {
|
||||
|
||||
this.feeStats.removeTX(item.blockHeight, this.bestHeight, item.bucketIndex);
|
||||
|
||||
delete this.map[hash];
|
||||
this.mapSize--;
|
||||
this.map.remove(hash);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -550,7 +558,7 @@ PolicyEstimator.prototype.processTX = function processTX(entry, current) {
|
||||
var hash = entry.tx.hash('hex');
|
||||
var fee, rate, priority, item;
|
||||
|
||||
if (this.map[hash]) {
|
||||
if (this.map.has(hash)) {
|
||||
this.logger.debug(
|
||||
'estimatefee: Mempool tx %s already tracked.',
|
||||
entry.tx.txid());
|
||||
@ -590,8 +598,7 @@ PolicyEstimator.prototype.processTX = function processTX(entry, current) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.map[hash] = item;
|
||||
this.mapSize++;
|
||||
this.map.set(hash, item);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -691,7 +698,7 @@ PolicyEstimator.prototype.processBlock = function processBlock(height, entries,
|
||||
|
||||
this.logger.debug('estimatefee: Done updating estimates'
|
||||
+ ' for %d confirmed entries. New mempool map size %d.',
|
||||
entries.length, this.mapSize);
|
||||
entries.length, this.map.size);
|
||||
|
||||
this.logger.debug('estimatefee: Rate: %d.', this.estimateFee());
|
||||
};
|
||||
@ -736,12 +743,6 @@ PolicyEstimator.prototype.estimateFee = function estimateFee(target, smart) {
|
||||
|
||||
target -= 1;
|
||||
|
||||
if (rate < this.network.feeRate)
|
||||
return this.network.feeRate;
|
||||
|
||||
if (rate > this.network.maxFeeRate)
|
||||
return this.network.maxFeeRate;
|
||||
|
||||
if (rate < 0)
|
||||
return 0;
|
||||
|
||||
@ -775,9 +776,6 @@ PolicyEstimator.prototype.estimatePriority = function estimatePriority(target, s
|
||||
return Math.floor(priority);
|
||||
}
|
||||
|
||||
// TODO: Add check for mempool limiting txs.
|
||||
// Should return INF_PRIORITY.
|
||||
|
||||
priority = -1;
|
||||
while (priority < 0 && target <= this.priStats.maxConfirms) {
|
||||
priority = this.priStats.estimateMedian(
|
||||
@ -800,7 +798,7 @@ PolicyEstimator.prototype.estimatePriority = function estimatePriority(target, s
|
||||
|
||||
PolicyEstimator.prototype.getSize = function getSize() {
|
||||
var size = 0;
|
||||
size += 8;
|
||||
size += 4;
|
||||
size += encoding.sizeVarlen(this.feeStats.getSize());
|
||||
size += encoding.sizeVarlen(this.priStats.getSize());
|
||||
return size;
|
||||
@ -815,7 +813,6 @@ PolicyEstimator.prototype.toRaw = function toRaw() {
|
||||
var size = this.getSize();
|
||||
var bw = new StaticWriter(size);
|
||||
|
||||
bw.writeU32(this.network.magic);
|
||||
bw.writeU32(this.bestHeight);
|
||||
bw.writeVarBytes(this.feeStats.toRaw());
|
||||
bw.writeVarBytes(this.priStats.toRaw());
|
||||
@ -832,13 +829,8 @@ PolicyEstimator.prototype.toRaw = function toRaw() {
|
||||
|
||||
PolicyEstimator.prototype.fromRaw = function fromRaw(data) {
|
||||
var br = new BufferReader(data);
|
||||
var network = Network.fromMagic(br.readU32());
|
||||
var bestHeight = br.readU32();
|
||||
|
||||
assert(this.network === network,
|
||||
'Network mistmatch for policy estimator.');
|
||||
|
||||
this.bestHeight = bestHeight;
|
||||
this.bestHeight = br.readU32();
|
||||
this.feeStats.fromRaw(br.readVarBytes());
|
||||
this.priStats.fromRaw(br.readVarBytes());
|
||||
|
||||
@ -848,13 +840,12 @@ PolicyEstimator.prototype.fromRaw = function fromRaw(data) {
|
||||
/**
|
||||
* Instantiate a policy estimator from serialized data.
|
||||
* @param {Buffer} data
|
||||
* @param {Network?} network
|
||||
* @param {Logger?} logger
|
||||
* @returns {PolicyEstimator}
|
||||
*/
|
||||
|
||||
PolicyEstimator.fromRaw = function fromRaw(data, network, logger) {
|
||||
return new PolicyEstimator(network, logger).fromRaw(data);
|
||||
PolicyEstimator.fromRaw = function fromRaw(data, logger) {
|
||||
return new PolicyEstimator(logger).fromRaw(data);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -864,13 +855,9 @@ PolicyEstimator.fromRaw = function fromRaw(data, network, logger) {
|
||||
*/
|
||||
|
||||
PolicyEstimator.prototype.inject = function inject(estimator) {
|
||||
assert(this.network === estimator.network,
|
||||
'Network mismatch for policy estimator.');
|
||||
|
||||
this.bestHeight = estimator.bestHeight;
|
||||
this.feeStats = estimator.feeStats;
|
||||
this.priStats = estimator.priStats;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
@ -2330,7 +2330,7 @@ MempoolCache.prototype.getFees = co(function* getFees() {
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
return Fees.fromRaw(data, this.network);
|
||||
return Fees.fromRaw(data);
|
||||
});
|
||||
|
||||
MempoolCache.prototype.getEntries = function getEntries() {
|
||||
|
||||
@ -63,7 +63,7 @@ function FullNode(options) {
|
||||
});
|
||||
|
||||
// Fee estimation.
|
||||
this.fees = new Fees(this.network, this.logger);
|
||||
this.fees = new Fees(this.logger);
|
||||
this.fees.init();
|
||||
|
||||
// Mempool needs access to the chain.
|
||||
|
||||
@ -477,10 +477,20 @@ WalletDB.prototype.send = co(function* send(tx) {
|
||||
*/
|
||||
|
||||
WalletDB.prototype.estimateFee = co(function* estimateFee(blocks) {
|
||||
var rate;
|
||||
|
||||
if (!this.client)
|
||||
return this.network.feeRate;
|
||||
|
||||
return yield this.client.estimateFee(blocks);
|
||||
rate = yield this.client.estimateFee(blocks);
|
||||
|
||||
if (rate < this.network.feeRate)
|
||||
return this.network.feeRate;
|
||||
|
||||
if (rate > this.network.maxFeeRate)
|
||||
return this.network.maxFeeRate;
|
||||
|
||||
return rate;
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user