fees. mempool. createTX.
This commit is contained in:
parent
7383971a75
commit
6303530c4f
@ -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() {
|
||||||
|
|||||||
@ -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
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user