1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 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.
8 #include "arith_uint256.h"
10 #include "chainparams.h"
11 #include "crypto/equihash.h"
12 #include "primitives/block.h"
19 unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
21 unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact();
24 if (pindexLast == NULL )
25 return nProofOfWorkLimit;
27 // Find the first block in the averaging interval
28 const CBlockIndex* pindexFirst = pindexLast;
29 arith_uint256 bnTot {0};
30 for (int i = 0; pindexFirst && i < params.nPowAveragingWindow; i++) {
32 bnTmp.SetCompact(pindexFirst->nBits);
34 pindexFirst = pindexFirst->pprev;
37 // Check we have enough blocks
38 if (pindexFirst == NULL)
39 return nProofOfWorkLimit;
41 arith_uint256 bnAvg {bnTot / params.nPowAveragingWindow};
43 return CalculateNextWorkRequired(bnAvg, pindexLast->GetMedianTimePast(), pindexFirst->GetMedianTimePast(), params);
46 unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg,
47 int64_t nLastBlockTime, int64_t nFirstBlockTime,
48 const Consensus::Params& params)
50 // Limit adjustment step
51 // Use medians to prevent time-warp attacks
52 int64_t nActualTimespan = nLastBlockTime - nFirstBlockTime;
53 LogPrint("pow", " nActualTimespan = %d before dampening\n", nActualTimespan);
54 nActualTimespan = params.AveragingWindowTimespan() + (nActualTimespan - params.AveragingWindowTimespan())/4;
55 LogPrint("pow", " nActualTimespan = %d before bounds\n", nActualTimespan);
57 if (nActualTimespan < params.MinActualTimespan())
58 nActualTimespan = params.MinActualTimespan();
59 if (nActualTimespan > params.MaxActualTimespan())
60 nActualTimespan = params.MaxActualTimespan();
63 const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
64 arith_uint256 bnNew {bnAvg};
65 bnNew /= params.AveragingWindowTimespan();
66 bnNew *= nActualTimespan;
68 if (bnNew > bnPowLimit)
72 LogPrint("pow", "GetNextWorkRequired RETARGET\n");
73 LogPrint("pow", "params.AveragingWindowTimespan() = %d nActualTimespan = %d\n", params.AveragingWindowTimespan(), nActualTimespan);
74 LogPrint("pow", "Current average: %08x %s\n", bnAvg.GetCompact(), bnAvg.ToString());
75 LogPrint("pow", "After: %08x %s\n", bnNew.GetCompact(), bnNew.ToString());
77 return bnNew.GetCompact();
80 bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams& params)
82 unsigned int n = params.EquihashN();
83 unsigned int k = params.EquihashK();
86 crypto_generichash_blake2b_state state;
87 EhInitialiseState(n, k, state);
89 // I = the block header minus nonce and solution.
90 CEquihashInput I{*pblock};
92 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
97 crypto_generichash_blake2b_update(&state, (unsigned char*)&ss[0], ss.size());
100 EhIsValidSolution(n, k, state, pblock->nSolution, isValid);
102 return error("CheckEquihashSolution(): invalid solution");
107 int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33);
109 bool CheckProofOfWork(int32_t height,uint8_t *pubkey33,uint256 hash, unsigned int nBits, const Consensus::Params& params)
111 bool fNegative,fOverflow; int32_t i,nonz=0,special,notaryid,flag = 0;
112 arith_uint256 bnTarget;
114 bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
115 if ( height > 34000 ) // 0 -> non-special notary
117 special = komodo_chosennotary(¬aryid,height,pubkey33);
120 if ( pubkey33[i] != 0 )
122 //fprintf(stderr,"%02x",pubkey33[i]);
124 //fprintf(stderr," height.%d special.%d nonz.%d\n",height,special,nonz);
126 return(true); // will come back via different path with pubkey set
127 if ( special > 0 ) // special notary id == (height % numnotaries)
129 if (UintToArith256(hash) <= bnTarget) // accept normal diff
131 bnTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
133 } //else bnTarget /= 8;
136 if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit))
137 return error("CheckProofOfWork(): nBits below minimum work");
138 // Check proof of work matches claimed amount
139 if (UintToArith256(hash) > bnTarget)
141 return error("CheckProofOfWork(): hash doesn't match nBits");
146 fprintf(stderr,"%02x",pubkey33[i]);
147 fprintf(stderr," <- Round Robin ht.%d for notary.%d special.%d\n",height,notaryid,special);
152 arith_uint256 GetBlockProof(const CBlockIndex& block)
154 arith_uint256 bnTarget;
157 bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow);
158 if (fNegative || fOverflow || bnTarget == 0)
160 // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256
161 // as it's too large for a arith_uint256. However, as 2**256 is at least as large
162 // as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / (bnTarget+1)) + 1,
163 // or ~bnTarget / (nTarget+1) + 1.
164 return (~bnTarget / (bnTarget + 1)) + 1;
167 int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params& params)
171 if (to.nChainWork > from.nChainWork) {
172 r = to.nChainWork - from.nChainWork;
174 r = from.nChainWork - to.nChainWork;
177 r = r * arith_uint256(params.nPowTargetSpacing) / GetBlockProof(tip);
179 return sign * std::numeric_limits<int64_t>::max();
181 return sign * r.GetLow64();