Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

pow.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2015 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <pow.h>
7 
8 #include <arith_uint256.h>
9 #include <chain.h>
10 #include <chainparams.h>
11 #include <primitives/block.h>
12 #include <uint256.h>
13 
14 #include <math.h>
15 
16 unsigned int static KimotoGravityWell(const CBlockIndex* pindexLast, const Consensus::Params& params) {
17  const CBlockIndex *BlockLastSolved = pindexLast;
18  const CBlockIndex *BlockReading = pindexLast;
19  uint64_t PastBlocksMass = 0;
20  int64_t PastRateActualSeconds = 0;
21  int64_t PastRateTargetSeconds = 0;
22  double PastRateAdjustmentRatio = double(1);
23  arith_uint256 PastDifficultyAverage;
24  arith_uint256 PastDifficultyAveragePrev;
25  double EventHorizonDeviation;
26  double EventHorizonDeviationFast;
27  double EventHorizonDeviationSlow;
28 
29  uint64_t pastSecondsMin = params.nPowTargetTimespan * 0.025;
30  uint64_t pastSecondsMax = params.nPowTargetTimespan * 7;
31  uint64_t PastBlocksMin = pastSecondsMin / params.nPowTargetSpacing;
32  uint64_t PastBlocksMax = pastSecondsMax / params.nPowTargetSpacing;
33 
34  if (BlockLastSolved == nullptr || BlockLastSolved->nHeight == 0 || (uint64_t)BlockLastSolved->nHeight < PastBlocksMin) { return UintToArith256(params.powLimit).GetCompact(); }
35 
36  for (unsigned int i = 1; BlockReading && BlockReading->nHeight > 0; i++) {
37  if (PastBlocksMax > 0 && i > PastBlocksMax) { break; }
38  PastBlocksMass++;
39 
40  PastDifficultyAverage.SetCompact(BlockReading->nBits);
41  if (i > 1) {
42  // handle negative arith_uint256
43  if(PastDifficultyAverage >= PastDifficultyAveragePrev)
44  PastDifficultyAverage = ((PastDifficultyAverage - PastDifficultyAveragePrev) / i) + PastDifficultyAveragePrev;
45  else
46  PastDifficultyAverage = PastDifficultyAveragePrev - ((PastDifficultyAveragePrev - PastDifficultyAverage) / i);
47  }
48  PastDifficultyAveragePrev = PastDifficultyAverage;
49 
50  PastRateActualSeconds = BlockLastSolved->GetBlockTime() - BlockReading->GetBlockTime();
51  PastRateTargetSeconds = params.nPowTargetSpacing * PastBlocksMass;
52  PastRateAdjustmentRatio = double(1);
53  if (PastRateActualSeconds < 0) { PastRateActualSeconds = 0; }
54  if (PastRateActualSeconds != 0 && PastRateTargetSeconds != 0) {
55  PastRateAdjustmentRatio = double(PastRateTargetSeconds) / double(PastRateActualSeconds);
56  }
57  EventHorizonDeviation = 1 + (0.7084 * pow((double(PastBlocksMass)/double(28.2)), -1.228));
58  EventHorizonDeviationFast = EventHorizonDeviation;
59  EventHorizonDeviationSlow = 1 / EventHorizonDeviation;
60 
61  if (PastBlocksMass >= PastBlocksMin) {
62  if ((PastRateAdjustmentRatio <= EventHorizonDeviationSlow) || (PastRateAdjustmentRatio >= EventHorizonDeviationFast))
63  { assert(BlockReading); break; }
64  }
65  if (BlockReading->pprev == nullptr) { assert(BlockReading); break; }
66  BlockReading = BlockReading->pprev;
67  }
68 
69  arith_uint256 bnNew(PastDifficultyAverage);
70  if (PastRateActualSeconds != 0 && PastRateTargetSeconds != 0) {
71  bnNew *= PastRateActualSeconds;
72  bnNew /= PastRateTargetSeconds;
73  }
74 
75  if (bnNew > UintToArith256(params.powLimit)) {
76  bnNew = UintToArith256(params.powLimit);
77  }
78 
79  return bnNew.GetCompact();
80 }
81 
82 unsigned int static DarkGravityWave(const CBlockIndex* pindexLast, const Consensus::Params& params) {
83  /* current difficulty formula, dash - DarkGravity v3, written by Evan Duffield - evan@dash.org */
84  const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
85  int64_t nPastBlocks = 24;
86 
87  // make sure we have at least (nPastBlocks + 1) blocks, otherwise just return powLimit
88  if (!pindexLast || pindexLast->nHeight < nPastBlocks) {
89  return bnPowLimit.GetCompact();
90  }
91 
92  const CBlockIndex *pindex = pindexLast;
93  arith_uint256 bnPastTargetAvg;
94 
95  for (unsigned int nCountBlocks = 1; nCountBlocks <= nPastBlocks; nCountBlocks++) {
96  arith_uint256 bnTarget = arith_uint256().SetCompact(pindex->nBits);
97  if (nCountBlocks == 1) {
98  bnPastTargetAvg = bnTarget;
99  } else {
100  // NOTE: that's not an average really...
101  bnPastTargetAvg = (bnPastTargetAvg * nCountBlocks + bnTarget) / (nCountBlocks + 1);
102  }
103 
104  if(nCountBlocks != nPastBlocks) {
105  assert(pindex->pprev); // should never fail
106  pindex = pindex->pprev;
107  }
108  }
109 
110  arith_uint256 bnNew(bnPastTargetAvg);
111 
112  int64_t nActualTimespan = pindexLast->GetBlockTime() - pindex->GetBlockTime();
113  // NOTE: is this accurate? nActualTimespan counts it for (nPastBlocks - 1) blocks only...
114  int64_t nTargetTimespan = nPastBlocks * params.nPowTargetSpacing;
115 
116  if (nActualTimespan < nTargetTimespan/3)
117  nActualTimespan = nTargetTimespan/3;
118  if (nActualTimespan > nTargetTimespan*3)
119  nActualTimespan = nTargetTimespan*3;
120 
121  // Retarget
122  bnNew *= nActualTimespan;
123  bnNew /= nTargetTimespan;
124 
125  if (bnNew > bnPowLimit) {
126  bnNew = bnPowLimit;
127  }
128 
129  return bnNew.GetCompact();
130 }
131 
132 unsigned int GetNextWorkRequiredBTC(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
133 {
134  assert(pindexLast != nullptr);
135  unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact();
136 
137  // Only change once per interval
138  if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0)
139  {
140  if (params.fPowAllowMinDifficultyBlocks)
141  {
142  // Special difficulty rule for testnet:
143  // If the new block's timestamp is more than 2* 2.5 minutes
144  // then allow mining of a min-difficulty block.
145  if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2)
146  return nProofOfWorkLimit;
147  else
148  {
149  // Return the last non-special-min-difficulty-rules-block
150  const CBlockIndex* pindex = pindexLast;
151  while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit)
152  pindex = pindex->pprev;
153  return pindex->nBits;
154  }
155  }
156  return pindexLast->nBits;
157  }
158 
159  // Go back by what we want to be 1 day worth of blocks
160  int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1);
161  assert(nHeightFirst >= 0);
162  const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst);
163  assert(pindexFirst);
164 
165  return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params);
166 }
167 
168 unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
169 {
170  assert(pindexLast != nullptr);
171  assert(pblock != nullptr);
172  const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
173 
174  // this is only active on devnets
175  if (pindexLast->nHeight < params.nMinimumDifficultyBlocks) {
176  return bnPowLimit.GetCompact();
177  }
178 
179  if (pindexLast->nHeight + 1 < params.nPowKGWHeight) {
180  return GetNextWorkRequiredBTC(pindexLast, pblock, params);
181  }
182 
183  // Note: GetNextWorkRequiredBTC has it's own special difficulty rule,
184  // so we only apply this to post-BTC algos.
185  if (params.fPowAllowMinDifficultyBlocks) {
186  // recent block is more than 2 hours old
187  if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + 2 * 60 * 60) {
188  return bnPowLimit.GetCompact();
189  }
190  // recent block is more than 10 minutes old
191  if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing * 4) {
192  arith_uint256 bnNew = arith_uint256().SetCompact(pindexLast->nBits) * 10;
193  if (bnNew > bnPowLimit) {
194  return bnPowLimit.GetCompact();
195  }
196  return bnNew.GetCompact();
197  }
198  }
199 
200  if (pindexLast->nHeight + 1 < params.nPowDGWHeight) {
201  return KimotoGravityWell(pindexLast, params);
202  }
203 
204  return DarkGravityWave(pindexLast, params);
205 }
206 
207 // for DIFF_BTC only!
208 unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
209 {
210  if (params.fPowNoRetargeting)
211  return pindexLast->nBits;
212 
213  // Limit adjustment step
214  int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime;
215  if (nActualTimespan < params.nPowTargetTimespan/4)
216  nActualTimespan = params.nPowTargetTimespan/4;
217  if (nActualTimespan > params.nPowTargetTimespan*4)
218  nActualTimespan = params.nPowTargetTimespan*4;
219 
220  // Retarget
221  const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
222  arith_uint256 bnNew;
223  bnNew.SetCompact(pindexLast->nBits);
224  bnNew *= nActualTimespan;
225  bnNew /= params.nPowTargetTimespan;
226 
227  if (bnNew > bnPowLimit)
228  bnNew = bnPowLimit;
229 
230  return bnNew.GetCompact();
231 }
232 
233 bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params)
234 {
235  bool fNegative;
236  bool fOverflow;
237  arith_uint256 bnTarget;
238 
239  bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
240 
241  // Check range
242  if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit))
243  return false;
244 
245  // Check proof of work matches claimed amount
246  if (UintToArith256(hash) > bnTarget)
247  return false;
248 
249  return true;
250 }
int64_t GetBlockTime() const
Definition: chain.h:297
int64_t nPowTargetTimespan
Definition: params.h:177
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:177
bool fPowNoRetargeting
Definition: params.h:175
unsigned int GetNextWorkRequiredBTC(const CBlockIndex *pindexLast, const CBlockHeader *pblock, const Consensus::Params &params)
Definition: pow.cpp:132
bool fPowAllowMinDifficultyBlocks
Definition: params.h:174
unsigned int CalculateNextWorkRequired(const CBlockIndex *pindexLast, int64_t nFirstBlockTime, const Consensus::Params &params)
Definition: pow.cpp:208
uint32_t GetCompact(bool fNegative=false) const
arith_uint256 UintToArith256(const uint256 &a)
int nMinimumDifficultyBlocks
these parameters are only used on devnet and can be configured from the outside
Definition: params.h:185
uint256 powLimit
Proof of work parameters.
Definition: params.h:173
unsigned int GetNextWorkRequired(const CBlockIndex *pindexLast, const CBlockHeader *pblock, const Consensus::Params &params)
Definition: pow.cpp:168
int64_t nPowTargetSpacing
Definition: params.h:176
Parameters that influence chain consensus.
Definition: params.h:130
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params &params)
Check whether a block hash satisfies the proof-of-work requirement specified by nBits.
Definition: pow.cpp:233
int64_t GetBlockTime() const
Definition: block.h:65
256-bit unsigned big integer.
unsigned static int DarkGravityWave(const CBlockIndex *pindexLast, const Consensus::Params &params)
Definition: pow.cpp:82
int64_t DifficultyAdjustmentInterval() const
Definition: params.h:180
256-bit opaque blob.
Definition: uint256.h:123
unsigned static int KimotoGravityWell(const CBlockIndex *pindexLast, const Consensus::Params &params)
Definition: pow.cpp:16
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: chain.h:170
arith_uint256 & SetCompact(uint32_t nCompact, bool *pfNegative=nullptr, bool *pfOverflow=nullptr)
The "compact" format is a representation of a whole number N using an unsigned 32bit number similar t...
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:183
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
Definition: chain.cpp:110
uint32_t nBits
Definition: chain.h:213
Nodes collect new transactions into a block, hash them into a hash tree, and scan through nonce value...
Definition: block.h:20
Released under the MIT license