Files
agrarian/src/pow.cpp
T

156 lines
4.9 KiB
C++

// 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
// Copyright (c) 2022-2036 Agrarian 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 == nullptr || 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 == nullptr) {
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;
}