From 4af0b18e91f882c53521bc05b64c505239ff6125 Mon Sep 17 00:00:00 2001 From: Jeremiah Buddenhagen Date: Sun, 17 Dec 2017 12:12:14 -0800 Subject: [PATCH] Difficulty adjustment forks --- src/chainparams.cpp | 27 +++++++++++--- src/consensus/params.h | 81 ++++++++++++++++++++++++++++++++++++++++-- src/pow.cpp | 24 +++++++------ src/rpc/mining.cpp | 2 +- 4 files changed, 116 insertions(+), 18 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 4a0bc1fe2..4731bd5ce 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -81,9 +81,7 @@ public: consensus.BIP34Hash = uint256S("fa09d204a83a768ed5a7c8d441fa62f2043abf420cff1226c7b4329aeb9d51cf"); consensus.BIP65Height = 918684; // bab3041e8977e0dc3eeff63fe707b92bde1dd449d8efafb248c27c8264cc311a consensus.BIP66Height = 811879; // 7aceee012833fa8952f8835d8b1b3ae233cd6ab08fdb27a771d2bd7bdc491894 - consensus.powLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); - consensus.nPowTargetTimespan = 60 * 60; // V1 difficulty for now - consensus.nPowTargetSpacing = 40; // V1 difficulty for now + consensus.powLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.fPowAllowMinDifficultyBlocks = false; consensus.fPowNoRetargeting = false; consensus.nRuleChangeActivationThreshold = 6048; // 75% of 8064 @@ -108,6 +106,27 @@ public: // By default assume that the signatures in ancestors of this block are valid. consensus.defaultAssumeValid = uint256S("0x4a8cb5ca397b7c92c270ccfa9139ffb93f7c5b9515e52486c635c7a1dee9d221"); // 2000000 + // Difficulty adjustments + consensus.nPowTargetSpacing = 40; // 40s block time + // V1 + consensus.nTargetTimespan_Version1 = 60 * 60; + consensus.nInterval_Version1 = 60 * 60 / 40; + consensus.nMaxAdjustUp_Version1 = 75; + consensus.nMaxAdjustDown_Version1 = 300; + consensus.nAveragingInterval_Version1 = consensus.nInterval_Version1; + // V2 + consensus.nHeight_Difficulty_Version2 = 208440; + consensus.nInterval_Version2 = 15; + consensus.nMaxAdjustDown_Version2 = 75; + consensus.nMaxAdjustUp_Version2 = 300; + consensus.nAveragingInterval_Version2 = consensus.nInterval_Version2; + // V3 + consensus.nHeight_Difficulty_Version3 = 426000; + consensus.nInterval_Version3 = 1; + consensus.nMaxAdjustDown_Version3 = 3; + consensus.nMaxAdjustUp_Version3 = 2; + consensus.nAveragingInterval_Version3 = 6; + /** * The message start string is designed to be unlikely to occur in normal data. * The characters are rarely used upper ASCII, not valid as UTF-8, and produce @@ -191,7 +210,6 @@ public: consensus.BIP65Height = 76; // 8075c771ed8b495ffd943980a95f702ab34fce3c8c54e379548bda33cc8c0573 consensus.BIP66Height = 76; // 8075c771ed8b495ffd943980a95f702ab34fce3c8c54e379548bda33cc8c0573 consensus.powLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); - consensus.nPowTargetTimespan = 3.5 * 24 * 60 * 60; // 3.5 days consensus.nPowTargetSpacing = 2.5 * 60; consensus.fPowAllowMinDifficultyBlocks = true; consensus.fPowNoRetargeting = false; @@ -278,7 +296,6 @@ public: consensus.BIP65Height = 1351; // BIP65 activated on regtest (Used in rpc activation tests) consensus.BIP66Height = 1251; // BIP66 activated on regtest (Used in rpc activation tests) consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); - consensus.nPowTargetTimespan = 3.5 * 24 * 60 * 60; // two weeks consensus.nPowTargetSpacing = 2.5 * 60; consensus.fPowAllowMinDifficultyBlocks = true; consensus.fPowNoRetargeting = true; diff --git a/src/consensus/params.h b/src/consensus/params.h index 6240e8285..269918c1b 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -59,10 +59,87 @@ struct Params { bool fPowAllowMinDifficultyBlocks; bool fPowNoRetargeting; int64_t nPowTargetSpacing; - int64_t nPowTargetTimespan; - int64_t DifficultyAdjustmentInterval() const { return nPowTargetTimespan / nPowTargetSpacing; } uint256 nMinimumChainWork; uint256 defaultAssumeValid; + + // Florincoin: Difficulty adjustment forks. + int64_t TargetTimespan(int height) const { + // V1 + if (height < nHeight_Difficulty_Version2) + return nTargetTimespan_Version1; + // V2 + if (height < nHeight_Difficulty_Version3) + return nInterval_Version2 * nPowTargetSpacing; + // V3 + return nInterval_Version3 * nPowTargetSpacing; + } + + int64_t DifficultyAdjustmentInterval(int height) const { + // V1 + if (height < nHeight_Difficulty_Version2) + return nInterval_Version1; + // V2 + if (height < nHeight_Difficulty_Version3) + return nInterval_Version2; + // V3 + return nInterval_Version3; + } + + int64_t MaxActualTimespan(int height) const { + const int64_t averagingTargetTimespan = AveragingInterval(height) * nPowTargetSpacing; + // V1 + if (height < nHeight_Difficulty_Version2) + return averagingTargetTimespan * (100 + nMaxAdjustDown_Version1) / 100; + // V2 + if (height < nHeight_Difficulty_Version3) + return averagingTargetTimespan * (100 + nMaxAdjustDown_Version2) / 100; + // V3 + return TargetTimespan(height) * (100 + nMaxAdjustDown_Version3) / 100; + } + + int64_t MinActualTimespan(int height) const { + // V1 + if (height < nHeight_Difficulty_Version2) + return TargetTimespan(height) * (100 - nMaxAdjustUp_Version1) / 100; + // V2 + if (height < nHeight_Difficulty_Version3) + return TargetTimespan(height) * (100 - nMaxAdjustUp_Version2) / 100; + // V3 + return TargetTimespan(height) * (100 - nMaxAdjustUp_Version3) / 100; + } + + int64_t AveragingInterval(int height) const { + // V1 + if (height < nHeight_Difficulty_Version2) + return nAveragingInterval_Version1; + // V2 + if (height < nHeight_Difficulty_Version3) + return nAveragingInterval_Version2; + // V3 + return nAveragingInterval_Version3; + } + + // V1 + int64_t nTargetTimespan_Version1; + int64_t nInterval_Version1; + int64_t nMaxAdjustUp_Version1; + int64_t nMaxAdjustDown_Version1; + int64_t nAveragingInterval_Version1; + + // V2 + int64_t nHeight_Difficulty_Version2; + int64_t nInterval_Version2; + int64_t nMaxAdjustDown_Version2; + int64_t nMaxAdjustUp_Version2; + int64_t nAveragingInterval_Version2; + + // V3 + int64_t nHeight_Difficulty_Version3; + int64_t nInterval_Version3; + int64_t nMaxAdjustDown_Version3; + int64_t nMaxAdjustUp_Version3; + int64_t nAveragingInterval_Version3; + }; } // namespace Consensus diff --git a/src/pow.cpp b/src/pow.cpp index a7e5a0d30..b50531ca4 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -17,7 +17,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact(); // Only change once per difficulty adjustment interval - if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0) + if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval(pindexLast->nHeight+1) != 0) { if (params.fPowAllowMinDifficultyBlocks) { @@ -30,7 +30,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead { // Return the last non-special-min-difficulty-rules-block const CBlockIndex* pindex = pindexLast; - while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit) + while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval(pindex->nHeight) != 0 && pindex->nBits == nProofOfWorkLimit) pindex = pindex->pprev; return pindex->nBits; } @@ -38,12 +38,13 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead return pindexLast->nBits; } + int averagingInterval = params.AveragingInterval(pindexLast->nHeight+1); // Go back by what we want to be 14 days worth of blocks // Litecoin: This fixes an issue where a 51% attack can change difficulty at will. // Go back the full period unless it's the first retarget after genesis. Code courtesy of Art Forz - int blockstogoback = params.DifficultyAdjustmentInterval()-1; - if ((pindexLast->nHeight+1) != params.DifficultyAdjustmentInterval()) - blockstogoback = params.DifficultyAdjustmentInterval(); + int blockstogoback = averagingInterval-1; + if ((pindexLast->nHeight+1) != averagingInterval) + blockstogoback = averagingInterval; // Go back by what we want to be 14 days worth of blocks const CBlockIndex* pindexFirst = pindexLast; @@ -60,12 +61,15 @@ unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nF if (params.fPowNoRetargeting) return pindexLast->nBits; + const int64_t nMinActualTimespan = params.MinActualTimespan(pindexLast->nHeight+1); + const int64_t nMaxActualTimespan = params.MaxActualTimespan(pindexLast->nHeight+1); + // Limit adjustment step int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime; - if (nActualTimespan < params.nPowTargetTimespan/4) - nActualTimespan = params.nPowTargetTimespan/4; - if (nActualTimespan > params.nPowTargetTimespan*4) - nActualTimespan = params.nPowTargetTimespan*4; + if (nActualTimespan < nMinActualTimespan) + nActualTimespan = nMinActualTimespan; + if (nActualTimespan > nMaxActualTimespan) + nActualTimespan = nMaxActualTimespan; // Retarget arith_uint256 bnNew; @@ -78,7 +82,7 @@ unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nF if (fShift) bnNew >>= 1; bnNew *= nActualTimespan; - bnNew /= params.nPowTargetTimespan; + bnNew /= params.AveragingInterval(pindexLast->nHeight+1) * params.nPowTargetSpacing; if (fShift) bnNew <<= 1; diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index dea159d56..55bb7e495 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -57,7 +57,7 @@ UniValue GetNetworkHashPS(int lookup, int height) { // If lookup is -1, then use blocks since last difficulty change. if (lookup <= 0) - lookup = pb->nHeight % Params().GetConsensus().DifficultyAdjustmentInterval() + 1; + lookup = pb->nHeight % Params().GetConsensus().DifficultyAdjustmentInterval(height) + 1; // If lookup is larger than chain, then set it to chain length. if (lookup > pb->nHeight)