From 3854f0462428b5e02a7333a46938e810c24847cc Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Thu, 10 Nov 2016 18:49:13 -0800 Subject: [PATCH] chain: spv reorganization. --- lib/chain/chain.js | 36 ++++++++++++++++++++++++++++++++++++ lib/chain/chaindb.js | 1 + 2 files changed, 37 insertions(+) diff --git a/lib/chain/chain.js b/lib/chain/chain.js index 2bada043..2bddba67 100644 --- a/lib/chain/chain.js +++ b/lib/chain/chain.js @@ -795,6 +795,36 @@ Chain.prototype.reorganize = co(function* reorganize(competitor, block) { this.emit('reorganize', block, tip.height, tip.hash); }); +/** + * Reorganize the blockchain for SPV. + * @private + * @param {ChainEntry} competitor - The competing chain's tip. + * @param {Block|MerkleBlock} block - The being being added. + * @returns {Promise} + */ + +Chain.prototype.reorganizeSPV = co(function* reorganizeSPV(competitor, block) { + var tip = this.tip; + var fork = yield this.findFork(tip, competitor); + var entry; + + assert(fork); + + // Blocks to disconnect. + entry = tip; + while (entry.hash !== fork.hash) { + this.emit('disconnect', entry, entry.toHeaders()); + entry = yield entry.getPrevious(); + assert(entry); + } + + // Reset the main chain back + // to the fork block. + yield this._reset(fork.hash); + + this.emit('reorganize', block, tip.height, tip.hash); +}); + /** * Disconnect an entry from the chain (updates the tip). * @param {ChainEntry} entry @@ -883,6 +913,12 @@ Chain.prototype.setBestChain = co(function* setBestChain(entry, block, prev) { // Time to reorganize the chain. if (entry.prevBlock !== this.tip.hash) { this.logger.warning('WARNING: Reorganizing chain.'); + + // In spv-mode, we reset the + // chain and redownload the blocks. + if (this.options.spv) + return yield this.reorganizeSPV(entry, block); + yield this.reorganize(entry, block); } diff --git a/lib/chain/chaindb.js b/lib/chain/chaindb.js index b69a6fc0..e5c19cd0 100644 --- a/lib/chain/chaindb.js +++ b/lib/chain/chaindb.js @@ -1458,6 +1458,7 @@ ChainDB.prototype.removeChain = co(function* removeChain(hash) { assert(!tip.isGenesis()); + this.del(layout.a(tip.hash)); this.del(layout.h(tip.hash)); this.del(layout.e(tip.hash)); this.del(layout.b(tip.hash));