fix chain preload.

This commit is contained in:
Christopher Jeffrey 2016-03-05 17:00:37 -08:00
parent df97d0ce11
commit 509ef15094

View File

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