Untitled

 avatar
unknown
plain_text
a year ago
4.9 kB
2
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 + 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);
                }
                //*******This is a definition of the PoS block preceding the PoW block that closed the gap.
                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()
                //******Isolate the situation where there is a PoS block at more than the target spacing between PoW blocks.
                If (nPoSPoWSpacing + nTargetSpacing < nActualSpacing) {
                    //******long PoW gaps are mostly accounted for in hypothetical calculation.  Here, we just account for the extra time between the PoS and PoW block.
                    nActualSpacing = nTargetSpacing + nPoSPoWSpacing
                    }
                }

        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