Added the checkpoints back in.

This commit is contained in:
Chris Kleeschulte 2017-08-07 19:29:57 -04:00
parent 408243de4b
commit 07a4b706c7
3 changed files with 54 additions and 24 deletions

View File

@ -482,6 +482,7 @@ BlockService.prototype._onBlock = function(block) {
BlockService.prototype._setListeners = function() { BlockService.prototype._setListeners = function() {
this._header.once('headers', this._onAllHeaders.bind(this)); this._header.once('headers', this._onAllHeaders.bind(this));
this._header.on('reorg', this._handleReorg.bind(this));
}; };

View File

@ -24,6 +24,7 @@ var HeaderService = function(options) {
this.subscriptions = {}; this.subscriptions = {};
this.subscriptions.block = []; this.subscriptions.block = [];
this._checkpoint = options.checkpoint || 2000;
this.GENESIS_HASH = constants.BITCOIN_GENESIS_HASH[this.node.network]; this.GENESIS_HASH = constants.BITCOIN_GENESIS_HASH[this.node.network];
}; };
@ -93,9 +94,10 @@ HeaderService.prototype.start = function(callback) {
function(tip, next) { function(tip, next) {
self._tip = tip; self._tip = tip;
self._originalTip = { self._originalTip = {
height: self._tip.height, hash: self._tip.hash,
hash: self._tip.hash height: self._tip.height
}; };
if (self._tip.height === 0) { if (self._tip.height === 0) {
var genesisHeader = { var genesisHeader = {
@ -128,9 +130,6 @@ HeaderService.prototype.start = function(callback) {
return callback(err); return callback(err);
} }
if (self._headers.size > 0) {
self._tip.hash = self._headers.getLastIndex().hash;
}
self._setListeners(); self._setListeners();
self._startSubscriptions(); self._startSubscriptions();
callback(); callback();
@ -224,7 +223,7 @@ HeaderService.prototype._onHeaders = function(headers) {
value: self._encoding.encodeHeaderValue(header) value: self._encoding.encodeHeaderValue(header)
}); });
prevHeader = header; prevHeader = header;
self._headers.set(header.hash, header); self._headers.set(header.hash, header, header.height);
} }
var tipOps = utils.encodeTip(self._tip, self.name); var tipOps = utils.encodeTip(self._tip, self.name);
@ -243,24 +242,33 @@ HeaderService.prototype._onHeaders = function(headers) {
log.debug('Header Service: download complete.'); log.debug('Header Service: download complete.');
// have we reorg'ed since we've been shutdown? // at this point, we can check our header list to see if our starting tip diverged from the tip
if (self._tip.height > 0) { // that we have now
if (self._detectReorg()) {
var headerHash = self._headers.getIndex(self._tip.height).hash; self._handleReorg();
if (self._tip.hash !== headerHash) { return;
self.emit('reorg', headerHash, self._headers);
return;
}
} }
log.debug('Header Service: emitting headers to block service.'); log.debug('Header Service: emitting headers to block service.');
self.emit('headers', self._headers); self.emit('headers', self._headers);
}); });
}; };
HeaderService.prototype._detectReorg = function() {
// is our original tip's height and hash the same after we rewound by the checkpoint amount of blocks
// and re-imported? If so, then we've reorg'ed since we've been shut down.
if (this._originalTip.hash !== this._headers.getIndex(this._originalTip.height).hash) {
return true;
}
return false;
};
HeaderService.prototype._handleReorg = function() {
this.emit('reorg', this._headers.getIndex(this._originalTip.height).hash, this._headers);
};
HeaderService.prototype._setListeners = function() { HeaderService.prototype._setListeners = function() {
this._p2p.once('bestHeight', this._onBestHeight.bind(this)); this._p2p.once('bestHeight', this._onBestHeight.bind(this));
@ -287,10 +295,10 @@ HeaderService.prototype._startSync = function() {
HeaderService.prototype._sync = function() { HeaderService.prototype._sync = function() {
log.debug('Header Service: download progress: ' + this._tip.height + '/' + log.debug('Header Service: download progress: ' + this._tip.height + '/' +
this._bestHeight + ' (' + (this._tip.height / this._bestHeight*100).toFixed(2) + '%)'); this._bestHeight + ' (' + (this._tip.height / this._bestHeight*100).toFixed(2) + '%)');
this._p2p.getHeaders({ startHash: this._tip.hash }); this._p2p.getHeaders({ startHash: this._tip.hash });
}; };
@ -302,8 +310,14 @@ HeaderService.prototype._getPersistedHeaders = function(callback) {
var self = this; var self = this;
var startingHeight = self._tip.height;
if (self._tip.height > self._checkpoint) {
self._tip.height -= self._checkpoint;
}
var removalOps = [];
var start = self._encoding.encodeHeaderKey(0); var start = self._encoding.encodeHeaderKey(0);
var end = self._encoding.encodeHeaderKey(self._tip.height + 1); var end = self._encoding.encodeHeaderKey(startingHeight + 1);
log.debug('Getting persisted headers from genesis block to block ' + (self._tip.height + 1)); log.debug('Getting persisted headers from genesis block to block ' + (self._tip.height + 1));
@ -320,14 +334,24 @@ HeaderService.prototype._getPersistedHeaders = function(callback) {
}); });
stream.on('data', function(data) { stream.on('data', function(data) {
self._headers.set(self._encoding.decodeHeaderKey(data.key).hash, self._encoding.decodeHeaderValue(data.value)); var header = self._encoding.decodeHeaderValue(data.value);
// any records with a height greater than our current tip height can be scheduled for removal
if (header.height > self._tip.height) {
removalOps.push({
type: 'del',
key: data.key
});
return;
}
self._headers.set(self._encoding.decodeHeaderKey(data.key).hash, header, header.height);
}); });
stream.on('end', function() { stream.on('end', function() {
if (streamErr) { if (streamErr) {
return streamErr; return streamErr;
} }
callback(); self._tip.hash = self._headers.getIndex(self._tip.height).hash;
self._db.batch(removalOps, callback);
}); });
}; };

View File

@ -76,9 +76,14 @@ utils.SimpleMap = function SimpleMap() {
return array[object[key]]; return array[object[key]];
}; };
this.set = function (key, value) { this.set = function (key, value, pos) {
object[key] = array.length; object[key] = array.length;
array.push(value);
if (pos >= 0) {
array[pos] = value;
} else {
array.push(value);
}
this.size = array.length; this.size = array.length;
this.length = array.length; this.length = array.length;