Added a reset tip routine.

This commit is contained in:
Chris Kleeschulte 2017-09-25 14:31:07 -04:00
parent d299856fdc
commit dcf1426221
No known key found for this signature in database
GPG Key ID: 33195D27EF6BDB7F

View File

@ -28,6 +28,7 @@ var BlockService = function(options) {
this._blockCount = 0;
this.GENESIS_HASH = constants.BITCOIN_GENESIS_HASH[this.node.network];
this._initialSync = true;
this._reorgBackToBlock = null;
};
inherits(BlockService, BaseService);
@ -167,10 +168,28 @@ BlockService.prototype.getRawBlock = function(hash, callback) {
});
};
BlockService.prototype._reorgBackTo = function(callback) {
var self = this;
self._header.getBlockHeader(self._reorgBackToBlock, function(err, header) {
if (err || !header) {
return callback(err || new Error('Header not found to reorg back to.'));
}
log.info('Block Service: we found the block to reorg back to, commencing reorg...');
self._handleReorg(header.hash, callback);
});
};
BlockService.prototype._checkTip = function(callback) {
var self = this;
log.info('Block Service: checking the saved tip...');
if (self._reorgBackToBlock) {
log.warn('Block Service: we were asked to reorg back to block: ' + self._reorgBackToBlock);
return self._reorgBackTo(callback);
}
self._header.getBlockHeader(self._tip.height, function(err, header) {
if (err) {
@ -209,8 +228,8 @@ BlockService.prototype._findCommonAncestor = function(callback) {
return headers.get(hash);
}, function(next) {
self._getBlock(hash, function(err, block) {
if(err) {
return next(err);
if(err || !block) {
return next(err || new Error('block must be found in order to find common ancestor.'));
}
hash = bcoin.util.revHex(block.prevBlock);
next();
@ -224,6 +243,85 @@ BlockService.prototype._findCommonAncestor = function(callback) {
});
};
BlockService.prototype._resetTip = function(callback) {
var self = this;
if (!self._tipResetNeeded) {
return callback();
}
self._tipResetNeeded = false;
log.warn('Block Service: resetting tip due to a non-existent tip block...');
var block;
var header = self._header.getLastHeader();
var height = header.height;
self._header.getAllHeaders(function(err, headers) {
if (err || !headers) {
return callback(err || new Error('headers required'));
}
log.info('Block Service: retrieved all the headers for lookups');
async.until(function() {
return block;
}, function(next) {
self._getBlock(header.hash, function(err, _block) {
if (err) {
return callback(err);
}
if (!_block) {
log.warn('Block Service: block: ' + header.hash + ' was not found, proceeding to older blocks.');
}
block = _block;
header = headers.getIndex(--height);
assert(header, 'Header not found for reset.');
if (!block) {
log.warn('Block Service: trying block: ' + header.hash);
}
next();
});
}, function(err) {
if (err || !block) {
return callback(err ||
new Error('Block Service: none of the blocks from the headers match what is already indexed in the block service.'));
}
self._setTip({ hash: block.rhash(), height: height + 1 });
callback();
});
});
};
BlockService.prototype._performSanityCheck = function(tip, callback) {
var self = this;
// is our tip saved in our database? If not, then find the latest block that is in
// in our database and set the tip to that
self._getBlock(tip.hash, function(err, block) {
if (err) {
return callback(err);
}
if (block) {
return callback(null, tip);
}
return callback(null, false);
});
};
BlockService.prototype.start = function(callback) {
var self = this;
@ -243,13 +341,23 @@ BlockService.prototype.start = function(callback) {
return callback(err);
}
self._blockProcessor = async.queue(self._onBlock.bind(self));
self._performSanityCheck(tip, function(err, tip) {
self._setListeners();
assert(tip.height >= 0, 'tip is not initialized');
self._setTip(tip);
self._bus = self.node.openBus({remoteAddress: 'localhost-block'});
callback();
if (err) {
return callback(err);
}
if (!tip) {
self._tipResetNeeded = true;
}
self._blockProcessor = async.queue(self._onBlock.bind(self));
self._setListeners();
self._setTip(tip);
self._bus = self.node.openBus({remoteAddress: 'localhost-block'});
callback();
});
});
@ -410,21 +518,26 @@ BlockService.prototype.onHeaders = function(callback) {
var self = this;
async.retry(function(next) {
self._resetTip(function(err) {
if (err) {
return callback(err);
}
async.retry(function(next) {
next(self._blockProcessor.length() !== 0);
next(self._blockProcessor.length() !== 0);
}, function() {
}, function() {
self._checkTip(function(err) {
self._checkTip(function(err) {
if(err) {
return callback(err);
}
if(err) {
return callback(err);
}
self._startSync();
callback();
self._startSync();
callback();
});
});
});