Added more checks.
This commit is contained in:
parent
66e82a3fe7
commit
d5e5904329
@ -263,7 +263,7 @@ HeaderService.prototype._queueBlock = function(block) {
|
|||||||
return self.node.stop();
|
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;
|
header.timestamp = header.time;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('about to set last header from onHeader function');
|
|
||||||
this._lastHeader = header;
|
this._lastHeader = header;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@ -546,13 +545,24 @@ HeaderService.prototype._detectReorg = function(block, callback) {
|
|||||||
return callback(null, false);
|
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) {
|
if (err) {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
// is this block's prevHash already referenced in the database? If so, reorg
|
|
||||||
if (header) {
|
if (header) {
|
||||||
return callback(null, header);
|
return callback(null, header);
|
||||||
}
|
}
|
||||||
@ -617,7 +627,6 @@ HeaderService.prototype._onReorg = function(reorgHeader, headers, commonHeader,
|
|||||||
// setting our tip to the common ancestor
|
// setting our tip to the common ancestor
|
||||||
this._tip.hash = commonHeader.hash;
|
this._tip.hash = commonHeader.hash;
|
||||||
this._tip.height = commonHeader.height;
|
this._tip.height = commonHeader.height;
|
||||||
console.log('about to set last header from reorg function');
|
|
||||||
this._lastHeader = commonHeader;
|
this._lastHeader = commonHeader;
|
||||||
|
|
||||||
this._db.batch(ops, callback);
|
this._db.batch(ops, callback);
|
||||||
@ -638,6 +647,7 @@ HeaderService.prototype._onBestHeight = function(height) {
|
|||||||
HeaderService.prototype._startSync = function() {
|
HeaderService.prototype._startSync = function() {
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
// if our tip height is less than the best height of this peer, then:
|
// if our tip height is less than the best height of this peer, then:
|
||||||
// 1. the peer is not fully synced.
|
// 1. the peer is not fully synced.
|
||||||
// 2. the peer has reorg'ed and we need to handle this
|
// 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;
|
self._numNeeded = self._bestHeight - self._tip.height;
|
||||||
|
|
||||||
|
// common case
|
||||||
if (self._numNeeded > 0) {
|
if (self._numNeeded > 0) {
|
||||||
log.info('Header Service: Gathering: ' + self._numNeeded + ' ' + 'header(s) from the peer-to-peer network.');
|
log.info('Header Service: Gathering: ' + self._numNeeded + ' ' + 'header(s) from the peer-to-peer network.');
|
||||||
self._sync();
|
self._sync();
|
||||||
} else if (self._numNeeded < 0) {
|
} else if (self._numNeeded < 0) {
|
||||||
|
// this should be very uncommon
|
||||||
self._handleLowTipHeight();
|
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) {
|
HeaderService.prototype._findReorgConditionInNewPeer = function(callback) {
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var allHeaders = ;
|
self._removeAllSubscriptions();
|
||||||
|
|
||||||
|
var newPeerHeaders = new utils.SimpleMap();
|
||||||
var headerCount = 0;
|
var headerCount = 0;
|
||||||
var tipHash = self.GENESIS_HASH;
|
|
||||||
|
|
||||||
self._bus.removeAllListeners();
|
self.getAllHeaders(function(err, allHeaders) {
|
||||||
|
|
||||||
self._bus.on('p2p/headers', function(headers) {
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
headers.forEach(function(header) {
|
|
||||||
allHeaders[header.hash] = header.prevHash;
|
|
||||||
headerCount++;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (headerCount < self._bestHeight) {
|
|
||||||
return self._p2p.getHeaders({ startHash: tipHash });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.getAllHeaders(function(err, allHeaders) {
|
self._bus.subscribe('p2p/headers');
|
||||||
|
self._bus.on('p2p/headers', function(headers) {
|
||||||
|
|
||||||
if (err) {
|
headers.forEach(function(header) {
|
||||||
return callback(err);
|
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 (' +
|
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.' +
|
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) {
|
self._findReorgConditionInNewPeer(function(err, reorgInfo) {
|
||||||
|
|
||||||
@ -716,41 +764,43 @@ HeaderService.prototype._handleLowTipHeight = function() {
|
|||||||
return self.node.stop();
|
return self.node.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
// case 1: there is a reorg condition in the new peer
|
// Our peer is not yet sync'ed.
|
||||||
if (reorgInfo) {
|
// We will just turn on our block subscription and wait until we get a block we haven't seen
|
||||||
return self._p2p.getP2PBlock({
|
if (!reorgInfo) {
|
||||||
filter: {
|
self._onHeadersSave();
|
||||||
startHash: reorgInfo.commonHeader.hash,
|
}
|
||||||
endHash: 0
|
|
||||||
},
|
|
||||||
blockHash: reorgInfo.blockHash
|
|
||||||
}, function(block) {
|
|
||||||
|
|
||||||
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);
|
log.error(err);
|
||||||
return self.node.stop();
|
return self.node.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
self._syncBlock(block, function(err) {
|
self._sync();
|
||||||
|
|
||||||
if (err) {
|
|
||||||
log.error(err);
|
|
||||||
return self.node.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
var self = this;
|
||||||
|
|
||||||
self._p2p.getHeaders({ startHash: self._tip.hash });
|
|
||||||
|
|
||||||
if (!self._headerInterval) {
|
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() {
|
self._headerInterval = setInterval(function() {
|
||||||
log.info('Header Service: retrying get headers since ' + self._tip.hash);
|
log.info('Header Service: we have not received a response to getHeaders from the network, retrying.');
|
||||||
self._p2p.getHeaders({ startHash: self._tip.hash });
|
self._p2p.getHeaders({ startHash: hash });
|
||||||
}, 2000);
|
}, 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
|
// this gets the header that is +2 places from hash or returns 0 if there is no such
|
||||||
|
|||||||
@ -251,6 +251,7 @@ P2P.prototype._initPool = function() {
|
|||||||
opts.listenAddr = false;
|
opts.listenAddr = false;
|
||||||
opts.maxPeers = this._maxPeers;
|
opts.maxPeers = this._maxPeers;
|
||||||
opts.network = this.node.network;
|
opts.network = this.node.network;
|
||||||
|
p2p.Pool.RetrySeconds = 5;
|
||||||
this._pool = new p2p.Pool(opts);
|
this._pool = new p2p.Pool(opts);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user