]>
Commit | Line | Data |
---|---|---|
df852d2b | 1 | // Copyright (c) 2009-2010 Satoshi Nakamoto |
f914f1a7 | 2 | // Copyright (c) 2009-2014 The Bitcoin Core developers |
78253fcb | 3 | // Distributed under the MIT software license, see the accompanying |
df852d2b | 4 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
5 | ||
6 | #include "pow.h" | |
7 | ||
734f85c4 | 8 | #include "arith_uint256.h" |
22c4272b | 9 | #include "chain.h" |
fdda3c50 JG |
10 | #include "chainparams.h" |
11 | #include "crypto/equihash.h" | |
d2270111 | 12 | #include "primitives/block.h" |
fdda3c50 | 13 | #include "streams.h" |
df852d2b | 14 | #include "uint256.h" |
ad49c256 | 15 | #include "util.h" |
df852d2b | 16 | |
fdda3c50 JG |
17 | #include "sodium.h" |
18 | ||
802ea76b SB |
19 | #ifdef ENABLE_RUST |
20 | #include "librustzcash.h" | |
21 | #endif // ENABLE_RUST | |
ae0bb3d3 | 22 | uint32_t komodo_chainactive_timestamp(); |
802ea76b | 23 | |
d698ef69 | 24 | unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) |
df852d2b | 25 | { |
fd311996 | 26 | unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact(); |
df852d2b | 27 | // Genesis block |
e583c8f8 | 28 | if (pindexLast == NULL ) |
df852d2b | 29 | return nProofOfWorkLimit; |
30 | ||
f2c48e15 JG |
31 | // Find the first block in the averaging interval |
32 | const CBlockIndex* pindexFirst = pindexLast; | |
7b173bd8 | 33 | arith_uint256 bnTot {0}; |
f2c48e15 | 34 | for (int i = 0; pindexFirst && i < params.nPowAveragingWindow; i++) { |
7b173bd8 JG |
35 | arith_uint256 bnTmp; |
36 | bnTmp.SetCompact(pindexFirst->nBits); | |
37 | bnTot += bnTmp; | |
f2c48e15 JG |
38 | pindexFirst = pindexFirst->pprev; |
39 | } | |
40 | ||
41 | // Check we have enough blocks | |
42 | if (pindexFirst == NULL) | |
43 | return nProofOfWorkLimit; | |
df852d2b | 44 | |
7b173bd8 JG |
45 | arith_uint256 bnAvg {bnTot / params.nPowAveragingWindow}; |
46 | ||
29842505 | 47 | return CalculateNextWorkRequired(bnAvg, pindexLast->GetMedianTimePast(), pindexFirst->GetMedianTimePast(), params); |
34e5015c RN |
48 | } |
49 | ||
29842505 JG |
50 | unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg, |
51 | int64_t nLastBlockTime, int64_t nFirstBlockTime, | |
52 | const Consensus::Params& params) | |
34e5015c | 53 | { |
df852d2b | 54 | // Limit adjustment step |
f2c48e15 | 55 | // Use medians to prevent time-warp attacks |
e99731b4 | 56 | int64_t nActualTimespan = nLastBlockTime - nFirstBlockTime; |
f2c48e15 JG |
57 | LogPrint("pow", " nActualTimespan = %d before dampening\n", nActualTimespan); |
58 | nActualTimespan = params.AveragingWindowTimespan() + (nActualTimespan - params.AveragingWindowTimespan())/4; | |
59 | LogPrint("pow", " nActualTimespan = %d before bounds\n", nActualTimespan); | |
60 | ||
61 | if (nActualTimespan < params.MinActualTimespan()) | |
62 | nActualTimespan = params.MinActualTimespan(); | |
63 | if (nActualTimespan > params.MaxActualTimespan()) | |
64 | nActualTimespan = params.MaxActualTimespan(); | |
df852d2b | 65 | |
66 | // Retarget | |
fd311996 | 67 | const arith_uint256 bnPowLimit = UintToArith256(params.powLimit); |
29842505 | 68 | arith_uint256 bnNew {bnAvg}; |
f2c48e15 | 69 | bnNew /= params.AveragingWindowTimespan(); |
aa86873a | 70 | bnNew *= nActualTimespan; |
df852d2b | 71 | |
fd311996 CF |
72 | if (bnNew > bnPowLimit) |
73 | bnNew = bnPowLimit; | |
df852d2b | 74 | |
75 | /// debug print | |
f2c48e15 JG |
76 | LogPrint("pow", "GetNextWorkRequired RETARGET\n"); |
77 | LogPrint("pow", "params.AveragingWindowTimespan() = %d nActualTimespan = %d\n", params.AveragingWindowTimespan(), nActualTimespan); | |
29842505 | 78 | LogPrint("pow", "Current average: %08x %s\n", bnAvg.GetCompact(), bnAvg.ToString()); |
f2c48e15 | 79 | LogPrint("pow", "After: %08x %s\n", bnNew.GetCompact(), bnNew.ToString()); |
df852d2b | 80 | |
81 | return bnNew.GetCompact(); | |
82 | } | |
83 | ||
fdda3c50 JG |
84 | bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams& params) |
85 | { | |
e9574728 JG |
86 | unsigned int n = params.EquihashN(); |
87 | unsigned int k = params.EquihashK(); | |
fdda3c50 | 88 | |
525c7b98 | 89 | if ( Params().NetworkIDString() == "regtest" ) |
90 | return(true); | |
fdda3c50 JG |
91 | // Hash state |
92 | crypto_generichash_blake2b_state state; | |
e9574728 | 93 | EhInitialiseState(n, k, state); |
fdda3c50 JG |
94 | |
95 | // I = the block header minus nonce and solution. | |
96 | CEquihashInput I{*pblock}; | |
97 | // I||V | |
98 | CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); | |
99 | ss << I; | |
100 | ss << pblock->nNonce; | |
101 | ||
102 | // H(I||V||... | |
103 | crypto_generichash_blake2b_update(&state, (unsigned char*)&ss[0], ss.size()); | |
104 | ||
802ea76b | 105 | #ifdef ENABLE_RUST |
6a0c7cea SB |
106 | // Ensure that our Rust interactions are working in production builds. This is |
107 | // temporary and should be removed. | |
108 | { | |
109 | assert(librustzcash_xor(0x0f0f0f0f0f0f0f0f, 0x1111111111111111) == 0x1e1e1e1e1e1e1e1e); | |
110 | } | |
802ea76b | 111 | #endif // ENABLE_RUST |
6a0c7cea | 112 | |
e9574728 JG |
113 | bool isValid; |
114 | EhIsValidSolution(n, k, state, pblock->nSolution, isValid); | |
115 | if (!isValid) | |
fdda3c50 JG |
116 | return error("CheckEquihashSolution(): invalid solution"); |
117 | ||
118 | return true; | |
119 | } | |
120 | ||
8683bd8d | 121 | int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); |
a4ea4a3f | 122 | int32_t komodo_is_special(uint8_t pubkeys[66][33],int32_t mids[66],uint32_t blocktimes[66],int32_t height,uint8_t pubkey33[33],uint32_t blocktime); |
c75c18fc | 123 | int32_t komodo_currentheight(); |
3617ec15 | 124 | CBlockIndex *komodo_chainactive(int32_t height); |
37955303 | 125 | void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height); |
c75c18fc | 126 | extern int32_t KOMODO_CHOSEN_ONE; |
6d649e09 | 127 | extern uint64_t ASSETCHAINS_STAKED; |
9edf27ec | 128 | extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; |
6c96293f | 129 | #define KOMODO_ELECTION_GAP 2000 |
c54cb7d5 | 130 | |
a4ea4a3f | 131 | int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t blocktimes[66],int32_t *nonzpkeysp,int32_t height); |
54f7311d | 132 | int32_t KOMODO_LOADINGBLOCKS = 1; |
29e60e48 | 133 | |
2a080a8a | 134 | extern std::string NOTARY_PUBKEY; |
135 | ||
a4ea4a3f | 136 | bool CheckProofOfWork(int32_t height,uint8_t *pubkey33,uint256 hash,unsigned int nBits,const Consensus::Params& params,uint32_t blocktime) |
df852d2b | 137 | { |
d8be8b2e | 138 | extern int32_t KOMODO_REWIND; |
a4ea4a3f | 139 | bool fNegative,fOverflow; uint8_t origpubkey33[33]; int32_t i,nonzpkeys=0,nonz=0,special=0,special2=0,notaryid=-1,flag = 0, mids[66]; uint32_t tiptime,blocktimes[66]; |
c54cb7d5 | 140 | arith_uint256 bnTarget; uint8_t pubkeys[66][33]; |
bf30e02d | 141 | //for (i=31; i>=0; i--) |
142 | // fprintf(stderr,"%02x",((uint8_t *)&hash)[i]); | |
143 | //fprintf(stderr," checkpow\n"); | |
54f7311d | 144 | memcpy(origpubkey33,pubkey33,33); |
a4ea4a3f | 145 | memset(blocktimes,0,sizeof(blocktimes)); |
146 | tiptime = komodo_chainactive_timestamp(); | |
df852d2b | 147 | bnTarget.SetCompact(nBits, &fNegative, &fOverflow); |
0d2cefb0 | 148 | if ( height == 0 ) |
c54cb7d5 | 149 | { |
c75c18fc | 150 | height = komodo_currentheight() + 1; |
c54cb7d5 | 151 | //fprintf(stderr,"set height to %d\n",height); |
152 | } | |
153 | if ( height > 34000 && ASSETCHAINS_SYMBOL[0] == 0 ) // 0 -> non-special notary | |
9997caa0 | 154 | { |
a4ea4a3f | 155 | special = komodo_chosennotary(¬aryid,height,pubkey33,tiptime); |
9997caa0 | 156 | for (i=0; i<33; i++) |
681589a5 | 157 | { |
158 | if ( pubkey33[i] != 0 ) | |
159 | nonz++; | |
681589a5 | 160 | } |
681589a5 | 161 | if ( nonz == 0 ) |
c54cb7d5 | 162 | { |
163 | //fprintf(stderr,"ht.%d null pubkey checkproof return\n",height); | |
f9e18307 | 164 | return(true); // will come back via different path with pubkey set |
c54cb7d5 | 165 | } |
a4ea4a3f | 166 | flag = komodo_eligiblenotary(pubkeys,mids,blocktimes,&nonzpkeys,height); |
167 | special2 = komodo_is_special(pubkeys,mids,blocktimes,height,pubkey33,blocktime); | |
8c0ffb40 | 168 | if ( notaryid >= 0 ) |
169 | { | |
8fa95955 | 170 | if ( height > 10000 && height < 80000 && (special != 0 || special2 > 0) ) |
8c0ffb40 | 171 | flag = 1; |
172 | else if ( height >= 80000 && height < 108000 && special2 > 0 ) | |
173 | flag = 1; | |
174 | else if ( height >= 108000 && special2 > 0 ) | |
67df454d | 175 | flag = (height > 1000000 || (height % KOMODO_ELECTION_GAP) > 64 || (height % KOMODO_ELECTION_GAP) == 0); |
c54cb7d5 | 176 | else if ( height == 790833 ) |
177 | flag = 1; | |
54f7311d | 178 | else if ( special2 < 0 ) |
179 | { | |
180 | if ( height > 792000 ) | |
181 | flag = 0; | |
182 | else fprintf(stderr,"ht.%d notaryid.%d special.%d flag.%d special2.%d\n",height,notaryid,special,flag,special2); | |
183 | } | |
a4ea4a3f | 184 | if ( (flag != 0 || special2 > 0) && special2 != -2 ) |
93684bd0 | 185 | { |
186 | //fprintf(stderr,"EASY MINING ht.%d\n",height); | |
187 | bnTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); | |
188 | } | |
fb9fcbf8 | 189 | } |
9997caa0 | 190 | } |
fd311996 | 191 | if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit)) |
5262fde0 | 192 | return error("CheckProofOfWork(): nBits below minimum work"); |
2ba9de01 | 193 | if ( ASSETCHAINS_STAKED != 0 ) |
194 | { | |
97a337f7 | 195 | arith_uint256 bnMaxPoSdiff; |
f108acf9 | 196 | bnTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); |
2ba9de01 | 197 | } |
df852d2b | 198 | // Check proof of work matches claimed amount |
4a4e912b | 199 | if ( UintToArith256(hash) > bnTarget ) |
f796b1fb | 200 | { |
54f7311d | 201 | if ( KOMODO_LOADINGBLOCKS != 0 ) |
202 | return true; | |
56aa66a0 | 203 | if ( ASSETCHAINS_SYMBOL[0] != 0 || height > 792000 ) |
a4ea4a3f | 204 | { |
6cbd97e3 | 205 | //if ( 0 && height > 792000 ) |
a4ea4a3f | 206 | { |
207 | for (i=31; i>=0; i--) | |
80afe35b | 208 | fprintf(stderr,"%02x",((uint8_t *)&hash)[i]); |
209 | fprintf(stderr," hash vs "); | |
a4ea4a3f | 210 | for (i=31; i>=0; i--) |
80afe35b | 211 | fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); |
bce6dbb3 | 212 | fprintf(stderr," ht.%d special.%d special2.%d flag.%d notaryid.%d mod.%d error\n",height,special,special2,flag,notaryid,(height % 35)); |
a4ea4a3f | 213 | for (i=0; i<33; i++) |
80afe35b | 214 | fprintf(stderr,"%02x",pubkey33[i]); |
215 | fprintf(stderr," <- pubkey\n"); | |
a4ea4a3f | 216 | for (i=0; i<33; i++) |
80afe35b | 217 | fprintf(stderr,"%02x",origpubkey33[i]); |
218 | fprintf(stderr," <- origpubkey\n"); | |
a4ea4a3f | 219 | } |
54f7311d | 220 | return false; |
a4ea4a3f | 221 | } |
f796b1fb | 222 | } |
a4ea4a3f | 223 | /*for (i=31; i>=0; i--) |
224 | fprintf(stderr,"%02x",((uint8_t *)&hash)[i]); | |
225 | fprintf(stderr," hash vs "); | |
226 | for (i=31; i>=0; i--) | |
227 | fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); | |
228 | fprintf(stderr," height.%d notaryid.%d PoW valid\n",height,notaryid);*/ | |
df852d2b | 229 | return true; |
230 | } | |
231 | ||
29977716 | 232 | |
734f85c4 | 233 | arith_uint256 GetBlockProof(const CBlockIndex& block) |
b343c1a1 | 234 | { |
734f85c4 | 235 | arith_uint256 bnTarget; |
b343c1a1 | 236 | bool fNegative; |
237 | bool fOverflow; | |
092b58d1 | 238 | bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow); |
b343c1a1 | 239 | if (fNegative || fOverflow || bnTarget == 0) |
240 | return 0; | |
241 | // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256 | |
734f85c4 | 242 | // as it's too large for a arith_uint256. However, as 2**256 is at least as large |
b343c1a1 | 243 | // as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / (bnTarget+1)) + 1, |
244 | // or ~bnTarget / (nTarget+1) + 1. | |
245 | return (~bnTarget / (bnTarget + 1)) + 1; | |
df852d2b | 246 | } |
f7303f97 PW |
247 | |
248 | int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params& params) | |
249 | { | |
250 | arith_uint256 r; | |
251 | int sign = 1; | |
252 | if (to.nChainWork > from.nChainWork) { | |
253 | r = to.nChainWork - from.nChainWork; | |
254 | } else { | |
255 | r = from.nChainWork - to.nChainWork; | |
256 | sign = -1; | |
257 | } | |
258 | r = r * arith_uint256(params.nPowTargetSpacing) / GetBlockProof(tip); | |
259 | if (r.bits() > 63) { | |
260 | return sign * std::numeric_limits<int64_t>::max(); | |
261 | } | |
262 | return sign * r.GetLow64(); | |
263 | } |