Changeset View
Changeset View
Standalone View
Standalone View
src/pow/eda.cpp
- This file was added.
// Copyright (c) 2017-2020 The Bitcoin developers | |||||
// Distributed under the MIT software license, see the accompanying | |||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | |||||
#include <pow/eda.h> | |||||
#include <arith_uint256.h> | |||||
#include <chain.h> | |||||
#include <consensus/params.h> | |||||
/** | |||||
* Do difficulty adjustement Satoshi's way. | |||||
*/ | |||||
uint32_t CalculateNextWorkRequired(const CBlockIndex *pindexPrev, | |||||
int64_t nFirstBlockTime, | |||||
const Consensus::Params ¶ms) { | |||||
if (params.fPowNoRetargeting) { | |||||
return pindexPrev->nBits; | |||||
} | |||||
// Limit adjustment step | |||||
int64_t nActualTimespan = pindexPrev->GetBlockTime() - nFirstBlockTime; | |||||
if (nActualTimespan < params.nPowTargetTimespan / 4) { | |||||
nActualTimespan = params.nPowTargetTimespan / 4; | |||||
} | |||||
if (nActualTimespan > params.nPowTargetTimespan * 4) { | |||||
nActualTimespan = params.nPowTargetTimespan * 4; | |||||
} | |||||
// Retarget | |||||
const arith_uint256 bnPowLimit = UintToArith256(params.powLimit); | |||||
arith_uint256 bnNew; | |||||
bnNew.SetCompact(pindexPrev->nBits); | |||||
bnNew *= nActualTimespan; | |||||
bnNew /= params.nPowTargetTimespan; | |||||
if (bnNew > bnPowLimit) { | |||||
bnNew = bnPowLimit; | |||||
} | |||||
return bnNew.GetCompact(); | |||||
} | |||||
/** | |||||
* Compute the next required proof of work using the legacy Bitcoin difficulty | |||||
* adjustment + Emergency Difficulty Adjustment (EDA). | |||||
*/ | |||||
uint32_t GetNextEDAWorkRequired(const CBlockIndex *pindexPrev, | |||||
const CBlockHeader *pblock, | |||||
const Consensus::Params ¶ms) { | |||||
// Only change once per difficulty adjustment interval | |||||
uint32_t nHeight = pindexPrev->nHeight + 1; | |||||
if (nHeight % params.DifficultyAdjustmentInterval() == 0) { | |||||
// Go back by what we want to be 14 days worth of blocks | |||||
assert(nHeight >= params.DifficultyAdjustmentInterval()); | |||||
uint32_t nHeightFirst = nHeight - params.DifficultyAdjustmentInterval(); | |||||
const CBlockIndex *pindexFirst = pindexPrev->GetAncestor(nHeightFirst); | |||||
assert(pindexFirst); | |||||
return CalculateNextWorkRequired(pindexPrev, | |||||
pindexFirst->GetBlockTime(), params); | |||||
} | |||||
const uint32_t nProofOfWorkLimit = | |||||
UintToArith256(params.powLimit).GetCompact(); | |||||
if (params.fPowAllowMinDifficultyBlocks) { | |||||
// Special difficulty rule for testnet: | |||||
// If the new block's timestamp is more than 2* 10 minutes then allow | |||||
// mining of a min-difficulty block. | |||||
if (pblock->GetBlockTime() > | |||||
pindexPrev->GetBlockTime() + 2 * params.nPowTargetSpacing) { | |||||
return nProofOfWorkLimit; | |||||
} | |||||
// Return the last non-special-min-difficulty-rules-block | |||||
const CBlockIndex *pindex = pindexPrev; | |||||
while (pindex->pprev && | |||||
pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && | |||||
pindex->nBits == nProofOfWorkLimit) { | |||||
pindex = pindex->pprev; | |||||
} | |||||
return pindex->nBits; | |||||
} | |||||
// We can't go below the minimum, so bail early. | |||||
uint32_t nBits = pindexPrev->nBits; | |||||
if (nBits == nProofOfWorkLimit) { | |||||
return nProofOfWorkLimit; | |||||
} | |||||
// If producing the last 6 blocks took less than 12h, we keep the same | |||||
// difficulty. | |||||
const CBlockIndex *pindex6 = pindexPrev->GetAncestor(nHeight - 7); | |||||
assert(pindex6); | |||||
int64_t mtp6blocks = | |||||
pindexPrev->GetMedianTimePast() - pindex6->GetMedianTimePast(); | |||||
if (mtp6blocks < 12 * 3600) { | |||||
return nBits; | |||||
} | |||||
// If producing the last 6 blocks took more than 12h, increase the | |||||
// difficulty target by 1/4 (which reduces the difficulty by 20%). | |||||
// This ensures that the chain does not get stuck in case we lose | |||||
// hashrate abruptly. | |||||
arith_uint256 nPow; | |||||
nPow.SetCompact(nBits); | |||||
nPow += (nPow >> 2); | |||||
// Make sure we do not go below allowed values. | |||||
const arith_uint256 bnPowLimit = UintToArith256(params.powLimit); | |||||
if (nPow > bnPowLimit) { | |||||
nPow = bnPowLimit; | |||||
} | |||||
return nPow.GetCompact(); | |||||
} |