diff --git a/lib/blockchain/chain.js b/lib/blockchain/chain.js index 5ac953dd..9c305ff7 100644 --- a/lib/blockchain/chain.js +++ b/lib/blockchain/chain.js @@ -855,6 +855,9 @@ class Chain extends AsyncEmitter { assert(fork, 'No free space or data corruption.'); + // Check NLR + if (await this.noLongReorg(tip, fork, competitor)) return true + // Blocks to disconnect. const disconnect = []; let entry = tip; @@ -912,6 +915,9 @@ class Chain extends AsyncEmitter { assert(fork, 'No free space or data corruption.'); + // Check NLR + if (await this.noLongReorg(tip, fork, competitor)) return true + // Buffer disconnected blocks. const disconnect = []; let entry = tip; @@ -950,6 +956,48 @@ class Chain extends AsyncEmitter { return this.emitAsync('reorganize', tip, competitor); } + /** + * Checks if a reorganization breaks the set nlrLimit, + * if it does, it invalidates necessary blocks and returns true + * else return false + * @param {ChainEntry} tip - Current tip of this chain. + * @param {ChainEntry} fork - The tip of the fork. + * @param {ChainEntry} competitor - The competing chain's tip. + * @returns {Promise} + */ + async noLongReorg (tip, fork, competitor) { + if (tip.height - fork.height >= this.network.nlrLimit) { + if (this.network.nlrLimit !== 0) { + this.logger.warning( + 'NLR Activated. Preventing reorganization: current=%h(%d) competitor=%h(%d) fork=%h(%d) reorg_size=%d nlr=%d', + tip.hash, + tip.height, + competitor.hash, + competitor.height, + fork.hash, + fork.height, + tip.height - fork.height, + this.network.nlrLimit + ); + + let indexWalk = competitor + + // mark invalid_child from tip of competitor to first block of fork + while (indexWalk.height > fork.height) { + await this.setInvalid(indexWalk.hash) + indexWalk = await this.getPrevious(indexWalk) + } + + // check + indexWalk = await this.getPrevious(indexWalk) + assert.strictEqual(indexWalk, fork) + + return true + } + } + return false + } + /** * Disconnect an entry from the chain (updates the tip). * @param {ChainEntry} entry @@ -2209,7 +2257,7 @@ class Chain extends AsyncEmitter { targetTimespan = pow.targetTimespan_Version1; } else if ((prev.height + 1) < pow.blockHeight_Version3){ - + retargetInterval = pow.retargetInterval_Version2; averagingInterval = pow.averagingInterval_Version2; targetTimespan = pow.targetTimespan_Version2 * targetSpacing; @@ -2247,10 +2295,10 @@ class Chain extends AsyncEmitter { // Back 6 block var back = averagingInterval - 1; - + if (prev.height + 1 !== averagingInterval) back = averagingInterval; - + let first = prev; for (let i = 0; i < back; i++){ if (first) diff --git a/lib/protocol/consensus.js b/lib/protocol/consensus.js index b8b8b490..bd91fab6 100644 --- a/lib/protocol/consensus.js +++ b/lib/protocol/consensus.js @@ -339,7 +339,8 @@ exports.getReward = function getReward(height, interval) { // BIP 42 (well, our own version of it, // since we can only handle 32 bit shifts). // https://github.com/bitcoin/bips/blob/master/bip-0042.mediawiki - if (halvings >= 33) + // FLO can safely handle 34 (instead of 33) halvings + if (halvings >= 34) return 0; // We need to shift right by `halvings`, diff --git a/lib/protocol/network.js b/lib/protocol/network.js index 41448153..a74fbe36 100644 --- a/lib/protocol/network.js +++ b/lib/protocol/network.js @@ -58,6 +58,7 @@ class Network { this.maxFeeRate = options.maxFeeRate; this.selfConnect = options.selfConnect; this.requestMempool = options.requestMempool; + this.nlrLimit = options.nlrLimit; this.time = new TimeData(); this.init(); diff --git a/lib/protocol/networks.js b/lib/protocol/networks.js index 96a4fcb8..d1c137b4 100644 --- a/lib/protocol/networks.js +++ b/lib/protocol/networks.js @@ -563,6 +563,8 @@ main.selfConnect = false; main.requestMempool = false; +main.nlrLimit = 100 // 100 * ~40s = ~66 minutes + /* * Testnet (v3) * https://en.bitcoin.it/wiki/Testnet @@ -800,6 +802,8 @@ testnet.selfConnect = false; testnet.requestMempool = false; +testnet.nlrLimit = 50; // 50 * ~40s = ~33 minutes + /* * Regtest */ @@ -1019,6 +1023,8 @@ regtest.selfConnect = true; regtest.requestMempool = true; +regtest.nlrLimit = 10; + /* * Simnet (btcd) */ diff --git a/package.json b/package.json index 60b41960..3ae2210d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fcoin", - "version": "1.1.3", + "version": "1.1.4", "description": "FLO bike-shed", "license": "MIT", "repository": "git://github.com/oipwg/fcoin.git",