I have create a new KGW ..."DUAL KGW3". For the next big update.
DUAL KGW3 is the retargeting resulting from KGW3 (in Bitsend) joined with a second virtual retarget,
that is hardcoded and it stabilizes the diff adjusting.
It increases the diff, if the blocktarget hits more then blocktime/6 earlyer, than the standart Blocktime.
Means in that case, diff is adding 15% and increases the dual diff and it makes on the other side,
Bitbreak, to jump in immediately, in case of a hash down-swing (after 6h) this diff is moving virtually in real-time.
unsigned int static DUAL_KGW3(const CBlockIndex* pindexLast, const Consensus::Params& params, const CBlockHeader *pblock) {
// current difficulty formula, ERC3 - DUAL_KGW3, written by Christian Knoepke -
[email protected] // BitSend and Eropecoin Developer
const CBlockIndex *BlockLastSolved = pindexLast;
const CBlockIndex *BlockReading = pindexLast;
bool kgwdebug=false;
uint64_t PastBlocksMass = 0;
int64_t PastRateActualSeconds = 0;
int64_t PastRateTargetSeconds = 0;
double PastRateAdjustmentRatio = double(1);
arith_uint256 PastDifficultyAverage;
arith_uint256 PastDifficultyAveragePrev;
double EventHorizonDeviation;
double EventHorizonDeviationFast;
double EventHorizonDeviationSlow;
//DUAL_KGW3 SETUP
static const uint64_t Blocktime = 5 * 60;
static const unsigned int timeDaySeconds = 60 * 60 * 24;
uint64_t pastSecondsMin = timeDaySeconds * 0.025;
uint64_t pastSecondsMax = timeDaySeconds * 7;
uint64_t PastBlocksMin = pastSecondsMin / Blocktime;
uint64_t PastBlocksMax = pastSecondsMax / Blocktime;
const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
if (BlockLastSolved == NULL || BlockLastSolved->nHeight == 0 || (uint64_t)BlockLastSolved->nHeight < PastBlocksMin) { return bnPowLimit.GetCompact(); }
for (unsigned int i = 1; BlockReading && BlockReading->nHeight > 0; i++) {
if (PastBlocksMax > 0 && i > PastBlocksMax) { break; }
PastBlocksMass++;
PastDifficultyAverage.SetCompact(BlockReading->nBits);
if (i > 1) {
if(PastDifficultyAverage >= PastDifficultyAveragePrev)
PastDifficultyAverage = ((PastDifficultyAverage - PastDifficultyAveragePrev) / i) + PastDifficultyAveragePrev;
else
PastDifficultyAverage = PastDifficultyAveragePrev - ((PastDifficultyAveragePrev - PastDifficultyAverage) / i);
}
PastDifficultyAveragePrev = PastDifficultyAverage;
PastRateActualSeconds = BlockLastSolved->GetBlockTime() - BlockReading->GetBlockTime();
PastRateTargetSeconds = Blocktime * PastBlocksMass;
PastRateAdjustmentRatio = double(1);
if (PastRateActualSeconds < 0) { PastRateActualSeconds = 0; }
if (PastRateActualSeconds != 0 && PastRateTargetSeconds != 0) {
PastRateAdjustmentRatio = double(PastRateTargetSeconds) / double(PastRateActualSeconds);
}
EventHorizonDeviation = 1 + (0.7084 * pow((double(PastBlocksMass)/double(72)), -1.228)); //28.2 and 144 possible
EventHorizonDeviationFast = EventHorizonDeviation;
EventHorizonDeviationSlow = 1 / EventHorizonDeviation;
if (PastBlocksMass >= PastBlocksMin) {
if ((PastRateAdjustmentRatio <= EventHorizonDeviationSlow) || (PastRateAdjustmentRatio >= EventHorizonDeviationFast))
{ assert(BlockReading); break; }
}
if (BlockReading->pprev == NULL) { assert(BlockReading); break; }
BlockReading = BlockReading->pprev;
}
//KGW Original
arith_uint256 kgw_dual1(PastDifficultyAverage);
arith_uint256 kgw_dual2;
kgw_dual2.SetCompact(pindexLast->nBits);
if (PastRateActualSeconds != 0 && PastRateTargetSeconds != 0) {
kgw_dual1 *= PastRateActualSeconds;
kgw_dual1 /= PastRateTargetSeconds;
}
int64_t nActualTime1 = pindexLast->GetBlockTime() - pindexLast->pprev->GetBlockTime();
int64_t nActualTimespanshort = nActualTime1;
// Retarget BTC Original ...not exactly
if (nActualTime1 < Blocktime / 3)
nActualTime1 = Blocktime / 3;
if (nActualTime1 > Blocktime * 3)
nActualTime1 = Blocktime * 3;
kgw_dual2 *= nActualTime1;
kgw_dual2 /= Blocktime;
//Fusion from Retarget and Classic KGW3 (BitSend=)
arith_uint256 bnNew;
bnNew = ((kgw_dual2 + kgw_dual1)/2);
// DUAL KGW3 increased rapidly the Diff if Blocktime to last block under Blocktime/6 sec.
if(kgwdebug)LogPrintf("nActualTimespanshort = %d \n", nActualTimespanshort );
if( nActualTimespanshort < Blocktime/6 )
{
if(kgwdebug)LogPrintf("Vordiff:%08x %s bnNew first \n", bnNew.GetCompact(), bnNew.ToString().c_str());
const int nLongShortNew1 = 85; const int nLongShortNew2 = 100;
bnNew = bnNew * nLongShortNew1;
bnNew = bnNew / nLongShortNew2;
if(kgwdebug)LogPrintf("Erhöhte Diff:\n %08x %s bnNew second \n", bnNew.GetCompact(), bnNew.ToString().c_str() );
}
//BitBreak BitSend
// Reduce difficulty if current block generation time has already exceeded maximum time limit.
const int nLongTimeLimit = 6 * 60 * 60;
if(kgwdebug)
{
LogPrintf("Prediff %08x %s\n", bnNew.GetCompact(), bnNew.ToString().c_str());
LogPrintf("Vordiff %d \n", nLongTimeLimit);
LogPrintf(" %d Block", BlockReading->nHeight );
}
if ((pblock-> nTime - pindexLast->GetBlockTime()) > nLongTimeLimit) //block.nTime
{
bnNew = bnPowLimit*30;
if(kgwdebug)LogPrintf("
Maximum block time hit - cute diff %08x %s\n", bnNew.GetCompact(), bnNew.ToString().c_str());
}
if (bnNew > bnPowLimit) {
bnNew = bnPowLimit;
}
return bnNew.GetCompact();
}