new verifyContext.
This commit is contained in:
parent
02e4c9e266
commit
ab610d6fa5
@ -666,11 +666,9 @@ Chain.prototype.resetTime = function resetTime(ts) {
|
|||||||
return this.resetHeight(entry.height);
|
return this.resetHeight(entry.height);
|
||||||
};
|
};
|
||||||
|
|
||||||
Chain.prototype.add = function add(block, peer, callback) {
|
Chain.prototype.add = function add(initial, peer, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var initial = block;
|
|
||||||
var code = Chain.codes.unchanged;
|
var code = Chain.codes.unchanged;
|
||||||
var hash, prevHash, prevHeight, entry, tip, existing, checkpoint, prev;
|
|
||||||
var total = 0;
|
var total = 0;
|
||||||
|
|
||||||
callback = utils.asyncify(callback);
|
callback = utils.asyncify(callback);
|
||||||
@ -678,10 +676,10 @@ Chain.prototype.add = function add(block, peer, callback) {
|
|||||||
if (this._locked)
|
if (this._locked)
|
||||||
return callback(null, total);
|
return callback(null, total);
|
||||||
|
|
||||||
// (function next(block) {
|
(function next(block) {
|
||||||
(function next() {
|
var hash = block.hash('hex');
|
||||||
hash = block.hash('hex');
|
var prevHash = block.prevBlock;
|
||||||
prevHash = block.prevBlock;
|
var prevHeight, entry, existing, checkpoint, prev;
|
||||||
|
|
||||||
// Find the previous block height/index.
|
// Find the previous block height/index.
|
||||||
prevHeight = self.heightLookup[prevHash];
|
prevHeight = self.heightLookup[prevHash];
|
||||||
@ -746,84 +744,93 @@ Chain.prototype.add = function add(block, peer, callback) {
|
|||||||
height: prevHeight + 1
|
height: prevHeight + 1
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add entry if we do not have it (or if
|
// Fork at checkpoint
|
||||||
// there is another entry at its height)
|
// Block did not match the checkpoint. The
|
||||||
|
// 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.
|
||||||
|
checkpoint = network.checkpoints[entry.height];
|
||||||
|
if (checkpoint) {
|
||||||
|
self.emit('checkpoint', entry.height, entry.hash, checkpoint);
|
||||||
|
if (hash !== checkpoint) {
|
||||||
|
// Resetting to the last checkpoint _really_ isn't
|
||||||
|
// necessary (even bitcoind doesn't do it), but it
|
||||||
|
// could be used if you want to be on the overly
|
||||||
|
// safe (see: paranoid) side.
|
||||||
|
// this.resetLastCheckpoint(entry.height);
|
||||||
|
code = Chain.codes.badCheckpoint;
|
||||||
|
self.emit('fork', {
|
||||||
|
height: entry.height,
|
||||||
|
expected: network.checkpoints[entry.height],
|
||||||
|
received: entry.hash,
|
||||||
|
checkpoint: true
|
||||||
|
});
|
||||||
|
return done(null, code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if the entry already exists.
|
||||||
existing = self.db.get(entry.height);
|
existing = self.db.get(entry.height);
|
||||||
if (!existing || existing.hash !== hash) {
|
|
||||||
assert(self.heightLookup[entry.hash] == null);
|
// Entry already exists.
|
||||||
|
if (existing) {
|
||||||
|
// We already have this block. Do regular
|
||||||
|
// orphan resolution (won't do anything).
|
||||||
|
if (existing.hash === hash)
|
||||||
|
return handleOrphans();
|
||||||
|
|
||||||
// A valid block with an already existing
|
// A valid block with an already existing
|
||||||
// height came in, that spells fork. We
|
// height came in, that spells fork. We
|
||||||
// don't store by hash so we can't compare
|
// don't store by hash so we can't compare
|
||||||
// chainworks. We reset the chain, find a
|
// chainworks. We reset the chain, find a
|
||||||
// new peer, and wait to see who wins.
|
// new peer, and wait to see who wins.
|
||||||
if (existing) {
|
assert(self.heightLookup[entry.hash] == null);
|
||||||
// The tip has more chainwork, it is a
|
|
||||||
// higher height than the entry. This is
|
// The tip has more chainwork, it is a
|
||||||
// not an alternate tip. Ignore it.
|
// higher height than the entry. This is
|
||||||
if (self.tip.chainwork.cmp(entry.chainwork) > 0) {
|
// not an alternate tip. Ignore it.
|
||||||
code = Chain.codes.unchanged;
|
if (self.tip.chainwork.cmp(entry.chainwork) > 0) {
|
||||||
return done(null, code);
|
code = Chain.codes.unchanged;
|
||||||
}
|
return done(null, code);
|
||||||
// Get _our_ tip as opposed to
|
|
||||||
// the attempted alternate tip.
|
|
||||||
tip = existing;
|
|
||||||
// The block has equal chainwork (an
|
|
||||||
// alternate tip). Reset the chain, find
|
|
||||||
// a new peer, and wait to see who wins.
|
|
||||||
self._locked = true;
|
|
||||||
return self._removeBlock(tip.hash, function(err) {
|
|
||||||
self._locked = false;
|
|
||||||
if (err)
|
|
||||||
return done(err);
|
|
||||||
self.resetHeight(entry.height - 1);
|
|
||||||
self.emit('fork', {
|
|
||||||
height: prevHeight + 1,
|
|
||||||
expected: tip.hash,
|
|
||||||
received: hash,
|
|
||||||
checkpoint: false
|
|
||||||
}, peer);
|
|
||||||
code = Chain.codes.forked;
|
|
||||||
return done(null, code);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fork at checkpoint
|
// The block has equal chainwork (an
|
||||||
// Block did not match the checkpoint. The
|
// alternate tip). Reset the chain, find
|
||||||
// chain could be reset to the last sane
|
// a new peer, and wait to see who wins.
|
||||||
// checkpoint, but it really isn't necessary,
|
self._locked = true;
|
||||||
// so we don't do it. The misbehaving peer has
|
return self._removeBlock(existing.hash, function(err) {
|
||||||
// been killed and hopefully we find a peer
|
self._locked = false;
|
||||||
// who isn't trying to fool us.
|
if (err)
|
||||||
checkpoint = network.checkpoints[entry.height];
|
return done(err);
|
||||||
if (checkpoint) {
|
self.resetHeight(entry.height - 1);
|
||||||
self.emit('checkpoint', entry.height, entry.hash, checkpoint);
|
self.emit('fork', {
|
||||||
if (hash !== checkpoint) {
|
height: prevHeight + 1,
|
||||||
// Resetting to the last checkpoint _really_ isn't
|
expected: existing.hash,
|
||||||
// necessary (even bitcoind doesn't do it), but it
|
received: hash,
|
||||||
// could be used if you want to be on the overly
|
checkpoint: false
|
||||||
// safe (see: paranoid) side.
|
}, peer);
|
||||||
// this.resetLastCheckpoint(entry.height);
|
code = Chain.codes.forked;
|
||||||
code = Chain.codes.badCheckpoint;
|
return done(null, code);
|
||||||
self.emit('fork', {
|
});
|
||||||
height: entry.height,
|
}
|
||||||
expected: network.checkpoints[entry.height],
|
|
||||||
received: entry.hash,
|
|
||||||
checkpoint: true
|
|
||||||
});
|
|
||||||
return done(null, code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lookup previous entry.
|
// Add entry if we do not have it.
|
||||||
prev = self.db.get(prevHeight);
|
assert(self.heightLookup[entry.hash] == null);
|
||||||
assert(prev);
|
|
||||||
|
|
||||||
// Do "contextual" verification on our block
|
// Lookup previous entry.
|
||||||
// now that we're certain its previous
|
prev = self.db.get(prevHeight);
|
||||||
// block is in the chain.
|
assert(prev);
|
||||||
// self._verifyContext(block, prev, function(err, verified) {
|
|
||||||
if (!block.verifyContext(prev)) {
|
// Do "contextual" verification on our block
|
||||||
|
// now that we're certain its previous
|
||||||
|
// block is in the chain.
|
||||||
|
self._verifyContext(block, prev, function(err, verified) {
|
||||||
|
if (err)
|
||||||
|
return done(err);
|
||||||
|
|
||||||
|
if (!verified) {
|
||||||
code = Chain.codes.invalid;
|
code = Chain.codes.invalid;
|
||||||
self.emit('invalid', {
|
self.emit('invalid', {
|
||||||
height: prevHeight + 1,
|
height: prevHeight + 1,
|
||||||
@ -869,9 +876,7 @@ Chain.prototype.add = function add(block, peer, callback) {
|
|||||||
|
|
||||||
handleOrphans();
|
handleOrphans();
|
||||||
});
|
});
|
||||||
} else {
|
});
|
||||||
handleOrphans();
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleOrphans() {
|
function handleOrphans() {
|
||||||
if (!self.orphan.map[hash])
|
if (!self.orphan.map[hash])
|
||||||
@ -884,9 +889,9 @@ Chain.prototype.add = function add(block, peer, callback) {
|
|||||||
self.orphan.count--;
|
self.orphan.count--;
|
||||||
self.orphan.size -= block.getSize();
|
self.orphan.size -= block.getSize();
|
||||||
|
|
||||||
next();
|
next(block);
|
||||||
}
|
}
|
||||||
})();
|
})(initial);
|
||||||
|
|
||||||
function done(err, code) {
|
function done(err, code) {
|
||||||
// Failsafe for large orphan chains. Do not
|
// Failsafe for large orphan chains. Do not
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user