Auto merge of #3559 - str4d:3552-testnet-min-difficulty-blocks, r=bitcartel
Allow minimum-difficulty blocks on testnet This is a consensus rule change on testnet that will result in a chain split (leaving the stuck chain, as desired). Reverts #2766 and part of #1338. Closes #3552.
This commit is contained in:
@@ -95,6 +95,7 @@ public:
|
|||||||
consensus.nPowMaxAdjustDown = 32; // 32% adjustment down
|
consensus.nPowMaxAdjustDown = 32; // 32% adjustment down
|
||||||
consensus.nPowMaxAdjustUp = 16; // 16% adjustment up
|
consensus.nPowMaxAdjustUp = 16; // 16% adjustment up
|
||||||
consensus.nPowTargetSpacing = 2.5 * 60;
|
consensus.nPowTargetSpacing = 2.5 * 60;
|
||||||
|
consensus.nPowAllowMinDifficultyBlocksAfterHeight = boost::none;
|
||||||
consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002;
|
consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002;
|
||||||
consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight =
|
consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight =
|
||||||
Consensus::NetworkUpgrade::ALWAYS_ACTIVE;
|
Consensus::NetworkUpgrade::ALWAYS_ACTIVE;
|
||||||
@@ -271,6 +272,7 @@ public:
|
|||||||
consensus.nPowMaxAdjustDown = 32; // 32% adjustment down
|
consensus.nPowMaxAdjustDown = 32; // 32% adjustment down
|
||||||
consensus.nPowMaxAdjustUp = 16; // 16% adjustment up
|
consensus.nPowMaxAdjustUp = 16; // 16% adjustment up
|
||||||
consensus.nPowTargetSpacing = 2.5 * 60;
|
consensus.nPowTargetSpacing = 2.5 * 60;
|
||||||
|
consensus.nPowAllowMinDifficultyBlocksAfterHeight = 299187;
|
||||||
consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002;
|
consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002;
|
||||||
consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight =
|
consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight =
|
||||||
Consensus::NetworkUpgrade::ALWAYS_ACTIVE;
|
Consensus::NetworkUpgrade::ALWAYS_ACTIVE;
|
||||||
@@ -391,6 +393,7 @@ public:
|
|||||||
consensus.nPowMaxAdjustDown = 0; // Turn off adjustment down
|
consensus.nPowMaxAdjustDown = 0; // Turn off adjustment down
|
||||||
consensus.nPowMaxAdjustUp = 0; // Turn off adjustment up
|
consensus.nPowMaxAdjustUp = 0; // Turn off adjustment up
|
||||||
consensus.nPowTargetSpacing = 2.5 * 60;
|
consensus.nPowTargetSpacing = 2.5 * 60;
|
||||||
|
consensus.nPowAllowMinDifficultyBlocksAfterHeight = 0;
|
||||||
consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002;
|
consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002;
|
||||||
consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight =
|
consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight =
|
||||||
Consensus::NetworkUpgrade::ALWAYS_ACTIVE;
|
Consensus::NetworkUpgrade::ALWAYS_ACTIVE;
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
|
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
namespace Consensus {
|
namespace Consensus {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -91,6 +93,7 @@ struct Params {
|
|||||||
NetworkUpgrade vUpgrades[MAX_NETWORK_UPGRADES];
|
NetworkUpgrade vUpgrades[MAX_NETWORK_UPGRADES];
|
||||||
/** Proof of work parameters */
|
/** Proof of work parameters */
|
||||||
uint256 powLimit;
|
uint256 powLimit;
|
||||||
|
boost::optional<uint32_t> nPowAllowMinDifficultyBlocksAfterHeight;
|
||||||
int64_t nPowAveragingWindow;
|
int64_t nPowAveragingWindow;
|
||||||
int64_t nPowMaxAdjustDown;
|
int64_t nPowMaxAdjustDown;
|
||||||
int64_t nPowMaxAdjustUp;
|
int64_t nPowMaxAdjustUp;
|
||||||
|
|||||||
@@ -68,3 +68,44 @@ TEST(PoW, DifficultyAveraging) {
|
|||||||
params),
|
params),
|
||||||
GetNextWorkRequired(&blocks[lastBlk], nullptr, 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<CBlockIndex> blocks(lastBlk+1);
|
||||||
|
for (int i = 0; i <= lastBlk; i++) {
|
||||||
|
blocks[i].pprev = i ? &blocks[i - 1] : nullptr;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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());
|
||||||
|
}
|
||||||
|
|||||||
@@ -101,6 +101,11 @@ public:
|
|||||||
void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
|
void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
|
||||||
{
|
{
|
||||||
pblock->nTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
|
pblock->nTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
|
||||||
|
|
||||||
|
// Updating time can change work required on testnet:
|
||||||
|
if (consensusParams.nPowAllowMinDifficultyBlocksAfterHeight != boost::none) {
|
||||||
|
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||||
@@ -722,6 +727,11 @@ void static BitcoinMiner()
|
|||||||
// Update nNonce and nTime
|
// Update nNonce and nTime
|
||||||
pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1);
|
pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1);
|
||||||
UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
|
UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
|
||||||
|
if (chainparams.GetConsensus().nPowAllowMinDifficultyBlocksAfterHeight != boost::none)
|
||||||
|
{
|
||||||
|
// Changing pblock->nTime can change work required on testnet:
|
||||||
|
hashTarget.SetCompact(pblock->nBits);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
14
src/pow.cpp
14
src/pow.cpp
@@ -24,6 +24,20 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
|
|||||||
if (pindexLast == NULL)
|
if (pindexLast == NULL)
|
||||||
return nProofOfWorkLimit;
|
return nProofOfWorkLimit;
|
||||||
|
|
||||||
|
{
|
||||||
|
// Comparing to pindexLast->nHeight with >= because this function
|
||||||
|
// returns the work required for the block after pindexLast.
|
||||||
|
if (params.nPowAllowMinDifficultyBlocksAfterHeight != boost::none &&
|
||||||
|
pindexLast->nHeight >= params.nPowAllowMinDifficultyBlocksAfterHeight.get())
|
||||||
|
{
|
||||||
|
// Special difficulty rule for testnet:
|
||||||
|
// If the new block's timestamp is more than 6 * 2.5 minutes
|
||||||
|
// then allow mining of a min-difficulty block.
|
||||||
|
if (pblock && pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing * 6)
|
||||||
|
return nProofOfWorkLimit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Find the first block in the averaging interval
|
// Find the first block in the averaging interval
|
||||||
const CBlockIndex* pindexFirst = pindexLast;
|
const CBlockIndex* pindexFirst = pindexLast;
|
||||||
arith_uint256 bnTot {0};
|
arith_uint256 bnTot {0};
|
||||||
|
|||||||
Reference in New Issue
Block a user