diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index 36682775..19c29c7c 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -345,6 +345,17 @@ Chain.prototype.add = function add(block) { this.orphan.count--; } while (true); + // Failsafe for large orphan chains + if (this.orphan.count > 10000) { + this.orphan.map = {}; + this.orphan.bmap = {}; + this.orphan.count = 0; + } + + // No need to have a huge chain + // if (this.size() > 100000) + // this.compact(); + // Compress old blocks this._compress(); @@ -652,36 +663,19 @@ Chain.prototype.retarget = function retarget(last, firstTs) { assert(false); }; -Chain.prototype.compact = function compact() { - assert(false); +Chain.prototype.compact = function compact(keep) { + var index = this._compact(keep); + this.index.hashes = index.hashes; + this.index.ts = index.ts; + this.index.heights = index.heights; + this.index.bloom.reset(); + this.index.hashes.forEach(function(hash) { + this.index.bloom.add(hash, 'hex'); + }, this); }; -Chain.prototype._save = function(hash, obj) { - var self = this; - - if (!this.storage) - return; - - this.storage.put(this.prefix + hash, obj, function(err) { - if (err) - self.emit('error', err); - }); -}; - -Chain.prototype._delete = function(hash) { - var self = this; - - if (!this.storage) - return; - - this.storage.del(this.prefix + hash, function(err) { - if (err) - self.emit('error', err); - }); -}; - -Chain.prototype.toJSON = function toJSON() { - var keep = 1000; +Chain.prototype._compact = function _compact(keep) { + keep = keep || 1000; // Keep only last 1000 consequent blocks, dilate others at: // 7 day range for blocks before 2013 @@ -728,15 +722,48 @@ Chain.prototype.toJSON = function toJSON() { } return { - v: 1, - type: 'chain', - network: network.type, hashes: first.hashes.concat(last.hashes), ts: first.ts.concat(last.ts), heights: first.heights.concat(last.heights) }; }; +Chain.prototype._save = function(hash, obj) { + var self = this; + + if (!this.storage) + return; + + this.storage.put(this.prefix + hash, obj, function(err) { + if (err) + self.emit('error', err); + }); +}; + +Chain.prototype._delete = function(hash) { + var self = this; + + if (!this.storage) + return; + + this.storage.del(this.prefix + hash, function(err) { + if (err) + self.emit('error', err); + }); +}; + +Chain.prototype.toJSON = function toJSON() { + var index = this._compact(); + return { + v: 1, + type: 'chain', + network: network.type, + hashes: index.hashes, + ts: index.ts, + heights: index.heights + }; +}; + Chain.prototype.fromJSON = function fromJSON(json) { var i; diff --git a/lib/bcoin/fullchain.js b/lib/bcoin/fullchain.js index 8554abed..7d66bf1e 100644 --- a/lib/bcoin/fullchain.js +++ b/lib/bcoin/fullchain.js @@ -260,6 +260,13 @@ Chain.prototype.add = function add(block) { this.orphan.count--; } + // Failsafe for large orphan chains + if (this.orphan.count > 10000) { + this.orphan.map = {}; + this.orphan.bmap = {}; + this.orphan.count = 0; + } + return err; }; @@ -537,7 +544,6 @@ Chain.prototype._delete = function(hash) { Chain.prototype.toJSON = function toJSON() { var entries = this.index.entries; - return { v: 1, type: 'chain',