123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- // Copyright (c) 2009-2010 Satoshi Nakamoto
- // Copyright (c) 2009-2014 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 "chainparams.h"
- #include "crypto/equihash.h"
- #include "primitives/block.h"
- #include "streams.h"
- #include "uint256.h"
- #include "util.h"
- #include "sodium.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 == NULL)
- return nProofOfWorkLimit;
- // Find the first block in the averaging interval
- const CBlockIndex* pindexFirst = pindexLast;
- arith_uint256 bnTot {0};
- for (int i = 0; pindexFirst && i < params.nPowAveragingWindow; i++) {
- arith_uint256 bnTmp;
- bnTmp.SetCompact(pindexFirst->nBits);
- bnTot += bnTmp;
- pindexFirst = pindexFirst->pprev;
- }
- // Check we have enough blocks
- if (pindexFirst == NULL)
- return nProofOfWorkLimit;
- arith_uint256 bnAvg {bnTot / params.nPowAveragingWindow};
- return CalculateNextWorkRequired(bnAvg, pindexLast->GetMedianTimePast(), pindexFirst->GetMedianTimePast(), params);
- }
- unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg,
- int64_t nLastBlockTime, int64_t nFirstBlockTime,
- const Consensus::Params& params)
- {
- // Limit adjustment step
- // Use medians to prevent time-warp attacks
- int64_t nActualTimespan = nLastBlockTime - nFirstBlockTime;
- LogPrint("pow", " nActualTimespan = %d before dampening\n", nActualTimespan);
- nActualTimespan = params.AveragingWindowTimespan() + (nActualTimespan - params.AveragingWindowTimespan())/4;
- LogPrint("pow", " nActualTimespan = %d before bounds\n", nActualTimespan);
- if (nActualTimespan < params.MinActualTimespan())
- nActualTimespan = params.MinActualTimespan();
- if (nActualTimespan > params.MaxActualTimespan())
- nActualTimespan = params.MaxActualTimespan();
- // Retarget
- const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
- arith_uint256 bnNew {bnAvg};
- bnNew /= params.AveragingWindowTimespan();
- bnNew *= nActualTimespan;
- if (bnNew > bnPowLimit)
- bnNew = bnPowLimit;
- /// debug print
- LogPrint("pow", "GetNextWorkRequired RETARGET\n");
- LogPrint("pow", "params.AveragingWindowTimespan() = %d nActualTimespan = %d\n", params.AveragingWindowTimespan(), nActualTimespan);
- LogPrint("pow", "Current average: %08x %s\n", bnAvg.GetCompact(), bnAvg.ToString());
- LogPrint("pow", "After: %08x %s\n", bnNew.GetCompact(), bnNew.ToString());
- return bnNew.GetCompact();
- }
- bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams& params)
- {
- unsigned int n = params.EquihashN();
- unsigned int k = params.EquihashK();
- // Hash state
- crypto_generichash_blake2b_state state;
- EhInitialiseState(n, k, state);
- // I = the block header minus nonce and solution.
- CEquihashInput I{*pblock};
- // I||V
- CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
- ss << I;
- ss << pblock->nNonce;
- // H(I||V||...
- crypto_generichash_blake2b_update(&state, (unsigned char*)&ss[0], ss.size());
- bool isValid;
- EhIsValidSolution(n, k, state, pblock->nSolution, isValid);
- if (!isValid)
- return error("CheckEquihashSolution(): invalid solution");
- return true;
- }
- 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 error("CheckProofOfWork(): nBits below minimum work");
- // Check proof of work matches claimed amount
- if (UintToArith256(hash) > bnTarget)
- return error("CheckProofOfWork(): hash doesn't match nBits");
- return true;
- }
- arith_uint256 GetBlockProof(const CBlockIndex& block)
- {
- arith_uint256 bnTarget;
- bool fNegative;
- bool fOverflow;
- bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow);
- if (fNegative || fOverflow || bnTarget == 0)
- return 0;
- // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256
- // as it's too large for a arith_uint256. However, as 2**256 is at least as large
- // as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / (bnTarget+1)) + 1,
- // or ~bnTarget / (nTarget+1) + 1.
- return (~bnTarget / (bnTarget + 1)) + 1;
- }
- int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params& params)
- {
- arith_uint256 r;
- int sign = 1;
- if (to.nChainWork > from.nChainWork) {
- r = to.nChainWork - from.nChainWork;
- } else {
- r = from.nChainWork - to.nChainWork;
- sign = -1;
- }
- r = r * arith_uint256(params.nPowTargetSpacing) / GetBlockProof(tip);
- if (r.bits() > 63) {
- return sign * std::numeric_limits<int64_t>::max();
- }
- return sign * r.GetLow64();
- }
|