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) { this.index = utils.binarySearch(this.items, key, function(a, b) {
return self.tree.compare(a.key, b); return self.tree.compare(a.key, b);
}, true); }, true);
item = this.items[this.index];
if (!item || this.tree.compare(item.key, key) !== 0)
this.index += 1;
}; };
Iterator.prototype._end = function end() { Iterator.prototype._end = function end() {

View File

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

View File

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

View File

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

View File

@ -1371,7 +1371,7 @@ TX.prototype.checkInputs = function checkInputs(spendHeight, ret) {
input = this.inputs[i]; input = this.inputs[i];
coin = input.coin; coin = input.coin;
if (coin.coinbase) { 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';
ret.score = 0; ret.score = 0;

View File

@ -2415,7 +2415,7 @@ utils.binarySearch = function binarySearch(items, key, compare, insert) {
if (!insert) if (!insert)
return -1; 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) { utils.binaryInsert = function binaryInsert(items, item, compare) {
var i = utils.binarySearch(items, item, compare, true); var i = utils.binarySearch(items, item, compare, true);
items.splice(i + 1, 0, item); items.splice(i, 0, item);
return items.length; 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, * sort the members according to BIP69, set locktime,
* and sign it (accesses db). * and sign it (accesses db).
* @param {Object} options - See {@link Wallet#fill options}. * @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}]. * @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 self = this;
var height = 0xffffffff; var outputs = options.outputs || [];
var tx, i; var i, tx;
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;
// Create mutable tx // Create mutable tx
tx = bcoin.mtx(); tx = bcoin.mtx();
if (outputs.length === 0)
outputs.push(options);
// Add the outputs // Add the outputs
for (i = 0; i < outputs.length; i++) { for (i = 0; i < outputs.length; i++) {
try { try {
@ -648,7 +635,7 @@ Wallet.prototype.createTX = function createTX(options, outputs, callback) {
if (!tx.isSane()) if (!tx.isSane())
return callback(new Error('CheckTransaction failed.')); return callback(new Error('CheckTransaction failed.'));
if (!tx.checkInputs(height)) if (!tx.checkInputs(options.height))
return callback(new Error('CheckInputs failed.')); return callback(new Error('CheckInputs failed.'));
self.scriptInputs(tx, function(err, total) { self.scriptInputs(tx, function(err, total) {