From 857e34d28d84a6c7d0910eb800397b5382e520f4 Mon Sep 17 00:00:00 2001 From: Evan Date: Mon, 24 Mar 2014 10:55:41 -0700 Subject: [PATCH] DGW v2 implementation with timewarp limitations --- src/main.cpp | 117 ++++++++++++++++++++++++++++++++++++++++++++++++--- src/util.cpp | 2 +- 2 files changed, 113 insertions(+), 6 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index b1a6c98d15..e49c3e8ade 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1345,6 +1345,82 @@ unsigned int static DarkGravityWave(const CBlockIndex* pindexLast, const CBlockH return bnNew.GetCompact(); } +unsigned int static DarkGravityWave2(const CBlockIndex* pindexLast, const CBlockHeader *pblock) { + /* current difficulty formula, darkcoin - DarkGravity v2, written by Evan Duffield - evan@darkcoin.io */ + const CBlockIndex *BlockLastSolved = pindexLast; + const CBlockIndex *BlockReading = pindexLast; + const CBlockHeader *BlockCreating = pblock; + BlockCreating = BlockCreating; + int64 nBlockTimeAverage = 0; + int64 nBlockTimeAveragePrev = 0; + int64 nBlockTimeCount = 0; + int64 nBlockTimeSum2 = 0; + int64 nBlockTimeCount2 = 0; + int64 LastBlockTime = 0; + int64 PastBlocksMin = 14; + int64 PastBlocksMax = 140; + int64 CountBlocks = 0; + CBigNum PastDifficultyAverage; + CBigNum PastDifficultyAveragePrev; + + if (BlockLastSolved == NULL || BlockLastSolved->nHeight == 0 || BlockLastSolved->nHeight < PastBlocksMin) { return bnProofOfWorkLimit.GetCompact(); } + + for (unsigned int i = 1; BlockReading && BlockReading->nHeight > 0; i++) { + if (PastBlocksMax > 0 && i > PastBlocksMax) { break; } + CountBlocks++; + + if(CountBlocks <= PastBlocksMin) { + if (CountBlocks == 1) { PastDifficultyAverage.SetCompact(BlockReading->nBits); } + else { PastDifficultyAverage = ((CBigNum().SetCompact(BlockReading->nBits) - PastDifficultyAveragePrev) / CountBlocks) + PastDifficultyAveragePrev; } + PastDifficultyAveragePrev = PastDifficultyAverage; + } + + if(LastBlockTime > 0){ + int64 Diff = (LastBlockTime - BlockReading->GetBlockTime()); + if(nBlockTimeCount <= PastBlocksMin) { + nBlockTimeCount++; + + if (nBlockTimeCount == 1) { nBlockTimeAverage = Diff; } + else { nBlockTimeAverage = ((Diff - nBlockTimeAveragePrev) / nBlockTimeCount) + nBlockTimeAveragePrev; } + nBlockTimeAveragePrev = nBlockTimeAverage; + } + nBlockTimeCount2++; + nBlockTimeSum2 += Diff; + } + LastBlockTime = BlockReading->GetBlockTime(); + + if (BlockReading->pprev == NULL) { assert(BlockReading); break; } + BlockReading = BlockReading->pprev; + } + + CBigNum bnNew(PastDifficultyAverage); + if (nBlockTimeCount != 0 && nBlockTimeCount2 != 0) { + double SmartAverage = ((((long double)nBlockTimeAverage)*0.7)+(((long double)nBlockTimeSum2 / (long double)nBlockTimeCount2)*0.3)); + if(SmartAverage < 1) SmartAverage = 1; + double Shift = nTargetSpacing/SmartAverage; + + double fActualTimespan = ((long double)CountBlocks*(double)nTargetSpacing)/Shift; + double fTargetTimespan = ((long double)CountBlocks*(double)nTargetSpacing); + + if (fActualTimespan < fTargetTimespan/3) + fActualTimespan = fTargetTimespan/3; + if (fActualTimespan > fTargetTimespan*3) + fActualTimespan = fTargetTimespan*3; + + int64 nActualTimespan = fActualTimespan; + int64 nTargetTimespan = fTargetTimespan; + + // Retarget + bnNew *= nActualTimespan; + bnNew /= nTargetTimespan; + } + + if (bnNew > bnProofOfWorkLimit){ + bnNew = bnProofOfWorkLimit; + } + + return bnNew.GetCompact(); +} unsigned int static GetNextWorkRequired_V2(const CBlockIndex* pindexLast, const CBlockHeader *pblock) { @@ -1362,17 +1438,20 @@ unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast, const CBl { int DiffMode = 1; if (fTestNet) { - if (pindexLast->nHeight+1 >= 5) { DiffMode = 3; } + if (pindexLast->nHeight+1 >= 15) { DiffMode = 4; } + else if (pindexLast->nHeight+1 >= 5) { DiffMode = 3; } } else { - if (pindexLast->nHeight+1 >= 34140) { DiffMode = 3; } + if (pindexLast->nHeight+1 >= 45000) { DiffMode = 4; } + else if (pindexLast->nHeight+1 >= 34140) { DiffMode = 3; } else if (pindexLast->nHeight+1 >= 15200) { DiffMode = 2; } } if (DiffMode == 1) { return GetNextWorkRequired_V1(pindexLast, pblock); } else if (DiffMode == 2) { return GetNextWorkRequired_V2(pindexLast, pblock); } else if (DiffMode == 3) { return DarkGravityWave(pindexLast, pblock); } - return DarkGravityWave(pindexLast, pblock); + else if (DiffMode == 4) { return DarkGravityWave2(pindexLast, pblock); } + return DarkGravityWave2(pindexLast, pblock); } @@ -2367,9 +2446,37 @@ bool CBlock::AcceptBlock(CValidationState &state, CDiskBlockPos *dbp) pindexPrev = (*mi).second; nHeight = pindexPrev->nHeight+1; + // Check proof of work - if (nBits != GetNextWorkRequired(pindexPrev, this)) - return state.DoS(100, error("AcceptBlock() : incorrect proof of work")); + /* + if(nHeight >= 34140 && nHeight <= 45000){ + unsigned int nBitsNext = GetNextWorkRequired(pindexPrev, this); + unsigned int a = 0; + if(nBits > nBitsNext) a = nBits - nBitsNext; + else if (nBits < nBitsNext) a = nBitsNext - nBits; + printf(" !--- %u %u, %u \n", nBits, nBitsNext, a); + double n1 = ConvertBitsToDouble(nBits); + double n2 = ConvertBitsToDouble(nBitsNext); + printf(" !--- %f %f, %f \n", n1, n2, n1-n2); + if (abs(n1-n2) > 5) + return state.DoS(100, error("AcceptBlock() : incorrect proof of work (DGW pre-fork)")); + } else {*/ + if (nBits != GetNextWorkRequired(pindexPrev, this)) + return state.DoS(100, error("AcceptBlock() : incorrect proof of work")); + //} + + + // Prevent blocks from too far in the future + if(fTestNet || nHeight >= 45000){ + if (GetBlockTime() > GetAdjustedTime() + 15 * 60) { + return error("AcceptBlock() : block's timestamp too far in the future"); + } + + // Check timestamp is not too far in the past + if (GetBlockTime() <= pindexPrev->GetBlockTime() - 15 * 60) { + return error("AcceptBlock() : block's timestamp is too early compare to last block"); + } + } // Check timestamp against prev if (GetBlockTime() <= pindexPrev->GetMedianTimePast()) diff --git a/src/util.cpp b/src/util.cpp index ca36b1a5cb..d9fb3b9c0b 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1336,7 +1336,7 @@ void AddTimeData(const CNetAddr& ip, int64 nTime) int64 nMedian = vTimeOffsets.median(); std::vector vSorted = vTimeOffsets.sorted(); // Only let other nodes change our time by so much - if (abs64(nMedian) < 35 * 60) // DarkCoin: changed maximum adjust to 35 mins to avoid letting peers change our time too much in case of an attack. + if (abs64(nMedian) < 14 * 60) // DarkCoin: changed maximum adjust to 35 mins to avoid letting peers change our time too much in case of an attack. { nTimeOffset = nMedian; }