cleanup chain db. fixes.

This commit is contained in:
Christopher Jeffrey 2016-01-20 19:56:47 -08:00
parent f6a35d0810
commit 43a365962b

View File

@ -45,40 +45,22 @@ function Chain(options) {
this.index = {
heights: {},
count: this.db.count(),
count: 0,
lastTs: 0
};
this.request = new utils.RequestCache();
this.fromJSON({
v: 2,
type: 'chain',
network: network.type,
entries: [
{
hash: network.genesis.hash,
version: network.genesis.version,
prevBlock: network.genesis.prevBlock,
merkleRoot: network.genesis.merkleRoot,
ts: network.genesis.ts,
bits: network.genesis.bits,
nonce: network.genesis.nonce,
height: 0
}
]
});
if (process.env.BCOIN_START_HEIGHT) {
this.storage = null;
if (network.type === 'main')
this.fromJSON(require('./protocol/preload-full'));
else if (network.type === 'testnet')
this.fromJSON(require('./protocol/preload-test-full'));
this.resetHeight(+process.env.BCOIN_START_HEIGHT);
}
this.tip = this.db.get(this.index.count - 1);
this._addIndex(ChainBlock.fromJSON(this, {
hash: network.genesis.hash,
version: network.genesis.version,
prevBlock: network.genesis.prevBlock,
merkleRoot: network.genesis.merkleRoot,
ts: network.genesis.ts,
bits: network.genesis.bits,
nonce: network.genesis.nonce,
height: 0
}), true);
// Last TS after preload, needed for fill percent
this.index.lastTs = this.tip.ts;
@ -121,44 +103,24 @@ Chain.prototype._init = function _init() {
this.loading = true;
if (!this.storage) {
utils.nextTick(function() {
self.loading = false;
self.emit('load');
});
return;
}
utils.debug('Chain is loading.');
utils.nextTick(function() {
utils.debug('Chain is loading.');
});
var count = self.db.count();
var i, entry;
s = this.storage.createReadStream({
start: this.prefix,
end: this.prefix + 'z'
});
for (i = 1; i < self.index.count; i++)
self._addIndex(self.db.get(i));
s.on('data', function(data) {
data.value.hash = data.key.slice(self.prefix.length);
self._addIndex(ChainBlock.fromJSON(self, data.value));
});
s.on('error', function(err) {
self.emit('error', err);
});
s.on('end', function() {
self.loading = false;
self.emit('load');
utils.debug('Chain successfully loaded.');
});
};
Chain.prototype.getEntry = function getEntry(height) {
};
Chain.prototype._addIndex = function _addIndex(entry, save) {
var self = this;
var existing;
// Already added
if (this.index.heights[entry.hash] != null) {
@ -167,7 +129,7 @@ Chain.prototype._addIndex = function _addIndex(entry, save) {
}
// Duplicate height
var existing = this.db.get(entry.height);
existing = this.db.get(entry.height);
if (existing && existing.hash === entry.hash)
return Chain.codes.unchanged;
@ -185,7 +147,9 @@ Chain.prototype._addIndex = function _addIndex(entry, save) {
}
}
this.db.save(entry);
if (save)
this.db.save(entry);
this.index.heights[entry.hash] = entry.height;
this.index.count++;
@ -257,7 +221,7 @@ Chain.prototype.resetTime = function resetTime(ts) {
Chain.prototype.add = function add(block, peer) {
var initial = block;
var code = Chain.codes.unchanged;
var hash, prevHash, prevHeight, entry, tip;
var hash, prevHash, prevHeight, entry, tip, existing;
var total = 0;
for (;;) {
@ -329,7 +293,7 @@ Chain.prototype.add = function add(block, peer) {
// Add entry if we do not have it (or if
// there is another entry at its height)
var existing = this.db.get(entry.height);
existing = this.db.get(entry.height);
if (!existing || existing.hash !== hash) {
assert(this.index.heights[entry.hash] == null);
@ -342,7 +306,6 @@ Chain.prototype.add = function add(block, peer) {
// The tip has more chainwork, it is a
// higher height than the entry. This is
// not an alternate tip. Ignore it.
if (0)
if (this.tip.chainwork.cmp(entry.chainwork) > 0) {
code = Chain.codes.unchanged;
break;
@ -474,12 +437,25 @@ Chain.prototype.byHash = function byHash(hash) {
};
Chain.prototype.byTime = function byTime(ts) {
for (var i = this.index.count - 1; i >= 0; i--) {
var existing = this.db.get(i);
var i, delta, existing;
var step = 1;
if (ts >= this.tip.ts)
return this.tip;
for (i = this.index.count - 1; i >= 0; i -= step) {
existing = this.db.get(i);
if (ts >= existing.ts)
return existing;
delta = existing.ts - ts;
// If they're more than 1000 blocks apart
if (delta > 1000 * 60 * 10)
step *= 2;
}
return null;
return this.db.get(0);
};
Chain.prototype.hasBlock = function hasBlock(hash) {
@ -540,7 +516,7 @@ Chain.prototype.locatorHashes = function locatorHashes(start) {
var hashes = [];
var top = this.height();
var step = 1;
var i;
var i, existing;
if (start) {
if (utils.isBuffer(start))
@ -564,11 +540,11 @@ Chain.prototype.locatorHashes = function locatorHashes(start) {
top = start;
}
// assert(chain[top]);
assert(this.db.get(top));
i = top;
for (;;) {
var existing = this.db.get(i);
existing = this.db.get(i);
if (existing)
hashes.push(existing.hash);
i = i - step;
@ -709,7 +685,7 @@ Chain.prototype.fromJSON = function fromJSON(json) {
assert.equal(json.network, network.type);
json.entries.forEach(function(entry) {
this._addIndex(ChainBlock.fromJSON(this, entry), true);
this._addIndex(ChainBlock.fromJSON(this, entry));
}, this);
};
@ -717,8 +693,8 @@ Chain.prototype.fromJSON = function fromJSON(json) {
* ChainDB
*/
var BLOCK_SIZE = 80;
// var BLOCK_SIZE = 144;
// var BLOCK_SIZE = 80;
var BLOCK_SIZE = 112;
function ChainDB(chain) {
var exists;
@ -952,8 +928,8 @@ function ChainBlock(chain, data) {
this.bits = data.bits;
this.nonce = data.nonce;
this.height = data.height;
this.chainwork = data.chainwork || new bn(0);
// this.chainwork = data.chainwork || this.getChainwork();
// this.chainwork = data.chainwork || new bn(0);
this.chainwork = data.chainwork || this.getChainwork();
}
ChainBlock.prototype.__defineGetter__('prev', function() {
@ -1041,8 +1017,7 @@ ChainBlock.prototype.toRaw = function toRaw() {
utils.writeU32(res, this.ts, 68);
utils.writeU32(res, this.bits, 72);
utils.writeU32(res, this.nonce, 76);
// utils.copy(utils.toArray(this.hash, 'hex'), res, 80);
// utils.copy(this.chainwork.toArray('be', 32), res, 112);
utils.copy(this.chainwork.toArray('be', 32), res, 80);
return res;
};
@ -1057,8 +1032,7 @@ ChainBlock.fromRaw = function fromRaw(chain, height, p) {
bits: utils.readU32(p, 72),
nonce: utils.readU32(p, 76),
height: height,
// hash: utils.toHex(utils.toArray(p.slice(80, 112))),
// chainwork: new bn(p.slice(112, 144))
chainwork: new bn(p.slice(80, 112))
});
};