// Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2015 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 "key.h" #include "primitives/block.h" #include "uint256.h" #include /* Locate a block meeting the range and type specified down the block index; * for instance, range 1 PoW means to search for the nearest PoW block including * the starting one, then find the previous PoW one and return its position */ const CBlockIndex *GetPrevBlockIndex(const CBlockIndex *pindex, unsigned int nRange, const bool fProofOfStake) { nRange++; while(nRange) { if (pindex->IsProofOfStake() == fProofOfStake) if (!(--nRange)) return pindex; if (pindex->pprev) pindex = pindex->pprev; else break; } return NULL; } unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, bool fProofOfStake, const Consensus::Params& params) { arith_uint256 bnNew, bnTargetLimit; bnTargetLimit.SetCompact(UintToArith256(params.powLimit).GetCompact()); /* The genesis block */ if (pindexLast == NULL) return bnTargetLimit.GetCompact(); /* The latest block of the type requested */ const CBlockIndex *pindexPrev = GetPrevBlockIndex(pindexLast, 0, fProofOfStake); if(pindexPrev == NULL) return(bnTargetLimit.GetCompact()); if (params.fPowNoRetargeting) return pindexLast->nBits; /* Orbitcoin Super Shield (OSS); * retargets every block using two averaging windows of 5 and 20 blocks, * 0.25 damping and further oscillation limiting */ int64_t nIntervalShort = 5, nIntervalLong = 20, nTargetSpacing, nTargetTimespan, nActualTimespan, nActualTimespanShort, nActualTimespanLong, nActualTimespanAvg, nActualTimespanMax, nActualTimespanMin; if (fProofOfStake) nTargetSpacing = 6 * params.nBaseTargetSpacing; else nTargetSpacing = 3 * params.nBaseTargetSpacing; nTargetTimespan = nTargetSpacing * nIntervalLong; /* The short averaging window */ const CBlockIndex *pindexShort = GetPrevBlockIndex(pindexPrev, nIntervalShort, fProofOfStake); if (!pindexShort) return(bnTargetLimit.GetCompact()); nActualTimespanShort = (int64_t)pindexPrev->nTime - (int64_t)pindexShort->nTime; /* The long averaging window */ const CBlockIndex *pindexLong = GetPrevBlockIndex(pindexShort, nIntervalLong - nIntervalShort, fProofOfStake); if (!pindexLong) return(bnTargetLimit.GetCompact()); nActualTimespanLong = (int64_t)pindexPrev->nTime - (int64_t)pindexLong->nTime; /* Time warp protection */ nActualTimespanShort = std::max(nActualTimespanShort, (nTargetSpacing * nIntervalShort / 2)); nActualTimespanShort = std::min(nActualTimespanShort, (nTargetSpacing * nIntervalShort * 2)); nActualTimespanLong = std::max(nActualTimespanLong, (nTargetSpacing * nIntervalLong / 2)); nActualTimespanLong = std::min(nActualTimespanLong, (nTargetSpacing * nIntervalLong * 2)); /* The average of both windows */ nActualTimespanAvg = (nActualTimespanShort * (nIntervalLong / nIntervalShort) + nActualTimespanLong) / 2; /* 0.25 damping */ nActualTimespan = nActualTimespanAvg + 3 * nTargetTimespan; nActualTimespan /= 4; /* Oscillation limiters */ /* +5% to -10% */ nActualTimespanMin = nTargetTimespan * 100 / 105; nActualTimespanMax = nTargetTimespan * 110 / 100; if (nActualTimespan < nActualTimespanMin) nActualTimespan = nActualTimespanMin; if (nActualTimespan > nActualTimespanMax) nActualTimespan = nActualTimespanMax; /* Retarget */ bnNew.SetCompact(pindexPrev->nBits); bnNew *= nActualTimespan; bnNew /= nTargetTimespan; if (bnNew > bnTargetLimit) bnNew = bnTargetLimit; 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; }