Added a reset tip routine.
This commit is contained in:
parent
d299856fdc
commit
dcf1426221
@ -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();
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user