refactor chain methods. check for orphans during fullnode sync.

This commit is contained in:
Christopher Jeffrey 2016-01-02 04:32:04 -08:00
parent 7a8a7a5a2b
commit 35ba5a5de5
3 changed files with 114 additions and 82 deletions

View File

@ -366,46 +366,38 @@ Chain.prototype._compress = function compress() {
this.block.bloom.add(this.block.list[i].hash('hex'), 'hex');
};
Chain.prototype.has = function has(hash, noProbe, cb) {
Chain.prototype.has = function has(hash, noIndex, cb) {
var i;
if (typeof noProbe === 'function') {
cb = noProbe;
noProbe = false;
if (typeof noIndex === 'function') {
cb = noIndex;
noIndex = false;
}
if (this.loading) {
this.once('load', function() {
this.has(hash, noProbe, cb);
this.has(hash, noIndex, cb);
});
return;
}
cb = utils.asyncify(cb);
if (this.block.bloom.test(hash, 'hex')) {
if (this.strict) {
for (i = 0; i < this.block.list.length; i++)
if (this.block.list[i].hash('hex') === hash)
return cb(true);
} else {
return cb(true);
}
}
if (this.hasCache(hash))
return cb(true);
if (this.hasOrphan(hash))
return cb(true);
if (!noProbe && this.hasBlock(hash))
return cb(true);
if (!noIndex) {
if (this.hasBlock(hash))
return cb(true);
}
return cb(false);
};
Chain.prototype.byHeight = function byHeight(height) {
if (this.loading)
return null;
var index = this.index.heights.indexOf(height);
if (index === -1)
@ -419,20 +411,7 @@ Chain.prototype.byHeight = function byHeight(height) {
};
};
Chain.prototype.getTip = function() {
var index = this.index.hashes.length - 1;
return {
index: index,
hash: this.index.hashes[index],
ts: this.index.ts[index],
height: this.index.heights[index]
};
};
Chain.prototype.byHash = function byHash(hash) {
if (this.loading)
return null;
if (Array.isArray(hash))
hash = utils.toHex(hash);
else if (hash.hash)
@ -452,27 +431,71 @@ Chain.prototype.byHash = function byHash(hash) {
};
Chain.prototype.hasBlock = function hasBlock(hash) {
if (this.loading)
return false;
if (Array.isArray(hash))
hash = utils.toHex(hash);
else if (hash.hash)
hash = hash.hash('hex');
// return this.byHash(hash);
return this.index.bloom.test(hash, 'hex');
};
Chain.prototype.hasOrphan = function hasOrphan(hash) {
if (this.loading)
return !!this.getOrphan(hash);
};
Chain.prototype.hasCache = function hasCache(hash) {
if (Array.isArray(hash))
hash = utils.toHex(hash);
else if (hash.hash)
hash = hash.hash('hex');
if (!this.block.bloom.test(hash, 'hex'))
return false;
if (this.strict)
return !!this.getCache(hash);
return true;
};
Chain.prototype.getBlock = function getBlock(hash) {
if (typeof hash === 'number')
return this.byHeight(hash);
return this.byHash(hash);
};
Chain.prototype.getOrphan = function getOrphan(hash) {
if (Array.isArray(hash))
hash = utils.toHex(hash);
else if (hash.hash)
hash = hash.hash('hex');
return this.orphan.bmap[hash] || null;
};
Chain.prototype.getCache = function getCache(hash) {
var i;
if (Array.isArray(hash))
hash = utils.toHex(hash);
else if (hash.hash)
hash = hash.hash('hex');
return !!this.orphan.bmap[hash];
for (i = 0; i < this.block.list.length; i++) {
if (this.block.list[i].hash('hex') === hash)
return this.block.list[i];
}
};
Chain.prototype.getTip = function() {
var index = this.index.hashes.length - 1;
return {
index: index,
hash: this.index.hashes[index],
ts: this.index.ts[index],
height: this.index.heights[index]
};
};
Chain.prototype.get = function get(hash, force, cb) {
@ -484,25 +507,20 @@ Chain.prototype.get = function get(hash, force, cb) {
}
// Cached block found
if (!force && this.block.bloom.test(hash, 'hex')) {
for (i = 0; i < this.block.list.length; i++) {
if (this.block.list[i].hash('hex') === hash) {
// NOTE: we return right after the statement - so `block` should be
// valid at the time of nextTick call
block = this.block.list[i];
bcoin.utils.nextTick(function() {
cb(block);
});
return;
if (!force) {
if (this.block.bloom.test(hash, 'hex')) {
block = this.getCache(hash);
if (block) {
bcoin.utils.nextTick(cb.bind(null, block));
return block;
}
// False positive:
// assert(false);
}
// False positive:
// assert(false);
if (this.hasOrphan(hash))
return cb(this.getOrphan(hash));
}
if (!force && this.orphan.bmap[hash])
return cb(this.orphan.bmap[hash]);
if (this.request.add(hash, cb))
this.emit('missing', hash, null, null);
};
@ -626,6 +644,18 @@ Chain.prototype.height = function height() {
return this.getTip().height;
};
Chain.prototype.target = function target(last) {
assert(false);
};
Chain.prototype.retarget = function retarget(last, firstTs) {
assert(false);
};
Chain.prototype.compact = function compact() {
assert(false);
};
Chain.prototype._save = function(hash, obj) {
var self = this;

View File

@ -263,37 +263,29 @@ Chain.prototype.add = function add(block) {
return err;
};
Chain.prototype.has = function has(hash, noProbe, cb) {
if (typeof noProbe === 'function') {
cb = noProbe;
noProbe = false;
Chain.prototype.has = function has(hash, noIndex, cb) {
if (typeof noIndex === 'function') {
cb = noIndex;
noIndex = false;
}
if (this.loading) {
this.once('load', function() {
this.has(hash, noProbe, cb);
this.has(hash, noIndex, cb);
});
return;
}
cb = utils.asyncify(cb);
// assert(!noProbe);
return cb(this.hasBlock(hash) || this.hasOrphan(hash));
};
Chain.prototype.byHeight = function byHeight(height) {
if (this.loading)
return null;
return this.index.entries[height] || null;
};
Chain.prototype.byHash = function byHash(hash) {
if (this.loading)
return null;
if (Array.isArray(hash))
hash = utils.toHex(hash);
else if (hash.hash)
@ -302,30 +294,39 @@ Chain.prototype.byHash = function byHash(hash) {
return this.byHeight(this.index.heights[hash]);
};
Chain.prototype.getTip = function getTip() {
if (this.loading)
return null;
return this.index.entries[this.index.entries.length - 1];
};
Chain.prototype.hasBlock = function hasBlock(hash) {
if (this.loading)
return false;
return !!this.byHash(hash);
};
Chain.prototype.hasOrphan = function hasOrphan(hash) {
if (this.loading)
return false;
return !!this.getOrphan(hash);
};
Chain.prototype.hasCache = function hasCache(hash) {
assert(false);
};
Chain.prototype.getBlock = function getBlock(hash) {
if (typeof hash === 'number')
return this.byHeight(hash);
return this.byHash(hash);
};
Chain.prototype.getOrphan = function getOrphan(hash) {
if (Array.isArray(hash))
hash = utils.toHex(hash);
else if (hash.hash)
hash = hash.hash('hex');
return !!this.orphan.bmap[hash];
return this.orphan.bmap[hash] || null;
};
Chain.prototype.getCache = function getCache(hash) {
assert(false);
};
Chain.prototype.getTip = function getTip() {
return this.index.entries[this.index.entries.length - 1];
};
Chain.prototype.get = function get(hash, force, cb) {
@ -360,9 +361,6 @@ Chain.prototype.getLast = function getLast(cb) {
};
Chain.prototype.getStartHeight = function getStartHeight() {
if (this.loading)
return 0;
return this.index.entries[this.index.entries.length - 1].height;
};
@ -509,6 +507,10 @@ Chain.prototype.retarget = function retarget(last, firstTs) {
return utils.toCompact(target);
};
Chain.prototype.compact = function compact() {
assert(false);
};
Chain.prototype._save = function(hash, obj) {
var self = this;

View File

@ -311,7 +311,7 @@ Pool.prototype._addLoader = function _addLoader() {
peer.loadBlocks(self.chain.locatorHashes(), 0);
// Request block if we don't have it
if (!self.chain.hasBlock(hash))
if (!self.chain.hasBlock(hash) && !self.chain.hasOrphan(hash))
self._request('block', hash);
}