Fixed pow (test and algo) (#1415)

* Extend pow test to actually check DGW3 diff adjustment

* Refactor pow
This commit is contained in:
UdjinM6 2017-04-11 13:55:07 +03:00 committed by GitHub
parent 68e1a8c790
commit 8bbcf62000
2 changed files with 171 additions and 83 deletions

View File

@ -82,78 +82,56 @@ unsigned int static KimotoGravityWell(const CBlockIndex* pindexLast, const Conse
unsigned int static DarkGravityWave(const CBlockIndex* pindexLast, const Consensus::Params& params) { unsigned int static DarkGravityWave(const CBlockIndex* pindexLast, const Consensus::Params& params) {
/* current difficulty formula, dash - DarkGravity v3, written by Evan Duffield - evan@dash.org */ /* current difficulty formula, dash - DarkGravity v3, written by Evan Duffield - evan@dash.org */
const CBlockIndex *BlockLastSolved = pindexLast; const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
const CBlockIndex *BlockReading = pindexLast; int64_t nPastBlocks = 24;
int64_t nActualTimespan = 0;
int64_t LastBlockTime = 0;
int64_t PastBlocksMin = 24;
int64_t PastBlocksMax = 24;
int64_t CountBlocks = 0;
arith_uint256 PastDifficultyAverage;
arith_uint256 PastDifficultyAveragePrev;
if (BlockLastSolved == NULL || BlockLastSolved->nHeight == 0 || BlockLastSolved->nHeight < PastBlocksMin) { // make sure we have at least (nPastBlocks + 1) blocks, otherwise just return powLimit
return UintToArith256(params.powLimit).GetCompact(); if (!pindexLast || pindexLast->nHeight < nPastBlocks) {
return bnPowLimit.GetCompact();
} }
for (unsigned int i = 1; BlockReading && BlockReading->nHeight > 0; i++) { const CBlockIndex *pindex = pindexLast;
if (PastBlocksMax > 0 && i > PastBlocksMax) { break; } arith_uint256 bnPastTargetAvg;
CountBlocks++;
if(CountBlocks <= PastBlocksMin) { for (unsigned int nCountBlocks = 1; nCountBlocks <= nPastBlocks; nCountBlocks++) {
if (CountBlocks == 1) { PastDifficultyAverage.SetCompact(BlockReading->nBits); } arith_uint256 bnTarget = arith_uint256().SetCompact(pindex->nBits);
else { PastDifficultyAverage = ((PastDifficultyAveragePrev * CountBlocks) + (arith_uint256().SetCompact(BlockReading->nBits))) / (CountBlocks + 1); } if (nCountBlocks == 1) {
PastDifficultyAveragePrev = PastDifficultyAverage; bnPastTargetAvg = bnTarget;
} else {
// NOTE: that's not an average really...
bnPastTargetAvg = (bnPastTargetAvg * nCountBlocks + bnTarget) / (nCountBlocks + 1);
} }
if(LastBlockTime > 0){ if(nCountBlocks != nPastBlocks) {
int64_t Diff = (LastBlockTime - BlockReading->GetBlockTime()); assert(pindex->pprev); // should never fail
nActualTimespan += Diff; pindex = pindex->pprev;
} }
LastBlockTime = BlockReading->GetBlockTime();
if (BlockReading->pprev == NULL) { assert(BlockReading); break; }
BlockReading = BlockReading->pprev;
} }
arith_uint256 bnNew(PastDifficultyAverage); arith_uint256 bnNew(bnPastTargetAvg);
int64_t _nTargetTimespan = CountBlocks * params.nPowTargetSpacing; int64_t nActualTimespan = pindexLast->GetBlockTime() - pindex->GetBlockTime();
// NOTE: is this accurate? nActualTimespan counts it for (nPastBlocks - 1) blocks only...
int64_t nTargetTimespan = nPastBlocks * params.nPowTargetSpacing;
if (nActualTimespan < _nTargetTimespan/3) if (nActualTimespan < nTargetTimespan/3)
nActualTimespan = _nTargetTimespan/3; nActualTimespan = nTargetTimespan/3;
if (nActualTimespan > _nTargetTimespan*3) if (nActualTimespan > nTargetTimespan*3)
nActualTimespan = _nTargetTimespan*3; nActualTimespan = nTargetTimespan*3;
// Retarget // Retarget
bnNew *= nActualTimespan; bnNew *= nActualTimespan;
bnNew /= _nTargetTimespan; bnNew /= nTargetTimespan;
if (bnNew > UintToArith256(params.powLimit)){ if (bnNew > bnPowLimit) {
bnNew = UintToArith256(params.powLimit); bnNew = bnPowLimit;
} }
return bnNew.GetCompact(); return bnNew.GetCompact();
} }
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) unsigned int GetNextWorkRequiredBTC(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
{ {
unsigned int retarget = DIFF_DGW;
// mainnet/regtest share a configuration
if (Params().NetworkIDString() == CBaseChainParams::MAIN || Params().NetworkIDString() == CBaseChainParams::REGTEST) {
if (pindexLast->nHeight + 1 >= 34140) retarget = DIFF_DGW;
else if (pindexLast->nHeight + 1 >= 15200) retarget = DIFF_KGW;
else retarget = DIFF_BTC;
// testnet -- we want a lot of coins in existance early on
} else {
if (pindexLast->nHeight + 1 >= 3000) retarget = DIFF_DGW;
else retarget = DIFF_BTC;
}
// Default Bitcoin style retargeting
if (retarget == DIFF_BTC)
{
unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact(); unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact();
// Genesis block // Genesis block
@ -189,6 +167,27 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
assert(pindexFirst); assert(pindexFirst);
return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params); return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params);
}
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
{
unsigned int retarget = DIFF_DGW;
// mainnet/regtest share a configuration
if (Params().NetworkIDString() == CBaseChainParams::MAIN || Params().NetworkIDString() == CBaseChainParams::REGTEST) {
if (pindexLast->nHeight + 1 >= 34140) retarget = DIFF_DGW;
else if (pindexLast->nHeight + 1 >= 15200) retarget = DIFF_KGW;
else retarget = DIFF_BTC;
// testnet -- we want a lot of coins in existance early on
} else {
if (pindexLast->nHeight + 1 >= 3000) retarget = DIFF_DGW;
else retarget = DIFF_BTC;
}
// Bitcoin style retargeting
if (retarget == DIFF_BTC)
{
return GetNextWorkRequiredBTC(pindexLast, pblock, params);
} }
// Retarget using Kimoto Gravity Wave // Retarget using Kimoto Gravity Wave
@ -197,12 +196,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
return KimotoGravityWell(pindexLast, params); return KimotoGravityWell(pindexLast, params);
} }
// Retarget using Dark Gravity Wave 3 // Retarget using Dark Gravity Wave 3 by default
else if (retarget == DIFF_DGW)
{
return DarkGravityWave(pindexLast, params);
}
return DarkGravityWave(pindexLast, params); return DarkGravityWave(pindexLast, params);
} }

