diff --git a/lib/mempool/fees.js b/lib/mempool/fees.js index 98fd6a17..792b4ef4 100644 --- a/lib/mempool/fees.js +++ b/lib/mempool/fees.js @@ -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; }; diff --git a/lib/mempool/mempool.js b/lib/mempool/mempool.js index 221fd82f..bbf92f8c 100644 --- a/lib/mempool/mempool.js +++ b/lib/mempool/mempool.js @@ -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() { diff --git a/lib/node/fullnode.js b/lib/node/fullnode.js index d736d073..d85b8c6f 100644 --- a/lib/node/fullnode.js +++ b/lib/node/fullnode.js @@ -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. diff --git a/lib/wallet/walletdb.js b/lib/wallet/walletdb.js index a66e392f..a6d0eadb 100644 --- a/lib/wallet/walletdb.js +++ b/lib/wallet/walletdb.js @@ -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; }); /**