From af2f9bbae7973a8118a34757f66075f3caed77ba Mon Sep 17 00:00:00 2001 From: metacoin Date: Wed, 19 Feb 2020 08:56:27 -0500 Subject: [PATCH 01/10] Add FLO block halving limit (34 halvings) --- lib/protocol/consensus.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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`, From f3606f2fe6cfe2767fce64d26678924fee5c66d9 Mon Sep 17 00:00:00 2001 From: Sky Young Date: Thu, 4 Jun 2020 17:57:43 -0600 Subject: [PATCH 02/10] v1.1.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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", From 430276b59229f1f08502877935d4d4e7e34b0903 Mon Sep 17 00:00:00 2001 From: ohryan Date: Wed, 15 Jul 2020 17:45:56 -0700 Subject: [PATCH 03/10] add nlr check to reorganize function --- lib/blockchain/chain.js | 37 ++++++++++++++++++++++++++++++++++--- lib/protocol/network.js | 1 + lib/protocol/networks.js | 6 ++++++ 3 files changed, 41 insertions(+), 3 deletions(-) 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) */ From 7a1816a3a8949a690874c0a5bf61718676c499a5 Mon Sep 17 00:00:00 2001 From: ohryan Date: Wed, 15 Jul 2020 19:07:25 -0700 Subject: [PATCH 04/10] refactor/update nlr function; check nlr for spv wallet --- lib/blockchain/chain.js | 75 ++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 30 deletions(-) diff --git a/lib/blockchain/chain.js b/lib/blockchain/chain.js index c97e428d..6c8822f0 100644 --- a/lib/blockchain/chain.js +++ b/lib/blockchain/chain.js @@ -855,36 +855,8 @@ 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 - } - } + // Check NLR + if (this.noLongReorg(tip, fork, competitor)) return true // Blocks to disconnect. const disconnect = []; @@ -943,6 +915,9 @@ class Chain extends AsyncEmitter { assert(fork, 'No free space or data corruption.'); + // Check NLR + if (this.noLongReorg(tip, fork, competitor)) return true + // Buffer disconnected blocks. const disconnect = []; let entry = tip; @@ -981,6 +956,46 @@ 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: current=%h(%d) fork=%h(%d) reorg_size=%d', + tip.hash, + tip.height, + competitor.hash, + competitor.height, + tip.height - fork.height + ); + + // mark invalid_child from tip of fork to second block of fork + while (competitor.height > fork.height + 2) { + const previous = await this.getPrevious(competitor) + this.invalidate(previous.hash) + } + + // mark invalid first block of fork + const previous = await this.getPrevious(competitor) + this.invalidate(previous.hash) + + // check + assert(this.getPrevious(previous), fork) + + return true + } + } + return false + } + /** * Disconnect an entry from the chain (updates the tip). * @param {ChainEntry} entry From 9f9c536efce1146955a609e7d0c55ee74b1f59da Mon Sep 17 00:00:00 2001 From: ohryan Date: Thu, 16 Jul 2020 08:31:10 -0700 Subject: [PATCH 05/10] add missing awaits --- lib/blockchain/chain.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/blockchain/chain.js b/lib/blockchain/chain.js index 6c8822f0..3a407547 100644 --- a/lib/blockchain/chain.js +++ b/lib/blockchain/chain.js @@ -856,7 +856,7 @@ class Chain extends AsyncEmitter { assert(fork, 'No free space or data corruption.'); // Check NLR - if (this.noLongReorg(tip, fork, competitor)) return true + if (await this.noLongReorg(tip, fork, competitor)) return true // Blocks to disconnect. const disconnect = []; @@ -916,7 +916,7 @@ class Chain extends AsyncEmitter { assert(fork, 'No free space or data corruption.'); // Check NLR - if (this.noLongReorg(tip, fork, competitor)) return true + if (await this.noLongReorg(tip, fork, competitor)) return true // Buffer disconnected blocks. const disconnect = []; @@ -980,12 +980,12 @@ class Chain extends AsyncEmitter { // mark invalid_child from tip of fork to second block of fork while (competitor.height > fork.height + 2) { const previous = await this.getPrevious(competitor) - this.invalidate(previous.hash) + await this.invalidate(previous.hash) } // mark invalid first block of fork const previous = await this.getPrevious(competitor) - this.invalidate(previous.hash) + await this.invalidate(previous.hash) // check assert(this.getPrevious(previous), fork) From 11534032f4192b84dfe46f01b031a4bb6323f123 Mon Sep 17 00:00:00 2001 From: ohryan Date: Thu, 16 Jul 2020 19:07:39 -0700 Subject: [PATCH 06/10] fix/update logger warning and fix incorrect assert usage --- lib/blockchain/chain.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/blockchain/chain.js b/lib/blockchain/chain.js index 3a407547..204fbb98 100644 --- a/lib/blockchain/chain.js +++ b/lib/blockchain/chain.js @@ -969,11 +969,13 @@ class Chain extends AsyncEmitter { if (tip.height - fork.height >= this.network.nlrLimit) { if (this.network.nlrLimit !== 0) { this.logger.warning( - 'NLR Activated: current=%h(%d) fork=%h(%d) reorg_size=%d', + 'NLR Activated. Preventing reorganization: current=%h(%d) competitor=%h(%d) fork=%h(%d) reorg_size=%d', tip.hash, tip.height, competitor.hash, competitor.height, + fork.hash, + fork.height, tip.height - fork.height ); @@ -988,7 +990,7 @@ class Chain extends AsyncEmitter { await this.invalidate(previous.hash) // check - assert(this.getPrevious(previous), fork) + assert.equal(this.getPrevious(previous), fork, 'nlr invalidation down to the fork') return true } From c6317a268dddb8a90286152a45bcb73b7c88d83e Mon Sep 17 00:00:00 2001 From: ohryan Date: Thu, 16 Jul 2020 19:20:49 -0700 Subject: [PATCH 07/10] update invalidation stepping to use just the while loop and add missing await to assert check --- lib/blockchain/chain.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/blockchain/chain.js b/lib/blockchain/chain.js index 204fbb98..4e5f53e8 100644 --- a/lib/blockchain/chain.js +++ b/lib/blockchain/chain.js @@ -979,18 +979,14 @@ class Chain extends AsyncEmitter { tip.height - fork.height ); - // mark invalid_child from tip of fork to second block of fork - while (competitor.height > fork.height + 2) { + // mark invalid_child from tip of fork to first block of fork + while (competitor.height !== fork.height + 1) { const previous = await this.getPrevious(competitor) await this.invalidate(previous.hash) } - // mark invalid first block of fork - const previous = await this.getPrevious(competitor) - await this.invalidate(previous.hash) - // check - assert.equal(this.getPrevious(previous), fork, 'nlr invalidation down to the fork') + assert.equal(await this.getPrevious(competitor), fork, 'nlr invalidation down to the fork') return true } From 36671d02ed0d4ba6d84548653c43b985fe246ace Mon Sep 17 00:00:00 2001 From: ohryan Date: Fri, 17 Jul 2020 20:03:07 -0700 Subject: [PATCH 08/10] pull loop variable outside for reassignment --- lib/blockchain/chain.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/blockchain/chain.js b/lib/blockchain/chain.js index 4e5f53e8..a86e3055 100644 --- a/lib/blockchain/chain.js +++ b/lib/blockchain/chain.js @@ -969,24 +969,27 @@ class Chain extends AsyncEmitter { 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 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 + tip.height - fork.height, + this.network.nlrLimit ); + let indexWalk = competitor + // mark invalid_child from tip of fork to first block of fork - while (competitor.height !== fork.height + 1) { - const previous = await this.getPrevious(competitor) - await this.invalidate(previous.hash) + while (indexWalk.height !== fork.height + 1) { + indexWalk = await this.getPrevious(indexWalk) + await this.invalidate(indexWalk.hash) } // check - assert.equal(await this.getPrevious(competitor), fork, 'nlr invalidation down to the fork') + assert.equal(await this.getPrevious(indexWalk), fork, 'nlr invalidation down to the fork') return true } From 83a11fbcb27c91d6ea883a5ce5b707277e123b3a Mon Sep 17 00:00:00 2001 From: ohryan Date: Mon, 20 Jul 2020 17:43:34 -0700 Subject: [PATCH 09/10] setInvalid instead of invalidate + strictEqual assert instead of running this.invalidate which deadlocks the chain, set the hash to invalid manually with this.setInvalid. update assertion to use strict equal --- lib/blockchain/chain.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/blockchain/chain.js b/lib/blockchain/chain.js index a86e3055..5e2cd14e 100644 --- a/lib/blockchain/chain.js +++ b/lib/blockchain/chain.js @@ -985,11 +985,12 @@ class Chain extends AsyncEmitter { // mark invalid_child from tip of fork to first block of fork while (indexWalk.height !== fork.height + 1) { indexWalk = await this.getPrevious(indexWalk) - await this.invalidate(indexWalk.hash) + await this.setInvalid(indexWalk.hash) } // check - assert.equal(await this.getPrevious(indexWalk), fork, 'nlr invalidation down to the fork') + indexWalk = await this.getPrevious(indexWalk) + assert.strictEqual(indexWalk, fork) return true } From 5321251db33ba197d0cb7ea7539d1df5d357d9d2 Mon Sep 17 00:00:00 2001 From: ohryan Date: Tue, 21 Jul 2020 14:01:48 -0700 Subject: [PATCH 10/10] set competitor chain tip to invaild setting the competitor chain tip to invaild fixes the problem where the chain continues to sync after nlr. main chain will no longer sync with competitor after nlr --- lib/blockchain/chain.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/blockchain/chain.js b/lib/blockchain/chain.js index 5e2cd14e..9c305ff7 100644 --- a/lib/blockchain/chain.js +++ b/lib/blockchain/chain.js @@ -982,10 +982,10 @@ class Chain extends AsyncEmitter { let indexWalk = competitor - // mark invalid_child from tip of fork to first block of fork - while (indexWalk.height !== fork.height + 1) { - indexWalk = await this.getPrevious(indexWalk) + // 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