View File

@ -21,13 +21,107 @@ BOOST_AUTO_TEST_CASE(get_next_work)
SelectParams(CBaseChainParams::MAIN); SelectParams(CBaseChainParams::MAIN);
const Consensus::Params& params = Params().GetConsensus(); const Consensus::Params& params = Params().GetConsensus();
CBlockIndex pindexLast; // build the chain of 24 blocks
pindexLast.nHeight = 123456; CBlockIndex blockIndexLast;
pindexLast.nTime = 1408732489; // Block #123456 blockIndexLast.nHeight = 123456;
pindexLast.nBits = 0x1b1418d4; blockIndexLast.nTime = 1408732489;
CBlockHeader pblock; blockIndexLast.nBits = 0x1b1418d4;
pblock.nTime = 1408732505; // Block #123457 CBlockIndex blockIndexPrev1 = CBlockIndex();
BOOST_CHECK_EQUAL(GetNextWorkRequired(&pindexLast, &pblock, params), 0x1b06b2f1); // Block #123457 has 0x1d00d86a blockIndexPrev1.nTime = 1408732257; // Block #123455
blockIndexPrev1.nBits = 0x1b13b83f;
blockIndexLast.pprev = &blockIndexPrev1;
CBlockIndex blockIndexPrev2 = CBlockIndex();
blockIndexPrev2.nTime = 1408732229; // Block #123454
blockIndexPrev2.nBits = 0x1b10460b;
blockIndexPrev1.pprev = &blockIndexPrev2;
CBlockIndex blockIndexPrev3 = CBlockIndex();
blockIndexPrev3.nTime = 1408731256; // Block #123453
blockIndexPrev3.nBits = 0x1b113ff1;
blockIndexPrev2.pprev = &blockIndexPrev3;
CBlockIndex blockIndexPrev4 = CBlockIndex();
blockIndexPrev4.nTime = 1408731242; // Block #123452
blockIndexPrev4.nBits = 0x1b0fed89;
blockIndexPrev3.pprev = &blockIndexPrev4;
CBlockIndex blockIndexPrev5 = CBlockIndex();
blockIndexPrev5.nTime = 1408730914; // Block #123451
blockIndexPrev5.nBits = 0x1b10b864;
blockIndexPrev4.pprev = &blockIndexPrev5;
CBlockIndex blockIndexPrev6 = CBlockIndex();
blockIndexPrev6.nTime = 1408730862; // Block #123450
blockIndexPrev6.nBits = 0x1b0dd168;
blockIndexPrev5.pprev = &blockIndexPrev6;
CBlockIndex blockIndexPrev7 = CBlockIndex();
blockIndexPrev7.nTime = 1408730179; // Block #123449
blockIndexPrev7.nBits = 0x1b0c03d6;
blockIndexPrev6.pprev = &blockIndexPrev7;
CBlockIndex blockIndexPrev8 = CBlockIndex();
blockIndexPrev8.nTime = 1408729678; // Block #123448
blockIndexPrev8.nBits = 0x1b0c9ab8;
blockIndexPrev7.pprev = &blockIndexPrev8;
CBlockIndex blockIndexPrev9 = CBlockIndex();
blockIndexPrev9.nTime = 1408729647; // Block #123447
blockIndexPrev9.nBits = 0x1b0dfaff;
blockIndexPrev8.pprev = &blockIndexPrev9;
CBlockIndex blockIndexPrev10 = CBlockIndex();
blockIndexPrev10.nTime = 1408729587; // Block #123446
blockIndexPrev10.nBits = 0x1b10e878;
blockIndexPrev9.pprev = &blockIndexPrev10;
CBlockIndex blockIndexPrev11 = CBlockIndex();
blockIndexPrev11.nTime = 1408729576; // Block #123445
blockIndexPrev11.nBits = 0x1b1063d0;
blockIndexPrev10.pprev = &blockIndexPrev11;
CBlockIndex blockIndexPrev12 = CBlockIndex();
blockIndexPrev12.nTime = 1408729474; // Block #123444
blockIndexPrev12.nBits = 0x1b104297;
blockIndexPrev11.pprev = &blockIndexPrev12;
CBlockIndex blockIndexPrev13 = CBlockIndex();
blockIndexPrev13.nTime = 1408729305; // Block #123443
blockIndexPrev13.nBits = 0x1b107556;
blockIndexPrev12.pprev = &blockIndexPrev13;
CBlockIndex blockIndexPrev14 = CBlockIndex();
blockIndexPrev14.nTime = 1408729179; // Block #123442
blockIndexPrev14.nBits = 0x1b110764;
blockIndexPrev13.pprev = &blockIndexPrev14;
CBlockIndex blockIndexPrev15 = CBlockIndex();
blockIndexPrev15.nTime = 1408729116; // Block #123441
blockIndexPrev15.nBits = 0x1b1141bf;
blockIndexPrev14.pprev = &blockIndexPrev15;
CBlockIndex blockIndexPrev16 = CBlockIndex();
blockIndexPrev16.nTime = 1408728950; // Block #123440
blockIndexPrev16.nBits = 0x1b1123f9;
blockIndexPrev15.pprev = &blockIndexPrev16;
CBlockIndex blockIndexPrev17 = CBlockIndex();
blockIndexPrev17.nTime = 1408728756; // Block #123439
blockIndexPrev17.nBits = 0x1b118d9c;
blockIndexPrev16.pprev = &blockIndexPrev17;
CBlockIndex blockIndexPrev18 = CBlockIndex();
blockIndexPrev18.nTime = 1408728744; // Block #123438
blockIndexPrev18.nBits = 0x1b11abac;
blockIndexPrev17.pprev = &blockIndexPrev18;
CBlockIndex blockIndexPrev19 = CBlockIndex();
blockIndexPrev19.nTime = 1408728608; // Block #123437
blockIndexPrev19.nBits = 0x1b11951e;
blockIndexPrev18.pprev = &blockIndexPrev19;
CBlockIndex blockIndexPrev20 = CBlockIndex();
blockIndexPrev20.nTime = 1408728495; // Block #123436
blockIndexPrev20.nBits = 0x1b121cf3;
blockIndexPrev19.pprev = &blockIndexPrev20;
CBlockIndex blockIndexPrev21 = CBlockIndex();
blockIndexPrev21.nTime = 1408728479; // Block #123435
blockIndexPrev21.nBits = 0x1b11a33c;
blockIndexPrev20.pprev = &blockIndexPrev21;
CBlockIndex blockIndexPrev22 = CBlockIndex();
blockIndexPrev22.nTime = 1408728332; // Block #123434
blockIndexPrev22.nBits = 0x1b10e09e;
blockIndexPrev21.pprev = &blockIndexPrev22;
CBlockIndex blockIndexPrev23 = CBlockIndex();
blockIndexPrev23.nTime = 1408728124; // Block #123433
blockIndexPrev23.nBits = 0x1b104be1;
blockIndexPrev22.pprev = &blockIndexPrev23;
CBlockHeader blockHeader;
blockHeader.nTime = 1408732505; // Block #123457
BOOST_CHECK_EQUAL(GetNextWorkRequired(&blockIndexLast, &blockHeader, params), 0x1b1441de); // Block #123457 has 0x1b1441de
} }
/* Test the constraint on the upper bound for next work */ /* Test the constraint on the upper bound for next work */