From 053775ffac0fcaa7c69a715ff58c7600c85ab4ef Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Fri, 19 Feb 2016 05:38:02 -0800 Subject: [PATCH] sync resetHeight --- lib/bcoin/chain.js | 126 ++++++++++++++++++++++++++------------------- 1 file changed, 72 insertions(+), 54 deletions(-) diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index abdd7124..5e2f22e2 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -39,9 +39,6 @@ function Chain(options) { this.loading = false; this.mempool = options.mempool; this.blockdb = options.blockdb; - this.resetting = false; - this.reverting = false; - this.syncing = false; this.locked = false; this.pending = []; this.pendingBlocks = {}; @@ -249,7 +246,7 @@ Chain.prototype._preload = function _preload(callback) { stream.on('error', function(err) { var start = Math.max(0, height - 2); - self.resetHeightSync(start); + self.resetHeight(start); return callback(err, start + 1); }); @@ -285,7 +282,7 @@ Chain.prototype._preload = function _preload(callback) { if (lastEntry && entry.prevBlock !== lastEntry.hash) { start = Math.max(0, height - 2); stream.destroy(); - self.resetHeightSync(start); + self.resetHeight(start); return callback(new Error('Corrupt headers.'), start + 1); } @@ -294,7 +291,7 @@ Chain.prototype._preload = function _preload(callback) { if (!block.verify()) { start = Math.max(0, height - 2); stream.destroy(); - self.resetHeightSync(start); + self.resetHeight(start); return callback(new Error('Bad headers.'), start + 1); } @@ -689,10 +686,11 @@ Chain.prototype.resetHeight = function resetHeight(height) { var self = this; var i, existing; - assert(!this.resetting); assert(height <= count - 1); assert(this.tip); + this._clearPending(); + if (height === count - 1) return; @@ -710,22 +708,26 @@ Chain.prototype.resetHeight = function resetHeight(height) { Chain.prototype.resetHeightAsync = function resetHeightAsync(height, callback) { var self = this; - var i, lock; + var lock = this.lock; + var i; - assert(!this.resetting); assert(height <= count - 1); assert(this.tip); - if (height === count - 1) - return utils.nextTick(callback); + this.lock = true; - this.resetting = true; + function done(err, result) { + self.lock = lock; + self._clearPending(); + callback(err, result); + } + + if (height === count - 1) + return utils.nextTick(done); this.db.resetHeightAsync(height, function(err) { - self.resetting = false; - if (err) - return callback(err); + return done(err); // Reset the orphan map completely. There may // have been some orphans on a forked chain we @@ -736,22 +738,22 @@ Chain.prototype.resetHeightAsync = function resetHeightAsync(height, callback) { self.orphan.count = 0; self.orphan.size = 0; - return callback(); + return done(); }); }; Chain.prototype.revertHeight = function revertHeight(height, callback) { var self = this; var chainHeight; - - assert(!this.reverting); + var lock = this.lock; callback = utils.asyncify(callback); - this.reverting = true; + this.lock = true; function done(err, result) { - self.reverting = false; + self.lock = lock; + self._clearPending(); callback(err, result); } @@ -760,11 +762,16 @@ Chain.prototype.revertHeight = function revertHeight(height, callback) { if (chainHeight < 0) return done(new Error('Bad chain height.')); - if (!this.blockdb) { - if (height > chainHeight) - return done(new Error('Cannot reset height.')); - return this.resetHeightAsync(height, done); - } + if (chainHeight < height) + return done(new Error('Cannot reset height.')); + + if (chainHeight === height) + return done(); + + this.resetHeight(height); + + if (!this.blockdb) + return done(); this.blockdb.getHeight(function(err, blockHeight) { if (err) @@ -773,20 +780,17 @@ Chain.prototype.revertHeight = function revertHeight(height, callback) { if (blockHeight < 0) return done(new Error('Bad block height.')); - if (chainHeight !== blockHeight) - return done(new Error('ChainDB and BlockDB are out of sync.')); - - if (height === chainHeight) - return done(); - - if (height > chainHeight) + if (blockHeight < height) return done(new Error('Cannot reset height.')); + if (blockHeight === height) + return done(); + self.blockdb.resetHeight(height, function(err) { if (err) return done(err); - self.resetHeightAsync(height, done); + return done(); }, function(block) { self.emit('remove block', block); }); @@ -795,34 +799,41 @@ Chain.prototype.revertHeight = function revertHeight(height, callback) { Chain.prototype._revertLast = function _revertLast(existing, callback) { var self = this; + var lock = this.lock; + + this.lock = true; + + function done(err, result) { + self.lock = lock; + self._clearPending(); + callback(err, result); + } + + this.resetHeight(existing.height - 1); + this._removeBlock(existing.hash, function(err, existingBlock) { if (err) - return callback(err); + return done(err); - self.resetHeightAsync(existing.height - 1, function(err) { - if (err) - return callback(err); + if (existingBlock) + self.emit('remove block', existingBlock); - if (existingBlock) - self.emit('remove block', existingBlock); - - return callback(); - }); + return done(); }); }; Chain.prototype.syncHeight = function syncHeight(callback) { var self = this; var chainHeight; + var lock = this.lock; callback = utils.asyncify(callback); - assert(!this.syncing); - - this.syncing = true; + this.lock = true; function done(err, result) { - self.syncing = false; + self.lock = lock; + self._clearPending(); callback(err, result); } @@ -848,7 +859,8 @@ Chain.prototype.syncHeight = function syncHeight(callback) { if (blockHeight < chainHeight) { utils.debug('BlockDB is higher than ChainDB. Syncing...'); - return self.resetHeightAsync(blockHeight, done); + self.resetHeight(blockHeight); + return done(); } if (blockHeight > chainHeight) { @@ -869,7 +881,7 @@ Chain.prototype.resetTime = function resetTime(ts) { var entry = this.byTime(ts); if (!entry) return; - return this.resetHeightSync(entry.height); + return this.resetHeight(entry.height); }; Chain.prototype.resetTimeAsync = function resetTimeAsync(ts, callback) { @@ -903,9 +915,6 @@ Chain.prototype.add = function add(initial, peer, callback) { return; } - if (this.resetting || this.reverting || this.syncing) - return callback(); - this.locked = true; (function next(block) { @@ -969,7 +978,7 @@ Chain.prototype.add = function add(initial, peer, callback) { // Clear the queue. No telling what other // blocks we're going to get after this. - self.pending.length = 0; + self._clearPending(); return done(); } @@ -1042,7 +1051,7 @@ Chain.prototype.add = function add(initial, peer, callback) { // Clear the queue. No telling what other // blocks we're going to get after this. - self.pending.length = 0; + self._clearPending(); return done(); } @@ -1103,7 +1112,7 @@ Chain.prototype.add = function add(initial, peer, callback) { // Clear the queue. No telling what other // blocks we're going to get after this. - self.pending.length = 0; + self._clearPending(); return done(); }); @@ -1234,6 +1243,15 @@ Chain.prototype.add = function add(initial, peer, callback) { } }; +Chain.prototype._clearPending = function _clearPending() { + var item; + while (this.pending.length) { + item = this.pending.pop(); + delete this.pendingBlocks[item[0].hash('hex')]; + this.pendingSize -= item[0].getSize(); + } +}; + Chain.prototype.has = function has(hash) { if (this.hasBlock(hash)) return true;