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,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);
}

View File

@ -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 */