Untitled

 avatar
unknown
plain_text
2 years ago
4.9 kB
13
Indexable
// 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>

#include <bignum.h>
#include <chainparams.h>
#include <kernel.h>

unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake, const Consensus::Params& params)
{
    if (pindexLast == nullptr)
        return UintToArith256(params.powLimit).GetCompact(); // genesis block

    const CBlockIndex* pindexPrev = GetLastBlockIndex(pindexLast, fProofOfStake);
    if (pindexPrev->pprev == nullptr)
        return UintToArith256(params.bnInitialHashTarget).GetCompact(); // first block
    const CBlockIndex* pindexPrevPrev = GetLastBlockIndex(pindexPrev->pprev, fProofOfStake);
    if (pindexPrevPrev->pprev == nullptr)
        return UintToArith256(params.bnInitialHashTarget).GetCompact(); // second block

    int64_t nActualSpacing = pindexPrev->GetBlockTime() - pindexPrevPrev->GetBlockTime();

    // rfc20
    int64_t nHypotheticalSpacing = pindexLast->GetBlockTime() - pindexPrev->GetBlockTime();
    // ***********For v13, we can keep the HypotheticalSpacing concept, but not overwrite the ActualSpacing
    if (!fProofOfStake && IsProtocolV12(pindexPrev) && (nHypotheticalSpacing > nActualSpacing) && !IsProtocolV13(pindexPrev))
        nActualSpacing = nHypotheticalSpacing;

    // peercoin: target change every block
    // peercoin: retarget with exponential moving toward target spacing
    CBigNum bnNew;
    bnNew.SetCompact(pindexPrev->nBits);
    if (Params().NetworkIDString() != CBaseChainParams::REGTEST) {
        int64_t nTargetSpacing;

        if (fProofOfStake) {
            nTargetSpacing = params.nStakeTargetSpacing;
        } else {
            if (IsProtocolV09(pindexLast->nTime)) {
                nTargetSpacing = params.nStakeTargetSpacing * 6;
            } else {
                nTargetSpacing = std::min(params.nTargetSpacingWorkMax, params.nStakeTargetSpacing * (1 + pindexLast->nHeight - pindexPrev->nHeight));
            }
        }

         //*********** for v13, we do the multiplication again with the hypothetical spacing, but let's just do all the v13 stuff up front so that we can adjust actual spacing for the PoS-PoW difference after.  This should account for every combination of late and early blocks (i.e. late-late [the difficult case], late-early, earl-late, and early-early [which is a trivial case])
          if (!fProofOfStake && (IsProtocolV13(pindexPrev)))
          {
                     //********we should only do this if it exceeds the target
                     if (nHypotheticalSpacing > nTargetSpacing))
                 {
                 int64_t nInterval = params.nTargetTimespan / nTargetSpacing;
                 bnNew *= ((nInterval - 1) * nTargetSpacing + nHypotheticalSpacing + nHypotheticalSpacing);
                 bnNew /= ((nInterval + 1) * nTargetSpacing);
                 }
                      //******* Here is where we avoid pow-gap doublecount, and replace it with a PoS-PoW difference.  This "if" case is such that we are always looking to adjust the difficulty based on a longer than target time.
                      if (nActualSpacing > nTargetSpacing)
                      {
                          const CBlockIndex* pindexPrevPoS = GetLastBlockIndex(pindexPrev->pprev, !fProofOfStake);
                          //********Using PoS block just before pprev, we get the delta between last PoW block and the PoS block before it
                        nPoSPoWSpacing = pindexPrev->GetBlockTime() - pindexPrevPoS->GetBlockTime()
                        If (nPoSPoWSpacing < nActualSpacing)
                        {
                            nActualSpacing = nTargetSpacing + nPoSPoWSpacing
                         }
                          //*************otherwise, nHypotheticalSpacing was zero
                       }

        int64_t nInterval = params.nTargetTimespan / nTargetSpacing;
        bnNew *= ((nInterval - 1) * nTargetSpacing + nActualSpacing + nActualSpacing);
        bnNew /= ((nInterval + 1) * nTargetSpacing);
        }

    if (bnNew > CBigNum(params.powLimit))
        bnNew = CBigNum(params.powLimit);

    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;
}
Editor is loading...
Leave a Comment