diff --git a/lib/services/block/index.js b/lib/services/block/index.js index 40eea813..2130825e 100644 --- a/lib/services/block/index.js +++ b/lib/services/block/index.js @@ -29,6 +29,7 @@ var BlockService = function(options) { this._blocksInQueue = 0; this._recentBlockHashesCount = options.recentBlockHashesCount || 50; // if you expect this chain to reorg deeper than 50, set this this._recentBlockHashes = new LRU(this._recentBlockHashesCount); + this._readAheadBlockCount = options.readAheadBlockCount || 2; // this is the number of blocks to direct the p2p service to read aheead }; inherits(BlockService, BaseService); @@ -943,13 +944,13 @@ BlockService.prototype._sync = function() { log.debug('Block Service: querying header service for next block using tip: ' + self._tip.hash); - self._header.getNextHash(self._tip, function(err, targetHash, nextHash) { + self._header.getEndHash(self._tip, self._readAheadBlockCount, function(err, targetHash, endHash) { if(err) { return self._handleError(err); } - if (!targetHash && !nextHash) { + if (!targetHash && !endHash) { return self.emit('synced'); } @@ -974,7 +975,7 @@ BlockService.prototype._sync = function() { self._p2p.getP2PBlock({ filter: { startHash: self._tip.hash, - endHash: nextHash + endHash: endHash }, blockHash: targetHash }, self._syncBlock.bind(self)); diff --git a/lib/services/header/index.js b/lib/services/header/index.js index db20892d..edf3fa7b 100644 --- a/lib/services/header/index.js +++ b/lib/services/header/index.js @@ -852,12 +852,13 @@ HeaderService.prototype._sync = function() { }; -// this gets the header that is +2 places from hash or returns 0 if there is no such -HeaderService.prototype.getNextHash = function(tip, callback) { +HeaderService.prototype.getEndHash = function(tip, blockCount, callback) { + + assert(blockCount >= 1, 'Header Service: block count to getEndHash must be at least 1.'); var self = this; - var numResultsNeeded = Math.min((self._tip.height - tip.height), 2); + var numResultsNeeded = Math.min((self._tip.height - tip.height), blockCount + 1); if (numResultsNeeded === 0 && self._tip.hash === tip.hash) { return callback(); @@ -867,14 +868,14 @@ HeaderService.prototype.getNextHash = function(tip, callback) { return callback(new Error('Header Service: block service is mis-aligned ')); } - - var start = self._encoding.encodeHeaderHeightKey(tip.height + 1); - var end = self._encoding.encodeHeaderHeightKey(tip.height + 3); + var startingHeight = tip.height + 1; + var start = self._encoding.encodeHeaderHeightKey(startingHeight); + var end = self._encoding.encodeHeaderHeightKey(startingHeight + blockCount); var results = []; var criteria = { gte: start, - lt: end + lte: end }; var stream = self._db.createReadStream(criteria); @@ -895,19 +896,18 @@ HeaderService.prototype.getNextHash = function(tip, callback) { return streamErr; } - assert(results.length === numResultsNeeded, 'GetNextHash returned incorrect number of results.'); + assert(results.length === numResultsNeeded, 'getEndHash returned incorrect number of results.'); - if (!results[1]) { - results[1] = 0; - } + var index = numResultsNeeded - 1; + var endHash = index <= 0 || !results[index] ? 0 : results[index]; if (self._slowMode) { return setTimeout(function() { - callback(null, results[0], results[1]); + callback(null, results[0], endHash); }, self._slowMode); } - callback(null, results[0], results[1]); + callback(null, results[0], endHash); }); diff --git a/lib/services/p2p/index.js b/lib/services/p2p/index.js index 0aa5e995..84ec2a74 100644 --- a/lib/services/p2p/index.js +++ b/lib/services/p2p/index.js @@ -27,6 +27,10 @@ var P2P = function(options) { this._currentBestHeight = null; this._latestBits = 0x1d00ffff; this._outgoingTxs = LRU(100); // these are outgoing txs that are awaiting getdata messages + this._blockCache = options.blockCacheCount || LRU({ + max: 10, + maxAge: 1000 * 60 * 5}); // keep this modest to avoid memory dumps [hash -> block] + }; util.inherits(P2P, BaseService); @@ -53,8 +57,18 @@ P2P.prototype.getNumberOfPeers = function() { }; P2P.prototype.getP2PBlock = function(opts, callback) { + // opts is { filter: {}, blockHash: block hash we want } + var self = this; + + // do we already have this block in our cache? + var block = self._blockCache.get(opts.blockHash); + + if (block) { + return callback(block); + } + var peer = self._getPeer(); var blockFilter = self._setResourceFilter(opts.filter, 'blocks'); @@ -291,6 +305,7 @@ P2P.prototype._initPubSub = function() { }; P2P.prototype._onPeerBlock = function(peer, message) { + this._blockCache.set(message.block.rhash(), message.block); this.emit(message.block.rhash(), message.block); this._broadcast(this.subscriptions.block, 'p2p/block', message.block); };