// Deprecated for Bitcoin Gold unsigned int BitcoinGetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) { assert(pindexLast != nullptr); unsigned int nProofOfWorkLimit = UintToArith256(params.PowLimit(false)).GetCompact(); // Only change once per difficulty adjustment interval if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0) { if (params.fPowAllowMinDifficultyBlocks) { // Special difficulty rule for testnet: // If the new block's timestamp is more than 2* 10 minutes // then allow mining of a min-difficulty block. if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2) return nProofOfWorkLimit; else { // Return the last non-special-min-difficulty-rules-block const CBlockIndex* pindex = pindexLast; while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit) pindex = pindex->pprev; return pindex->nBits; } } return pindexLast->nBits; } // Go back by what we want to be 14 days worth of blocks int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1); assert(nHeightFirst >= 0); const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst); assert(pindexFirst); return BitcoinCalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), 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(); }
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; // Jupitercoin: Special rules for minimum difficulty blocks with Digishield if (AllowDigishieldMinDifficultyForBlock(pindexLast, pblock, params)) { // Special difficulty rule for testnet: // If the new block's timestamp is more than 2* nTargetSpacing minutes // then allow mining of a min-difficulty block. return nProofOfWorkLimit; } // Only change once per difficulty adjustment interval if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0) { if (params.fPowAllowMinDifficultyBlocks) { // Special difficulty rule for testnet: // If the new block's timestamp is more than 2* 10 minutes // then allow mining of a min-difficulty block. if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2) return nProofOfWorkLimit; else { // Return the last non-special-min-difficulty-rules-block const CBlockIndex* pindex = pindexLast; while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit) pindex = pindex->pprev; return pindex->nBits; } } return pindexLast->nBits; } // Litecoin: This fixes an issue where a 51% attack can change difficulty at will. // Go back the full period unless it's the first retarget after genesis. Code courtesy of Art Forz int blockstogoback = params.DifficultyAdjustmentInterval()-1; if ((pindexLast->nHeight+1) != params.DifficultyAdjustmentInterval()) blockstogoback = params.DifficultyAdjustmentInterval(); // Go back by what we want to be 14 days worth of blocks int nHeightFirst = pindexLast->nHeight - blockstogoback; assert(nHeightFirst >= 0); const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst); assert(pindexFirst); return CalculateJupitercoinNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params); }
int64_t GetActualMiningTimespan(const CBlockIndex* pindexLast, const Consensus::Params& params) { int64_t TotalTime = 0; if (pindexLast->nHeight >= params.DifficultyAdjustmentInterval() - 1) { const CBlockIndex* pindex = pindexLast; for (int i = 0; i < params.DifficultyAdjustmentInterval() && pindex != NULL; i++) { CBlock block; if (!ReadBlockFromDisk(block, pindex)) { LogPrintf("ERROR : %s() Read block fail at block hash %s\n", __func__, pindex->GetBlockHash().ToString()); return params.nPowTargetTimespan; } TotalTime += (pindex->nTime - block.vtx[0].nLockTime); pindex = pindex->pprev; } } return TotalTime; }
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) { assert(pindexLast != nullptr); int nHeight = pindexLast->nHeight + 1; bool postfork = nHeight >= params.BTGHeight; unsigned int nProofOfWorkLimit = UintToArith256(params.PowLimit(postfork)).GetCompact(); if (postfork == false) { return BitcoinGetNextWorkRequired(pindexLast, pblock, params); } else if (nHeight < params.BTGHeight + params.BTGPremineWindow) { return nProofOfWorkLimit; } else if (nHeight < params.BTGHeight + params.BTGPremineWindow + params.nPowAveragingWindow){ return UintToArith256(params.powLimitStart).GetCompact(); } 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; } 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 int64_t nActualTimespan = nLastBlockTime - nFirstBlockTime; if (nActualTimespan < params.MinActualTimespan()) nActualTimespan = params.MinActualTimespan(); if (nActualTimespan > params.MaxActualTimespan()) nActualTimespan = params.MaxActualTimespan(); // Retarget const arith_uint256 bnPowLimit = UintToArith256(params.PowLimit(true)); arith_uint256 bnNew {bnAvg}; bnNew /= params.AveragingWindowTimespan(); bnNew *= nActualTimespan; if (bnNew > bnPowLimit) bnNew = bnPowLimit; return bnNew.GetCompact(); }
int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev) { int64_t nOldTime = pblock->nTime; int64_t nNewTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); if (nOldTime < nNewTime) pblock->nTime = nNewTime; // Updating time can change work required on testnet: if (consensusParams.AllowMinDifficultyBlocks(pblock->GetBlockTime())) pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams); return nNewTime - nOldTime; }
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; // Only change once per difficulty adjustment interval if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0) { if (params.AllowMinDifficultyBlocks(pblock->GetBlockTime())) { /* khal's port of this code from Bitcoin to the old namecoind has a bug: Comparison of block times is done by an unsigned difference. Consequently, the minimum difficulty is also applied if the block's timestamp is earlier than the preceding block's. Reproduce this. */ if (pblock->GetBlockTime() < pindexLast->GetBlockTime()) return nProofOfWorkLimit; // Special difficulty rule for testnet: // If the new block's timestamp is more than 2* 10 minutes // then allow mining of a min-difficulty block. if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2) return nProofOfWorkLimit; else { // Return the last non-special-min-difficulty-rules-block const CBlockIndex* pindex = pindexLast; while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit) pindex = pindex->pprev; return pindex->nBits; } } return pindexLast->nBits; } /* Adapt the retargeting interval after merge-mining start according to the changed Namecoin rules. */ int nBlocksBack = params.DifficultyAdjustmentInterval() - 1; if (pindexLast->nHeight >= params.nAuxpowStartHeight && (pindexLast->nHeight + 1 > params.DifficultyAdjustmentInterval())) nBlocksBack = params.DifficultyAdjustmentInterval(); // Go back by what we want to be 14 days worth of blocks int nHeightFirst = pindexLast->nHeight - nBlocksBack; assert(nHeightFirst >= 0); const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst); assert(pindexFirst); return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params); }
bool CheckProofOfWork(uint256 hash, unsigned int nBits, bool postfork, 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(postfork))) return false; // Check proof of work matches claimed amount if (UintToArith256(hash) > bnTarget) return false; return true; }
// Depricated for Bitcoin Gold unsigned int BitcoinCalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params) { if (params.fPowNoRetargeting) return pindexLast->nBits; // Limit adjustment step int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime; if (nActualTimespan < params.nPowTargetTimespanLegacy/4) nActualTimespan = params.nPowTargetTimespanLegacy/4; if (nActualTimespan > params.nPowTargetTimespanLegacy*4) nActualTimespan = params.nPowTargetTimespanLegacy*4; // Retarget const arith_uint256 bnPowLimit = UintToArith256(params.PowLimit(false)); arith_uint256 bnNew; bnNew.SetCompact(pindexLast->nBits); bnNew *= nActualTimespan; bnNew /= params.nPowTargetTimespanLegacy; if (bnNew > bnPowLimit) bnNew = bnPowLimit; return bnNew.GetCompact(); }
unsigned int GetNextWorkRequiredV1(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) { unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact(); // Genesis block if (pindexLast == NULL) return nProofOfWorkLimit; // Only change once per difficulty adjustment interval if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0) { if (params.fPowAllowMinDifficultyBlocks) { // Special difficulty rule for testnet: // If the new block's timestamp is more than 2* 10 minutes // then allow mining of a min-difficulty block. if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2) return nProofOfWorkLimit; else { // Return the last non-special-min-difficulty-rules-block const CBlockIndex* pindex = pindexLast; while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit) pindex = pindex->pprev; return pindex->nBits; } } return pindexLast->nBits; } // Go back by what we want to be 1 hourworth of blocks int nBlocksLookupRange = params.DifficultyAdjustmentInterval()-1; if (pindexLast->nHeight > 99988) { nBlocksLookupRange = params.DifficultyAdjustmentInterval() * 24; } const CBlockIndex* pindexFirst = pindexLast->GetAncestor( pindexLast->nHeight - nBlocksLookupRange); assert(pindexFirst); // Limit adjustment step int64_t nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime(); if (pindexLast->nHeight > 101908) { nActualTimespan = nActualTimespan / 3; } else if (pindexLast->nHeight > 99988) { nActualTimespan = nActualTimespan / 24; } LogPrintf(" nActualTimespan = %d before bounds\n", nActualTimespan); if (nActualTimespan < params.nPowTargetTimespan/4) nActualTimespan = params.nPowTargetTimespan/4; if (nActualTimespan > params.nPowTargetTimespan*4) nActualTimespan = params.nPowTargetTimespan*4; // Retarget const arith_uint256 bnPowLimit = UintToArith256(params.powLimit); arith_uint256 bnNew; arith_uint256 bnOld; bnNew.SetCompact(pindexLast->nBits); bnOld = bnNew; bnNew *= nActualTimespan; bnNew /= params.nPowTargetTimespan; if (bnNew > bnPowLimit) bnNew = bnPowLimit; /// debug print LogPrintf("GetNextWorkRequired RETARGET\n"); LogPrintf("params.nPowTargetTimespan = %d nActualTimespan = %d\n", params.nPowTargetTimespan, nActualTimespan); LogPrintf("Before: %08x %s\n", pindexLast->nBits, bnOld.ToString()); LogPrintf("After: %08x %s\n", bnNew.GetCompact(), bnNew.ToString()); return bnNew.GetCompact(); }
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) { const arith_uint256 powLimit = UintToArith256(params.powLimit); unsigned int nProofOfWorkLimit = powLimit.GetCompact(); // Genesis block if (pindexLast == NULL) return nProofOfWorkLimit; if (params.fPowNoRetargeting) return pindexLast->nBits; const int height = pindexLast->nHeight + 1; //okay, maybe not this line if (height < 14640) return GetNextWorkRequired_OLD(pindexLast, params); //hardcoded switch to 256.0 difficulty at block 14639 if (height == 14640) return 0x1C00FFFF; // Only change once per interval const int64_t nInterval = params.DifficultyAdjustmentInterval(); const int64_t nTargetSpacing = params.nPowTargetSpacing; if ((pindexLast->nHeight+1) % nInterval != 0) { // Special difficulty rule for testnet: if (params.fPowAllowMinDifficultyBlocks) { // If the new block's timestamp is more than 2* 10 minutes // then allow mining of a min-difficulty block. if (pblock->nTime > pindexLast->nTime + nTargetSpacing*2) return nProofOfWorkLimit; else { // Return the last non-special-min-difficulty-rules-block const CBlockIndex* pindex = pindexLast; while (pindex->pprev && pindex->nHeight % nInterval != 0 && pindex->nBits == nProofOfWorkLimit) pindex = pindex->pprev; return pindex->nBits; } } return pindexLast->nBits; } // This fixes an issue where a 51% attack can change difficulty at will. // Go back the full period unless it's the first retarget after genesis. Code courtesy of Art Forz // Patch modified from Litecoin. int blockstogoback = nInterval-1; if (height >= 150000 && height != nInterval) blockstogoback = nInterval; // Go back by what we want to be 14 days worth of blocks const CBlockIndex* pindexFirst = pindexLast; for (int i = 0; pindexFirst && i < blockstogoback; i++) pindexFirst = pindexFirst->pprev; assert(pindexFirst); // Limit adjustment step const int64_t nTargetTimespan = params.nPowTargetTimespan; int64_t nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime(); // assymmetric retarget (slow difficulty rise / fast difficulty drop) can be // abused to make a 51% attack more profitable than it should be, // therefore we adopt (starting at block 895000) a symmetric algorithm based // on bitcoin's algorithm. // // we retarget at most by a factor of 4^(120/2016) = 1.086 if (height < 895000) { // use the old retarget algorithm const int64_t nTwoPercent = nTargetTimespan/50; if (nActualTimespan < nTargetTimespan) //is time taken for a block less than 3minutes? { //limit increase to a much lower amount than dictates to get past the pump-n-dump mining phase //due to retargets being done more often it also needs to be lowered significantly from the 4x increase if(nActualTimespan<(nTwoPercent*16)) //less than a minute? nActualTimespan=(nTwoPercent*45); //pretend it was only 10% faster than desired else if(nActualTimespan<(nTwoPercent*32)) //less than 2 minutes? nActualTimespan=(nTwoPercent*47); //pretend it was only 6% faster than desired else nActualTimespan=(nTwoPercent*49); //pretend it was only 2% faster than desired //int64 nTime=nTargetTimespan-nActualTimespan; //nActualTimespan = nTargetTimespan/2; } else if (nActualTimespan > nTargetTimespan*4) nActualTimespan = nTargetTimespan*4; } else { // new algorithm // use integer aritmmetic to make sure that // all architectures return the exact same answers, // so instead of: // // foo < bar/1.086 we do foo < (1000*bar)/1086 // foo = bar/1.086 we do foo = (1000*bar)/1086 // foo > bar*1.086 we do foo > (1086*bar)/1000 // foo = bar*1.086 we do foo = (1086*bar)/1000 // // (parentheses to stress desired operator precedence) // // risk of overflow? no way; bar is quite small and // we have it under control, it is defined as 3*60*60 if (nActualTimespan < (1000*nTargetTimespan)/1086) nActualTimespan = (1000*nTargetTimespan)/1086; else if (nActualTimespan > (1086*nTargetTimespan)/1000) nActualTimespan = (1086*nTargetTimespan)/1000; } // Retarget arith_uint256 bnNew; bnNew.SetCompact(pindexLast->nBits); bnNew *= nActualTimespan; bnNew /= nTargetTimespan; if (bnNew > powLimit) bnNew = powLimit; /// debug print LogPrintf("GetNextWorkRequired RETARGET\n"); LogPrintf("nTargetTimespan = %ld nActualTimespan = %ld\n", nTargetTimespan, nActualTimespan); LogPrintf("Before: %08x\n", pindexLast->nBits); LogPrintf("After: %08x\n", bnNew.GetCompact()); return bnNew.GetCompact(); }