From 5ead4b171388b5fe96d6639a0ffccb0c390a3ccd Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 3 Oct 2018 16:08:00 +0100 Subject: [PATCH 1/7] Revert "Get rid of consensus.fPowAllowMinDifficultyBlocks." This reverts commit dffc025d38bb12b655bfde53de6dd237840c7d8e. --- src/chainparams.cpp | 3 +++ src/consensus/params.h | 1 + src/miner.cpp | 9 +++++++++ 3 files changed, 13 insertions(+) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 46777f54e..b0352a66d 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -95,6 +95,7 @@ public: consensus.nPowMaxAdjustDown = 32; // 32% adjustment down consensus.nPowMaxAdjustUp = 16; // 16% adjustment up consensus.nPowTargetSpacing = 2.5 * 60; + consensus.fPowAllowMinDifficultyBlocks = false; consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002; consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight = Consensus::NetworkUpgrade::ALWAYS_ACTIVE; @@ -271,6 +272,7 @@ public: consensus.nPowMaxAdjustDown = 32; // 32% adjustment down consensus.nPowMaxAdjustUp = 16; // 16% adjustment up consensus.nPowTargetSpacing = 2.5 * 60; + consensus.fPowAllowMinDifficultyBlocks = true; consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002; consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight = Consensus::NetworkUpgrade::ALWAYS_ACTIVE; @@ -391,6 +393,7 @@ public: consensus.nPowMaxAdjustDown = 0; // Turn off adjustment down consensus.nPowMaxAdjustUp = 0; // Turn off adjustment up consensus.nPowTargetSpacing = 2.5 * 60; + consensus.fPowAllowMinDifficultyBlocks = true; consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002; consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight = Consensus::NetworkUpgrade::ALWAYS_ACTIVE; diff --git a/src/consensus/params.h b/src/consensus/params.h index c21607046..50eb69a45 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -91,6 +91,7 @@ struct Params { NetworkUpgrade vUpgrades[MAX_NETWORK_UPGRADES]; /** Proof of work parameters */ uint256 powLimit; + bool fPowAllowMinDifficultyBlocks; int64_t nPowAveragingWindow; int64_t nPowMaxAdjustDown; int64_t nPowMaxAdjustUp; diff --git a/src/miner.cpp b/src/miner.cpp index e22ac2c62..19912eb67 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -101,6 +101,10 @@ public: void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev) { pblock->nTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); + + // Updating time can change work required on testnet: + if (consensusParams.fPowAllowMinDifficultyBlocks) + pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams); } CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) @@ -722,6 +726,11 @@ void static BitcoinMiner() // Update nNonce and nTime pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1); UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); + if (chainparams.GetConsensus().fPowAllowMinDifficultyBlocks) + { + // Changing pblock->nTime can change work required on testnet: + hashTarget.SetCompact(pblock->nBits); + } } } } From 639e46b4d7c6d9fcaab1a76433fb174364c84413 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 3 Oct 2018 16:15:03 +0100 Subject: [PATCH 2/7] Revert "Remove testnet-only difficulty rules" This reverts commit 333ea3c4266179da5d40e496ae60bcce0259c790. --- src/gtest/test_rpc.cpp | 27 +++++++++++++++++++++++++++ src/pow.cpp | 17 +++++++++++++++++ src/rpc/blockchain.cpp | 26 +++++++++++++++++--------- 3 files changed, 61 insertions(+), 9 deletions(-) diff --git a/src/gtest/test_rpc.cpp b/src/gtest/test_rpc.cpp index 3733379a8..ad80393f5 100644 --- a/src/gtest/test_rpc.cpp +++ b/src/gtest/test_rpc.cpp @@ -9,6 +9,33 @@ #include "streams.h" #include "utilstrencodings.h" +TEST(rpc, GetDifficultyTestnetRules) { + SelectParams(CBaseChainParams::TESTNET); + + CBlockIndex prev; + prev.nTime = 1472700000; + prev.nBits = 0x201fffff; + + CBlockIndex curr; + curr.pprev = &prev; + curr.nTime = 1472700300; + curr.nBits = 0x207fffff; + + // Time interval is within 5 minutes, so the min-difficulty block should be + // interpreted as a valid network difficulty. + EXPECT_EQ(1, GetDifficulty(&curr)); + EXPECT_EQ(1, GetNetworkDifficulty(&curr)); + + curr.nTime += 1; + + // Time interval is over 5 minutes, so the min-difficulty block should be + // ignored for network difficulty determination. + EXPECT_EQ(1, GetDifficulty(&curr)); + // We have to check this directly, because of some combination of rounding + // and truncation issues that result in Google Test displaying 4 != 4 + EXPECT_EQ((double)0x7fffff/(double)0x1fffff, GetNetworkDifficulty(&curr)); +} + extern UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false); TEST(rpc, check_blockToJSON_returns_minified_solution) { diff --git a/src/pow.cpp b/src/pow.cpp index 18873d4ee..0eb81414a 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -24,6 +24,23 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead if (pindexLast == NULL) return nProofOfWorkLimit; + const CBlockIndex* pindexBits = pindexLast; + { + if (params.fPowAllowMinDifficultyBlocks) + { + // Special difficulty rule for testnet: + // If the new block's timestamp is more than 2* 2.5 minutes + // then allow mining of a min-difficulty block. + if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2) + return nProofOfWorkLimit; + else { + // Get the last non-min-difficulty (or at worst the genesis difficulty) + while (pindexBits->pprev && pindexBits->nBits == nProofOfWorkLimit) + pindexBits = pindexBits->pprev; + } + } + } + // Find the first block in the averaging interval const CBlockIndex* pindexFirst = pindexLast; arith_uint256 bnTot {0}; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 9a9b0fd57..c7afe7af8 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -38,21 +38,29 @@ double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficul blockindex = chainActive.Tip(); } - uint32_t bits; - if (networkDifficulty) { - bits = GetNextWorkRequired(blockindex, nullptr, Params().GetConsensus()); - } else { - bits = blockindex->nBits; - } - uint32_t powLimit = UintToArith256(Params().GetConsensus().powLimit).GetCompact(); - int nShift = (bits >> 24) & 0xff; + { + if (networkDifficulty && Params().GetConsensus().fPowAllowMinDifficultyBlocks) + { + // Special difficulty rule for testnet: + // If a block's timestamp is more than 2*nPowTargetSpacing minutes after + // the previous block, then it is permitted to be min-difficulty. So + // get the last non-min-difficulty (or at worst the genesis difficulty). + auto window = Params().GetConsensus().nPowTargetSpacing*2; + while (blockindex->pprev && blockindex->nBits == powLimit && + blockindex->GetBlockTime() > blockindex->pprev->GetBlockTime() + window) { + blockindex = blockindex->pprev; + } + } + } + + int nShift = (blockindex->nBits >> 24) & 0xff; int nShiftAmount = (powLimit >> 24) & 0xff; double dDiff = (double)(powLimit & 0x00ffffff) / - (double)(bits & 0x00ffffff); + (double)(blockindex->nBits & 0x00ffffff); while (nShift < nShiftAmount) { From 1702a86455c426da46473770c990257c4a1e087d Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 3 Oct 2018 17:50:17 +0100 Subject: [PATCH 3/7] Allow minimum-difficulty blocks on testnet and regtest A block may be mined with nBits set to the minimum difficulty if its nTime is set more than six block intervals (15 minutes) after its parent block. This is a consensus rule change on testnet that will result in a chain split (as desired). --- src/gtest/test_pow.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ src/gtest/test_rpc.cpp | 27 --------------------------- src/pow.cpp | 10 ++-------- src/rpc/blockchain.cpp | 26 +++++++++----------------- 4 files changed, 52 insertions(+), 52 deletions(-) diff --git a/src/gtest/test_pow.cpp b/src/gtest/test_pow.cpp index ac3ce59e1..80e0d0921 100644 --- a/src/gtest/test_pow.cpp +++ b/src/gtest/test_pow.cpp @@ -68,3 +68,44 @@ TEST(PoW, DifficultyAveraging) { params), GetNextWorkRequired(&blocks[lastBlk], nullptr, params)); } + +TEST(PoW, MinDifficultyRules) { + SelectParams(CBaseChainParams::TESTNET); + const Consensus::Params& params = Params().GetConsensus(); + size_t lastBlk = 2*params.nPowAveragingWindow; + size_t firstBlk = lastBlk - params.nPowAveragingWindow; + + // Start with blocks evenly-spaced and equal difficulty + std::vector blocks(lastBlk+1); + for (int i = 0; i <= lastBlk; i++) { + blocks[i].pprev = i ? &blocks[i - 1] : nullptr; + blocks[i].nHeight = i; + blocks[i].nTime = 1269211443 + i * params.nPowTargetSpacing; + blocks[i].nBits = 0x1e7fffff; /* target 0x007fffff000... */ + blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + GetBlockProof(blocks[i - 1]) : arith_uint256(0); + } + + // Create a new block at the target spacing + CBlockHeader next; + next.nTime = blocks[lastBlk].nTime + params.nPowTargetSpacing; + + // Result should be unchanged, modulo integer division precision loss + arith_uint256 bnRes; + bnRes.SetCompact(0x1e7fffff); + bnRes /= params.AveragingWindowTimespan(); + bnRes *= params.AveragingWindowTimespan(); + EXPECT_EQ(GetNextWorkRequired(&blocks[lastBlk], &next, params), bnRes.GetCompact()); + + // Delay last block up to the edge of the min-difficulty limit + next.nTime += params.nPowTargetSpacing * 5; + + // Result should be unchanged, modulo integer division precision loss + EXPECT_EQ(GetNextWorkRequired(&blocks[lastBlk], &next, params), bnRes.GetCompact()); + + // Delay last block over the min-difficulty limit + next.nTime += 1; + + // Result should be the minimum difficulty + EXPECT_EQ(GetNextWorkRequired(&blocks[lastBlk], &next, params), + UintToArith256(params.powLimit).GetCompact()); +} diff --git a/src/gtest/test_rpc.cpp b/src/gtest/test_rpc.cpp index ad80393f5..3733379a8 100644 --- a/src/gtest/test_rpc.cpp +++ b/src/gtest/test_rpc.cpp @@ -9,33 +9,6 @@ #include "streams.h" #include "utilstrencodings.h" -TEST(rpc, GetDifficultyTestnetRules) { - SelectParams(CBaseChainParams::TESTNET); - - CBlockIndex prev; - prev.nTime = 1472700000; - prev.nBits = 0x201fffff; - - CBlockIndex curr; - curr.pprev = &prev; - curr.nTime = 1472700300; - curr.nBits = 0x207fffff; - - // Time interval is within 5 minutes, so the min-difficulty block should be - // interpreted as a valid network difficulty. - EXPECT_EQ(1, GetDifficulty(&curr)); - EXPECT_EQ(1, GetNetworkDifficulty(&curr)); - - curr.nTime += 1; - - // Time interval is over 5 minutes, so the min-difficulty block should be - // ignored for network difficulty determination. - EXPECT_EQ(1, GetDifficulty(&curr)); - // We have to check this directly, because of some combination of rounding - // and truncation issues that result in Google Test displaying 4 != 4 - EXPECT_EQ((double)0x7fffff/(double)0x1fffff, GetNetworkDifficulty(&curr)); -} - extern UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false); TEST(rpc, check_blockToJSON_returns_minified_solution) { diff --git a/src/pow.cpp b/src/pow.cpp index 0eb81414a..40e69bb52 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -24,20 +24,14 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead if (pindexLast == NULL) return nProofOfWorkLimit; - const CBlockIndex* pindexBits = pindexLast; { if (params.fPowAllowMinDifficultyBlocks) { // Special difficulty rule for testnet: - // If the new block's timestamp is more than 2* 2.5 minutes + // If the new block's timestamp is more than 6 * 2.5 minutes // then allow mining of a min-difficulty block. - if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2) + if (pblock && pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing * 6) return nProofOfWorkLimit; - else { - // Get the last non-min-difficulty (or at worst the genesis difficulty) - while (pindexBits->pprev && pindexBits->nBits == nProofOfWorkLimit) - pindexBits = pindexBits->pprev; - } } } diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index c7afe7af8..9a9b0fd57 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -38,29 +38,21 @@ double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficul blockindex = chainActive.Tip(); } - uint32_t powLimit = - UintToArith256(Params().GetConsensus().powLimit).GetCompact(); - { - if (networkDifficulty && Params().GetConsensus().fPowAllowMinDifficultyBlocks) - { - // Special difficulty rule for testnet: - // If a block's timestamp is more than 2*nPowTargetSpacing minutes after - // the previous block, then it is permitted to be min-difficulty. So - // get the last non-min-difficulty (or at worst the genesis difficulty). - auto window = Params().GetConsensus().nPowTargetSpacing*2; - while (blockindex->pprev && blockindex->nBits == powLimit && - blockindex->GetBlockTime() > blockindex->pprev->GetBlockTime() + window) { - blockindex = blockindex->pprev; - } - } + uint32_t bits; + if (networkDifficulty) { + bits = GetNextWorkRequired(blockindex, nullptr, Params().GetConsensus()); + } else { + bits = blockindex->nBits; } - int nShift = (blockindex->nBits >> 24) & 0xff; + uint32_t powLimit = + UintToArith256(Params().GetConsensus().powLimit).GetCompact(); + int nShift = (bits >> 24) & 0xff; int nShiftAmount = (powLimit >> 24) & 0xff; double dDiff = (double)(powLimit & 0x00ffffff) / - (double)(blockindex->nBits & 0x00ffffff); + (double)(bits & 0x00ffffff); while (nShift < nShiftAmount) { From b86dc98047a1cf373c11cbb5bb9cfde65aa4a67c Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 4 Oct 2018 14:05:27 +0100 Subject: [PATCH 4/7] Only enable min-difficulty blocks on testnet from a particular height The min-difficulty change is a bilateral consensus rule change, and so must be conditionally enabled in order for the earlier section of the chain to synchronise. Technically this could be implemented as a network upgrade, but as this will never be deployed to mainnet, a targeted fork will suffice. --- src/chainparams.cpp | 6 +++--- src/consensus/params.h | 4 +++- src/miner.cpp | 5 +++-- src/pow.cpp | 3 ++- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index b0352a66d..25f9f45f3 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -95,7 +95,7 @@ public: consensus.nPowMaxAdjustDown = 32; // 32% adjustment down consensus.nPowMaxAdjustUp = 16; // 16% adjustment up consensus.nPowTargetSpacing = 2.5 * 60; - consensus.fPowAllowMinDifficultyBlocks = false; + consensus.nPowAllowMinDifficultyBlocksFromHeight = boost::none; consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002; consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight = Consensus::NetworkUpgrade::ALWAYS_ACTIVE; @@ -272,7 +272,7 @@ public: consensus.nPowMaxAdjustDown = 32; // 32% adjustment down consensus.nPowMaxAdjustUp = 16; // 16% adjustment up consensus.nPowTargetSpacing = 2.5 * 60; - consensus.fPowAllowMinDifficultyBlocks = true; + consensus.nPowAllowMinDifficultyBlocksFromHeight = 299187; consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002; consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight = Consensus::NetworkUpgrade::ALWAYS_ACTIVE; @@ -393,7 +393,7 @@ public: consensus.nPowMaxAdjustDown = 0; // Turn off adjustment down consensus.nPowMaxAdjustUp = 0; // Turn off adjustment up consensus.nPowTargetSpacing = 2.5 * 60; - consensus.fPowAllowMinDifficultyBlocks = true; + consensus.nPowAllowMinDifficultyBlocksFromHeight = 0; consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002; consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight = Consensus::NetworkUpgrade::ALWAYS_ACTIVE; diff --git a/src/consensus/params.h b/src/consensus/params.h index 50eb69a45..4e6f7b86a 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -8,6 +8,8 @@ #include "uint256.h" +#include + namespace Consensus { /** @@ -91,7 +93,7 @@ struct Params { NetworkUpgrade vUpgrades[MAX_NETWORK_UPGRADES]; /** Proof of work parameters */ uint256 powLimit; - bool fPowAllowMinDifficultyBlocks; + boost::optional nPowAllowMinDifficultyBlocksFromHeight; int64_t nPowAveragingWindow; int64_t nPowMaxAdjustDown; int64_t nPowMaxAdjustUp; diff --git a/src/miner.cpp b/src/miner.cpp index 19912eb67..960ac60de 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -103,8 +103,9 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, pblock->nTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); // Updating time can change work required on testnet: - if (consensusParams.fPowAllowMinDifficultyBlocks) + if (consensusParams.nPowAllowMinDifficultyBlocksFromHeight) { pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams); + } } CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) @@ -726,7 +727,7 @@ void static BitcoinMiner() // Update nNonce and nTime pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1); UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); - if (chainparams.GetConsensus().fPowAllowMinDifficultyBlocks) + if (chainparams.GetConsensus().nPowAllowMinDifficultyBlocksFromHeight) { // Changing pblock->nTime can change work required on testnet: hashTarget.SetCompact(pblock->nBits); diff --git a/src/pow.cpp b/src/pow.cpp index 40e69bb52..7bc2fa79f 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -25,7 +25,8 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead return nProofOfWorkLimit; { - if (params.fPowAllowMinDifficultyBlocks) + if (params.nPowAllowMinDifficultyBlocksFromHeight && + pindexLast->nHeight >= params.nPowAllowMinDifficultyBlocksFromHeight.get()) { // Special difficulty rule for testnet: // If the new block's timestamp is more than 6 * 2.5 minutes From 1f7ee4af70ece8759f7a4e6d8df9c39284bb1482 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 4 Oct 2018 23:26:05 +0100 Subject: [PATCH 5/7] Rename min-difficulty flag to remove off-by-one in the name --- src/chainparams.cpp | 6 +++--- src/consensus/params.h | 2 +- src/miner.cpp | 4 ++-- src/pow.cpp | 6 ++++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 25f9f45f3..8ebf04c6f 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -95,7 +95,7 @@ public: consensus.nPowMaxAdjustDown = 32; // 32% adjustment down consensus.nPowMaxAdjustUp = 16; // 16% adjustment up consensus.nPowTargetSpacing = 2.5 * 60; - consensus.nPowAllowMinDifficultyBlocksFromHeight = boost::none; + consensus.nPowAllowMinDifficultyBlocksAfterHeight = boost::none; consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002; consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight = Consensus::NetworkUpgrade::ALWAYS_ACTIVE; @@ -272,7 +272,7 @@ public: consensus.nPowMaxAdjustDown = 32; // 32% adjustment down consensus.nPowMaxAdjustUp = 16; // 16% adjustment up consensus.nPowTargetSpacing = 2.5 * 60; - consensus.nPowAllowMinDifficultyBlocksFromHeight = 299187; + consensus.nPowAllowMinDifficultyBlocksAfterHeight = 299187; consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002; consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight = Consensus::NetworkUpgrade::ALWAYS_ACTIVE; @@ -393,7 +393,7 @@ public: consensus.nPowMaxAdjustDown = 0; // Turn off adjustment down consensus.nPowMaxAdjustUp = 0; // Turn off adjustment up consensus.nPowTargetSpacing = 2.5 * 60; - consensus.nPowAllowMinDifficultyBlocksFromHeight = 0; + consensus.nPowAllowMinDifficultyBlocksAfterHeight = 0; consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002; consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight = Consensus::NetworkUpgrade::ALWAYS_ACTIVE; diff --git a/src/consensus/params.h b/src/consensus/params.h index 4e6f7b86a..26288f243 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -93,7 +93,7 @@ struct Params { NetworkUpgrade vUpgrades[MAX_NETWORK_UPGRADES]; /** Proof of work parameters */ uint256 powLimit; - boost::optional nPowAllowMinDifficultyBlocksFromHeight; + boost::optional nPowAllowMinDifficultyBlocksAfterHeight; int64_t nPowAveragingWindow; int64_t nPowMaxAdjustDown; int64_t nPowMaxAdjustUp; diff --git a/src/miner.cpp b/src/miner.cpp index 960ac60de..b76226ecc 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -103,7 +103,7 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, pblock->nTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); // Updating time can change work required on testnet: - if (consensusParams.nPowAllowMinDifficultyBlocksFromHeight) { + if (consensusParams.nPowAllowMinDifficultyBlocksAfterHeight) { pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams); } } @@ -727,7 +727,7 @@ void static BitcoinMiner() // Update nNonce and nTime pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1); UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); - if (chainparams.GetConsensus().nPowAllowMinDifficultyBlocksFromHeight) + if (chainparams.GetConsensus().nPowAllowMinDifficultyBlocksAfterHeight) { // Changing pblock->nTime can change work required on testnet: hashTarget.SetCompact(pblock->nBits); diff --git a/src/pow.cpp b/src/pow.cpp index 7bc2fa79f..82c817efb 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -25,8 +25,10 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead return nProofOfWorkLimit; { - if (params.nPowAllowMinDifficultyBlocksFromHeight && - pindexLast->nHeight >= params.nPowAllowMinDifficultyBlocksFromHeight.get()) + // Comparing to pindexLast->nHeight with >= because this function + // returns the work required for the block after pindexLast. + if (params.nPowAllowMinDifficultyBlocksAfterHeight && + pindexLast->nHeight >= params.nPowAllowMinDifficultyBlocksAfterHeight.get()) { // Special difficulty rule for testnet: // If the new block's timestamp is more than 6 * 2.5 minutes From 4c90270469e32cbf3459ec2fd25d46a089bd5c58 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 4 Oct 2018 23:29:11 +0100 Subject: [PATCH 6/7] Explicitly check the min-difficulty flag against boost::none It isn't clear how a boost::optional that holds 0 (which is the case for regtest) is coerced to a boolean, unless you pore over the Boost documentation. An explicit check is clearer. --- src/miner.cpp | 4 ++-- src/pow.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index b76226ecc..e2e5d2f7e 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -103,7 +103,7 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, pblock->nTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); // Updating time can change work required on testnet: - if (consensusParams.nPowAllowMinDifficultyBlocksAfterHeight) { + if (consensusParams.nPowAllowMinDifficultyBlocksAfterHeight != boost::none) { pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams); } } @@ -727,7 +727,7 @@ void static BitcoinMiner() // Update nNonce and nTime pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1); UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); - if (chainparams.GetConsensus().nPowAllowMinDifficultyBlocksAfterHeight) + if (chainparams.GetConsensus().nPowAllowMinDifficultyBlocksAfterHeight != boost::none) { // Changing pblock->nTime can change work required on testnet: hashTarget.SetCompact(pblock->nBits); diff --git a/src/pow.cpp b/src/pow.cpp index 82c817efb..743df08ee 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -27,7 +27,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead { // Comparing to pindexLast->nHeight with >= because this function // returns the work required for the block after pindexLast. - if (params.nPowAllowMinDifficultyBlocksAfterHeight && + if (params.nPowAllowMinDifficultyBlocksAfterHeight != boost::none && pindexLast->nHeight >= params.nPowAllowMinDifficultyBlocksAfterHeight.get()) { // Special difficulty rule for testnet: From 2b47b0de7d3a809170d239386a291e954cb3f32b Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 4 Oct 2018 23:46:50 +0100 Subject: [PATCH 7/7] Position PoW.MinDifficultyRules test after rule activates --- src/gtest/test_pow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gtest/test_pow.cpp b/src/gtest/test_pow.cpp index 80e0d0921..4557f6db1 100644 --- a/src/gtest/test_pow.cpp +++ b/src/gtest/test_pow.cpp @@ -79,7 +79,7 @@ TEST(PoW, MinDifficultyRules) { std::vector blocks(lastBlk+1); for (int i = 0; i <= lastBlk; i++) { blocks[i].pprev = i ? &blocks[i - 1] : nullptr; - blocks[i].nHeight = i; + blocks[i].nHeight = params.nPowAllowMinDifficultyBlocksAfterHeight.get() + i; blocks[i].nTime = 1269211443 + i * params.nPowTargetSpacing; blocks[i].nBits = 0x1e7fffff; /* target 0x007fffff000... */ blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + GetBlockProof(blocks[i - 1]) : arith_uint256(0);