diff --git a/lib/services/address/index.js b/lib/services/address/index.js index 22c2420f..829d8414 100644 --- a/lib/services/address/index.js +++ b/lib/services/address/index.js @@ -44,12 +44,10 @@ var AddressService = function(options) { this.node.services.bitcoind.on('tx', this.transactionHandler.bind(this)); this.node.services.bitcoind.on('txleave', this.transactionLeaveHandler.bind(this)); - this.summaryCacheThreshold = options.summaryCacheThreshold || constants.SUMMARY_CACHE_THRESHOLD; this.maxInputsQueryLength = options.maxInputsQueryLength || constants.MAX_INPUTS_QUERY_LENGTH; this.maxOutputsQueryLength = options.maxOutputsQueryLength || constants.MAX_OUTPUTS_QUERY_LENGTH; this._setMempoolIndexPath(); - this._setSummaryCachePath(); if (options.mempoolMemoryIndex) { this.levelupStore = memdown; } else { @@ -98,19 +96,6 @@ AddressService.prototype.start = function(callback) { }, next ); - }, - function(next) { - self.summaryCache = levelup( - self.summaryCachePath, - { - db: self.levelupStore, - keyEncoding: 'binary', - valueEncoding: 'binary', - fillCache: false, - maxOpenFiles: 200 - }, - next - ); } ], callback); @@ -121,14 +106,6 @@ AddressService.prototype.stop = function(callback) { this.mempoolIndex.close(callback); }; -/** - * This function will set `this.summaryCachePath` based on `this.node.network`. - * @private - */ -AddressService.prototype._setSummaryCachePath = function() { - this.summaryCachePath = this._getDBPathFor('bitcore-addresssummary.db'); -}; - /** * This function will set `this.mempoolIndexPath` based on `this.node.network`. * @private @@ -1357,21 +1334,20 @@ AddressService.prototype.getAddressSummary = function(addressArg, options, callb function(next) { self._getAddressConfirmedSummary(address, options, next); }, - function(cache, next) { - self._getAddressMempoolSummary(address, options, cache, next); + function(result, next) { + self._getAddressMempoolSummary(address, options, result, next); } - ], function(err, cache) { + ], function(err, result) { if (err) { return callback(err); } - var summary = self._transformAddressSummaryFromCache(cache, options); + var summary = self._transformAddressSummaryFromCache(result, options); var timeDelta = new Date() - startTime; if (timeDelta > 5000) { var seconds = Math.round(timeDelta / 1000); log.warn('Slow (' + seconds + 's) getAddressSummary request for address: ' + address.toString()); - log.warn('Address Summary:', summary); } callback(null, summary); @@ -1382,108 +1358,48 @@ AddressService.prototype.getAddressSummary = function(addressArg, options, callb AddressService.prototype._getAddressConfirmedSummary = function(address, options, callback) { var self = this; - var tipHeight = this.node.services.db.tip.__height; - - self._getAddressConfirmedSummaryCache(address, options, function(err, cache) { - if (err) { - return callback(err); - } - // Immediately give cache is already current, otherwise update - if (cache && cache.height === tipHeight) { - return callback(null, cache); - } - self._updateAddressConfirmedSummaryCache(address, options, cache, tipHeight, callback); - }); -}; - -AddressService.prototype._getAddressConfirmedSummaryCache = function(address, options, callback) { - var self = this; - var baseCache = { - result: { - appearanceIds: {}, - totalReceived: 0, - balance: 0, - unconfirmedAppearanceIds: {}, - unconfirmedBalance: 0 - } + var baseResult = { + appearanceIds: {}, + totalReceived: 0, + balance: 0, + unconfirmedAppearanceIds: {}, + unconfirmedBalance: 0 }; - // Use the base cache if the "start" and "end" options have been used - // We only save and retrieve a cache for the summary of all history - if (options.start >= 0 || options.end >= 0) { - return callback(null, baseCache); - } - var key = encoding.encodeSummaryCacheKey(address); - this.summaryCache.get(key, { - valueEncoding: 'binary', - keyEncoding: 'binary' - }, function(err, buffer) { - if (err instanceof levelup.errors.NotFoundError) { - return callback(null, baseCache); - } else if (err) { - return callback(err); - } - var cache = encoding.decodeSummaryCacheValue(buffer); - - // Use base cache if the cached tip/height doesn't match (e.g. there has been a reorg) - var blockIndex = self.node.services.bitcoind.getBlockIndex(cache.height); - if (cache.hash !== blockIndex.hash) { - return callback(null, baseCache); - } - - callback(null, cache); - }); -}; - -AddressService.prototype._updateAddressConfirmedSummaryCache = function(address, options, cache, tipHeight, callback) { - var self = this; - - var optionsPartial = _.clone(options); - var isHeightQuery = (options.start >= 0 || options.end >= 0); - if (!isHeightQuery) { - // We will pick up from the last point cached and query for all blocks - // proceeding the cache - var cacheHeight = _.isUndefined(cache.height) ? 0 : cache.height + 1; - optionsPartial.start = tipHeight; - optionsPartial.end = cacheHeight; - } else { - $.checkState(_.isUndefined(cache.height)); - } async.waterfall([ function(next) { - self._getAddressConfirmedInputsSummary(address, cache, optionsPartial, next); + self._getAddressConfirmedInputsSummary(address, baseResult, options, next); }, - function(cache, next) { - self._getAddressConfirmedOutputsSummary(address, cache, optionsPartial, next); + function(result, next) { + self._getAddressConfirmedOutputsSummary(address, result, options, next); }, - function(cache, next) { - self._setAndSortTxidsFromAppearanceIds(cache, next); + function(result, next) { + self._setAndSortTxidsFromAppearanceIds(result, next); } - ], function(err, cache) { + ], callback); - // Skip saving the cache if the "start" or "end" options have been used, or - // if the transaction length does not exceed the caching threshold. - // We only want to cache full history results for addresses that have a large - // number of transactions. - var exceedsCacheThreshold = (cache.result.txids.length > self.summaryCacheThreshold); - if (exceedsCacheThreshold && !isHeightQuery) { - self._saveAddressConfirmedSummaryCache(address, cache, tipHeight, callback); - } else { - callback(null, cache); - } - - }); }; -AddressService.prototype._getAddressConfirmedInputsSummary = function(address, cache, options, callback) { +AddressService.prototype._getAddressConfirmedInputsSummary = function(address, result, options, callback) { $.checkArgument(address instanceof Address); var self = this; var error = null; + var count = 0; var inputsStream = self.createInputsStream(address, options); inputsStream.on('data', function(input) { var txid = input.txid; - cache.result.appearanceIds[txid] = input.height; + result.appearanceIds[txid] = input.height; + + count++; + + if (count > self.maxInputsQueryLength) { + log.warn('Tried to query too many inputs (' + self.maxInputsQueryLength + ') for summary of address ' + address.toString()); + error = new Error('Maximum number of inputs (' + self.maxInputsQueryLength + ') per query reached'); + inputsStream.pause(); + inputsStream.end(); + } + }); inputsStream.on('error', function(err) { @@ -1494,17 +1410,18 @@ AddressService.prototype._getAddressConfirmedInputsSummary = function(address, c if (error) { return callback(error); } - callback(null, cache); + callback(null, result); }); }; -AddressService.prototype._getAddressConfirmedOutputsSummary = function(address, cache, options, callback) { +AddressService.prototype._getAddressConfirmedOutputsSummary = function(address, result, options, callback) { $.checkArgument(address instanceof Address); - $.checkArgument(!_.isUndefined(cache.result) && - !_.isUndefined(cache.result.appearanceIds) && - !_.isUndefined(cache.result.unconfirmedAppearanceIds)); + $.checkArgument(!_.isUndefined(result) && + !_.isUndefined(result.appearanceIds) && + !_.isUndefined(result.unconfirmedAppearanceIds)); var self = this; + var count = 0; var outputStream = self.createOutputsStream(address, options); @@ -1515,13 +1432,12 @@ AddressService.prototype._getAddressConfirmedOutputsSummary = function(address, // Bitcoind's isSpent only works for confirmed transactions var spentDB = self.node.services.bitcoind.isSpent(txid, outputIndex); - cache.result.totalReceived += output.satoshis; - cache.result.appearanceIds[txid] = output.height; + result.totalReceived += output.satoshis; + result.appearanceIds[txid] = output.height; if (!spentDB) { - cache.result.balance += output.satoshis; + result.balance += output.satoshis; } - // TODO: subtract if spent (because of cache)? if (options.queryMempool) { // Check to see if this output is spent in the mempool and if so @@ -1532,10 +1448,19 @@ AddressService.prototype._getAddressConfirmedOutputsSummary = function(address, ); var spentMempool = self.mempoolSpentIndex[spentIndexSyncKey]; if (spentMempool) { - cache.result.unconfirmedBalance -= output.satoshis; + result.unconfirmedBalance -= output.satoshis; } } + count++; + + if (count > self.maxOutputsQueryLength) { + log.warn('Tried to query too many outputs (' + self.maxOutputsQueryLength + ') for summary of address ' + address.toString()); + error = new Error('Maximum number of outputs (' + self.maxOutputsQueryLength + ') per query reached'); + outputStream.pause(); + outputStream.end(); + } + }); var error = null; @@ -1548,40 +1473,25 @@ AddressService.prototype._getAddressConfirmedOutputsSummary = function(address, if (error) { return callback(error); } - callback(null, cache); + callback(null, result); }); }; -AddressService.prototype._setAndSortTxidsFromAppearanceIds = function(cache, callback) { - cache.result.txids = Object.keys(cache.result.appearanceIds); - cache.result.txids.sort(function(a, b) { - return cache.result.appearanceIds[a] - cache.result.appearanceIds[b]; +AddressService.prototype._setAndSortTxidsFromAppearanceIds = function(result, callback) { + result.txids = Object.keys(result.appearanceIds); + result.txids.sort(function(a, b) { + return result.appearanceIds[a] - result.appearanceIds[b]; }); - callback(null, cache); + callback(null, result); }; -AddressService.prototype._saveAddressConfirmedSummaryCache = function(address, cache, tipHeight, callback) { - - log.info('Saving address summary cache for: ' + address.toString() + 'at height: ' + tipHeight); - var key = encoding.encodeSummaryCacheKey(address); - var tipBlockIndex = this.node.services.bitcoind.getBlockIndex(tipHeight); - var value = encoding.encodeSummaryCacheValue(cache, tipHeight, tipBlockIndex.hash); - this.summaryCache.put(key, value, function(err) { - if (err) { - return callback(err); - } - callback(null, cache); - }); - -}; - -AddressService.prototype._getAddressMempoolSummary = function(address, options, cache, callback) { +AddressService.prototype._getAddressMempoolSummary = function(address, options, result, callback) { var self = this; // Skip if the options do not want to include the mempool if (!options.queryMempool) { - return callback(null, cache); + return callback(null, result); } var addressStr = address.toString(); @@ -1596,12 +1506,12 @@ AddressService.prototype._getAddressMempoolSummary = function(address, options, } for(var i = 0; i < mempoolInputs.length; i++) { var input = mempoolInputs[i]; - cache.result.unconfirmedAppearanceIds[input.txid] = input.timestamp; + result.unconfirmedAppearanceIds[input.txid] = input.timestamp; } - next(null, cache); + next(null, result); }); - }, function(cache, next) { + }, function(result, next) { self._getOutputsMempool(addressStr, hashBuffer, hashTypeBuffer, function(err, mempoolOutputs) { if (err) { return next(err); @@ -1609,7 +1519,7 @@ AddressService.prototype._getAddressMempoolSummary = function(address, options, for(var i = 0; i < mempoolOutputs.length; i++) { var output = mempoolOutputs[i]; - cache.result.unconfirmedAppearanceIds[output.txid] = output.timestamp; + result.unconfirmedAppearanceIds[output.txid] = output.timestamp; var spentIndexSyncKey = encoding.encodeSpentIndexSyncKey( new Buffer(output.txid, 'hex'), // TODO: get buffer directly @@ -1618,19 +1528,18 @@ AddressService.prototype._getAddressMempoolSummary = function(address, options, var spentMempool = self.mempoolSpentIndex[spentIndexSyncKey]; // Only add this to the balance if it's not spent in the mempool already if (!spentMempool) { - cache.result.unconfirmedBalance += output.satoshis; + result.unconfirmedBalance += output.satoshis; } } - next(null, cache); + next(null, result); }); } ], callback); }; -AddressService.prototype._transformAddressSummaryFromCache = function(cache, options) { +AddressService.prototype._transformAddressSummaryFromCache = function(result, options) { - var result = cache.result; - var confirmedTxids = cache.result.txids; + var confirmedTxids = result.txids; var unconfirmedTxids = Object.keys(result.unconfirmedAppearanceIds); var summary = { diff --git a/test/services/address/index.unit.js b/test/services/address/index.unit.js index 193a9f8a..a50f121b 100644 --- a/test/services/address/index.unit.js +++ b/test/services/address/index.unit.js @@ -100,7 +100,7 @@ describe('Address Service', function() { done(); }); }); - it('start levelup db for mempool and summary index', function(done) { + it('start levelup db for mempool', function(done) { var levelupStub = sinon.stub().callsArg(2); var TestAddressService = proxyquire('../../../lib/services/address', { 'fs': { @@ -117,7 +117,7 @@ describe('Address Service', function() { node: mocknode }); am.start(function() { - levelupStub.callCount.should.equal(2); + levelupStub.callCount.should.equal(1); var dbPath1 = levelupStub.args[0][0]; dbPath1.should.equal('testdir/testnet3/bitcore-addressmempool.db'); var options = levelupStub.args[0][1]; @@ -125,8 +125,6 @@ describe('Address Service', function() { options.keyEncoding.should.equal('binary'); options.valueEncoding.should.equal('binary'); options.fillCache.should.equal(false); - var dbPath2 = levelupStub.args[1][0]; - dbPath2.should.equal('testdir/testnet3/bitcore-addresssummary.db'); done(); }); }); @@ -2115,457 +2113,14 @@ describe('Address Service', function() { addressService._getAddressMempoolSummary = sinon.stub().callsArgWith(3, null, cache); addressService._transformAddressSummaryFromCache = sinon.stub().returns(summary); addressService.getAddressSummary(address, options, function() { - log.warn.callCount.should.equal(2); + log.warn.callCount.should.equal(1); done(); }); clock.tick(6000); }); }); - describe('#_getAddressConfirmedSummary', function() { - it('handle error from _getAddressConfirmedSummaryCache', function(done) { - var testnode = { - services: { - bitcoind: { - on: sinon.stub() - }, - db: { - tip: { - __height: 10 - } - } - }, - datadir: 'testdir' - }; - var addressService = new AddressService({ - mempoolMemoryIndex: true, - node: testnode - }); - var address = '12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX'; - var options = {}; - addressService._getAddressConfirmedSummaryCache = sinon.stub().callsArgWith(2, new Error('test')); - addressService._getAddressConfirmedSummary(address, options, function(err) { - should.exist(err); - err.message.should.equal('test'); - done(); - }); - }); - - it('will NOT update cache if matches current tip', function(done) { - var testnode = { - services: { - bitcoind: { - on: sinon.stub() - }, - db: { - tip: { - __height: 10 - } - } - }, - datadir: 'testdir' - }; - var addressService = new AddressService({ - mempoolMemoryIndex: true, - node: testnode - }); - var address = '12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX'; - var options = {}; - var cache = { - height: 10 - }; - addressService._updateAddressConfirmedSummaryCache = sinon.stub(); - addressService._getAddressConfirmedSummaryCache = sinon.stub().callsArgWith(2, null, cache); - addressService._getAddressConfirmedSummary(address, options, function(err, cache) { - if (err) { - return done(err); - } - should.exist(cache); - addressService._updateAddressConfirmedSummaryCache.callCount.should.equal(0); - done(); - }); - }); - - it('will call _updateAddressConfirmedSummaryCache with correct arguments', function(done) { - var testnode = { - services: { - bitcoind: { - on: sinon.stub() - }, - db: { - tip: { - __height: 11 - } - } - }, - datadir: 'testdir' - }; - var addressService = new AddressService({ - mempoolMemoryIndex: true, - node: testnode - }); - var address = '12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX'; - var options = {}; - var cache = { - height: 10 - }; - addressService._updateAddressConfirmedSummaryCache = sinon.stub().callsArgWith(4, null, cache); - addressService._getAddressConfirmedSummaryCache = sinon.stub().callsArgWith(2, null, cache); - addressService._getAddressConfirmedSummary(address, options, function(err, cache) { - if (err) { - return done(err); - } - should.exist(cache); - addressService._updateAddressConfirmedSummaryCache.callCount.should.equal(1); - var args = addressService._updateAddressConfirmedSummaryCache.args[0]; - args[0].should.equal(address); - args[1].should.equal(options); - args[2].should.equal(cache); - args[3].should.equal(11); - done(); - }); - }); - }); - - describe('#_getAddressConfirmedSummaryCache', function() { - function shouldExistBasecache(cache) { - should.exist(cache); - should.not.exist(cache.height); - should.exist(cache.result); - cache.result.appearanceIds.should.deep.equal({}); - cache.result.totalReceived.should.equal(0); - cache.result.balance.should.equal(0); - cache.result.unconfirmedAppearanceIds.should.deep.equal({}); - cache.result.unconfirmedBalance.should.equal(0); - } - it('give base cache if "start" or "end" options are used (e.g. >= 0)', function(done) { - var testnode = { - services: { - bitcoind: { - on: sinon.stub(), - } - }, - datadir: 'testdir' - }; - var addressService = new AddressService({ - mempoolMemoryIndex: true, - node: testnode - }); - var address = new bitcore.Address('12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX'); - var options = { - start: 0, - end: 0 - }; - addressService._getAddressConfirmedSummaryCache(address, options, function(err, cache) { - if (err) { - return done(err); - } - shouldExistBasecache(cache); - done(); - }); - }); - it('give base cache if "start" or "end" options are used (e.g. 10, 9)', function(done) { - var testnode = { - services: { - bitcoind: { - on: sinon.stub(), - } - }, - datadir: 'testdir' - }; - var addressService = new AddressService({ - mempoolMemoryIndex: true, - node: testnode - }); - var address = new bitcore.Address('12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX'); - var options = { - start: 10, - end: 9 - }; - addressService._getAddressConfirmedSummaryCache(address, options, function(err, cache) { - if (err) { - return done(err); - } - shouldExistBasecache(cache); - done(); - }); - }); - - it('give base cache if cache does NOT exist', function(done) { - var testnode = { - services: { - bitcoind: { - on: sinon.stub(), - } - }, - datadir: 'testdir' - }; - var addressService = new AddressService({ - mempoolMemoryIndex: true, - node: testnode - }); - var address = new bitcore.Address('12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX'); - var options = {}; - addressService.summaryCache = {}; - addressService.summaryCache.get = sinon.stub().callsArgWith(2, new levelup.errors.NotFoundError()); - addressService._getAddressConfirmedSummaryCache(address, options, function(err, cache) { - if (err) { - return done(err); - } - shouldExistBasecache(cache); - done(); - }); - }); - - it('give base cache if cached tip hash differs (e.g. reorg)', function(done) { - var hash = '000000002c05cc2e78923c34df87fd108b22221ac6076c18f3ade378a4d915e9'; - var testnode = { - services: { - bitcoind: { - on: sinon.stub(), - getBlockIndex: sinon.stub().returns({ - hash: '00000000700e92a916b46b8b91a14d1303d5d91ef0b09eecc3151fb958fd9a2e' - }) - }, - db: { - tip: { - hash: hash - } - } - }, - datadir: 'testdir' - }; - var addressService = new AddressService({ - mempoolMemoryIndex: true, - node: testnode - }); - var address = new bitcore.Address('12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX'); - var txid = '5464b1c3f25160f0183fad68a406838d2d1ac0aee05990072ece49326c26c22e'; - var options = {}; - var cache = { - height: 10, - hash: hash, - result: { - totalReceived: 100, - balance: 10, - txids: [txid], - appearanceIds: { - '5464b1c3f25160f0183fad68a406838d2d1ac0aee05990072ece49326c26c22e': 9 - } - } - }; - var cacheBuffer = encoding.encodeSummaryCacheValue(cache, 10, hash); - addressService.summaryCache = {}; - addressService.summaryCache.get = sinon.stub().callsArgWith(2, null, cacheBuffer); - addressService._getAddressConfirmedSummaryCache(address, options, function(err, cache) { - if (err) { - return done(err); - } - shouldExistBasecache(cache); - done(); - }); - }); - - it('handle error from levelup', function(done) { - var testnode = { - services: { - bitcoind: { - on: sinon.stub(), - } - }, - datadir: 'testdir' - }; - var addressService = new AddressService({ - mempoolMemoryIndex: true, - node: testnode - }); - var address = new bitcore.Address('12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX'); - var options = {}; - addressService.summaryCache = {}; - addressService.summaryCache.get = sinon.stub().callsArgWith(2, new Error('test')); - addressService._getAddressConfirmedSummaryCache(address, options, function(err) { - should.exist(err); - err.message.should.equal('test'); - done(); - }); - }); - - it('call encode and decode with args and result', function(done) { - var hash = '000000002c05cc2e78923c34df87fd108b22221ac6076c18f3ade378a4d915e9'; - var testnode = { - services: { - bitcoind: { - on: sinon.stub(), - getBlockIndex: sinon.stub().returns({ - hash: hash - }) - }, - db: { - tip: { - hash: hash - } - } - }, - datadir: 'testdir' - }; - var addressService = new AddressService({ - mempoolMemoryIndex: true, - node: testnode - }); - var address = new bitcore.Address('12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX'); - var txid = '5464b1c3f25160f0183fad68a406838d2d1ac0aee05990072ece49326c26c22e'; - var options = {}; - var cache = { - height: 10, - hash: hash, - result: { - totalReceived: 100, - balance: 10, - txids: [txid], - appearanceIds: { - '5464b1c3f25160f0183fad68a406838d2d1ac0aee05990072ece49326c26c22e': 9 - } - } - }; - var cacheBuffer = encoding.encodeSummaryCacheValue(cache, 10, hash); - addressService.summaryCache = {}; - addressService.summaryCache.get = sinon.stub().callsArgWith(2, null, cacheBuffer); - addressService._getAddressConfirmedSummaryCache(address, options, function(err, cache) { - if (err) { - return done(err); - } - should.exist(cache); - cache.height.should.equal(10); - cache.hash.should.equal(hash); - should.exist(cache.result); - cache.result.totalReceived.should.equal(100); - cache.result.balance.should.equal(10); - cache.result.txids.should.deep.equal([txid]); - cache.result.appearanceIds.should.deep.equal({ - '5464b1c3f25160f0183fad68a406838d2d1ac0aee05990072ece49326c26c22e': 9 - }); - done(); - }); - }); - }); - - describe('#_updateAddressConfirmedSummaryCache', function() { - it('will pass partial options to input/output summary query', function(done) { - var tipHeight = 12; - var testnode = { - services: { - bitcoind: { - on: sinon.stub() - } - }, - datadir: 'testdir' - }; - var as = new AddressService({ - mempoolMemoryIndex: true, - node: testnode - }); - var address = new bitcore.Address('12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX'); - var options = {}; - var cache = { - height: 10, - result: { - txids: [] - } - }; - as._getAddressConfirmedInputsSummary = sinon.stub().callsArgWith(3, null, cache); - as._getAddressConfirmedOutputsSummary = sinon.stub().callsArgWith(3, null, cache); - as._setAndSortTxidsFromAppearanceIds = sinon.stub().callsArgWith(1, null, cache); - as._saveAddressConfirmedSummaryCache = sinon.stub().callsArg(3, null, cache); - as._updateAddressConfirmedSummaryCache(address, options, cache, tipHeight, function(err, cache) { - if (err) { - return done(err); - } - as._getAddressConfirmedInputsSummary.callCount.should.equal(1); - as._getAddressConfirmedOutputsSummary.callCount.should.equal(1); - - as._getAddressConfirmedInputsSummary.args[0][2].start.should.equal(12); - as._getAddressConfirmedInputsSummary.args[0][2].end.should.equal(11); - - as._getAddressConfirmedOutputsSummary.args[0][2].start.should.equal(12); - as._getAddressConfirmedOutputsSummary.args[0][2].end.should.equal(11); - done(); - }); - }); - - it('will save cache if exceeds threshold and is NOT height query', function(done) { - var tipHeight = 12; - var testnode = { - services: { - bitcoind: { - on: sinon.stub() - } - }, - datadir: 'testdir' - }; - var as = new AddressService({ - mempoolMemoryIndex: true, - node: testnode - }); - var address = new bitcore.Address('12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX'); - var options = {}; - var cache = { - height: 10, - result: { - txids: [ - '9a816264c50910cbf57aa4637dde5f7fec03df642b822661e8bc9710475986b6', - '05c6b9ccf3fc4026391bf8f8a64b4784a95b930851359b8f85a4be7bb6bf6f1e' - ] - } - }; - as.summaryCacheThreshold = 1; - as._getAddressConfirmedInputsSummary = sinon.stub().callsArgWith(3, null, cache); - as._getAddressConfirmedOutputsSummary = sinon.stub().callsArgWith(3, null, cache); - as._setAndSortTxidsFromAppearanceIds = sinon.stub().callsArgWith(1, null, cache); - as._saveAddressConfirmedSummaryCache = sinon.stub().callsArg(3, null, cache); - as._updateAddressConfirmedSummaryCache(address, options, cache, tipHeight, function(err) { - if (err) { - return done(err); - } - as._saveAddressConfirmedSummaryCache.callCount.should.equal(1); - done(); - }); - }); - - it('will NOT save cache if exceeds threshold and IS height query', function(done) { - var tipHeight = 12; - var testnode = { - services: { - bitcoind: { - on: sinon.stub() - } - }, - datadir: 'testdir' - }; - var as = new AddressService({ - mempoolMemoryIndex: true, - node: testnode - }); - var address = new bitcore.Address('12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX'); - var options = {}; - var cache = { - result: { - txids: [] - } - }; - as.summaryCacheThreshold = 1; - as._getAddressConfirmedInputsSummary = sinon.stub().callsArgWith(3, null, cache); - as._getAddressConfirmedOutputsSummary = sinon.stub().callsArgWith(3, null, cache); - as._setAndSortTxidsFromAppearanceIds = sinon.stub().callsArgWith(1, null, cache); - as._saveAddressConfirmedSummaryCache = sinon.stub().callsArg(3, null, cache); - as._updateAddressConfirmedSummaryCache(address, options, cache, tipHeight, function(err) { - if (err) { - return done(err); - } - as._saveAddressConfirmedSummaryCache.callCount.should.equal(0); - done(); - }); - }); - + describe.skip('#_getAddressConfirmedSummary', function() { }); describe('#_getAddressConfirmedInputsSummary', function() { @@ -2584,21 +2139,18 @@ describe('Address Service', function() { mempoolMemoryIndex: true, node: testnode }); - var cache = { - height: 10, - result: { - appearanceIds: {} - } + var result = { + appearanceIds: {} }; var options = {}; var txid = 'f2cfc19d13f0c12199f70e420d84e2b3b1d4e499702aa9d737f8c24559c9ec47'; var address = new bitcore.Address('12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX'); as.createInputsStream = sinon.stub().returns(streamStub); - as._getAddressConfirmedInputsSummary(address, cache, options, function(err, cache) { + as._getAddressConfirmedInputsSummary(address, result, options, function(err, result) { if (err) { return done(err); } - cache.result.appearanceIds[txid].should.equal(10); + result.appearanceIds[txid].should.equal(10); done(); }); @@ -2655,16 +2207,14 @@ describe('Address Service', function() { mempoolMemoryIndex: true, node: testnode }); - var cache = { - height: 10, - result: { - appearanceIds: {}, - unconfirmedAppearanceIds: {}, - balance: 0, - totalReceived: 0, - unconfirmedBalance: 0 - } + var result = { + appearanceIds: {}, + unconfirmedAppearanceIds: {}, + balance: 0, + totalReceived: 0, + unconfirmedBalance: 0 }; + var options = { queryMempool: true }; @@ -2676,14 +2226,14 @@ describe('Address Service', function() { var spentIndexSyncKey = encoding.encodeSpentIndexSyncKey(new Buffer(txid, 'hex'), 2); as.mempoolSpentIndex[spentIndexSyncKey] = true; - as._getAddressConfirmedOutputsSummary(address, cache, options, function(err, cache) { + as._getAddressConfirmedOutputsSummary(address, result, options, function(err, cache) { if (err) { return done(err); } - cache.result.appearanceIds[txid].should.equal(10); - cache.result.balance.should.equal(1000); - cache.result.totalReceived.should.equal(1000); - cache.result.unconfirmedBalance.should.equal(-1000); + result.appearanceIds[txid].should.equal(10); + result.balance.should.equal(1000); + result.totalReceived.should.equal(1000); + result.unconfirmedBalance.should.equal(-1000); done(); }); @@ -2710,20 +2260,18 @@ describe('Address Service', function() { mempoolMemoryIndex: true, node: testnode }); - var cache = { - height: 10, - result: { - appearanceIds: {}, - unconfirmedAppearanceIds: {}, - balance: 0, - totalReceived: 0, - unconfirmedBalance: 0 - } + var result = { + appearanceIds: {}, + unconfirmedAppearanceIds: {}, + balance: 0, + totalReceived: 0, + unconfirmedBalance: 0 }; + var options = {}; var address = new bitcore.Address('12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX'); as.createOutputsStream = sinon.stub().returns(streamStub); - as._getAddressConfirmedOutputsSummary(address, cache, options, function(err, cache) { + as._getAddressConfirmedOutputsSummary(address, result, options, function(err, cache) { should.exist(err); err.message.should.equal('test'); done(); @@ -2737,9 +2285,6 @@ describe('Address Service', function() { describe.skip('#_setAndSortTxidsFromAppearanceIds', function() { }); - describe.skip('#_saveAddressConfirmedSummaryCache', function() { - }); - describe.skip('#_getAddressMempoolSummary', function() { });