diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index dfd04f23..07f7bebe 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -269,7 +269,7 @@ Chain.prototype._ensureGenesis = function _ensureGenesis(callback) { Chain.prototype._preload = function _preload(callback) { var self = this; var url = 'https://headers.electrum.org/blockchain_headers'; - var chainHeight, buf, height, stream; + var buf, height, stream; var request; if (!this.options.preload) @@ -289,114 +289,118 @@ Chain.prototype._preload = function _preload(callback) { utils.debug('Loading %s', url); - stream = request.get(url); - chainHeight = this.db.getSize() - 1; - height = 0; - buf = { - data: [], - size: 0 - }; + this.db.getChainHeight(function(err, chainHeight) { + if (err) + return callback(err); - stream.on('response', function(res) { - if (res.statusCode >= 400) { - stream.destroy(); - return callback(new Error('Bad response code: ' + res.statusCode)); - } - }); + stream = request.get(url); + height = 0; + buf = { + data: [], + size: 0 + }; - stream.on('error', function(err) { - var start = Math.max(0, height - 2); - self.reset(start, function(e) { - if (e) - throw e; - return callback(err, start + 1); + stream.on('response', function(res) { + if (res.statusCode >= 400) { + stream.destroy(); + return callback(new Error('Bad response code: ' + res.statusCode)); + } }); - }); - stream.on('data', function(data) { - var blocks = []; - var need = 80 - buf.size; - var i, lastEntry; - - while (data.length >= need) { - buf.data.push(data.slice(0, need)); - blocks.push(Buffer.concat(buf.data)); - buf.data.length = 0; - buf.size = 0; - data = data.slice(need); - need = 80 - buf.size; - } - - if (data.length > 0) { - assert(data.length < 80); - buf.data.push(data); - buf.size += data.length; - } - - if (blocks.length === 0) - return; - - blocks.forEach(function(data) { - var entry = bcoin.chainblock.fromRaw(self, data); - var block, start; - - entry.height = height; - - block = bcoin.headers(entry); - - // Do some paranoid checks. - if (lastEntry && entry.prevBlock !== lastEntry.hash) { - start = Math.max(0, height - 2); - stream.destroy(); - return self.reset(start, function(err) { - if (err) - throw err; - return callback(new Error('Corrupt headers.'), start + 1); - }); - } - - // Verify the block headers. We don't want to - // trust an external centralized source completely. - if (!block.verifyHeaders()) { - start = Math.max(0, height - 2); - stream.destroy(); - return self.reset(start, function(err) { - if (err) - throw err; - return callback(new Error('Bad headers.'), start + 1); - }); - } - - // Calculate chainwork. - delete entry.chainwork; - entry.chainwork = entry.getChainwork(lastEntry); - - lastEntry = entry; - - // Make sure the genesis block is correct. - if (height === 0 && entry.hash !== network.genesis.hash) { - stream.destroy(); - return callback(new Error('Bad genesis block.'), 0); - } - - // Filthy hack to avoid writing - // redundant blocks to disk! - if (height <= chainHeight) { - self.db.addCache(entry); - self.db.bloom(entry.hash, 'hex'); - } else { - self.db.save(entry); - } - - height++; - - if ((height + 1) % 50000 === 0) - utils.debug('Received %d headers from electrum.org.', height + 1); + stream.on('error', function(err) { + var start = Math.max(0, height - 2); + self.reset(start, function(e) { + if (e) + throw e; + return callback(err, start + 1); + }); }); - }); - stream.on('end', function() { - return callback(null, height + 1); + stream.on('data', function(data) { + var blocks = []; + var need = 80 - buf.size; + var i, lastEntry; + + while (data.length >= need) { + buf.data.push(data.slice(0, need)); + blocks.push(Buffer.concat(buf.data)); + buf.data.length = 0; + buf.size = 0; + data = data.slice(need); + need = 80 - buf.size; + } + + if (data.length > 0) { + assert(data.length < 80); + buf.data.push(data); + buf.size += data.length; + } + + if (blocks.length === 0) + return; + + blocks.forEach(function(data) { + var entry = bcoin.chainblock.fromRaw(self, data); + var block, start; + + entry.height = height; + + block = bcoin.headers(entry); + + // Do some paranoid checks. + if (lastEntry && entry.prevBlock !== lastEntry.hash) { + start = Math.max(0, height - 2); + stream.destroy(); + return self.reset(start, function(err) { + if (err) + throw err; + return callback(new Error('Corrupt headers.'), start + 1); + }); + } + + // Verify the block headers. We don't want to + // trust an external centralized source completely. + if (!block.verifyHeaders()) { + start = Math.max(0, height - 2); + stream.destroy(); + return self.reset(start, function(err) { + if (err) + throw err; + return callback(new Error('Bad headers.'), start + 1); + }); + } + + // Calculate chainwork. + delete entry.chainwork; + entry.chainwork = entry.getChainwork(lastEntry); + + lastEntry = entry; + + // Make sure the genesis block is correct. + if (height === 0 && entry.hash !== network.genesis.hash) { + stream.destroy(); + return callback(new Error('Bad genesis block.'), 0); + } + + // Filthy hack to avoid writing + // redundant blocks to disk! + if (height <= chainHeight) { + self.db.addCache(entry); + self.db.bloom(entry.hash, 'hex'); + } else { + self.db.save(entry); + } + + height++; + + if ((height + 1) % 50000 === 0) + utils.debug('Received %d headers from electrum.org.', height + 1); + }); + }); + + stream.on('end', function() { + return callback(null, height + 1); + }); }); };