From 4415f978a6319f974caba7aefc8b91e909ea5db6 Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Sat, 10 May 2014 22:31:51 +0400 Subject: [PATCH] chain: kill forks :) --- lib/bcoin/chain.js | 52 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index 839a8c39..edcf3522 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -105,7 +105,7 @@ Chain.prototype._probeIndex = function _probeIndex(hash, ts) { for (var i = start; i <= end; i++) if (this.index.hashes[i] === hash) - return { height: this.index.heights[i], ts: this.index.ts[i] }; + return { i: i, height: this.index.heights[i], ts: this.index.ts[i] }; return false; }; @@ -139,6 +139,52 @@ Chain.prototype._addIndex = function _addIndex(hash, ts, height) { }); }; +Chain.prototype._killFork = function _killFork(probe) { + var delta = 2 * 3600; + var upper = probe.ts + delta; + var lower = probe.ts - delta; + + // Search duplicate heights down + var index = -1; + for (var i = probe.i - 1; i > 0 && this.index.ts[i] > lower; i--) { + if (probe.height === this.index.heights[i]) { + index = i; + break; + } + } + + // And up + if (index === -1) { + var len = this.index.ts.length; + for (var i = probe.i + 1; i < len && this.index.ts[i] < upper; i++) { + if (probe.height === this.index.heights[i]) { + index = i; + break; + } + } + } + + if (index === -1) + return false; + + var hash = this.index.hashes[index]; + this.index.hashes.splice(index, 1); + this.index.ts.splice(index, 1); + this.index.heights.splice(index, 1); + + // Delete both blocks, let's see what others will choose + if (!this.storage) + return true; + + var self = this; + this.storage.del(this.prefix + hash, obj, function(err) { + if (err) + self.emit('error', err); + }); + + return true; +}; + Chain.prototype.add = function add(block) { if (this.loading) { this.once('load', function() { @@ -163,6 +209,10 @@ Chain.prototype.add = function add(block) { var prevProbe = this._probeIndex(prev, block.ts); + // Remove forked nodes from storage, if shorter chain is detected + if (this._killFork(prevProbe)) + break; + // If previous block wasn't ever seen - add current to orphans if (!this._probeIndex(hash, block.ts) && !prevProbe) { this.orphan.count++;