move more logic into chaindb.
This commit is contained in:
parent
5053fa2eeb
commit
8b17c09116
@ -37,10 +37,11 @@ function Chain(options) {
|
|||||||
this.db = new bcoin.chaindb(this);
|
this.db = new bcoin.chaindb(this);
|
||||||
this.request = new utils.RequestCache();
|
this.request = new utils.RequestCache();
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.tip = null;
|
|
||||||
this.height = -1;
|
|
||||||
this.mempool = options.mempool;
|
this.mempool = options.mempool;
|
||||||
this.blockdb = options.blockdb;
|
this.blockdb = options.blockdb;
|
||||||
|
this.resetting = false;
|
||||||
|
this.reverting = false;
|
||||||
|
this.syncing = false;
|
||||||
this.locked = false;
|
this.locked = false;
|
||||||
this.pending = [];
|
this.pending = [];
|
||||||
this.pendingBlocks = {};
|
this.pendingBlocks = {};
|
||||||
@ -144,11 +145,6 @@ Chain.prototype._init = function _init() {
|
|||||||
self.mempool.removeBlock(block);
|
self.mempool.removeBlock(block);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.db.on('tip', function(tip) {
|
|
||||||
self.tip = tip;
|
|
||||||
self.height = tip.height;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
|
||||||
utils.debug('Chain is loading.');
|
utils.debug('Chain is loading.');
|
||||||
@ -179,22 +175,19 @@ Chain.prototype._init = function _init() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Chain.prototype.__defineGetter__('tip', function() {
|
||||||
|
return this.db.tip;
|
||||||
|
});
|
||||||
|
|
||||||
|
Chain.prototype.__defineGetter__('height', function() {
|
||||||
|
return this.db.height;
|
||||||
|
});
|
||||||
|
|
||||||
Chain.prototype._ensureGenesis = function _ensureGenesis(callback) {
|
Chain.prototype._ensureGenesis = function _ensureGenesis(callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
callback = utils.asyncify(callback);
|
callback = utils.asyncify(callback);
|
||||||
|
|
||||||
this.db.save(bcoin.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
|
|
||||||
}));
|
|
||||||
|
|
||||||
if (!this.blockdb)
|
if (!this.blockdb)
|
||||||
return callback();
|
return callback();
|
||||||
|
|
||||||
@ -681,6 +674,7 @@ Chain.prototype.resetHeight = function resetHeight(height) {
|
|||||||
var count = this.db.count();
|
var count = this.db.count();
|
||||||
var i, existing;
|
var i, existing;
|
||||||
|
|
||||||
|
assert(!this.resetting);
|
||||||
assert(height <= count - 1);
|
assert(height <= count - 1);
|
||||||
assert(this.tip);
|
assert(this.tip);
|
||||||
|
|
||||||
@ -704,17 +698,17 @@ Chain.prototype.resetHeightAsync = function resetHeightAsync(height, callback) {
|
|||||||
var count = this.db.count();
|
var count = this.db.count();
|
||||||
var i, lock;
|
var i, lock;
|
||||||
|
|
||||||
|
assert(!this.resetting);
|
||||||
assert(height <= count - 1);
|
assert(height <= count - 1);
|
||||||
assert(this.tip);
|
assert(this.tip);
|
||||||
|
|
||||||
if (height === count - 1)
|
if (height === count - 1)
|
||||||
return utils.nextTick(callback);
|
return utils.nextTick(callback);
|
||||||
|
|
||||||
lock = this.locked;
|
this.resetting = true;
|
||||||
this.locked = true;
|
|
||||||
|
|
||||||
this.db.resetHeightAsync(height, function(err) {
|
this.db.resetHeightAsync(height, function(err) {
|
||||||
self.locked = lock;
|
self.resetting = false;
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
@ -735,16 +729,15 @@ Chain.prototype.resetHeightAsync = function resetHeightAsync(height, callback) {
|
|||||||
Chain.prototype.revertHeight = function revertHeight(height, callback) {
|
Chain.prototype.revertHeight = function revertHeight(height, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var chainHeight;
|
var chainHeight;
|
||||||
var lock = this.locked;
|
|
||||||
|
|
||||||
assert(!this.locked);
|
assert(!this.reverting);
|
||||||
|
|
||||||
callback = utils.asyncify(callback);
|
callback = utils.asyncify(callback);
|
||||||
|
|
||||||
this.locked = true;
|
this.reverting = true;
|
||||||
|
|
||||||
function done(err, result) {
|
function done(err, result) {
|
||||||
self.locked = lock;
|
self.reverting = false;
|
||||||
callback(err, result);
|
callback(err, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -756,8 +749,7 @@ Chain.prototype.revertHeight = function revertHeight(height, callback) {
|
|||||||
if (!this.blockdb) {
|
if (!this.blockdb) {
|
||||||
if (height > chainHeight)
|
if (height > chainHeight)
|
||||||
return done(new Error('Cannot reset height.'));
|
return done(new Error('Cannot reset height.'));
|
||||||
this.resetHeight(height);
|
return this.resetHeightAsync(height, done);
|
||||||
return done();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.blockdb.getHeight(function(err, blockHeight) {
|
this.blockdb.getHeight(function(err, blockHeight) {
|
||||||
@ -780,9 +772,7 @@ Chain.prototype.revertHeight = function revertHeight(height, callback) {
|
|||||||
if (err)
|
if (err)
|
||||||
return done(err);
|
return done(err);
|
||||||
|
|
||||||
self.resetHeight(height);
|
self.resetHeightAsync(height, done);
|
||||||
|
|
||||||
return done();
|
|
||||||
}, function(block) {
|
}, function(block) {
|
||||||
self.emit('remove block', block);
|
self.emit('remove block', block);
|
||||||
});
|
});
|
||||||
@ -791,32 +781,34 @@ Chain.prototype.revertHeight = function revertHeight(height, callback) {
|
|||||||
|
|
||||||
Chain.prototype._revertLast = function _revertLast(existing, callback) {
|
Chain.prototype._revertLast = function _revertLast(existing, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
return this._removeBlock(existing.hash, function(err, existingBlock) {
|
this._removeBlock(existing.hash, function(err, existingBlock) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
self.resetHeight(existing.height - 1);
|
self.resetHeightAsync(existing.height - 1, function(err) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
if (existingBlock)
|
if (existingBlock)
|
||||||
self.emit('remove block', existingBlock);
|
self.emit('remove block', existingBlock);
|
||||||
|
|
||||||
return callback();
|
return callback();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Chain.prototype.syncHeight = function syncHeight(callback) {
|
Chain.prototype.syncHeight = function syncHeight(callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var chainHeight;
|
var chainHeight;
|
||||||
var lock = this.locked;
|
|
||||||
|
|
||||||
callback = utils.asyncify(callback);
|
callback = utils.asyncify(callback);
|
||||||
|
|
||||||
assert(!this.locked);
|
assert(!this.syncing);
|
||||||
|
|
||||||
this.locked = true;
|
this.syncing = true;
|
||||||
|
|
||||||
function done(err, result) {
|
function done(err, result) {
|
||||||
self.locked = lock;
|
self.syncing = false;
|
||||||
callback(err, result);
|
callback(err, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -842,8 +834,7 @@ Chain.prototype.syncHeight = function syncHeight(callback) {
|
|||||||
|
|
||||||
if (blockHeight < chainHeight) {
|
if (blockHeight < chainHeight) {
|
||||||
utils.debug('BlockDB is higher than ChainDB. Syncing...');
|
utils.debug('BlockDB is higher than ChainDB. Syncing...');
|
||||||
self.resetHeight(blockHeight);
|
return self.resetHeightAsync(blockHeight, done);
|
||||||
return done();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blockHeight > chainHeight) {
|
if (blockHeight > chainHeight) {
|
||||||
@ -874,6 +865,9 @@ Chain.prototype.add = function add(initial, peer, callback) {
|
|||||||
|
|
||||||
assert(!this.loading);
|
assert(!this.loading);
|
||||||
|
|
||||||
|
if (this.resetting || this.reverting || this.syncing)
|
||||||
|
return callback();
|
||||||
|
|
||||||
if (this.locked) {
|
if (this.locked) {
|
||||||
this.pending.push([initial, peer, callback]);
|
this.pending.push([initial, peer, callback]);
|
||||||
this.pendingBlocks[initial.hash('hex')] = true;
|
this.pendingBlocks[initial.hash('hex')] = true;
|
||||||
@ -890,7 +884,7 @@ Chain.prototype.add = function add(initial, peer, callback) {
|
|||||||
(function next(block) {
|
(function next(block) {
|
||||||
var hash = block.hash('hex');
|
var hash = block.hash('hex');
|
||||||
var prevHash = block.prevBlock;
|
var prevHash = block.prevBlock;
|
||||||
var prevHeight, entry, existing, checkpoint, prev, orphan;
|
var prevHeight, entry, checkpoint, prev, orphan;
|
||||||
|
|
||||||
// Special case for genesis block.
|
// Special case for genesis block.
|
||||||
if (block.isGenesis())
|
if (block.isGenesis())
|
||||||
@ -1018,52 +1012,54 @@ Chain.prototype.add = function add(initial, peer, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// See if the entry already exists.
|
// See if the entry already exists.
|
||||||
existing = self.db.get(entry.height);
|
if (self.db.has(entry.height)) {
|
||||||
|
return self.db.getAsync(entry.height, function(err, existing) {
|
||||||
// Entry already exists.
|
|
||||||
if (existing) {
|
|
||||||
// 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.
|
|
||||||
if (existing.hash === hash) {
|
|
||||||
self.emit('exists', block, {
|
|
||||||
height: entry.height,
|
|
||||||
hash: entry.hash
|
|
||||||
}, peer);
|
|
||||||
return utils.nextTick(handleOrphans);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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) == null);
|
|
||||||
|
|
||||||
// The tip has more chainwork, it is a
|
|
||||||
// higher height than the entry. This is
|
|
||||||
// not an alternate tip. Ignore it.
|
|
||||||
if (self.tip.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)
|
if (err)
|
||||||
return done(err);
|
return done(err);
|
||||||
|
|
||||||
self.emit('fork', block, {
|
// We already have this block. Do regular
|
||||||
height: existing.height,
|
// orphan resolution (won't do anything).
|
||||||
expected: existing.hash,
|
// NOTE: Wrap this in a nextTick to avoid
|
||||||
received: entry.hash,
|
// a stack overflow if there are a lot of
|
||||||
checkpoint: false
|
// existing blocks.
|
||||||
}, peer);
|
if (existing.hash === hash) {
|
||||||
|
self.emit('exists', block, {
|
||||||
|
height: entry.height,
|
||||||
|
hash: entry.hash
|
||||||
|
}, peer);
|
||||||
|
return utils.nextTick(handleOrphans);
|
||||||
|
}
|
||||||
|
|
||||||
return done();
|
// 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) == null);
|
||||||
|
|
||||||
|
// The tip has more chainwork, it is a
|
||||||
|
// higher height than the entry. This is
|
||||||
|
// not an alternate tip. Ignore it.
|
||||||
|
if (self.tip.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();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1071,6 +1067,8 @@ Chain.prototype.add = function add(initial, peer, callback) {
|
|||||||
assert(self.db.getHeight(entry.hash) == null);
|
assert(self.db.getHeight(entry.hash) == null);
|
||||||
|
|
||||||
// Lookup previous entry.
|
// Lookup previous entry.
|
||||||
|
// We can do this synchronously:
|
||||||
|
// it is already cached.
|
||||||
prev = self.db.get(prevHeight);
|
prev = self.db.get(prevHeight);
|
||||||
assert(prev);
|
assert(prev);
|
||||||
|
|
||||||
@ -1247,7 +1245,7 @@ Chain.prototype.byTime = function byTime(ts) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Chain.prototype.hasBlock = function hasBlock(hash) {
|
Chain.prototype.hasBlock = function hasBlock(hash) {
|
||||||
return !!this.byHash(hash);
|
return this.db.has(hash);
|
||||||
};
|
};
|
||||||
|
|
||||||
Chain.prototype.hasOrphan = function hasOrphan(hash) {
|
Chain.prototype.hasOrphan = function hasOrphan(hash) {
|
||||||
@ -1400,49 +1398,47 @@ Chain.prototype.getLocatorAsync = function getLocatorAsync(start, callback) {
|
|||||||
return callback(null, hashes);
|
return callback(null, hashes);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.db.hasAsync(top, function(err, has) {
|
try {
|
||||||
var pending;
|
assert(this.db.has(top));
|
||||||
|
} catch (e) {
|
||||||
|
return done(new Error('Potential reset.'));
|
||||||
|
}
|
||||||
|
|
||||||
if (err)
|
var pending;
|
||||||
return done(err);
|
|
||||||
|
|
||||||
if (!has)
|
i = top;
|
||||||
return done(new Error('Potential reset.'));
|
for (;;) {
|
||||||
|
hashes.push(i);
|
||||||
|
i = i - step;
|
||||||
|
if (i <= 0) {
|
||||||
|
if (i + step !== 0)
|
||||||
|
hashes.push(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (hashes.length >= 10)
|
||||||
|
step *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
i = top;
|
pending = hashes.length;
|
||||||
for (;;) {
|
|
||||||
hashes.push(i);
|
hashes.forEach(function(height, i) {
|
||||||
i = i - step;
|
if (typeof height === 'string') {
|
||||||
if (i <= 0) {
|
if (!--pending)
|
||||||
if (i + step !== 0)
|
done();
|
||||||
hashes.push(0);
|
return;
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (hashes.length >= 10)
|
|
||||||
step *= 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pending = hashes.length;
|
self.db.getAsync(height, function(err, existing) {
|
||||||
|
if (err)
|
||||||
|
return done(err);
|
||||||
|
|
||||||
hashes.forEach(function(height, i) {
|
if (!existing)
|
||||||
if (typeof height === 'string') {
|
return done(new Error('Potential reset.'));
|
||||||
if (!--pending)
|
|
||||||
done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.db.getAsync(height, function(err, existing) {
|
hashes[i] = existing.hash;
|
||||||
if (err)
|
|
||||||
return done(err);
|
|
||||||
|
|
||||||
if (!existing)
|
if (!--pending)
|
||||||
return done(new Error('Potential reset.'));
|
done();
|
||||||
|
|
||||||
hashes[i] = existing.hash;
|
|
||||||
|
|
||||||
if (!--pending)
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -1467,11 +1463,11 @@ Chain.prototype.getOrphanRoot = function getOrphanRoot(hash) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Chain.prototype.getHeight = function getHeight(hash) {
|
Chain.prototype.getHeight = function getHeight(hash) {
|
||||||
var entry = this.byHash(hash);
|
var height = this.db.getHeight(hash);
|
||||||
if (!entry)
|
if (height == null)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return entry.height;
|
return height;
|
||||||
};
|
};
|
||||||
|
|
||||||
Chain.prototype.getNextBlock = function getNextBlock(hash) {
|
Chain.prototype.getNextBlock = function getNextBlock(hash) {
|
||||||
|
|||||||
@ -53,6 +53,8 @@ ChainBlock.prototype.getProof = function getProof() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ChainBlock.prototype.getChainwork = function getChainwork() {
|
ChainBlock.prototype.getChainwork = function getChainwork() {
|
||||||
|
if (!this.chain.db)
|
||||||
|
return;
|
||||||
var prev = this.prev;
|
var prev = this.prev;
|
||||||
return (prev ? prev.chainwork : new bn(0)).add(this.getProof());
|
return (prev ? prev.chainwork : new bn(0)).add(this.getProof());
|
||||||
};
|
};
|
||||||
|
|||||||
@ -61,9 +61,21 @@ function ChainDB(chain, options) {
|
|||||||
inherits(ChainDB, EventEmitter);
|
inherits(ChainDB, EventEmitter);
|
||||||
|
|
||||||
ChainDB.prototype._init = function _init() {
|
ChainDB.prototype._init = function _init() {
|
||||||
|
var genesis = bcoin.chainblock.fromJSON(this.chain, {
|
||||||
|
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 (!bcoin.fs) {
|
if (!bcoin.fs) {
|
||||||
utils.debug('`fs` module not available. Falling back to ramdisk.');
|
utils.debug('`fs` module not available. Falling back to ramdisk.');
|
||||||
this.ramdisk = new bcoin.ramdisk(40 * 1024 * 1024);
|
this.ramdisk = new bcoin.ramdisk(40 * 1024 * 1024);
|
||||||
|
this.saveSync(genesis);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,6 +100,13 @@ ChainDB.prototype._init = function _init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.fd = fs.openSync(this.file, 'r+');
|
this.fd = fs.openSync(this.file, 'r+');
|
||||||
|
|
||||||
|
if (this.size === 0) {
|
||||||
|
this.saveSync(genesis);
|
||||||
|
} else {
|
||||||
|
this.getSync(0);
|
||||||
|
assert(this.tip.hash === genesis.hash);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ChainDB.prototype.load = function load(start, callback) {
|
ChainDB.prototype.load = function load(start, callback) {
|
||||||
@ -403,15 +422,19 @@ ChainDB.prototype.drop = function drop(height) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ChainDB.prototype.resetHeight = function resetHeight(height) {
|
ChainDB.prototype.resetHeight = function resetHeight(height) {
|
||||||
|
var size, count, existing;
|
||||||
|
|
||||||
if (typeof height === 'string')
|
if (typeof height === 'string')
|
||||||
height = this.heightLookup[height];
|
height = this.heightLookup[height];
|
||||||
|
|
||||||
assert(height >= 0);
|
assert(height >= 0);
|
||||||
|
|
||||||
var size = (height + 1) * BLOCK_SIZE;
|
size = (height + 1) * BLOCK_SIZE;
|
||||||
var count = this.count();
|
count = this.count();
|
||||||
|
|
||||||
if (height === count - 1)
|
if (height === count - 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
assert(height <= count - 1);
|
assert(height <= count - 1);
|
||||||
assert(this.tip);
|
assert(this.tip);
|
||||||
|
|
||||||
@ -422,19 +445,10 @@ ChainDB.prototype.resetHeight = function resetHeight(height) {
|
|||||||
delete this.heightLookup[existing.hash];
|
delete this.heightLookup[existing.hash];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bcoin.fs) {
|
if (!bcoin.fs)
|
||||||
this.ramdisk.truncate(size);
|
this.ramdisk.truncate(size);
|
||||||
|
else
|
||||||
this.size = size;
|
fs.ftruncateSync(this.fd, size);
|
||||||
this.highest = height;
|
|
||||||
this.tip = this.get(height);
|
|
||||||
assert(this.tip);
|
|
||||||
this.height = this.tip.height;
|
|
||||||
this.emit('tip', this.tip);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.ftruncateSync(this.fd, size);
|
|
||||||
|
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.highest = height;
|
this.highest = height;
|
||||||
@ -446,7 +460,7 @@ ChainDB.prototype.resetHeight = function resetHeight(height) {
|
|||||||
|
|
||||||
ChainDB.prototype.resetHeightAsync = function resetHeightAsync(height, callback) {
|
ChainDB.prototype.resetHeightAsync = function resetHeightAsync(height, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var called;
|
var size, count, pending, called;
|
||||||
|
|
||||||
if (typeof height === 'string')
|
if (typeof height === 'string')
|
||||||
height = this.heightLookup[height];
|
height = this.heightLookup[height];
|
||||||
@ -455,15 +469,16 @@ ChainDB.prototype.resetHeightAsync = function resetHeightAsync(height, callback)
|
|||||||
|
|
||||||
callback = utils.asyncify(callback);
|
callback = utils.asyncify(callback);
|
||||||
|
|
||||||
var size = (height + 1) * BLOCK_SIZE;
|
size = (height + 1) * BLOCK_SIZE;
|
||||||
var count = this.count() - 1;
|
count = this.count() - 1;
|
||||||
|
pending = count - (height + 1);
|
||||||
|
|
||||||
if (height === count - 1)
|
if (height === count - 1)
|
||||||
return callback();
|
return callback();
|
||||||
|
|
||||||
assert(height <= count - 1);
|
assert(height <= count - 1);
|
||||||
assert(this.tip);
|
assert(this.tip);
|
||||||
|
|
||||||
var pending = count - (height + 1);
|
|
||||||
|
|
||||||
for (i = height + 1; i < count; i++)
|
for (i = height + 1; i < count; i++)
|
||||||
dropEntry(i);
|
dropEntry(i);
|
||||||
|
|
||||||
@ -491,12 +506,6 @@ ChainDB.prototype.resetHeightAsync = function resetHeightAsync(height, callback)
|
|||||||
|
|
||||||
if (!bcoin.fs) {
|
if (!bcoin.fs) {
|
||||||
self.ramdisk.truncate(size);
|
self.ramdisk.truncate(size);
|
||||||
self.size = size;
|
|
||||||
self.highest = height;
|
|
||||||
self.tip = self.get(height);
|
|
||||||
assert(self.tip);
|
|
||||||
self.height = self.tip.height;
|
|
||||||
self.emit('tip', self.tip);
|
|
||||||
return callback();
|
return callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -583,6 +592,9 @@ ChainDB.prototype._readAsync = function _readAsync(size, offset, callback) {
|
|||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!bytes)
|
||||||
|
throw new Error('_readAsync() failed.');
|
||||||
|
|
||||||
index += bytes;
|
index += bytes;
|
||||||
size -= bytes;
|
size -= bytes;
|
||||||
offset += bytes;
|
offset += bytes;
|
||||||
@ -655,6 +667,9 @@ ChainDB.prototype._writeAsync = function _writeAsync(data, offset, callback) {
|
|||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!bytes)
|
||||||
|
throw new Error('_writeAsync() failed.');
|
||||||
|
|
||||||
index += bytes;
|
index += bytes;
|
||||||
size -= bytes;
|
size -= bytes;
|
||||||
offset += bytes;
|
offset += bytes;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user