chain events.

This commit is contained in:
Christopher Jeffrey 2016-07-01 14:27:43 -07:00
parent 2b05bd0581
commit 6566620c5d
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
2 changed files with 54 additions and 122 deletions

View File

@ -133,48 +133,31 @@ Chain.prototype._init = function _init() {
}); });
this.on('resolved', function(block, entry) { this.on('resolved', function(block, entry) {
bcoin.debug('Orphan %s (%d) was resolved.', bcoin.debug('Orphan %s (%d) was resolved.', block.rhash, entry.height);
utils.revHex(entry.hash), entry.height);
}); });
this.on('checkpoint', function(block, data) { this.on('checkpoint', function(block, height) {
bcoin.debug('Hit checkpoint block %s (%d).', bcoin.debug('Hit checkpoint block %s (%d).', block.rhash, height);
utils.revHex(data.checkpoint), data.height);
}); });
this.on('fork', function(block, data) { this.on('fork', function(block, height, expected) {
bcoin.debug( bcoin.debug(
'Fork at height %d: expected=%s received=%s checkpoint=%s', 'Fork at height %d: expected=%s received=%s',
data.height, height,
utils.revHex(data.expected), utils.revHex(expected),
utils.revHex(data.received), block.rhash
data.checkpoint
); );
if (data.checkpoint)
bcoin.debug('WARNING: Block failed a checkpoint.');
}); });
this.on('invalid', function(block, data) { this.on('invalid', function(block, height) {
bcoin.debug( bcoin.debug('Invalid block at height %d: hash=%s', height, block.rhash);
'Invalid block at height %d: hash=%s',
data.height,
utils.revHex(data.hash)
);
if (data.chain) {
bcoin.debug(
'Peer is sending an invalid continuation chain.');
} else if (data.seen) {
bcoin.debug('Peer is sending an invalid chain.');
}
}); });
this.on('exists', function(block, data) { this.on('exists', function(block, height) {
bcoin.debug('Already have block %s (%d).', bcoin.debug('Already have block %s (%d).', block.rhash, height);
utils.revHex(data.hash), data.height);
});
this.on('orphan', function(block, data) { this.on('orphan', function(block, height) {
bcoin.debug('Handled orphan %s.', utils.revHex(data.hash)); bcoin.debug('Handled orphan %s (%d).', block.rhash, height);
}); });
this.on('purge', function(count, size) { this.on('purge', function(count, size) {
@ -1068,12 +1051,7 @@ Chain.prototype.reorganize = function reorganize(entry, block, callback) {
if (err) if (err)
return callback(err); return callback(err);
self.emit('fork', block, { self.emit('fork', block, tip.height, tip.hash);
height: fork.height,
expected: tip.hash,
received: entry.hash,
checkpoint: false
});
return callback(); return callback();
}); });
@ -1141,12 +1119,7 @@ Chain.prototype.connect = function connect(entry, callback) {
if (err) { if (err) {
if (err.type === 'VerifyError') { if (err.type === 'VerifyError') {
self.invalid[entry.hash] = true; self.invalid[entry.hash] = true;
self.emit('invalid', block, { self.emit('invalid', block, entry.height);
height: entry.height,
hash: entry.hash,
seen: false,
chain: false
});
} }
return callback(err); return callback(err);
} }
@ -1200,12 +1173,7 @@ Chain.prototype.setBestChain = function setBestChain(entry, block, prev, callbac
if (err.type === 'VerifyError') { if (err.type === 'VerifyError') {
self.invalid[entry.hash] = true; self.invalid[entry.hash] = true;
self.emit('invalid', block, { self.emit('invalid', block, entry.height);
height: entry.height,
hash: entry.hash,
seen: false,
chain: false
});
} }
return callback(err); return callback(err);
@ -1372,22 +1340,14 @@ Chain.prototype.add = function add(block, callback, force) {
// Do not revalidate known invalid blocks. // Do not revalidate known invalid blocks.
if (self.invalid[hash] || self.invalid[prevHash]) { if (self.invalid[hash] || self.invalid[prevHash]) {
self.emit('invalid', block, { self.emit('invalid', block, block.getCoinbaseHeight());
height: block.getCoinbaseHeight(),
hash: hash,
seen: !!self.invalid[hash],
chain: !!self.invalid[prevHash]
});
self.invalid[hash] = true; self.invalid[hash] = true;
return done(new VerifyError(block, 'duplicate', 'duplicate', 100)); return done(new VerifyError(block, 'duplicate', 'duplicate', 100));
} }
// Do we already have this block? // Do we already have this block?
if (self.hasPending(hash)) { if (self.hasPending(hash)) {
self.emit('exists', block, { self.emit('exists', block, block.getCoinbaseHeight());
height: block.getCoinbaseHeight(),
hash: hash
});
return done(new VerifyError(block, 'duplicate', 'duplicate', 0)); return done(new VerifyError(block, 'duplicate', 'duplicate', 0));
} }
@ -1395,22 +1355,14 @@ Chain.prototype.add = function add(block, callback, force) {
// an orphan, ignore it. // an orphan, ignore it.
orphan = self.orphan.map[prevHash]; orphan = self.orphan.map[prevHash];
if (orphan) { if (orphan) {
// If the orphan chain forked, simply // The orphan chain forked.
// reset the orphans.
if (orphan.hash('hex') !== hash) { if (orphan.hash('hex') !== hash) {
self.emit('fork', block, { self.emit('fork', block,
height: block.getCoinbaseHeight(), block.getCoinbaseHeight(),
expected: orphan.hash('hex'), orphan.hash('hex'));
received: hash,
checkpoint: false
});
} }
self.emit('orphan', block, { self.emit('orphan', block, block.getCoinbaseHeight());
height: block.getCoinbaseHeight(),
hash: hash,
seen: true
});
return done(new VerifyError(block, 'invalid', 'bad-prevblk', 0)); return done(new VerifyError(block, 'invalid', 'bad-prevblk', 0));
} }
@ -1425,12 +1377,7 @@ Chain.prototype.add = function add(block, callback, force) {
// orphans. // orphans.
if (initial && !block.verify(ret)) { if (initial && !block.verify(ret)) {
self.invalid[hash] = true; self.invalid[hash] = true;
self.emit('invalid', block, { self.emit('invalid', block, block.getCoinbaseHeight());
height: block.getCoinbaseHeight(),
hash: hash,
seen: false,
chain: false
});
return done(new VerifyError(block, 'invalid', ret.reason, ret.score)); return done(new VerifyError(block, 'invalid', ret.reason, ret.score));
} }
@ -1440,10 +1387,7 @@ Chain.prototype.add = function add(block, callback, force) {
// Do we already have this block? // Do we already have this block?
if (existing) { if (existing) {
self.emit('exists', block, { self.emit('exists', block, block.getCoinbaseHeight());
height: block.getCoinbaseHeight(),
hash: hash
});
return done(new VerifyError(block, 'duplicate', 'duplicate', 0)); return done(new VerifyError(block, 'duplicate', 'duplicate', 0));
} }
@ -1476,44 +1420,28 @@ Chain.prototype.add = function add(block, callback, force) {
self.network.updateHeight(self.bestHeight); self.network.updateHeight(self.bestHeight);
} }
self.emit('orphan', block, { self.emit('orphan', block, block.getCoinbaseHeight());
height: block.getCoinbaseHeight(),
hash: hash,
seen: false
});
return done(new VerifyError(block, 'invalid', 'bad-prevblk', 0)); return done(new VerifyError(block, 'invalid', 'bad-prevblk', 0));
} }
// Verify the checkpoint. // Verify the checkpoint.
checkpoint = self.network.checkpoints[height]; if (self.options.useCheckpoints) {
if (checkpoint) { checkpoint = self.network.checkpoints[height];
self.emit('checkpoint', block, { if (checkpoint) {
height: height, // Someone is very likely trying to fool us.
hash: hash, if (hash !== checkpoint) {
checkpoint: checkpoint self.purgeOrphans();
});
// Block did not match the checkpoint. The self.emit('fork', block, height, checkpoint);
// chain could be reset to the last sane
// checkpoint, but it really isn't necessary,
// so we don't do it. The misbehaving peer has
// been killed and hopefully we find a peer
// who isn't trying to fool us.
if (hash !== checkpoint) {
self.purgeOrphans();
self.emit('fork', block, { return done(new VerifyError(block,
height: height, 'checkpoint',
expected: checkpoint, 'checkpoint mismatch',
received: hash, 100));
checkpoint: true }
});
return done(new VerifyError(block, self.emit('checkpoint', block, height);
'checkpoint',
'checkpoint mismatch',
100));
} }
} }

View File

@ -231,24 +231,28 @@ Pool.prototype._init = function _init() {
}); });
} }
this.chain.on('block', function(block, entry, peer) { this.chain.on('block', function(block, entry) {
self.emit('block', block, peer); self.emit('block', block, entry);
}); });
this.chain.on('fork', function(block, data, peer) { this.chain.on('competitor', function(block, entry) {
self.emit('fork', data, peer); self.emit('competitor', block, entry);
}); });
this.chain.on('invalid', function(block, data, peer) { this.chain.on('fork', function(block, height, expected) {
self.emit('invalid', data, peer); self.emit('fork', block, height, expected);
}); });
this.chain.on('exists', function(block, data, peer) { this.chain.on('invalid', function(block, height) {
self.emit('exists', data, peer); self.emit('invalid', block, height);
}); });
this.chain.on('orphan', function(block, data, peer) { this.chain.on('exists', function(block, height) {
self.emit('orphan', data, peer); self.emit('exists', block, height);
});
this.chain.on('orphan', function(block, height) {
self.emit('orphan', block, height);
}); });
this.chain.on('full', function() { this.chain.on('full', function() {