r1
This commit is contained in:
+154
@@ -0,0 +1,154 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Copyright (c) 2014-2015 The Dash developers
|
||||
// Copyright (c) 2015-2018 The PIVX developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "pow.h"
|
||||
|
||||
#include "chain.h"
|
||||
#include "chainparams.h"
|
||||
#include "main.h"
|
||||
#include "primitives/block.h"
|
||||
#include "uint256.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
||||
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader* pblock)
|
||||
{
|
||||
if (Params().NetworkID() == CBaseChainParams::REGTEST)
|
||||
return pindexLast->nBits;
|
||||
|
||||
/* current difficulty formula, agrarian - DarkGravity v3, written by Evan Duffield - evan@dashpay.io */
|
||||
const CBlockIndex* BlockLastSolved = pindexLast;
|
||||
const CBlockIndex* BlockReading = pindexLast;
|
||||
int64_t nActualTimespan = 0;
|
||||
int64_t LastBlockTime = 0;
|
||||
int64_t PastBlocksMin = 24;
|
||||
int64_t PastBlocksMax = 24;
|
||||
int64_t CountBlocks = 0;
|
||||
uint256 PastDifficultyAverage;
|
||||
uint256 PastDifficultyAveragePrev;
|
||||
|
||||
if (BlockLastSolved == NULL || BlockLastSolved->nHeight == 0 || BlockLastSolved->nHeight < PastBlocksMin) {
|
||||
return Params().ProofOfWorkLimit().GetCompact();
|
||||
}
|
||||
|
||||
if (pindexLast->nHeight > Params().LAST_POW_BLOCK()) {
|
||||
uint256 bnTargetLimit = (~uint256(0) >> 24);
|
||||
int64_t nTargetSpacing = 60;
|
||||
int64_t nTargetTimespan = 60 * 40;
|
||||
|
||||
int64_t nActualSpacing = 0;
|
||||
if (pindexLast->nHeight != 0)
|
||||
nActualSpacing = pindexLast->GetBlockTime() - pindexLast->pprev->GetBlockTime();
|
||||
|
||||
if (nActualSpacing < 0)
|
||||
nActualSpacing = 1;
|
||||
|
||||
// ppcoin: target change every block
|
||||
// ppcoin: retarget with exponential moving toward target spacing
|
||||
uint256 bnNew;
|
||||
bnNew.SetCompact(pindexLast->nBits);
|
||||
|
||||
int64_t nInterval = nTargetTimespan / nTargetSpacing;
|
||||
bnNew *= ((nInterval - 1) * nTargetSpacing + nActualSpacing + nActualSpacing);
|
||||
bnNew /= ((nInterval + 1) * nTargetSpacing);
|
||||
|
||||
if (bnNew <= 0 || bnNew > bnTargetLimit)
|
||||
bnNew = bnTargetLimit;
|
||||
|
||||
return bnNew.GetCompact();
|
||||
}
|
||||
|
||||
for (unsigned int i = 1; BlockReading && BlockReading->nHeight > 0; i++) {
|
||||
if (PastBlocksMax > 0 && i > PastBlocksMax) {
|
||||
break;
|
||||
}
|
||||
CountBlocks++;
|
||||
|
||||
if (CountBlocks <= PastBlocksMin) {
|
||||
if (CountBlocks == 1) {
|
||||
PastDifficultyAverage.SetCompact(BlockReading->nBits);
|
||||
} else {
|
||||
PastDifficultyAverage = ((PastDifficultyAveragePrev * CountBlocks) + (uint256().SetCompact(BlockReading->nBits))) / (CountBlocks + 1);
|
||||
}
|
||||
PastDifficultyAveragePrev = PastDifficultyAverage;
|
||||
}
|
||||
|
||||
if (LastBlockTime > 0) {
|
||||
int64_t Diff = (LastBlockTime - BlockReading->GetBlockTime());
|
||||
nActualTimespan += Diff;
|
||||
}
|
||||
LastBlockTime = BlockReading->GetBlockTime();
|
||||
|
||||
if (BlockReading->pprev == NULL) {
|
||||
assert(BlockReading);
|
||||
break;
|
||||
}
|
||||
BlockReading = BlockReading->pprev;
|
||||
}
|
||||
|
||||
uint256 bnNew(PastDifficultyAverage);
|
||||
|
||||
int64_t _nTargetTimespan = CountBlocks * Params().TargetSpacing();
|
||||
|
||||
if (nActualTimespan < _nTargetTimespan / 3)
|
||||
nActualTimespan = _nTargetTimespan / 3;
|
||||
if (nActualTimespan > _nTargetTimespan * 3)
|
||||
nActualTimespan = _nTargetTimespan * 3;
|
||||
|
||||
// Retarget
|
||||
bnNew *= nActualTimespan;
|
||||
bnNew /= _nTargetTimespan;
|
||||
|
||||
if (bnNew > Params().ProofOfWorkLimit()) {
|
||||
bnNew = Params().ProofOfWorkLimit();
|
||||
}
|
||||
|
||||
return bnNew.GetCompact();
|
||||
}
|
||||
|
||||
bool CheckProofOfWork(uint256 hash, unsigned int nBits)
|
||||
{
|
||||
bool fNegative;
|
||||
bool fOverflow;
|
||||
uint256 bnTarget;
|
||||
|
||||
if (Params().SkipProofOfWorkCheck())
|
||||
return true;
|
||||
|
||||
bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
|
||||
|
||||
// Check range
|
||||
if (fNegative || bnTarget == 0 || fOverflow || bnTarget > Params().ProofOfWorkLimit())
|
||||
return error("CheckProofOfWork() : nBits below minimum work");
|
||||
|
||||
// Check proof of work matches claimed amount
|
||||
if (hash > bnTarget) {
|
||||
if (Params().MineBlocksOnDemand())
|
||||
return false;
|
||||
else
|
||||
return error("CheckProofOfWork() : hash doesn't match nBits");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint256 GetBlockProof(const CBlockIndex& block)
|
||||
{
|
||||
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 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;
|
||||
}
|
||||
Reference in New Issue
Block a user