chain improvements.

This commit is contained in:
Christopher Jeffrey 2016-01-09 14:21:17 -08:00
parent 314c14f422
commit 0658444eb5
2 changed files with 47 additions and 38 deletions

View File

@ -109,7 +109,7 @@ Chain.messages = {
}; };
Chain.msg = function msg(code) { Chain.msg = function msg(code) {
return new Error(Chain.messages[code] || 'Unknown'); return Chain.messages[code] || 'Unknown';
}; };
Chain.prototype._init = function _init() { Chain.prototype._init = function _init() {
@ -286,13 +286,7 @@ Chain.prototype.add = function add(block, peer) {
var initial = block; var initial = block;
var code = Chain.codes.unchanged; var code = Chain.codes.unchanged;
var hash, prevHash, prevHeight, entry, tip; var hash, prevHash, prevHeight, entry, tip;
var total = 0;
if (this.loading) {
this.once('load', function() {
this.add(block);
});
return;
}
for (;;) { for (;;) {
// Validate the block we want to add. // Validate the block we want to add.
@ -310,6 +304,22 @@ Chain.prototype.add = function add(block, peer) {
// If the block is already known to be // If the block is already known to be
// an orphan, ignore it. // an orphan, ignore it.
if (this.orphan.map[prevHash]) { if (this.orphan.map[prevHash]) {
// If the orphan chain forked, simply
// reset the orphans and find a new peer.
if (this.orphan.map[prevHash].hash('hex') !== hash) {
this.orphan.map = {};
this.orphan.bmap = {};
this.orphan.count = 0;
this.orphan.size = 0;
this.emit('fork', {
height: -1,
expected: this.orphan.map[prevHash].hash('hex'),
received: hash,
checkpoint: null
});
code = Chain.codes.forked;
break;
}
code = Chain.codes.knownOrphan; code = Chain.codes.knownOrphan;
break; break;
} }
@ -325,6 +335,7 @@ Chain.prototype.add = function add(block, peer) {
this.orphan.map[prevHash] = block; this.orphan.map[prevHash] = block;
this.orphan.bmap[hash] = block; this.orphan.bmap[hash] = block;
code = Chain.codes.newOrphan; code = Chain.codes.newOrphan;
total++;
break; break;
} }
@ -398,6 +409,10 @@ Chain.prototype.add = function add(block, peer) {
if (code !== Chain.codes.okay) if (code !== Chain.codes.okay)
break; break;
// Keep track of the number of blocks we
// added and the number of orphans resolved.
total++;
// Emit our block (and potentially resolved // Emit our block (and potentially resolved
// orphan) so the programmer can save it. // orphan) so the programmer can save it.
this.emit('block', block, peer); this.emit('block', block, peer);
@ -436,7 +451,10 @@ Chain.prototype.add = function add(block, peer) {
// this.compact(); // this.compact();
// } // }
return code; if (code !== Chain.codes.okay)
this.emit('debug', 'Chain Error: %s', Chain.msg(code));
return total;
}; };
Chain.prototype.has = function has(hash, cb) { Chain.prototype.has = function has(hash, cb) {

View File

@ -326,15 +326,21 @@ Pool.prototype._addLoader = function _addLoader() {
}); });
peer.on('merkleblock', function(block) { peer.on('merkleblock', function(block) {
self._startInterval(); // If the peer sent us a block that was added
self._startTimer(); // to the chain (not orphans), reset the timeout.
self._handleBlock(block, peer); if (self._handleBlock(block, peer)) {
self._startInterval();
self._startTimer();
}
}); });
peer.on('block', function(block) { peer.on('block', function(block) {
self._startInterval(); // If the peer sent us a block that was added
self._startTimer(); // to the chain (not orphans), reset the timeout.
self._handleBlock(block, peer); if (self._handleBlock(block, peer)) {
self._startInterval();
self._startTimer();
}
}); });
if (self.options.headers) { if (self.options.headers) {
@ -499,7 +505,7 @@ Pool.prototype._handleBlock = function _handleBlock(block, peer) {
// Ignore if we already have // Ignore if we already have
if (this.chain.has(block)) { if (this.chain.has(block)) {
this.emit('debug', 'Already have block %s (%s)', block.height, peer.host); this.emit('debug', 'Already have block %s (%s)', block.height, peer.host);
return; return false;
} }
// Make sure the block is valid // Make sure the block is valid
@ -507,7 +513,7 @@ Pool.prototype._handleBlock = function _handleBlock(block, peer) {
this.emit('debug', this.emit('debug',
'Block verification failed for %s (%s)', 'Block verification failed for %s (%s)',
block.rhash, peer.host); block.rhash, peer.host);
return; return false;
} }
// Someone is sending us blocks without us requesting them. // Someone is sending us blocks without us requesting them.
@ -531,38 +537,23 @@ Pool.prototype._handleBlock = function _handleBlock(block, peer) {
this.chain.getOrphanRoot(block) this.chain.getOrphanRoot(block)
); );
this.emit('debug', 'Handled orphan %s (%s)', block.rhash, peer.host); this.emit('debug', 'Handled orphan %s (%s)', block.rhash, peer.host);
return; return false;
} }
} }
// Add to index and emit/save // Add to index and emit/save
if (this._addIndex(block, peer)) if (this._addIndex(block, peer)) {
this.emit('pool block', block, peer); this.emit('pool block', block, peer);
return true;
}
}; };
Pool.prototype._addIndex = function _addIndex(block, peer) { Pool.prototype._addIndex = function _addIndex(block, peer) {
var self = this; var added = this.chain.add(block, peer);
var hash, size, orphans, res;
hash = block.hash('hex');
size = this.chain.size();
orphans = this.chain.orphan.count;
res = this.chain.add(block, peer);
if (res !== bcoin.chain.codes.okay)
this.emit('chain-error', bcoin.chain.msg(res));
// Do not emit if nothing was added to the chain
if (this.chain.size() === size) {
if (this.chain.orphan.count > orphans)
return true;
return false;
}
this.emit('chain-progress', this.chain.fillPercent(), peer); this.emit('chain-progress', this.chain.fillPercent(), peer);
return true; return added > 0;
}; };
Pool.prototype.isFull = function isFull() { Pool.prototype.isFull = function isFull() {