Added more checks.

This commit is contained in:
Chris Kleeschulte 2017-09-19 11:03:39 -04:00
parent 66e82a3fe7
commit d5e5904329
No known key found for this signature in database
GPG Key ID: 33195D27EF6BDB7F
2 changed files with 112 additions and 56 deletions

View File

@ -263,7 +263,7 @@ HeaderService.prototype._queueBlock = function(block) {
return self.node.stop();
}
log.info('Header Service: completed processing block: ' + block.rhash() + ' prev hash: ' + bcoin.util.revHex(block.prevBlock));
log.debug('Header Service: completed processing block: ' + block.rhash() + ' prev hash: ' + bcoin.util.revHex(block.prevBlock));
});
@ -373,7 +373,6 @@ HeaderService.prototype._onHeader = function(header) {
header.timestamp = header.time;
}
console.log('about to set last header from onHeader function');
this._lastHeader = header;
return [
@ -546,13 +545,24 @@ HeaderService.prototype._detectReorg = function(block, callback) {
return callback(null, false);
}
this.getBlockHeader(prevHash, function(err, header) {
// first we check if the new block's prev hash is already in our data set
// if it is and this block isn't already in our data set too, then we have a reorg
async.waterfall([
function(next) {
self.getBlockHeader(block.rhash(), next);
},
function(header, next) {
if (header) {
return callback(null, false);
}
self.getBlockHeader(prevHash, next);
}
], function(err, header) {
if (err) {
return callback(err);
}
// is this block's prevHash already referenced in the database? If so, reorg
if (header) {
return callback(null, header);
}
@ -617,7 +627,6 @@ HeaderService.prototype._onReorg = function(reorgHeader, headers, commonHeader,
// setting our tip to the common ancestor
this._tip.hash = commonHeader.hash;
this._tip.height = commonHeader.height;
console.log('about to set last header from reorg function');
this._lastHeader = commonHeader;
this._db.batch(ops, callback);
@ -638,6 +647,7 @@ HeaderService.prototype._onBestHeight = function(height) {
HeaderService.prototype._startSync = function() {
var self = this;
// if our tip height is less than the best height of this peer, then:
// 1. the peer is not fully synced.
// 2. the peer has reorg'ed and we need to handle this
@ -656,10 +666,12 @@ HeaderService.prototype._startSync = function() {
self._numNeeded = self._bestHeight - self._tip.height;
// common case
if (self._numNeeded > 0) {
log.info('Header Service: Gathering: ' + self._numNeeded + ' ' + 'header(s) from the peer-to-peer network.');
self._sync();
} else if (self._numNeeded < 0) {
// this should be very uncommon
self._handleLowTipHeight();
}
@ -667,38 +679,74 @@ HeaderService.prototype._startSync = function() {
};
HeaderService.prototype._removeAllSubscriptions = function() {
this._bus.unsubscribe('p2p/headers');
this._bus.unsubscribe('p2p/block');
this._bus.removeAllListeners();
};
HeaderService.prototype._findReorgConditionInNewPeer = function(callback) {
var self = this;
var allHeaders = ;
self._removeAllSubscriptions();
var newPeerHeaders = new utils.SimpleMap();
var headerCount = 0;
var tipHash = self.GENESIS_HASH;
self._bus.removeAllListeners();
self.getAllHeaders(function(err, allHeaders) {
self._bus.on('p2p/headers', function(headers) {
headers.forEach(function(header) {
allHeaders[header.hash] = header.prevHash;
headerCount++;
});
if (headerCount < self._bestHeight) {
return self._p2p.getHeaders({ startHash: tipHash });
if (err) {
return callback(err);
}
self.getAllHeaders(function(err, allHeaders) {
self._bus.subscribe('p2p/headers');
self._bus.on('p2p/headers', function(headers) {
if (err) {
return callback(err);
headers.forEach(function(header) {
newPeerHeaders.set(header.hash, header);
headerCount++;
});
if (headerCount < self._bestHeight) {
return self._getP2PHeaders(headers[headers.length - 1].hash);
}
if (allHeaders.get(
// We should have both sets of headers, work from latest header to oldest and find the common header.
// Use the new set since we know this is a shorter list.
var reorgInfo = { commonHeader: null, blockHash: null };
for(var i = newPeerHeaders.length - 1; i >= 0; i--) {
var newHeader = newPeerHeaders.getIndex(i);
var oldHeader = allHeaders.get(newHeader.hash);
if (oldHeader) {
self._removeAllSubscriptions();
// we found a common header, but no headers that at a greater height, this peer is not synced
if (!reorgInfo.blockHash) {
return callback();
}
reorgInfo.commonHeader = oldHeader;
return callback(null, reorgInfo);
}
reorgInfo.blockHash = newHeader.hash;
}
// nothing matched...
// at this point, we should wonder if we are connected to the wrong network
assert(true, 'We tried to find a common header between current set of headers ' +
'and the new peer\'s set of headers, but there were none. This should be impossible ' +
' if the new peer is using the same genesis block.');
});
});
self._getP2PHeaders(self.GENESIS_HASH);
});
};
@ -707,7 +755,7 @@ HeaderService.prototype._handleLowTipHeight = function() {
log.warn('Header Service: Connected Peer has a best height (' + self._bestHeight + ') which is lower than our tip height (' +
self._tip.height + '). This means that this peer is not fully synchronized with the network -or- the peer has reorganized itself.' +
' Checking the new peer\'s header for a reorganization event.');
' Checking the new peer\'s headers for a reorganization event.');
self._findReorgConditionInNewPeer(function(err, reorgInfo) {
@ -716,41 +764,43 @@ HeaderService.prototype._handleLowTipHeight = function() {
return self.node.stop();
}
// case 1: there is a reorg condition in the new peer
if (reorgInfo) {
return self._p2p.getP2PBlock({
filter: {
startHash: reorgInfo.commonHeader.hash,
endHash: 0
},
blockHash: reorgInfo.blockHash
}, function(block) {
// Our peer is not yet sync'ed.
// We will just turn on our block subscription and wait until we get a block we haven't seen
if (!reorgInfo) {
self._onHeadersSave();
}
self._handleReorg(block, reorgInfo.commonHeader, function(err) {
// our peer has reorg'ed to lower overall height.
// we should get the first block after the split, reorg back to this height and then continue.
self._p2p.getP2PBlock({
filter: {
startHash: reorgInfo.commonHeader.hash,
endHash: 0
},
blockHash: reorgInfo.blockHash
}, function(block) {
if(err) {
self._handleReorg(block, reorgInfo.commonHeader, function(err) {
if(err) {
log.error(err);
return self.node.stop();
}
self._syncBlock(block, function(err) {
if (err) {
log.error(err);
return self.node.stop();
}
self._syncBlock(block, function(err) {
if (err) {
log.error(err);
return self.node.stop();
}
self._sync();
});
self._sync();
});
});
});
}
// case 2: the new peer is just not synced up, so we must wait
self._sync();
});
@ -776,21 +826,26 @@ HeaderService.prototype._logProgress = function() {
};
HeaderService.prototype._sync = function() {
HeaderService.prototype._getP2PHeaders = function(hash) {
var self = this;
self._p2p.getHeaders({ startHash: self._tip.hash });
if (!self._headerInterval) {
// when connecting to a peer that isn't yet responding to getHeaders, we will start a interval timer
// to retry until we can get headers, this may be a very long interval
self._headerInterval = setInterval(function() {
log.info('Header Service: retrying get headers since ' + self._tip.hash);
self._p2p.getHeaders({ startHash: self._tip.hash });
log.info('Header Service: we have not received a response to getHeaders from the network, retrying.');
self._p2p.getHeaders({ startHash: hash });
}, 2000);
}
self._p2p.getHeaders({ startHash: hash });
};
HeaderService.prototype._sync = function() {
this._getP2PHeaders(this._tip.hash);
};
// this gets the header that is +2 places from hash or returns 0 if there is no such

View File

@ -251,6 +251,7 @@ P2P.prototype._initPool = function() {
opts.listenAddr = false;
opts.maxPeers = this._maxPeers;
opts.network = this.node.network;
p2p.Pool.RetrySeconds = 5;
this._pool = new p2p.Pool(opts);
};