Merge pull request #96 from jc23424/pow-adjust

Smooth out difficulty adjustment during fork
This commit is contained in:
Jon Layton 2018-02-28 19:19:44 -06:00 committed by GitHub
commit e96711d3ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 37 additions and 17 deletions

View File

@ -27,7 +27,7 @@ TEST(PoW, DifficultyAveraging) {
EXPECT_EQ(CalculateNextWorkRequired(bnAvg,
blocks[lastBlk].GetMedianTimePast(),
blocks[firstBlk].GetMedianTimePast(),
params),
params, UintToArith256(params.powLimit)),
GetNextWorkRequired(&blocks[lastBlk], nullptr, params));
// Result should be unchanged, modulo integer division precision loss
arith_uint256 bnRes;
@ -44,7 +44,7 @@ TEST(PoW, DifficultyAveraging) {
EXPECT_EQ(CalculateNextWorkRequired(bnAvg,
blocks[lastBlk].GetMedianTimePast(),
blocks[firstBlk].GetMedianTimePast(),
params),
params, UintToArith256(params.powLimit)),
GetNextWorkRequired(&blocks[lastBlk], nullptr, params));
// Result should not be unchanged
EXPECT_NE(0x1e7fffff, GetNextWorkRequired(&blocks[lastBlk], nullptr, params));
@ -57,7 +57,7 @@ TEST(PoW, DifficultyAveraging) {
EXPECT_NE(CalculateNextWorkRequired(bnAvg,
blocks[lastBlk].GetMedianTimePast(),
blocks[firstBlk].GetMedianTimePast(),
params),
params, UintToArith256(params.powLimit)),
GetNextWorkRequired(&blocks[lastBlk], nullptr, params));
// Result should be the same as if the average difficulty was used
@ -65,6 +65,6 @@ TEST(PoW, DifficultyAveraging) {
EXPECT_EQ(CalculateNextWorkRequired(average,
blocks[lastBlk].GetMedianTimePast(),
blocks[firstBlk].GetMedianTimePast(),
params),
params, UintToArith256(params.powLimit)),
GetNextWorkRequired(&blocks[lastBlk], nullptr, params));
}

View File

@ -1457,7 +1457,16 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams)
}
assert(nHeight > consensusParams.SubsidySlowStartShift());
int halvings = (nHeight - consensusParams.SubsidySlowStartShift()) / consensusParams.nSubsidyHalvingInterval;
int halvingInterval = consensusParams.nSubsidyHalvingInterval;
if(isForkEnabled(nHeight)) {
halvingInterval >>= 2;
}
int halvings = (nHeight - consensusParams.SubsidySlowStartShift()) / halvingInterval;
if(isForkEnabled(nHeight))
halvings += 2;
// Force block reward to zero when right shift is undefined.
if (halvings >= 64)
return 0;

View File

@ -23,17 +23,29 @@
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
{
unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact();
int nHeight = pindexLast->nHeight + 1;
arith_uint256 proofOfWorkLimit;
if(isForkBlock(nHeight) || isForkBlock(nHeight - params.nPowAveragingWindow))
proofOfWorkLimit = UintToArith256(uint256S("07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"));
else
proofOfWorkLimit = UintToArith256(params.powLimit);
unsigned int nProofOfWorkLimit = proofOfWorkLimit.GetCompact();
unsigned int nProofOfWorkBomb = UintToArith256(uint256S("000000000000000000000000000000000000000000000000000000000000ffff")).GetCompact();
// Genesis block
if (pindexLast == NULL)
return nProofOfWorkLimit;
// right post fork
else if(!isForkBlock(pindexLast->nHeight + 1) && isForkBlock(pindexLast->nHeight + 1 - params.nPowAveragingWindow))
// right at fork
else if(isForkBlock(nHeight) && !isForkBlock(nHeight - params.nPowAveragingWindow))
return nProofOfWorkLimit;
// right post fork
else if(!isForkBlock(nHeight) && isForkBlock(nHeight - params.nPowAveragingWindow))
return nProofOfWorkLimit;
// difficulty bomb
else if(pindexLast->nHeight > params.nPowDifficultyBombHeight)
return nProofOfWorkBomb;
@ -55,12 +67,12 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
arith_uint256 bnAvg {bnTot / params.nPowAveragingWindow};
bool isFork = isForkBlock(pindexLast->nHeight + 1);
return CalculateNextWorkRequired(bnAvg, pindexLast->GetMedianTimePast(), pindexFirst->GetMedianTimePast(), params, isFork);
return CalculateNextWorkRequired(bnAvg, pindexLast->GetMedianTimePast(), pindexFirst->GetMedianTimePast(), params, proofOfWorkLimit, isFork);
}
unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg,
int64_t nLastBlockTime, int64_t nFirstBlockTime,
const Consensus::Params& params, bool isFork)
const Consensus::Params& params, const arith_uint256 bnPowLimit, bool isFork)
{
// Limit adjustment step
// Use medians to prevent time-warp attacks
@ -75,7 +87,6 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg,
nActualTimespan = params.MaxActualTimespan(isFork);
// Retarget
const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
arith_uint256 bnNew {bnAvg};
bnNew /= params.AveragingWindowTimespan(isFork);
bnNew *= nActualTimespan;

View File

@ -19,7 +19,7 @@ class arith_uint256;
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params&);
unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg,
int64_t nLastBlockTime, int64_t nFirstBlockTime,
const Consensus::Params&, bool isFork = false);
const Consensus::Params&, const arith_uint256, bool isFork = false);
/** Check whether the Equihash solution in a block header is valid */
bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams&);

View File

@ -24,7 +24,7 @@ BOOST_AUTO_TEST_CASE(get_next_work)
arith_uint256 bnAvg;
bnAvg.SetCompact(0x1d00ffff);
BOOST_CHECK_EQUAL(0x1d011998,
CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params));
CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params, UintToArith256(params.powLimit)));
}
/* Test the constraint on the upper bound for next work */
@ -38,7 +38,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_pow_limit)
arith_uint256 bnAvg;
bnAvg.SetCompact(0x1f07ffff);
BOOST_CHECK_EQUAL(0x1f07ffff,
CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params));
CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params, UintToArith256(params.powLimit)));
}
/* Test the constraint on the lower bound for actual time taken */
@ -52,7 +52,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual)
arith_uint256 bnAvg;
bnAvg.SetCompact(0x1c05a3f4);
BOOST_CHECK_EQUAL(0x1c04bceb,
CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params));
CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params, UintToArith256(params.powLimit)));
}
/* Test the constraint on the upper bound for actual time taken */
@ -66,7 +66,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual)
arith_uint256 bnAvg;
bnAvg.SetCompact(0x1c387f6f);
BOOST_CHECK_EQUAL(0x1c4a93bb,
CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params));
CalculateNextWorkRequired(bnAvg, nThisTime, nLastRetargetTime, params, UintToArith256(params.powLimit)));
}
BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test)