diff --git a/lib/blockchain/chain.js b/lib/blockchain/chain.js index 5ac953dd..c97e428d 100644 --- a/lib/blockchain/chain.js +++ b/lib/blockchain/chain.js @@ -855,6 +855,37 @@ class Chain extends AsyncEmitter { assert(fork, 'No free space or data corruption.'); + // Check NLR (No Large Reorganization) + if (tip.height - fork.height >= this.nlrLimit) { + if (this.nlrLimit !== 0) { + this.logger.warning( + 'NLR Activated: current=%h(%d) fork=%h(%d) reorg_size=%d', + tip.hash, + tip.height, + competitor.hash, + competitor.height, + tip.height - fork.height + ); + + const entryWithMostWork = (tip.height > competitor.height) ? tip : competitor + + // mark invalid_child from tip of fork to second block of fork + while (entryWithMostWork.height > fork.height + 2) { + const previous = await this.getPrevious(entryWithMostWork) + this.invalidate(previous.hash) + } + + // mark invalid first block of fork + const previous = await this.getPrevious(entryWithMostWork) + this.invalidate(previous.hash) + + // check + assert(this.getPrevious(previous), fork) + + return true + } + } + // Blocks to disconnect. const disconnect = []; let entry = tip; @@ -2209,7 +2240,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 +2278,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/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) */