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._block = this.node.services.block;
this._timestamp = this.node.services.timestamp;
this._transaction = this.node.services.transaction;
this._network = this.node.network;
this._db = this.node.services.db;

View File

@ -565,7 +565,7 @@ HeaderService.prototype._detectReorg = function(block, callback) {
var nextBlock = prevHash === self._lastHeader.hash;
// 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);
}
@ -575,7 +575,7 @@ HeaderService.prototype._detectReorg = function(block, callback) {
}
// 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) {
@ -621,28 +621,39 @@ HeaderService.prototype._detectStartupReorg = function(callback) {
HeaderService.prototype._handleReorg = function(block, header, callback) {
var self = this;
self.getAllHeaders(function(err, headers) {
if (err || !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 +
' 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) {
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
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.');
self.emit('reorg', hash, headers);
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() {
this._p2p.once('bestHeight', this._onBestHeight.bind(this));

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "bitcore-node",
"version": "5.0.0-beta.5",
"version": "5.0.0-beta.6",
"lockfileVersion": 1,
"requires": true,
"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) {
var _processTransaction = sandbox.stub(txService, '_processTransaction');
var _processTransaction = sandbox.stub(txService, '_processTransaction').callsArgWith(2, null, {});
txService.onBlock(block, function(err, ops) {
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);
txService._db = { put: put };
@ -112,12 +112,12 @@ describe('Transaction Service', function() {
tx.__inputValues = [];
txService.getInputValues(tx, {}, function(err, tx) {
txService._getInputValues(tx, {}, function(err, values) {
if (err) {
return done(err);
}
tx.__inputValues.should.deep.equal([1139033, 1139033, 500000, 1139033]);
values.should.deep.equal([1139033, 1139033, 500000, 1139033]);
done();
});