do verification on forked blocks.

This commit is contained in:
Christopher Jeffrey 2016-02-19 20:40:48 -08:00
parent 70553c884c
commit ad95ffbfcd

View File

@ -980,7 +980,6 @@ Chain.prototype._onFlush = function _onFlush(callback) {
Chain.prototype.add = function add(initial, peer, callback, force) {
var self = this;
var host = peer ? peer.host : 'unknown';
var total = 0;
assert(!this.loading);
@ -994,17 +993,13 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
var prevHash = block.prevBlock;
var prevHeight, entry, checkpoint, prev, orphan;
// We already have this block. Do regular
// orphan resolution (won't do anything).
// NOTE: Wrap this in a nextTick to avoid
// a stack overflow if there are a lot of
// existing blocks.
// We already have this block.
if (self.db.has(hash)) {
self.emit('exists', block, {
height: entry.height,
hash: entry.hash
}, peer);
return utils.nextTick(handleOrphans);
return done();
}
// Do not revalidate known invalid blocks.
@ -1012,9 +1007,10 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
self.emit('invalid', block, {
height: -1,
hash: hash,
seen: true,
chain: self.invalid[prevHash]
seen: !!self.invalid[hash],
chain: !!self.invalid[prevHash]
}, peer);
self.invalid[hash] = true;
return done();
}
@ -1133,57 +1129,6 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
}
}
// See if the entry already exists.
if (self.db.has(entry.height)) {
return self.db.getAsync(entry.height, function(err, existing) {
if (err)
return done(err);
// Shouldn't be the same by this point.
assert(existing.hash !== entry.hash);
// A valid block with an already existing
// height came in, that spells fork. We
// don't store by hash so we can't compare
// chainworks. We reset the chain, find a
// new peer, and wait to see who wins.
assert(self.db.getHeight(entry.hash) === -1);
// The tip has more chainwork, it is a
// higher height than the entry. This is
// not an alternate tip. Ignore it.
if (existing.chainwork.cmp(entry.chainwork) > 0)
return done();
// NOTE: We should do contextual verification
// here if we were a fullnode that actually
// stored multiple chains, but since we backoff,
// we can ignore that until the shorter chain
// stops being propogated.
// The block has equal chainwork (an
// alternate tip). Reset the chain, find
// a new peer, and wait to see who wins.
// self.revertHeight(existing.height - 1, function(err) {
self._revertLast(existing, function(err, existingBlock) {
if (err)
return done(err);
self.emit('fork', block, {
height: existing.height,
expected: existing.hash,
received: entry.hash,
checkpoint: false
}, peer);
return done();
}, true);
});
}
// Add entry if we do not have it.
assert(self.db.getHeight(entry.hash) === -1);
// Lookup previous entry.
// We can do this synchronously:
// it is already cached.
@ -1197,6 +1142,56 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
if (err)
return done(err);
// Real fork resolution would just be this.
// if (entry.chainwork.cmp(self.tip.chainwork) > 0)
// return self.setBestChain(entry);
// return done();
// See if the entry already exists.
if (self.db.has(entry.height)) {
return self.db.getAsync(entry.height, function(err, existing) {
if (err)
return done(err);
// Shouldn't be the same by this point.
assert(existing.hash !== entry.hash);
// A valid block with an already existing
// height came in, that spells fork. We
// don't store by hash so we can't compare
// chainworks. We reset the chain, find a
// new peer, and wait to see who wins.
assert(self.db.getHeight(entry.hash) === -1);
// The tip has more chainwork, it is a
// higher height than the entry. This is
// not an alternate tip. Ignore it.
if (existing.chainwork.cmp(entry.chainwork) > 0)
return done();
// The block has equal chainwork (an
// alternate tip). Reset the chain, find
// a new peer, and wait to see who wins.
// self.revertHeight(existing.height - 1, function(err) {
self._revertLast(existing, function(err, existingBlock) {
if (err)
return done(err);
self.emit('fork', block, {
height: existing.height,
expected: existing.hash,
received: entry.hash,
checkpoint: false
}, peer);
return done();
}, true);
});
}
// Add entry if we do not have it.
assert(self.db.getHeight(entry.hash) === -1);
if (!verified) {
self.invalid[entry.hash] = true;
self.emit('invalid', block, {