git / moonbite-core / src/pow.cpp · raw

// 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 <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){    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;}