Fixed pow (test and algo) (#1415)
* Extend pow test to actually check DGW3 diff adjustment * Refactor pow
This commit is contained in:
parent
68e1a8c790
commit
8bbcf62000
146
src/pow.cpp
146
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);
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user