chain: remove spv preload.

This commit is contained in:
Christopher Jeffrey 2016-07-27 06:27:27 -07:00
parent d2ec66c4b7
commit 868512e054
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
2 changed files with 25 additions and 199 deletions

View File

@ -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

View File

@ -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();