handle verification better. make use of cache.
This commit is contained in:
parent
ad95ffbfcd
commit
8ed054cbda
@ -1131,67 +1131,27 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
|
|||||||
|
|
||||||
// Lookup previous entry.
|
// Lookup previous entry.
|
||||||
// We can do this synchronously:
|
// We can do this synchronously:
|
||||||
// it is already cached.
|
// This will be cached in 99.9% of cases.
|
||||||
prev = self.db.getSync(prevHeight);
|
if (!self.db.isCached(prevHeight))
|
||||||
|
utils.debug('Warning: height %d is not cached.', prevHeight);
|
||||||
|
|
||||||
|
try {
|
||||||
|
prev = self.db.getSync(prevHeight);
|
||||||
|
} catch (e) {
|
||||||
|
return done(e);
|
||||||
|
}
|
||||||
|
|
||||||
assert(prev);
|
assert(prev);
|
||||||
|
|
||||||
// Do "contextual" verification on our block
|
// Do "contextual" verification on our block
|
||||||
// now that we're certain its previous
|
// now that we're certain its previous
|
||||||
// block is in the chain.
|
// block is in the chain.
|
||||||
self._verifyContext(block, prev, function(err, verified) {
|
self._verifyContext(block, prev, function(err, verified) {
|
||||||
|
var existing;
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
return done(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) {
|
if (!verified) {
|
||||||
self.invalid[entry.hash] = true;
|
self.invalid[entry.hash] = true;
|
||||||
self.emit('invalid', block, {
|
self.emit('invalid', block, {
|
||||||
@ -1203,6 +1163,62 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
|
|||||||
return done();
|
return done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Real fork resolution would just be this.
|
||||||
|
// if (entry.chainwork.cmp(self.tip.chainwork) > 0)
|
||||||
|
// return self.setBestChain(entry);
|
||||||
|
// return done();
|
||||||
|
|
||||||
|
// See if the height already exists (fork).
|
||||||
|
// Do this synchronously: This will
|
||||||
|
// be cached in 99.9% of cases.
|
||||||
|
if (self.db.has(entry.height)) {
|
||||||
|
if (!self.db.isCached(entry.height))
|
||||||
|
utils.debug('Warning: height %d is not cached.', entry.height);
|
||||||
|
|
||||||
|
try {
|
||||||
|
existing = self.db.getSync(entry.height);
|
||||||
|
} catch (e) {
|
||||||
|
return done(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
// return self.revertHeight(existing.height - 1, function(err) {
|
||||||
|
return 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);
|
||||||
|
|
||||||
// Update the block height
|
// Update the block height
|
||||||
block.height = entry.height;
|
block.height = entry.height;
|
||||||
block.txs.forEach(function(tx) {
|
block.txs.forEach(function(tx) {
|
||||||
|
|||||||
@ -243,6 +243,16 @@ ChainDB.prototype._cache = function _cache(entry) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ChainDB.prototype.isCached = function isCached(height) {
|
||||||
|
if (this.queue[height] != null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (this.cache[height] != null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
ChainDB.prototype.getHeight = function getHeight(hash) {
|
ChainDB.prototype.getHeight = function getHeight(hash) {
|
||||||
var height = this.heightLookup[hash];
|
var height = this.heightLookup[hash];
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user