]> Git Repo - VerusCoin.git/blob - src/pow.cpp
Test
[VerusCoin.git] / src / pow.cpp
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.
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 "util.h"
16
17 #include "sodium.h"
18
19 #ifdef ENABLE_RUST
20 #include "librustzcash.h"
21 #endif // ENABLE_RUST
22 uint32_t komodo_chainactive_timestamp();
23
24 unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
25 {
26     unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact();
27     // Genesis block
28     if (pindexLast == NULL )
29         return nProofOfWorkLimit;
30
31     // Find the first block in the averaging interval
32     const CBlockIndex* pindexFirst = pindexLast;
33     arith_uint256 bnTot {0};
34     for (int i = 0; pindexFirst && i < params.nPowAveragingWindow; i++) {
35         arith_uint256 bnTmp;
36         bnTmp.SetCompact(pindexFirst->nBits);
37         bnTot += bnTmp;
38         pindexFirst = pindexFirst->pprev;
39     }
40
41     // Check we have enough blocks
42     if (pindexFirst == NULL)
43         return nProofOfWorkLimit;
44
45     arith_uint256 bnAvg {bnTot / params.nPowAveragingWindow};
46
47     return CalculateNextWorkRequired(bnAvg, pindexLast->GetMedianTimePast(), pindexFirst->GetMedianTimePast(), params);
48 }
49
50 unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg,
51                                        int64_t nLastBlockTime, int64_t nFirstBlockTime,
52                                        const Consensus::Params& params)
53 {
54     // Limit adjustment step
55     // Use medians to prevent time-warp attacks
56     int64_t nActualTimespan = nLastBlockTime - nFirstBlockTime;
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();
65
66     // Retarget
67     const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
68     arith_uint256 bnNew {bnAvg};
69     bnNew /= params.AveragingWindowTimespan();
70     bnNew *= nActualTimespan;
71
72     if (bnNew > bnPowLimit)
73         bnNew = bnPowLimit;
74
75     /// debug print
76     LogPrint("pow", "GetNextWorkRequired RETARGET\n");
77     LogPrint("pow", "params.AveragingWindowTimespan() = %d    nActualTimespan = %d\n", params.AveragingWindowTimespan(), nActualTimespan);
78     LogPrint("pow", "Current average: %08x  %s\n", bnAvg.GetCompact(), bnAvg.ToString());
79     LogPrint("pow", "After:  %08x  %s\n", bnNew.GetCompact(), bnNew.ToString());
80
81     return bnNew.GetCompact();
82 }
83
84 bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams& params)
85 {
86     unsigned int n = params.EquihashN();
87     unsigned int k = params.EquihashK();
88
89     // Hash state
90     crypto_generichash_blake2b_state state;
91     EhInitialiseState(n, k, state);
92
93     // I = the block header minus nonce and solution.
94     CEquihashInput I{*pblock};
95     // I||V
96     CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
97     ss << I;
98     ss << pblock->nNonce;
99
100     // H(I||V||...
101     crypto_generichash_blake2b_update(&state, (unsigned char*)&ss[0], ss.size());
102
103     #ifdef ENABLE_RUST
104     // Ensure that our Rust interactions are working in production builds. This is
105     // temporary and should be removed.
106     {
107         assert(librustzcash_xor(0x0f0f0f0f0f0f0f0f, 0x1111111111111111) == 0x1e1e1e1e1e1e1e1e);
108     }
109     #endif // ENABLE_RUST
110
111     bool isValid;
112     EhIsValidSolution(n, k, state, pblock->nSolution, isValid);
113     if (!isValid)
114         return error("CheckEquihashSolution(): invalid solution");
115
116     return true;
117 }
118
119 void komodo_pindex_init(CBlockIndex *pindex,int32_t height);
120 int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp);
121 int32_t komodo_is_special(uint8_t pubkeys[66][33],int32_t mids[66],int32_t height,uint8_t pubkey33[33],uint32_t timestamp);
122 int32_t komodo_currentheight();
123 CBlockIndex *komodo_chainactive(int32_t height);
124 void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height);
125 extern int32_t KOMODO_CHOSEN_ONE;
126 extern uint64_t ASSETCHAINS_STAKED;
127 extern char ASSETCHAINS_SYMBOL[];
128 #define KOMODO_ELECTION_GAP 2000
129  
130 int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,int32_t *nonzpkeysp,int32_t height);
131 int32_t KOMODO_LOADINGBLOCKS = 1;
132
133 extern std::string NOTARY_PUBKEY;
134
135 bool CheckProofOfWork(int32_t height,uint8_t *pubkey33,uint256 hash, unsigned int nBits, const Consensus::Params& params)
136 {
137     extern int32_t KOMODO_REWIND;
138     bool fNegative,fOverflow; int32_t i,nonzpkeys=0,nonz=0,special=0,special2=0,notaryid=-1,flag = 0, mids[66]; uint32_t timestamp = 0; CBlockIndex *pindex=0;
139     arith_uint256 bnTarget; uint8_t pubkeys[66][33];
140     timestamp = komodo_chainactive_timestamp();
141     bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
142     if ( height == 0 )
143     {
144         height = komodo_currentheight() + 1;
145         //fprintf(stderr,"set height to %d\n",height);
146     }
147     if ( height > 34000 && ASSETCHAINS_SYMBOL[0] == 0 ) // 0 -> non-special notary
148     {
149         if ( (pindex= komodo_chainactive(height)) != 0 )
150         {
151             komodo_pindex_init(pindex,height);
152             memcpy(pubkey33,pindex->pubkey33,33);
153         }
154         special = komodo_chosennotary(&notaryid,height,pubkey33,timestamp);
155         for (i=0; i<33; i++)
156         {
157             if ( pubkey33[i] != 0 )
158                 nonz++;
159         }
160         if ( nonz == 0 )
161         {
162             //fprintf(stderr,"ht.%d null pubkey checkproof return\n",height);
163             return(true); // will come back via different path with pubkey set
164         }
165         flag = komodo_eligiblenotary(pubkeys,mids,&nonzpkeys,height);
166         special2 = komodo_is_special(pubkeys,mids,height,pubkey33,timestamp);
167         fprintf(stderr,"ht.%d notaryid.%d special.%d flag.%d special2.%d\n",height,notaryid,special,flag,special2);
168         if ( notaryid >= 0 )
169         {
170             if ( height > 10000 && height < 80000 && (special != 0 || special2 > 0) )
171                 flag = 1;
172             else if ( height >= 80000 && height < 108000 && special2 > 0 )
173                 flag = 1;
174             else if ( height >= 108000 && special2 > 0 )
175                 flag = ((height % KOMODO_ELECTION_GAP) > 64 || (height % KOMODO_ELECTION_GAP) == 0);
176             else if ( height == 790833 )
177                 flag = 1;
178             else if ( special2 < 0 && height > 792000 )
179                 flag = 0;
180             if ( flag != 0 || special2 > 0 )
181             {
182                 //fprintf(stderr,"EASY MINING ht.%d\n",height);
183                 bnTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
184             }
185         }
186     }
187     if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit))
188         return error("CheckProofOfWork(): nBits below minimum work");
189     // Check proof of work matches claimed amount
190     if ( UintToArith256(hash) > bnTarget )
191     {
192         for (i=31; i>=0; i--)
193             printf("%02x",((uint8_t *)&hash)[i]);
194         printf(" hash vs ");
195         for (i=31; i>=0; i--)
196             printf("%02x",((uint8_t *)&bnTarget)[i]);
197         printf(" ht.%d special.%d notaryid.%d ht.%d mod.%d error\n",height,special,notaryid,height,(height % 35));
198         if ( pindex != 0 )
199         {
200             pindex->didinit = 0;
201             komodo_pindex_init(pindex,height);
202         }
203         for (i=0; i<33; i++)
204             printf("%02x",pubkey33[i]);
205         printf(" <- pubkey\n");
206         for (i=0; i<66; i++)
207             printf("%d ",mids[i]);
208         printf(" minerids from ht.%d pindex.%p\n",height,pindex);
209         if ( KOMODO_LOADINGBLOCKS == 0 )
210             return false;
211     }
212     return true;
213 }
214
215 arith_uint256 GetBlockProof(const CBlockIndex& block)
216 {
217     arith_uint256 bnTarget;
218     bool fNegative;
219     bool fOverflow;
220     bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow);
221     if (fNegative || fOverflow || bnTarget == 0)
222         return 0;
223     // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256
224     // as it's too large for a arith_uint256. However, as 2**256 is at least as large
225     // as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / (bnTarget+1)) + 1,
226     // or ~bnTarget / (nTarget+1) + 1.
227     return (~bnTarget / (bnTarget + 1)) + 1;
228 }
229
230 int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params& params)
231 {
232     arith_uint256 r;
233     int sign = 1;
234     if (to.nChainWork > from.nChainWork) {
235         r = to.nChainWork - from.nChainWork;
236     } else {
237         r = from.nChainWork - to.nChainWork;
238         sign = -1;
239     }
240     r = r * arith_uint256(params.nPowTargetSpacing) / GetBlockProof(tip);
241     if (r.bits() > 63) {
242         return sign * std::numeric_limits<int64_t>::max();
243     }
244     return sign * r.GetLow64();
245 }
This page took 0.037171 seconds and 4 git commands to generate.