fees. mempool. createTX.

This commit is contained in:
Christopher Jeffrey 2016-06-15 17:02:12 -07:00
parent 7383971a75
commit 6303530c4f
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
7 changed files with 69 additions and 49 deletions

View File

@ -680,11 +680,6 @@ Iterator.prototype.seek = function seek(key) {
this.index = utils.binarySearch(this.items, key, function(a, b) {
return self.tree.compare(a.key, b);
}, true);
item = this.items[this.index];
if (!item || this.tree.compare(item.key, key) !== 0)
this.index += 1;
};
Iterator.prototype._end = function end() {

View File

@ -9,6 +9,8 @@
'use strict';
var bcoin = require('./env');
var utils = bcoin.utils;
var assert = require('assert');
var constants = bcoin.protocol.constants;
var global = bcoin.utils.global;
var Float64Array = global.Float64Array || Array;
@ -55,11 +57,11 @@ function ConfirmStats(buckets, maxConfirms, decay, type) {
this.type = type;
this.buckets = new Float64Array(buckets.length);
this.bucketMap = {};
this.bucketMap = new DoubleMap();
for (i = 0; i < buckets.length; i++) {
this.buckets[i] = buckets[i];
this.bucketMap[buckets[i]] = i;
this.bucketMap.insert(buckets[i], i);
}
this.confAvg = new Array(maxConfirms);
@ -109,7 +111,7 @@ ConfirmStats.prototype.record = function record(blocks, val) {
if (blocks < 1)
return;
bucketIndex = this.bucketMap[val];
bucketIndex = this.bucketMap.search(val);
for (i = blocks; i <= this.curBlockConf.length; i++)
this.curBlockConf[i - 1][bucketIndex]++;
@ -210,9 +212,10 @@ ConfirmStats.prototype.estimateMedian = function estimateMedian(target, needed,
}
}
// bcoin.debug('estimatefee: target=%d.'
// + ' For conf success %s %d need %s %s: %d from buckets %d - %d.'
// + ' Cur Bucket stats %d% %d/%d (%d mempool).',
// bcoin.debug('estimatefee: '
// + ' For confirmation success in %d blocks'
// + ' %s %d need %s %s: %d from buckets %d - %d.'
// + ' Current bucket stats %d% %d/%d (%d mempool).',
// target,
// greater ? '>' : '<',
// breakpoint,
@ -237,10 +240,10 @@ ConfirmStats.prototype.estimateMedian = function estimateMedian(target, needed,
*/
ConfirmStats.prototype.addTX = function addTX(height, val) {
var bucketIndex = this.bucketMap[val];
var bucketIndex = this.bucketMap.search(val);
var blockIndex = height % this.unconfTX.length;
this.unconfTX[blockIndex][bucketIndex]++;
bcoin.debug('estimatefee: Adding TX to %s.', this.type);
bcoin.debug('estimatefee: Adding tx to %s.', this.type);
return bucketIndex;
};
@ -268,7 +271,7 @@ ConfirmStats.prototype.removeTX = function removeTX(entryHeight, bestHeight, buc
this.oldUnconfTX[bucketIndex]--;
} else {
bcoin.debug('estimatefee:'
+ ' Mempool tx removed from >25 blocks,bucketIndex=%d already.',
+ ' Mempool tx removed >25 blocks (bucket=%d).',
bucketIndex);
}
} else {
@ -277,7 +280,7 @@ ConfirmStats.prototype.removeTX = function removeTX(entryHeight, bestHeight, buc
this.unconfTX[blockIndex][bucketIndex]--;
} else {
bcoin.debug('estimatefee:'
+ ' Mempool tx removed from blockIndex=%d,bucketIndex=%d already.',
+ ' Mempool tx removed (block=%d, bucket=%d).',
blockIndex, bucketIndex);
}
}
@ -352,7 +355,7 @@ PolicyEstimator.prototype.removeTX = function removeTX(hash) {
var item = this.map[hash];
if (!item) {
bcoin.debug('estimatefee: mempool tx %s not found.', hash);
bcoin.debug('estimatefee: Mempool tx %s not found.', hash);
return;
}
@ -437,7 +440,7 @@ PolicyEstimator.prototype.processTX = function processTX(entry, current) {
};
bcoin.debug('estimatefee: Rate: %d.', this.estimateFee());
} else {
bcoin.debug('estimatefee: Not adding ts %s.', hash);
bcoin.debug('estimatefee: Not adding tx %s.', hash);
}
};
@ -457,7 +460,11 @@ PolicyEstimator.prototype.processBlockTX = function processBlockTX(height, entry
blocks = height - entry.height;
if (blocks <= 0) {
bcoin.debug('estimatefee: TX had negative blocks to confirm.');
bcoin.debug(
'estimatefee: Block tx %s had negative blocks to confirm (%d, %d).',
entry.tx.hash('hex'),
height,
entry.height);
return;
}
@ -632,6 +639,37 @@ PolicyEstimator.prototype.estimatePriority = function estimatePriority(target, s
return priority;
};
/**
* DoubleMap
* @private
*/
function DoubleMap() {
if (!(this instanceof DoubleMap))
return new DoubleMap();
this.buckets = [];
}
DoubleMap.prototype.insert = function insert(key, value) {
var i = utils.binarySearch(this.buckets, key, compare, true);
this.buckets.splice(i, 0, [key, value]);
};
DoubleMap.prototype.search = function search(key) {
var i = utils.binarySearch(this.buckets, key, compare, true);
assert(this.buckets.length !== 0, 'Cannot search.');
return this.buckets[i][1];
};
/*
* Helpers
*/
function compare(a, b) {
return a[0] - b;
}
/*
* Expose
*/

View File

@ -414,12 +414,8 @@ HTTPServer.prototype._init = function _init() {
this.post('/wallet/:id/send', function(req, res, next, send) {
var id = req.options.id;
var options = req.options;
var outputs = req.options.outputs;
if (!Array.isArray(outputs))
return send(400);
self.walletdb.createTX(id, options, outputs, function(err, tx) {
self.walletdb.createTX(id, options, function(err, tx) {
if (err)
return next(err);

View File

@ -727,8 +727,12 @@ Mempool.prototype.addTX = function addTX(tx, callback, force) {
}
if (this.requireStandard) {
if (!tx.isStandard(flags, ret))
return callback(new VerifyError(tx, ret.reason, 0));
if (!tx.isStandard(flags, ret)) {
return callback(new VerifyError(tx,
'nonstandard',
ret.reason,
0));
}
if (!this.chain.csvActive && tx.version >= 2) {
return callback(new VerifyError(tx,

View File

@ -1371,7 +1371,7 @@ TX.prototype.checkInputs = function checkInputs(spendHeight, ret) {
input = this.inputs[i];
coin = input.coin;
if (coin.coinbase) {
if (coin.coinbase && spendHeight != null) {
if (spendHeight - coin.height < constants.tx.COINBASE_MATURITY) {
ret.reason = 'bad-txns-premature-spend-of-coinbase';
ret.score = 0;

View File

@ -2415,7 +2415,7 @@ utils.binarySearch = function binarySearch(items, key, compare, insert) {
if (!insert)
return -1;
return start - 1;
return start;
};
/**
@ -2428,7 +2428,7 @@ utils.binarySearch = function binarySearch(items, key, compare, insert) {
utils.binaryInsert = function binaryInsert(items, item, compare) {
var i = utils.binarySearch(items, item, compare, true);
items.splice(i + 1, 0, item);
items.splice(i, 0, item);
return items.length;
};

View File

@ -592,34 +592,21 @@ Wallet.prototype.fill = function fill(tx, options, callback) {
* sort the members according to BIP69, set locktime,
* and sign it (accesses db).
* @param {Object} options - See {@link Wallet#fill options}.
* @param {Object[]} outputs - See {@link Script.createOutputScript}.
* @param {Object[]} options.outputs - See {@link Script.createOutputScript}.
* @param {Function} callback - Returns [Error, {@link MTX}].
*/
Wallet.prototype.createTX = function createTX(options, outputs, callback) {
Wallet.prototype.createTX = function createTX(options, callback) {
var self = this;
var height = 0xffffffff;
var tx, i;
if (typeof outputs === 'function') {
callback = outputs;
outputs = null;
}
if (!outputs) {
outputs = options;
options = {};
}
if (!Array.isArray(outputs))
outputs = [outputs];
if (options.height >= 0)
height = options.height;
var outputs = options.outputs || [];
var i, tx;
// Create mutable tx
tx = bcoin.mtx();
if (outputs.length === 0)
outputs.push(options);
// Add the outputs
for (i = 0; i < outputs.length; i++) {
try {
@ -648,7 +635,7 @@ Wallet.prototype.createTX = function createTX(options, outputs, callback) {
if (!tx.isSane())
return callback(new Error('CheckTransaction failed.'));
if (!tx.checkInputs(height))
if (!tx.checkInputs(options.height))
return callback(new Error('CheckInputs failed.'));
self.scriptInputs(tx, function(err, total) {