// Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2018 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include #include #include unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) { assert(pindexLast != nullptr); unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact(); // Only change once per difficulty adjustment interval if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0) { if (params.fPowAllowMinDifficultyBlocks) { // Special difficulty rule for testnet: // If the new block's timestamp is more than 2 * nPowTargetSpacing // then allow mining of a min-difficulty block. if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2) return nProofOfWorkLimit; else { // Return the last non-special-min-difficulty-rules-block const CBlockIndex* pindex = pindexLast; while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit) pindex = pindex->pprev; return pindex->nBits; } } return pindexLast->nBits; } // Go back by what we want to be one retarget period (nPowTargetTimespan) 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(); // Go back by one retarget period worth of blocks const CBlockIndex* pindexFirst = pindexLast; for (int i = 0; pindexFirst && i < blockstogoback; i++) pindexFirst = pindexFirst->pprev; assert(pindexFirst); return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params); } unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params) { if (params.fPowNoRetargeting) return pindexLast->nBits; // 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; // Retarget arith_uint256 bnNew; arith_uint256 bnOld; bnNew.SetCompact(pindexLast->nBits); bnOld = bnNew; // MoonBite: the intermediate (target * nActualTimespan) can overflow // 256 bits when the target is near powLimit. Litecoin drops exactly one // bit, which is only enough for its own (3.5 day, 00000fff..) parameters; // here the headroom is computed so the product always fits, and the // dropped low bits are far below the 23-bit precision of the compact // encoding anyway. const arith_uint256 bnPowLimit = UintToArith256(params.powLimit); unsigned int nTimespanBits = 0; for (uint64_t t = (uint64_t)nActualTimespan; t != 0; t >>= 1) nTimespanBits++; unsigned int nShift = 0; if (bnNew.bits() + nTimespanBits > 256) nShift = bnNew.bits() + nTimespanBits - 256; bnNew >>= nShift; bnNew *= nActualTimespan; bnNew /= params.nPowTargetTimespan; bnNew <<= nShift; if (bnNew > bnPowLimit) bnNew = bnPowLimit; return bnNew.GetCompact(); } bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params) { bool fNegative; bool fOverflow; arith_uint256 bnTarget; bnTarget.SetCompact(nBits, &fNegative, &fOverflow); // Check range if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit)) return false; // Check proof of work matches claimed amount if (UintToArith256(hash) > bnTarget) return false; return true; }