Added cache miss function for input values.

This commit is contained in:
Chris Kleeschulte 2017-08-08 14:45:13 -04:00
parent 5ff8e7c6c1
commit a8d709caf6
3 changed files with 73 additions and 8 deletions

View File

@ -202,8 +202,7 @@ P2P.prototype._hasPeers = function() {
};
P2P.prototype._initCache = function() {
this._inv = LRU(2000);
this._cache = [];
this._inv = LRU(1000);
};
P2P.prototype._initP2P = function() {
@ -332,7 +331,7 @@ P2P.prototype._setResourceFilter = function(filter, resource) {
};
P2P.prototype._startBcoin = function() {
const network = ['livenet', 'live', 'main', 'mainnet'].indexOf(this.node.network) !== -1? 'main' : 'testnet'
const network = ['livenet', 'live', 'main', 'mainnet'].indexOf(this.node.network) !== -1? 'main' : 'testnet';
this._bcoin = new Bcoin({
network: network,
prefix: this.node.datadir

View File

@ -8,6 +8,8 @@ var _ = require('lodash');
var LRU = require('lru-cache');
var Unit = require('bitcore-lib').Unit;
var log = require('../../index').log;
var async = require('async');
var assert = require('assert');
function TransactionService(options) {
BaseService.call(this, options);
@ -16,7 +18,7 @@ function TransactionService(options) {
this._block = this.node.services.block;
this._p2p = this.node.services.p2p;
this._timestamp = this.node.services.timestamp;
this._inputValuesCache = LRU(1E6); // this should speed up syncing
this._inputValuesCache = LRU(500000); // this should speed up syncing
}
inherits(TransactionService, BaseService);
@ -48,9 +50,11 @@ TransactionService.prototype.getTransaction = function(txid, options, callback)
var self = this;
var _tx;
var queryMempool = _.isUndefined(options.queryMempool) ? true : options.queryMempool;
var key = self.encoding.encodeTransactionKey(txid);
self._db.get(key, function(err, tx) {
if(err) {
@ -67,9 +71,8 @@ TransactionService.prototype.getTransaction = function(txid, options, callback)
if (memTx) {
memTx.confirmations = 0;
return callback(null, memTx);
_tx = memTx;
}
return callback();
});
@ -77,16 +80,61 @@ TransactionService.prototype.getTransaction = function(txid, options, callback)
if (tx) {
tx.confirmations = self._p2p.getBestHeight - tx.__height;
return callback(null, tx);
_tx = tx;
}
return callback();
}
if (!_tx) {
return callback();
}
// TODO: this could cause crazy amounts of recursion if input values are missing from the entire chain of txs
self._addMissingInputValues(_tx, callback);
});
};
TransactionService.prototype._addMissingInputValues = function(tx, callback) {
// if we have cache misses from when we populated input values,
// then we must go and find them after the fact (lazy-load).
var self = this;
async.eachOfLimit(tx.inputs, 4, function(input, index, next) {
var inputSatoshis = tx.__inputValues[index];
if (inputSatoshis >= 0) {
return next();
}
var outputIndex = input.prevout.index;
self.getTransaction(input.prevout.txid(), function(err, _tx) {
if (err || !_tx) {
return next(err || new Error('tx not found for tx id: ' + input.prevout.txid()));
}
var output = _tx.outputs[outputIndex];
assert(output, 'Expected an output, but did not get one for tx: ' + _tx.txid() + ' outputIndex: ' + outputIndex);
tx.__inputValues[index] = Unit.fromBTC(output.value).toSatoshis();
next();
});
}, function(err) {
if (err) {
return callback(err);
}
callback(null, tx);
});
};
TransactionService.prototype.sendTransaction = function(tx, callback) {
this._p2p.sendTransaction(tx, callback);
};
@ -216,6 +264,10 @@ TransactionService.prototype._processTransaction = function(tx, opts) {
// input values
tx.__inputValues = this._getInputValues(tx); //if there are any nulls here, this is a cache miss
if (_.compact(tx.__inputValues).length < tx.inputs.length) {
log.debug('Transaction Service: Cache miss for tx id: ' + tx.txid());
}
//timestamp
tx.__timestamp = this._getBlockTimestamp(opts.block.rhash());
//height

View File

@ -122,4 +122,18 @@ describe('Transaction Service', function() {
});
});
describe('#_addMissingInputValues', function() {
it('should add missing input values on a tx', function(done) {
sandbox.stub(txService, 'getTransaction').callsArgWith(1, null, tx);
tx.__inputValues = [];
txService._addMissingInputValues(tx, function(err, tx) {
if (err) {
return done(err);
}
tx.__inputValues.should.deep.equal([113903300000000, 113903300000000, 50000000000000, 113903300000000 ]);
done();
});
});
});
});