diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index 7b24049e..14ce5ae3 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -197,49 +197,44 @@ Chain.prototype._open = function open(callback) { if (err) return callback(err); - self.preload(function(err) { + self.db.getTip(function(err, tip) { if (err) return callback(err); - self.db.getTip(function(err, tip) { + assert(tip); + + self.tip = tip; + self.height = tip.height; + + if (tip.height > self.bestHeight) { + self.bestHeight = tip.height; + self.network.updateHeight(tip.height); + } + + self.logger.memory(); + + self.getDeploymentState(function(err, state) { if (err) return callback(err); - assert(tip); + self.state = state; - self.tip = tip; - self.height = tip.height; + if (state.hasCSV()) + self.logger.info('CSV is active.'); - if (tip.height > self.bestHeight) { - self.bestHeight = tip.height; - self.network.updateHeight(tip.height); - } + if (state.hasWitness()) + self.logger.info('Segwit is active.'); self.logger.memory(); - self.getDeploymentState(function(err, state) { - if (err) - return callback(err); + self.emit('tip', tip); - self.state = state; + if (!self.synced && self.isFull()) { + self.synced = true; + self.emit('full'); + } - if (state.hasCSV()) - self.logger.info('CSV is active.'); - - if (state.hasWitness()) - self.logger.info('Segwit is active.'); - - self.logger.memory(); - - self.emit('tip', tip); - - if (!self.synced && self.isFull()) { - self.synced = true; - self.emit('full'); - } - - callback(); - }); + callback(); }); }); }); @@ -265,156 +260,6 @@ Chain.prototype._lock = function _lock(func, args, force) { return this.locker.lock(func, args, force); }; -/** - * Stream headers from electrum.org for quickly - * preloading the chain. Electrum.org stores - * headers in the standard block header format, - * but they do not store chainwork, so we have - * to calculate it ourselves. - * @private - * @param {Function} callback - */ - -Chain.prototype.preload = function preload(callback) { - var self = this; - var url = 'https://headers.electrum.org/blockchain_headers'; - var request = require('./http/request'); - var locker = new bcoin.locker(); - var flushed = 0; - var chunks, size, height, stream, ended; - - if (!this.options.preload) - return callback(); - - if (!this.options.spv) - return callback(); - - if (this.network.type !== 'main') - return callback(); - - this.logger.info('Loading %s.', url); - - function save(entry, header) { - var unlock = locker.lock(save, [entry]); - if (!unlock) - return; - - self.db.save(entry, header, null, true, function(err) { - if (err) { - stream.destroy(); - locker.destroy(); - return callback(err); - } - - if ((++flushed % 50000) === 0) - self.logger.info('Flushed %d headers to DB.', flushed); - - if (locker.jobs.length === 0 && ended) - return callback(); - - unlock(); - }); - } - - this.db.getChainHeight(function(err, chainHeight) { - if (err) - return callback(err); - - stream = request({ method: 'GET', uri: url }); - height = 0; - chunks = []; - size = 0; - - stream.on('response', function(res) { - var height = Math.floor(+res.headers['content-length'] / 80); - if (res.statusCode >= 400) { - stream.destroy(); - return callback(new Error('Bad response code: ' + res.statusCode)); - } - if (chainHeight > height - 30000) { - self.logger.info('Preload height is %d. Skipping.', height); - stream.destroy(); - return callback(); - } - }); - - stream.on('error', function(err) { - stream.destroy(); - return callback(err); - }); - - stream.on('data', function(data) { - var blocks = []; - var need = 80 - size; - var i, lastEntry, block, entry; - - while (data.length >= need) { - chunks.push(data.slice(0, need)); - blocks.push(Buffer.concat(chunks)); - chunks.length = 0; - data = data.slice(need); - need = 80; - } - - if (data.length > 0) { - assert(data.length < 80); - chunks.push(data); - size += data.length; - } - - for (i = 0; i < blocks.length; i++) { - block = blocks[i]; - - try { - block = bcoin.headers.fromAbbr(block); - } catch (e) { - stream.destroy(); - return callback(e); - } - - block.setHeight(height); - - // Make sure the genesis block is correct. - if (block.height === 0 && !self.isGenesis(block)) { - stream.destroy(); - return callback(new Error('Bad genesis block.')); - } - - // Do some paranoid checks. - if (lastEntry && block.prevBlock !== lastEntry.hash) { - stream.destroy(); - return callback(new Error('Corrupt headers.')); - } - - // Verify the block headers. We don't want to - // trust an external centralized source completely. - if (!block.verify()) { - stream.destroy(); - return callback(new Error('Bad headers.')); - } - - // Create a chain entry. - entry = bcoin.chainentry.fromBlock(self, block, lastEntry); - - if (entry.height > chainHeight) - save(entry, block); - - if ((height + 1) % 50000 === 0) - self.logger.info('Received %d headers.', height + 1); - - lastEntry = entry; - height++; - } - }); - - stream.on('end', function() { - ended = true; - if (!locker.busy && locker.jobs.length === 0) - return callback(); - }); - }); -}; - /** * Perform all necessary contextual verification on a block. * @private diff --git a/lib/bcoin/spvnode.js b/lib/bcoin/spvnode.js index 340e7985..fdbc10a9 100644 --- a/lib/bcoin/spvnode.js +++ b/lib/bcoin/spvnode.js @@ -47,7 +47,6 @@ function SPVNode(options) { db: this.db, location: this.location('spvchain'), witness: this.network.witness, - preload: this.options.preload, useCheckpoints: this.options.useCheckpoints, spv: true }); @@ -220,24 +219,6 @@ SPVNode.prototype._open = function open(callback) { next(); }); }, - function(next) { - if (!self.chain.options.preload) - return next(); - - // If we preloaded, we want to reset - // the chain to our last height. - self.walletdb.getLastTime(function(err, ts, height) { - if (err) - return next(err); - - if (height === -1) - return next(); - - self.logger.info('Rewinding chain to height %s.', height); - - self.chain.reset(height, next); - }); - }, function(next) { if (!self.http) return next();