diff --git a/lib/node.js b/lib/node.js index ff8ed4e6..ca0160c6 100644 --- a/lib/node.js +++ b/lib/node.js @@ -144,39 +144,40 @@ Node.prototype._syncBitcoindRewind = function(block, done) { self._syncBitcoindAncestor(block, function(err, ancestorHash) { // Rewind the chain to the common ancestor - async.doWhilst( + async.whilst( + function() { + // Wait until the tip equals the ancestor hash + return self.chain.tip.hash !== ancestorHash; + }, function(removeDone) { - var block = self.chain.tip; + var tip = self.chain.tip; - self.getBlock(block.prevHash, function(err, previousTip) { + self.getBlock(tip.prevHash, function(err, previousTip) { if (err) { removeDone(err); } - self.db._onChainRemoveBlock(block, function(err) { + // Undo the related indexes for this block + self.db._onChainRemoveBlock(tip, function(err) { if (err) { return removeDone(err); } + // Set the new tip delete self.chain.tip.__transactions; - var previousHeight = self.chain.tip.__height - 1; - previousTip.__height = previousHeight; + previousTip.__height = self.chain.tip.__height - 1; self.chain.tip = previousTip; self.chain.saveMetadata(); - self.chain.emit('removeblock', block); + self.chain.emit('removeblock', tip); removeDone(); }); }); - }, function() { - return self.chain.tip.hash !== ancestorHash; }, done ); - }); - }; /** diff --git a/test/node.unit.js b/test/node.unit.js index 39464b6c..97cee6e7 100644 --- a/test/node.unit.js +++ b/test/node.unit.js @@ -116,6 +116,51 @@ describe('Bitcoind Node', function() { }); }); }); + describe('#_syncBitcoindRewind', function() { + it('will undo blocks 6 deep', function() { + var node = new Node({}); + var ancestorHash = chainHashes[chainHashes.length - 6]; + node.chain = { + tip: { + __height: 10, + hash: chainHashes[chainHashes.length], + prevHash: chainHashes[chainHashes.length - 1] + }, + saveMetadata: sinon.stub(), + emit: sinon.stub() + }; + node.getBlock = function(hash, callback) { + setImmediate(function() { + for(var i = chainHashes.length; i > 0; i--) { + if (chainHashes[i] === hash) { + callback(null, { + hash: chainHashes[i], + prevHash: chainHashes[i - 1] + }); + } + } + }); + }; + node.db = { + _onChainRemoveBlock: function(block, callback) { + setImmediate(callback); + } + }; + node._syncBitcoindAncestor = function(block, callback) { + setImmediate(function() { + callback(null, ancestorHash); + }); + }; + var forkedBlock = {}; + node._syncBitcoindRewind(forkedBlock, function(err) { + if (err) { + throw err; + } + node.chain.tip.__height.should.equal(4); + node.chain.tip.hash.should.equal(ancestorHash); + }); + }); + }); describe('#_syncBitcoind', function() { it('will get and add block up to the tip height', function(done) { var node = new Node({});