// 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::max(); } return sign * r.GetLow64(); }