Fabcoin Core  0.16.2
P2P Digital Currency
pow.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2017 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 <crypto/equihash.h>
12 #include <primitives/block.h>
13 #include <streams.h>
14 #include <uint256.h>
15 #include <crypto/equihash.h>
16 #include <util.h>
17 
18 unsigned int GetNextWorkRequired(const CBlockIndex* pindexPrev, const CBlockHeader *pblock, const Consensus::Params& params)
19 {
20  unsigned int nProofOfWorkLimit = UintToArith256(params.PowLimit(true)).GetCompact();
21 
22  // Genesis block
23  if (pindexPrev == NULL)
24  return nProofOfWorkLimit;
25 
26  if (params.fPowNoRetargeting)
27  return pindexPrev->nBits;
28 
29  uint32_t nHeight = pindexPrev->nHeight + 1;
30 
31  if (nHeight < params.LWMAHeight)
32  {
33  // Digishield v3.
34  return DigishieldGetNextWorkRequired(pindexPrev, pblock, params);
35  }
36  else if (nHeight < params.LWMAHeight + params.nZawyLwmaAveragingWindow && params.LWMAHeight == params.EquihashFABHeight )
37  {
38  // Reduce the difficulty of the first forked block by 100x and keep it for N blocks.
39  if (nHeight == params.LWMAHeight)
40  {
41  if( Params().NetworkIDString() == CBaseChainParams::MAIN )
42  {
43  LogPrintf("Use minimum difficulty for the first N blocks since forking. height=%d\n", nHeight);
44  return UintToArith256(params.PowLimit(true)).GetCompact();
45  }
46  else
47  {
48  // Reduce the difficulty of the first forked block by 100x and keep it for N blocks.
49  return ReduceDifficultyBy(pindexPrev, 100, params);
50  }
51  }
52  else
53  {
54  return pindexPrev->nBits;
55  }
56  }
57  else
58  {
59  // Zawy's LWMA.
60  return LwmaGetNextWorkRequired(pindexPrev, pblock, params);
61  }
62 }
63 
64 unsigned int LwmaGetNextWorkRequired(const CBlockIndex* pindexPrev, const CBlockHeader *pblock, const Consensus::Params& params)
65 {
66  // If the new block's timestamp is more than 10 * T minutes
67  // then halve the difficulty
68  int64_t diff = pblock->GetBlockTime() - pindexPrev->GetBlockTime();
69  if ( params.fPowAllowMinDifficultyBlocks && diff > ( pindexPrev->nHeight+1 < params.EquihashFABHeight ? params.nPowTargetSpacing : 2*params.nPowTargetSpacing ) * params.MaxBlockInterval )
70  {
71 #if 1
72  LogPrintf("The new block(height=%d) will come too late. Use minimum difficulty.\n", pblock->nHeight);
73  return UintToArith256(params.PowLimit(true)).GetCompact();
74 #else
75  arith_uint256 target;
76  target.SetCompact(pindexPrev->nBits);
77  int n = diff / ( pindexPrev->nHeight+1<params.EquihashFABHeight:params.nPowTargetSpacing:2*params.nPowTargetSpacing ) * params.MaxBlockInterval);
78 
79  while( n-- > 0 )
80  {
81  target <<= 1;
82  }
83 
84  const arith_uint256 pow_limit = UintToArith256(params.PowLimit(true));
85  if (target > pow_limit) {
86  target = pow_limit;
87  }
88 
89  LogPrintf("The new block(height=%d) will come too late. Halve the difficulty to %x.\n", pblock->nHeight, target.GetCompact());
90  return target.GetCompact();
91 #endif
92  }
93  return LwmaCalculateNextWorkRequired(pindexPrev, params);
94 }
95 
96 unsigned int LwmaCalculateNextWorkRequired(const CBlockIndex* pindexPrev, const Consensus::Params& params)
97 {
98  if (params.fPowNoRetargeting)
99  {
100  return pindexPrev->nBits;
101  }
102 
103  const int height = pindexPrev->nHeight + 1;
104 
105  const int64_t T = height<params.EquihashFABHeight ? params.nPowTargetSpacing : 2*params.nPowTargetSpacing;
106  const int N = params.nZawyLwmaAveragingWindow;
107  const int k = (N+1)/2 * 0.998 * T; // ( (N+1)/2 * adjust * T )
108 
109  assert(height > N);
110 
111  arith_uint256 sum_target, sum_last10_target,sum_last5_target;;
112  int sum_time = 0, nWeight = 0;
113 
114  int sum_last10_time=0; //Solving time of the last ten block
115  int sum_last5_time=0;
116 
117  // Loop through N most recent blocks.
118  for (int i = height - N; i < height; i++) {
119  const CBlockIndex* block = pindexPrev->GetAncestor(i);
120  const CBlockIndex* block_Prev = block->GetAncestor(i - 1);
121  int64_t solvetime = block->GetBlockTime() - block_Prev->GetBlockTime();
122 
123  if (params.bZawyLwmaSolvetimeLimitation && solvetime > 6 * T) {
124  solvetime = 6 * T;
125  }
126 
127  nWeight++;
128  sum_time += solvetime * nWeight; // Weighted solvetime sum.
129 
130  // Target sum divided by a factor, (k N^2).
131  // The factor is a part of the final equation. However we divide sum_target here to avoid
132  // potential overflow.
133  arith_uint256 target;
134  target.SetCompact(block->nBits);
135  sum_target += target / (k * N * N);
136 
137  if(i >= height-10)
138  {
139  sum_last10_time += solvetime;
140  sum_last10_target += target;
141  if(i >= height-5)
142  {
143  sum_last5_time += solvetime;
144  sum_last5_target += target;
145  }
146  }
147  }
148 
149  // Keep sum_time reasonable in case strange solvetimes occurred.
150  if (sum_time < N * k / 10) {
151  sum_time = N * k / 10;
152  }
153 
154  const arith_uint256 pow_limit = UintToArith256(params.PowLimit(true));
155  arith_uint256 next_target = sum_time * sum_target;
156 
157 #if 1
158  /*if the last 10 blocks are generated in 5 minutes, we tripple the difficulty of average of the last 10 blocks*/
159  if( sum_last5_time <= T )
160  {
161  arith_uint256 avg_last5_target;
162  avg_last5_target = sum_last5_target/5;
163  if(next_target > avg_last5_target/4) next_target = avg_last5_target/4;
164  }
165  else if(sum_last10_time <= 2 * T)
166  {
167  arith_uint256 avg_last10_target;
168  avg_last10_target = sum_last10_target/10;
169  if(next_target > avg_last10_target/3) next_target = avg_last10_target/3;
170  }
171  else if(sum_last10_time <= 5 * T)
172  {
173  arith_uint256 avg_last10_target;
174  avg_last10_target = sum_last10_target/10;
175  if(next_target > avg_last10_target*2/3) next_target = avg_last10_target*2/3;
176  }
177 
178  arith_uint256 last_target;
179  last_target.SetCompact(pindexPrev->nBits);
180  if( next_target > last_target * 13/10 ) next_target = last_target * 13/10;
181  /*in case difficulty drops too soon compared to the last block, especially
182  *when the effect of the last rule wears off in the new block
183  *DAA will switch to normal LWMA and cause dramatically diff drops*/
184 #endif
185 
186  if (next_target > pow_limit) {
187  next_target = pow_limit;
188  }
189 
190  return next_target.GetCompact();
191 }
192 
193 unsigned int DigishieldGetNextWorkRequired(const CBlockIndex* pindexPrev, const CBlockHeader *pblock,
194  const Consensus::Params& params)
195 {
196  assert(pindexPrev != nullptr);
197  unsigned int nProofOfWorkLimit = UintToArith256(params.PowLimit(true)).GetCompact();
198 
199  // Find the first block in the averaging interval
200  const CBlockIndex* pindexFirst = pindexPrev;
201  arith_uint256 bnTot {0};
202  for (int i = 0; pindexFirst && i < params.nDigishieldPowAveragingWindow; i++) {
203  arith_uint256 bnTmp;
204  bnTmp.SetCompact(pindexFirst->nBits);
205  bnTot += bnTmp;
206  pindexFirst = pindexFirst->pprev;
207  }
208 
209  // Check we have enough blocks
210  if (pindexFirst == NULL)
211  return nProofOfWorkLimit;
212 
213  arith_uint256 bnAvg { bnTot / params.nDigishieldPowAveragingWindow };
214  return DigishieldCalculateNextWorkRequired(pindexPrev, bnAvg, pindexPrev->GetMedianTimePast(), pindexFirst->GetMedianTimePast(), params);
215 }
216 
217 
218 unsigned int DigishieldCalculateNextWorkRequired(const CBlockIndex* pindexPrev, arith_uint256 bnAvg, int64_t nLastBlockTime, int64_t nFirstBlockTime, const Consensus::Params& params)
219 {
220  // Limit adjustment
221  // Use medians to prevent time-warp attacks
222  int64_t nActualTimespan = nLastBlockTime - nFirstBlockTime;
223  nActualTimespan = params.DigishieldAveragingWindowTimespan(pindexPrev->nHeight) + (nActualTimespan - params.DigishieldAveragingWindowTimespan(pindexPrev->nHeight))/4;
224 
225  if (nActualTimespan < params.DigishieldMinActualTimespan(pindexPrev->nHeight))
226  nActualTimespan = params.DigishieldMinActualTimespan(pindexPrev->nHeight);
227  if (nActualTimespan > params.DigishieldMaxActualTimespan(pindexPrev->nHeight))
228  nActualTimespan = params.DigishieldMaxActualTimespan(pindexPrev->nHeight);
229 
230  // Retarget
231  const arith_uint256 bnPowLimit = UintToArith256(params.PowLimit(true));
232  arith_uint256 bnNew {bnAvg};
233  bnNew /= params.DigishieldAveragingWindowTimespan(pindexPrev->nHeight);
234  bnNew *= nActualTimespan;
235 
236  if (bnNew > bnPowLimit)
237  bnNew = bnPowLimit;
238 
239  return bnNew.GetCompact();
240 }
241 
242 unsigned int ReduceDifficultyBy(const CBlockIndex* pindexPrev, int64_t multiplier, const Consensus::Params& params)
243 {
244  arith_uint256 target;
245 
246  target.SetCompact(pindexPrev->nBits);
247  target *= multiplier;
248 
249  const arith_uint256 pow_limit = UintToArith256(params.PowLimit(true));
250  if (target > pow_limit)
251  {
252  target = pow_limit;
253  }
254  return target.GetCompact();
255 }
256 
257 
258 bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams& params)
259 {
260 
261  unsigned int n = params.EquihashN(pblock->nHeight );
262  unsigned int k = params.EquihashK(pblock->nHeight );
263 
264  // Hash state
265  crypto_generichash_blake2b_state state;
266  EhInitialiseState(n, k, state);
267 
268  // I = the block header minus nonce and solution.
269  CEquihashInput I{*pblock};
270  // I||V
271  int ser_flags = (pblock->nHeight < (uint32_t)params.GetConsensus().ContractHeight) ? SERIALIZE_BLOCK_NO_CONTRACT : 0;
272  CDataStream ss(SER_NETWORK, PROTOCOL_VERSION |ser_flags );
273  ss << I;
274  ss << pblock->nNonce;
275 
276  // H(I||V||...
277  crypto_generichash_blake2b_update(&state, (unsigned char*)&ss[0], ss.size());
278 
279  bool isValid;
280  EhIsValidSolution(n, k, state, pblock->nSolution, isValid);
281  if (!isValid) {
282  LogPrintf("EhIsValidSolution is invalid, n=%d k=%d ss.size=%d \npblock=%s ", n,k, ss.size(), pblock->ToString() );
283  return error("CheckEquihashSolution(): invalid solution");
284  }
285 
286  return true;
287 }
288 
289 
290 bool CheckProofOfWork(uint256 hash, unsigned int nBits, bool postfork, const Consensus::Params& params)
291 {
292  bool fNegative;
293  bool fOverflow;
294  arith_uint256 bnTarget;
295 
296  bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
297 
298  // Check range
299  if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.PowLimit(postfork)))
300  return false;
301 
302  // Check proof of work matches claimed amount
303  if (UintToArith256(hash) > bnTarget)
304  return false;
305 
306  return true;
307 }
bool error(const char *fmt, const Args &...args)
Definition: util.h:178
uint256 nNonce
Definition: block.h:53
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:184
bool fPowNoRetargeting
Definition: params.h:80
unsigned int EquihashN(uint32_t nHeight=0) const
Definition: chainparams.h:72
#define EhInitialiseState(n, k, base_state)
Definition: equihash.h:204
#define T(i, x)
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:60
uint32_t nHeight
Definition: block.h:46
bool bZawyLwmaSolvetimeLimitation
Definition: params.h:92
bool fPowAllowMinDifficultyBlocks
Definition: params.h:79
assert(len-trim+(2 *lenIndices)<=WIDTH)
CChainParams defines various tweakable parameters of a given instance of the Fabcoin system...
Definition: chainparams.h:47
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:146
int64_t DigishieldMaxActualTimespan(uint32_t nheight=0) const
Definition: params.h:101
const uint256 & PowLimit(bool postfork) const
Definition: params.h:78
arith_uint256 UintToArith256(const uint256 &a)
static const std::string MAIN
BIP70 chain name strings (main, test or regtest)
bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams &params)
Check whether the Equihash solution in a block header is valid.
Definition: pow.cpp:258
uint32_t GetCompact(bool fNegative=false) const
#define LogPrintf(...)
Definition: util.h:153
bool CheckProofOfWork(uint256 hash, unsigned int nBits, bool postfork, const Consensus::Params &params)
Check whether a block hash satisfies the proof-of-work requirement specified by nBits.
Definition: pow.cpp:290
int64_t GetBlockTime() const
Definition: block.h:127
size_type size() const
Definition: streams.h:237
int64_t nPowTargetSpacing
Definition: params.h:82
uint32_t ContractHeight
Block height at which Fabcoin Smart Contract hard fork becomes active.
Definition: params.h:56
int64_t nDigishieldPowAveragingWindow
Definition: params.h:96
unsigned int DigishieldCalculateNextWorkRequired(const CBlockIndex *pindexPrev, arith_uint256 bnAvg, int64_t nLastBlockTime, int64_t nFirstBlockTime, const Consensus::Params &params)
Definition: pow.cpp:218
unsigned int nBits
Definition: chain.h:224
#define EhIsValidSolution(n, k, base_state, soln, ret)
Definition: equihash.h:271
Parameters that influence chain consensus.
Definition: params.h:39
std::vector< unsigned char > nSolution
Definition: block.h:54
256-bit unsigned big integer.
Custom serializer for CBlockHeader that omits the nonce and solution, for use as input to Equihash...
Definition: block.h:215
uint8_t MaxBlockInterval
Definition: params.h:93
unsigned int LwmaGetNextWorkRequired(const CBlockIndex *pindexPrev, const CBlockHeader *pblock, const Consensus::Params &params)
Zawy&#39;s LWMA - next generation algorithm.
Definition: pow.cpp:64
256-bit opaque blob.
Definition: uint256.h:132
std::string ToString() const
Definition: block.cpp:51
unsigned int ReduceDifficultyBy(const CBlockIndex *pindexPrev, int64_t multiplier, const Consensus::Params &params)
Reduce the difficulty by a given multiplier.
Definition: pow.cpp:242
unsigned int DigishieldGetNextWorkRequired(const CBlockIndex *pindexPrev, const CBlockHeader *pblock, const Consensus::Params &params)
Digishield v3 - used in Fabcoin mainnet currently.
Definition: pow.cpp:193
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: chain.h:177
const CChainParams & Params()
Return the currently selected parameters.
#define I(x, y, z)
Definition: Hash.cpp:82
unsigned int GetNextWorkRequired(const CBlockIndex *pindexPrev, const CBlockHeader *pblock, const Consensus::Params &params)
Definition: pow.cpp:18
N diff(N const &_a, N const &_b)
Definition: Common.h:212
uint32_t EquihashFABHeight
Block height at which EquihashFAB (184,7) becomes active.
Definition: params.h:58
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...
int64_t DigishieldMinActualTimespan(uint32_t nheight=0) const
Definition: params.h:100
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:193
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
Definition: chain.cpp:85
int64_t GetBlockTime() const
Definition: chain.h:329
int64_t GetMedianTimePast() const
Definition: chain.h:341
int64_t DigishieldAveragingWindowTimespan(uint32_t nheight=0) const
Definition: params.h:99
unsigned int LwmaCalculateNextWorkRequired(const CBlockIndex *pindexPrev, const Consensus::Params &params)
Definition: pow.cpp:96
unsigned int EquihashK(uint32_t nHeight=0) const
Definition: chainparams.h:73
Nodes collect new transactions into a block, hash them into a hash tree, and scan through nonce value...
Definition: block.h:35
uint32_t LWMAHeight
Block height at which LWMA becomes active.
Definition: params.h:54
int64_t nZawyLwmaAveragingWindow
Definition: params.h:91