// 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 <pow.h> #include <lbry.h> #include <arith_uint256.h> #include <chain.h> #include <primitives/block.h> #include <uint256.h> unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) { unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact(); // Genesis block if (pindexLast == nullptr) return nProofOfWorkLimit; if (params.fPowAllowMinDifficultyBlocks && pindexLast->nHeight >= params.nAllowMinDiffMinHeight && pindexLast->nHeight < params.nAllowMinDiffMaxHeight) { // Special difficulty rule for testnet: // If the new block's timestamp is twice the target block time // then allow mining of a min-difficulty block. // This is to prevent the testnet from getting stuck when a large amount // of hashrate drops off the network. // This rule was not implemented properly until testnet block 277299. if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2){ return nProofOfWorkLimit; } // Special difficulty rule for LBRY testnet killed at block 1100000. } // Go back the full period unless it's the first retarget after genesis. int blockstogoback = params.DifficultyAdjustmentInterval(); blockstogoback = std::min(blockstogoback, pindexLast->nHeight); int nHeightFirst = pindexLast->nHeight - blockstogoback; assert(nHeightFirst >= 0); const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst); assert(pindexFirst); return CalculateLbryNextWorkRequired(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 const arith_uint256 bnPowLimit = UintToArith256(params.powLimit); arith_uint256 bnNew; bnNew.SetCompact(pindexLast->nBits); bnNew *= nActualTimespan; bnNew /= params.nPowTargetTimespan; 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; }