mirror of
https://github.com/dogecoin/dogecoin.git
synced 2026-02-01 11:00:57 +00:00
126 lines
4.7 KiB
C++
126 lines
4.7 KiB
C++
// Copyright (c) 2015-2021 The Dogecoin Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#include <boost/random/mersenne_twister.hpp>
|
|
#include <boost/random/uniform_int.hpp>
|
|
|
|
#include <arith_uint256.h>
|
|
#include <chain.h>
|
|
#include <dogecoin.h>
|
|
#include <logging.h>
|
|
|
|
#ifdef __clang__
|
|
__attribute__((no_sanitize("unsigned-integer-overflow")))
|
|
#endif // __clang__
|
|
int static generateMTRandom(unsigned int s, int range)
|
|
{
|
|
boost::mt19937 gen(s);
|
|
boost::uniform_int<> dist(1, range);
|
|
return dist(gen);
|
|
}
|
|
|
|
CAmount GetDogecoinBlockSubsidy(int nHeight, const Consensus::Params& consensusParams, uint256 prevHash)
|
|
{
|
|
int halvings = nHeight / consensusParams.nSubsidyHalvingInterval;
|
|
|
|
if (nHeight < 145000 && !consensusParams.fSimplifiedRewards)
|
|
{
|
|
// Old-style rewards derived from the previous block hash
|
|
|
|
// This extracts 7*4 bits out of the middle of the previous block hash to use as a seed.
|
|
// It's longer than the 1.14 code, but avoids the locale-sensitive strtol() function.
|
|
const int bitsPerNibble = 4;
|
|
const int totalNibbles = 256 / bitsPerNibble;
|
|
const int nibblesToClear = 7;
|
|
const int nibblesToKeep = 7;
|
|
arith_uint256 upperBits = UintToArith256(prevHash) << (nibblesToClear * bitsPerNibble);
|
|
arith_uint256 cleanedBits = upperBits >> ((totalNibbles - nibblesToKeep) * bitsPerNibble);
|
|
uint64_t seed = ArithToUint256(cleanedBits).GetUint64(0);
|
|
|
|
// Convert the seed into a subsidy value.
|
|
CAmount maxReward = (1000000 >> halvings) - 1;
|
|
int rand = generateMTRandom(seed, maxReward);
|
|
|
|
return (1 + rand) * COIN;
|
|
} else if (nHeight < (6 * consensusParams.nSubsidyHalvingInterval)) {
|
|
// New-style constant rewards for each halving interval
|
|
return (500000 * COIN) >> halvings;
|
|
} else {
|
|
// Constant inflation
|
|
return 10000 * COIN;
|
|
}
|
|
}
|
|
|
|
|
|
// Dogecoin: Normally minimum difficulty blocks can only occur in between
|
|
// retarget blocks. However, once we introduce Digishield every block is
|
|
// a retarget, so we need to handle minimum difficulty on all blocks.
|
|
bool AllowDigishieldMinDifficultyForBlock(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
|
|
{
|
|
// check if the chain allows minimum difficulty blocks
|
|
if (!params.fPowAllowMinDifficultyBlocks)
|
|
return false;
|
|
|
|
// check if the chain allows minimum difficulty blocks on recalc blocks
|
|
if (pindexLast->nHeight < 157500)
|
|
// if (!params.fPowAllowDigishieldMinDifficultyBlocks)
|
|
return false;
|
|
|
|
// Allow for a minimum block time if the elapsed time > 2*nTargetSpacing
|
|
return (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2);
|
|
}
|
|
|
|
unsigned int CalculateDogecoinNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
|
|
{
|
|
if (params.fPowNoRetargeting)
|
|
return pindexLast->nBits;
|
|
|
|
int nHeight = pindexLast->nHeight + 1;
|
|
bool fNewDifficultyProtocol = (nHeight >= 145000);
|
|
// bool fNewDifficultyProtocol = (nHeight >= params.GetDigiShieldForkBlock());
|
|
const int64_t nRetargetTimespan = fNewDifficultyProtocol
|
|
? 60 // params.DigiShieldTargetTimespan()
|
|
: params.nPowTargetTimespan;
|
|
|
|
int64_t nTimespan = pindexLast->GetBlockTime() - nFirstBlockTime;
|
|
int64_t nMaxTimespan;
|
|
int64_t nMinTimespan;
|
|
|
|
if (fNewDifficultyProtocol) //DigiShield implementation - thanks to RealSolid & WDC for this code
|
|
{
|
|
// amplitude filter - thanks to daft27 for this code
|
|
nTimespan = nRetargetTimespan + (nTimespan - nRetargetTimespan) / 8;
|
|
|
|
nMinTimespan = nRetargetTimespan - (nRetargetTimespan / 4);
|
|
nMaxTimespan = nRetargetTimespan + (nRetargetTimespan / 2);
|
|
} else if (nHeight > 10000) {
|
|
nMinTimespan = nRetargetTimespan / 4;
|
|
nMaxTimespan = nRetargetTimespan * 4;
|
|
} else if (nHeight > 5000) {
|
|
nMinTimespan = nRetargetTimespan / 8;
|
|
nMaxTimespan = nRetargetTimespan * 4;
|
|
} else {
|
|
nMinTimespan = nRetargetTimespan / 16;
|
|
nMaxTimespan = nRetargetTimespan * 4;
|
|
}
|
|
|
|
// Limit adjustment step
|
|
if (nTimespan < nMinTimespan)
|
|
nTimespan = nMinTimespan;
|
|
else if (nTimespan > nMaxTimespan)
|
|
nTimespan = nMaxTimespan;
|
|
|
|
// Retarget
|
|
const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
|
|
arith_uint256 bnNew;
|
|
bnNew.SetCompact(pindexLast->nBits);
|
|
bnNew *= nTimespan;
|
|
bnNew /= nRetargetTimespan;
|
|
|
|
if (bnNew > bnPowLimit)
|
|
bnNew = bnPowLimit;
|
|
|
|
return bnNew.GetCompact();
|
|
}
|