Fixed reorging.

This commit is contained in:
Chris Kleeschulte 2017-09-08 14:18:55 -04:00
parent 02ff6c680c
commit 82dd1dfe3f
No known key found for this signature in database
GPG Key ID: 33195D27EF6BDB7F
4 changed files with 61 additions and 14 deletions

View File

@ -18,6 +18,7 @@ var AddressService = function(options) {
this._header = this.node.services.header; this._header = this.node.services.header;
this._block = this.node.services.block; this._block = this.node.services.block;
this._timestamp = this.node.services.timestamp; this._timestamp = this.node.services.timestamp;
this._transaction = this.node.services.transaction;
this._network = this.node.network; this._network = this.node.network;
this._db = this.node.services.db; this._db = this.node.services.db;

View File

@ -565,7 +565,7 @@ HeaderService.prototype._detectReorg = function(block, callback) {
var nextBlock = prevHash === self._lastHeader.hash; var nextBlock = prevHash === self._lastHeader.hash;
// this is the last block the block service asked for // this is the last block the block service asked for
if (prevHash === this.lastBlockQueried) { if (prevHash === this.lastBlockQueried && this.blockServiceSyncing) {
return callback(null, false, true); return callback(null, false, true);
} }
@ -575,7 +575,7 @@ HeaderService.prototype._detectReorg = function(block, callback) {
} }
// could really be a reorg block // could really be a reorg block
var key = this._encoding.encodeHeaderHashKey(bcoin.util.revHex(block.prevBlock)); var key = this._encoding.encodeHeaderHashKey(prevHash);
this._db.get(key, function(err, val) { this._db.get(key, function(err, val) {
@ -621,28 +621,39 @@ HeaderService.prototype._detectStartupReorg = function(callback) {
HeaderService.prototype._handleReorg = function(block, header, callback) { HeaderService.prototype._handleReorg = function(block, header, callback) {
var self = this; var self = this;
self.getAllHeaders(function(err, headers) { self.getAllHeaders(function(err, headers) {
if (err || !headers) { if (err || !headers) {
return callback(err || new Error('Missing headers')); return callback(err || new Error('Missing headers'));
} }
var header = headers.getIndex(self._originalTip.height); var originalTipHeader = headers.getIndex(self._originalTip.height);
assert(header, 'Atempted to get reorg header for the original tip: ' + self._originalTip.hash + assert(header, 'Atempted to get reorg header for the original tip: ' + self._originalTip.hash +
' at height: ' + self._originalTip.height + ' but could not find in the database.'); ' at height: ' + self._originalTip.height + ' but could not find in the database.');
var hash = header.hash; var hash = originalTipHeader.hash;
// reorg from new blocks
if (block && header) { if (block && header) {
hash = block.rhash(); hash = block.rhash();
self._lastHeader = headers.get(header.prevHash);
assert(self._lastHeader, 'Expected our reorg block to have a header entry, but it did not.');
headers.set(hash, header); // appends to the end headers.set(hash, header); // appends to the end
self.emit('reorg', hash, headers, block);
return callback(); // this will ensure our own headers collection is correct
return self._onReorg(block, headers, function(err) {
if (err) {
return callback(err);
}
self.emit('reorg', hash, headers, block);
return callback();
});
} }
// reorg from startup
assert(hash, 'To reorg, we need a hash to reorg to.'); assert(hash, 'To reorg, we need a hash to reorg to.');
self.emit('reorg', hash, headers); self.emit('reorg', hash, headers);
callback(); callback();
@ -651,6 +662,41 @@ HeaderService.prototype._handleReorg = function(block, header, callback) {
}; };
HeaderService.prototype._onReorg = function(block, headers, callback) {
// this will be called when a new block (not historical) arrives and
// has a common ancestor with a block that we already received.
var self = this;
// remove the current last header from the db
var ops = [
{
type: 'del',
key: self._encoding.encodeHeaderHashKey(self._lastHeader.hash)
},
{
type: 'del',
key: self._encoding.encodeHeaderHeightKey(self._lastHeader.height)
}
];
self._db.batch(ops, function(err) {
if (err) {
return callback(err);
}
// set the last header to the common ancestor
self._lastHeader = headers.get(bcoin.util.revHex(block.prevBlock));
assert(self._lastHeader, 'Expected our reorg block to have a header entry, but it did not.');
// add the new block
self._syncBlock(block, callback);
});
};
HeaderService.prototype._setListeners = function() { HeaderService.prototype._setListeners = function() {
this._p2p.once('bestHeight', this._onBestHeight.bind(this)); this._p2p.once('bestHeight', this._onBestHeight.bind(this));

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "bitcore-node", "name": "bitcore-node",
"version": "5.0.0-beta.5", "version": "5.0.0-beta.6",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

View File

@ -73,7 +73,7 @@ describe('Transaction Service', function() {
it('should process new blocks that come in from the block service', function(done) { it('should process new blocks that come in from the block service', function(done) {
var _processTransaction = sandbox.stub(txService, '_processTransaction'); var _processTransaction = sandbox.stub(txService, '_processTransaction').callsArgWith(2, null, {});
txService.onBlock(block, function(err, ops) { txService.onBlock(block, function(err, ops) {
if (err) { if (err) {
@ -101,9 +101,9 @@ describe('Transaction Service', function() {
}); });
describe('#getInputValues', function() { describe('#_getInputValues', function() {
it('should add missing input values on a tx', function(done) { it('should get input values', function(done) {
var put = sandbox.stub().callsArgWith(2, null); var put = sandbox.stub().callsArgWith(2, null);
txService._db = { put: put }; txService._db = { put: put };
@ -112,12 +112,12 @@ describe('Transaction Service', function() {
tx.__inputValues = []; tx.__inputValues = [];
txService.getInputValues(tx, {}, function(err, tx) { txService._getInputValues(tx, {}, function(err, values) {
if (err) { if (err) {
return done(err); return done(err);
} }
tx.__inputValues.should.deep.equal([1139033, 1139033, 500000, 1139033]); values.should.deep.equal([1139033, 1139033, 500000, 1139033]);
done(); done();
}); });