chain: remove spv preload.
This commit is contained in:
parent
d2ec66c4b7
commit
868512e054
@ -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
|
||||
|
||||
@ -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();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user