I believe this is the solution:
unsigned int static DarkGravityWave3(const CBlockIndex* pindexLast, const CBlockHeader *pblock) {
/* current difficulty formula, darkcoin - DarkGravity v3, written by Evan Duffield -
evan@darkcoin.io */
const CBlockIndex *BlockLastSolved = pindexLast;
const CBlockIndex *BlockReading = pindexLast;
const CBlockHeader *BlockCreating = pblock;
BlockCreating = BlockCreating;
int64 nActualTimespan = 0;
int64 LastBlockTime = 0;
int64 PastBlocksMin = 12;
int64 PastBlocksMax = 12; int64 CountBlocks = 0;
CBigNum PastDifficultyAverage;
CBigNum PastDifficultyAveragePrev;
if (BlockLastSolved == NULL || BlockLastSolved->nHeight == 0 || BlockLastSolved->nHeight < PastBlocksMin) {
// This is the first block or the height is < PastBlocksMin
// Return minimal required work. (1e0fffff)
return bnProofOfWorkLimit.GetCompact();
}
// loop over the past n blocks, where n == PastBlocksMax
for (unsigned int i = 1; BlockReading && BlockReading->nHeight > 0; i++) {
if (PastBlocksMax > 0 && i > PastBlocksMax) { break; }
CountBlocks++;
// Calculate average difficulty based on the blocks we iterate over in this for loop
if(CountBlocks <= PastBlocksMin) {
if (CountBlocks == 1) { PastDifficultyAverage.SetCompact(BlockReading->nBits); }
else { PastDifficultyAverage = ((PastDifficultyAveragePrev * CountBlocks)+(CBigNum().SetCompact(BlockReading->nBits))) / (CountBlocks+1); }
PastDifficultyAveragePrev = PastDifficultyAverage;
}
// If this is the second iteration (LastBlockTime was set)
if(LastBlockTime > 0){
// Calculate time difference between previous block and current block
int64 Diff = (LastBlockTime - BlockReading->GetBlockTime());
// Increment the actual timespan
nActualTimespan += Diff;
}
// Set LasBlockTime to the block time for the block in current iteration
LastBlockTime = BlockReading->GetBlockTime();
if (BlockReading->pprev == NULL) { assert(BlockReading); break; }
BlockReading = BlockReading->pprev;
}
// bnNew is the difficulty
CBigNum bnNew(PastDifficultyAverage);
// nTargetTimespan is the time that the CountBlocks should have taken to be generated.
int64 nTargetTimespan = CountBlocks*nTargetSpacing;
// Limit the re-adjustment to 2x or 0.5x
// We don't want to increase/decrease diff too much.
if (nActualTimespan < nTargetTimespan/2)
nActualTimespan = nTargetTimespan/2;
if (nActualTimespan > nTargetTimespan*2)
nActualTimespan = nTargetTimespan*2; // Calculate the new difficulty based on actual and target timespan.
bnNew *= nActualTimespan;
bnNew /= nTargetTimespan;
// If calculated difficulty is lower than the minimal diff, set the new difficulty to be the minimal diff.
if (bnNew > bnProofOfWorkLimit){
bnNew = bnProofOfWorkLimit;
}
// Some logging.
// TODO: only display these log messages for a certain debug option.
printf("Difficulty Retarget - Dark Gravity Wave 3\n");
printf("Before: %08x %s\n", BlockLastSolved->nBits, CBigNum().SetCompact(BlockLastSolved->nBits).getuint256().ToString().c_str());
printf("After: %08x %s\n", bnNew.GetCompact(), bnNew.getuint256().ToString().c_str());
// Return the new diff.
return bnNew.GetCompact();
}
Essentially we need the difficulty change to happen faster, but it would be a lesser change. Calculating the difficulty on 24 blocks would mean at least 2 HIGH difficulty blocks. That jacks up the moving average. The difficulty on average would be higher, but it should even out a little bit better. At least in my mind that's how it would work.
-Fuse