From 8bbcf620001ad4a7e12b579ce89d99e6c9140eed Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Tue, 11 Apr 2017 13:55:07 +0300 Subject: [PATCH] Fixed pow (test and algo) (#1415) * Extend pow test to actually check DGW3 diff adjustment * Refactor pow --- src/pow.cpp | 146 ++++++++++++++++++++--------------------- src/test/pow_tests.cpp | 108 ++++++++++++++++++++++++++++-- 2 files changed, 171 insertions(+), 83 deletions(-) diff --git a/src/pow.cpp b/src/pow.cpp index b92aa6d82..920185a23 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -82,60 +82,93 @@ unsigned int static KimotoGravityWell(const CBlockIndex* pindexLast, const Conse unsigned int static DarkGravityWave(const CBlockIndex* pindexLast, const Consensus::Params& params) { /* current difficulty formula, dash - DarkGravity v3, written by Evan Duffield - evan@dash.org */ - const CBlockIndex *BlockLastSolved = pindexLast; - const CBlockIndex *BlockReading = pindexLast; - 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; + const arith_uint256 bnPowLimit = UintToArith256(params.powLimit); + int64_t nPastBlocks = 24; - if (BlockLastSolved == NULL || BlockLastSolved->nHeight == 0 || BlockLastSolved->nHeight < PastBlocksMin) { - return UintToArith256(params.powLimit).GetCompact(); + // make sure we have at least (nPastBlocks + 1) blocks, otherwise just return powLimit + if (!pindexLast || pindexLast->nHeight < nPastBlocks) { + return bnPowLimit.GetCompact(); } - for (unsigned int i = 1; BlockReading && BlockReading->nHeight > 0; i++) { - if (PastBlocksMax > 0 && i > PastBlocksMax) { break; } - CountBlocks++; + const CBlockIndex *pindex = pindexLast; + arith_uint256 bnPastTargetAvg; - if(CountBlocks <= PastBlocksMin) { - if (CountBlocks == 1) { PastDifficultyAverage.SetCompact(BlockReading->nBits); } - else { PastDifficultyAverage = ((PastDifficultyAveragePrev * CountBlocks) + (arith_uint256().SetCompact(BlockReading->nBits))) / (CountBlocks + 1); } - PastDifficultyAveragePrev = PastDifficultyAverage; + for (unsigned int nCountBlocks = 1; nCountBlocks <= nPastBlocks; nCountBlocks++) { + arith_uint256 bnTarget = arith_uint256().SetCompact(pindex->nBits); + if (nCountBlocks == 1) { + bnPastTargetAvg = bnTarget; + } else { + // NOTE: that's not an average really... + bnPastTargetAvg = (bnPastTargetAvg * nCountBlocks + bnTarget) / (nCountBlocks + 1); } - if(LastBlockTime > 0){ - int64_t Diff = (LastBlockTime - BlockReading->GetBlockTime()); - nActualTimespan += Diff; + if(nCountBlocks != nPastBlocks) { + assert(pindex->pprev); // should never fail + 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) - nActualTimespan = _nTargetTimespan/3; - if (nActualTimespan > _nTargetTimespan*3) - nActualTimespan = _nTargetTimespan*3; + if (nActualTimespan < nTargetTimespan/3) + nActualTimespan = nTargetTimespan/3; + if (nActualTimespan > nTargetTimespan*3) + nActualTimespan = nTargetTimespan*3; // Retarget bnNew *= nActualTimespan; - bnNew /= _nTargetTimespan; + bnNew /= nTargetTimespan; - if (bnNew > UintToArith256(params.powLimit)){ - bnNew = UintToArith256(params.powLimit); + if (bnNew > bnPowLimit) { + bnNew = bnPowLimit; } return bnNew.GetCompact(); } +unsigned int GetNextWorkRequiredBTC(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) +{ + unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact(); + + // Genesis block + if (pindexLast == NULL) + return nProofOfWorkLimit; + + // Only change once per interval + if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0) + { + 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 + { + // Return the last non-special-min-difficulty-rules-block + const CBlockIndex* pindex = pindexLast; + while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit) + pindex = pindex->pprev; + return pindex->nBits; + } + } + return pindexLast->nBits; + } + + // Go back by what we want to be 1 day worth of blocks + int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1); + assert(nHeightFirst >= 0); + const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst); + assert(pindexFirst); + + return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params); +} + unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) { unsigned int retarget = DIFF_DGW; @@ -151,44 +184,10 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead else retarget = DIFF_BTC; } - // Default Bitcoin style retargeting + // Bitcoin style retargeting if (retarget == DIFF_BTC) { - unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact(); - - // Genesis block - if (pindexLast == NULL) - return nProofOfWorkLimit; - - // Only change once per interval - if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0) - { - 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 - { - // Return the last non-special-min-difficulty-rules-block - const CBlockIndex* pindex = pindexLast; - while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit) - pindex = pindex->pprev; - return pindex->nBits; - } - } - return pindexLast->nBits; - } - - // Go back by what we want to be 1 day worth of blocks - int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1); - assert(nHeightFirst >= 0); - const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst); - assert(pindexFirst); - - return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params); + return GetNextWorkRequiredBTC(pindexLast, pblock, params); } // Retarget using Kimoto Gravity Wave @@ -197,12 +196,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead return KimotoGravityWell(pindexLast, params); } - // Retarget using Dark Gravity Wave 3 - else if (retarget == DIFF_DGW) - { - return DarkGravityWave(pindexLast, params); - } - + // Retarget using Dark Gravity Wave 3 by default return DarkGravityWave(pindexLast, params); } diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index 235573b3d..d978d49b0 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -21,13 +21,107 @@ BOOST_AUTO_TEST_CASE(get_next_work) SelectParams(CBaseChainParams::MAIN); const Consensus::Params& params = Params().GetConsensus(); - CBlockIndex pindexLast; - pindexLast.nHeight = 123456; - pindexLast.nTime = 1408732489; // Block #123456 - pindexLast.nBits = 0x1b1418d4; - CBlockHeader pblock; - pblock.nTime = 1408732505; // Block #123457 - BOOST_CHECK_EQUAL(GetNextWorkRequired(&pindexLast, &pblock, params), 0x1b06b2f1); // Block #123457 has 0x1d00d86a + // build the chain of 24 blocks + CBlockIndex blockIndexLast; + blockIndexLast.nHeight = 123456; + blockIndexLast.nTime = 1408732489; + blockIndexLast.nBits = 0x1b1418d4; + CBlockIndex blockIndexPrev1 = CBlockIndex(); + 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 */