]> Git Repo - VerusCoin.git/blob - src/miner.cpp
Merge pull request #2852 from petertodd/getblock-chainwork
[VerusCoin.git] / src / miner.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #include "core.h"
7 #include "wallet.h"
8 #include "miner.h"
9 #include "main.h"
10
11
12
13
14
15
16 //////////////////////////////////////////////////////////////////////////////
17 //
18 // BitcoinMiner
19 //
20
21 int static FormatHashBlocks(void* pbuffer, unsigned int len)
22 {
23     unsigned char* pdata = (unsigned char*)pbuffer;
24     unsigned int blocks = 1 + ((len + 8) / 64);
25     unsigned char* pend = pdata + 64 * blocks;
26     memset(pdata + len, 0, 64 * blocks - len);
27     pdata[len] = 0x80;
28     unsigned int bits = len * 8;
29     pend[-1] = (bits >> 0) & 0xff;
30     pend[-2] = (bits >> 8) & 0xff;
31     pend[-3] = (bits >> 16) & 0xff;
32     pend[-4] = (bits >> 24) & 0xff;
33     return blocks;
34 }
35
36 static const unsigned int pSHA256InitState[8] =
37 {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
38
39 void SHA256Transform(void* pstate, void* pinput, const void* pinit)
40 {
41     SHA256_CTX ctx;
42     unsigned char data[64];
43
44     SHA256_Init(&ctx);
45
46     for (int i = 0; i < 16; i++)
47         ((uint32_t*)data)[i] = ByteReverse(((uint32_t*)pinput)[i]);
48
49     for (int i = 0; i < 8; i++)
50         ctx.h[i] = ((uint32_t*)pinit)[i];
51
52     SHA256_Update(&ctx, data, sizeof(data));
53     for (int i = 0; i < 8; i++)
54         ((uint32_t*)pstate)[i] = ctx.h[i];
55 }
56
57 //
58 // ScanHash scans nonces looking for a hash with at least some zero bits.
59 // It operates on big endian data.  Caller does the byte reversing.
60 // All input buffers are 16-byte aligned.  nNonce is usually preserved
61 // between calls, but periodically or if nNonce is 0xffff0000 or above,
62 // the block is rebuilt and nNonce starts over at zero.
63 //
64 unsigned int static ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1, char* phash, unsigned int& nHashesDone)
65 {
66     unsigned int& nNonce = *(unsigned int*)(pdata + 12);
67     for (;;)
68     {
69         // Crypto++ SHA256
70         // Hash pdata using pmidstate as the starting state into
71         // pre-formatted buffer phash1, then hash phash1 into phash
72         nNonce++;
73         SHA256Transform(phash1, pdata, pmidstate);
74         SHA256Transform(phash, phash1, pSHA256InitState);
75
76         // Return the nonce if the hash has at least some zero bits,
77         // caller will check if it has enough to reach the target
78         if (((unsigned short*)phash)[14] == 0)
79             return nNonce;
80
81         // If nothing found after trying for a while, return -1
82         if ((nNonce & 0xffff) == 0)
83         {
84             nHashesDone = 0xffff+1;
85             return (unsigned int) -1;
86         }
87         if ((nNonce & 0xfff) == 0)
88             boost::this_thread::interruption_point();
89     }
90 }
91
92 // Some explaining would be appreciated
93 class COrphan
94 {
95 public:
96     CTransaction* ptx;
97     set<uint256> setDependsOn;
98     double dPriority;
99     double dFeePerKb;
100
101     COrphan(CTransaction* ptxIn)
102     {
103         ptx = ptxIn;
104         dPriority = dFeePerKb = 0;
105     }
106
107     void print() const
108     {
109         printf("COrphan(hash=%s, dPriority=%.1f, dFeePerKb=%.1f)\n",
110                ptx->GetHash().ToString().c_str(), dPriority, dFeePerKb);
111         BOOST_FOREACH(uint256 hash, setDependsOn)
112             printf("   setDependsOn %s\n", hash.ToString().c_str());
113     }
114 };
115
116
117 uint64 nLastBlockTx = 0;
118 uint64 nLastBlockSize = 0;
119
120 // We want to sort transactions by priority and fee, so:
121 typedef boost::tuple<double, double, CTransaction*> TxPriority;
122 class TxPriorityCompare
123 {
124     bool byFee;
125 public:
126     TxPriorityCompare(bool _byFee) : byFee(_byFee) { }
127     bool operator()(const TxPriority& a, const TxPriority& b)
128     {
129         if (byFee)
130         {
131             if (a.get<1>() == b.get<1>())
132                 return a.get<0>() < b.get<0>();
133             return a.get<1>() < b.get<1>();
134         }
135         else
136         {
137             if (a.get<0>() == b.get<0>())
138                 return a.get<1>() < b.get<1>();
139             return a.get<0>() < b.get<0>();
140         }
141     }
142 };
143
144 CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
145 {
146     // Create new block
147     auto_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate());
148     if(!pblocktemplate.get())
149         return NULL;
150     CBlock *pblock = &pblocktemplate->block; // pointer for convenience
151
152     // Create coinbase tx
153     CTransaction txNew;
154     txNew.vin.resize(1);
155     txNew.vin[0].prevout.SetNull();
156     txNew.vout.resize(1);
157     CPubKey pubkey;
158     if (!reservekey.GetReservedKey(pubkey))
159         return NULL;
160     txNew.vout[0].scriptPubKey << pubkey << OP_CHECKSIG;
161
162     // Add our coinbase tx as first transaction
163     pblock->vtx.push_back(txNew);
164     pblocktemplate->vTxFees.push_back(-1); // updated at end
165     pblocktemplate->vTxSigOps.push_back(-1); // updated at end
166
167     // Largest block you're willing to create:
168     unsigned int nBlockMaxSize = GetArg("-blockmaxsize", MAX_BLOCK_SIZE_GEN/2);
169     // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity:
170     nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize));
171
172     // How much of the block should be dedicated to high-priority transactions,
173     // included regardless of the fees they pay
174     unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", DEFAULT_BLOCK_PRIORITY_SIZE);
175     nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize);
176
177     // Minimum block size you want to create; block will be filled with free transactions
178     // until there are no more or the block reaches this size:
179     unsigned int nBlockMinSize = GetArg("-blockminsize", 0);
180     nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize);
181
182     // Collect memory pool transactions into the block
183     int64 nFees = 0;
184     {
185         LOCK2(cs_main, mempool.cs);
186         CBlockIndex* pindexPrev = pindexBest;
187         CCoinsViewCache view(*pcoinsTip, true);
188
189         // Priority order to process transactions
190         list<COrphan> vOrphan; // list memory doesn't move
191         map<uint256, vector<COrphan*> > mapDependers;
192         bool fPrintPriority = GetBoolArg("-printpriority", false);
193
194         // This vector will be sorted into a priority queue:
195         vector<TxPriority> vecPriority;
196         vecPriority.reserve(mempool.mapTx.size());
197         for (map<uint256, CTransaction>::iterator mi = mempool.mapTx.begin(); mi != mempool.mapTx.end(); ++mi)
198         {
199             CTransaction& tx = (*mi).second;
200             if (tx.IsCoinBase() || !IsFinalTx(tx))
201                 continue;
202
203             COrphan* porphan = NULL;
204             double dPriority = 0;
205             int64 nTotalIn = 0;
206             bool fMissingInputs = false;
207             BOOST_FOREACH(const CTxIn& txin, tx.vin)
208             {
209                 // Read prev transaction
210                 if (!view.HaveCoins(txin.prevout.hash))
211                 {
212                     // This should never happen; all transactions in the memory
213                     // pool should connect to either transactions in the chain
214                     // or other transactions in the memory pool.
215                     if (!mempool.mapTx.count(txin.prevout.hash))
216                     {
217                         printf("ERROR: mempool transaction missing input\n");
218                         if (fDebug) assert("mempool transaction missing input" == 0);
219                         fMissingInputs = true;
220                         if (porphan)
221                             vOrphan.pop_back();
222                         break;
223                     }
224
225                     // Has to wait for dependencies
226                     if (!porphan)
227                     {
228                         // Use list for automatic deletion
229                         vOrphan.push_back(COrphan(&tx));
230                         porphan = &vOrphan.back();
231                     }
232                     mapDependers[txin.prevout.hash].push_back(porphan);
233                     porphan->setDependsOn.insert(txin.prevout.hash);
234                     nTotalIn += mempool.mapTx[txin.prevout.hash].vout[txin.prevout.n].nValue;
235                     continue;
236                 }
237                 const CCoins &coins = view.GetCoins(txin.prevout.hash);
238
239                 int64 nValueIn = coins.vout[txin.prevout.n].nValue;
240                 nTotalIn += nValueIn;
241
242                 int nConf = pindexPrev->nHeight - coins.nHeight + 1;
243
244                 dPriority += (double)nValueIn * nConf;
245             }
246             if (fMissingInputs) continue;
247
248             // Priority is sum(valuein * age) / txsize
249             unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
250             dPriority /= nTxSize;
251
252             // This is a more accurate fee-per-kilobyte than is used by the client code, because the
253             // client code rounds up the size to the nearest 1K. That's good, because it gives an
254             // incentive to create smaller transactions.
255             double dFeePerKb =  double(nTotalIn-GetValueOut(tx)) / (double(nTxSize)/1000.0);
256
257             if (porphan)
258             {
259                 porphan->dPriority = dPriority;
260                 porphan->dFeePerKb = dFeePerKb;
261             }
262             else
263                 vecPriority.push_back(TxPriority(dPriority, dFeePerKb, &(*mi).second));
264         }
265
266         // Collect transactions into block
267         uint64 nBlockSize = 1000;
268         uint64 nBlockTx = 0;
269         int nBlockSigOps = 100;
270         bool fSortedByFee = (nBlockPrioritySize <= 0);
271
272         TxPriorityCompare comparer(fSortedByFee);
273         std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
274
275         while (!vecPriority.empty())
276         {
277             // Take highest priority transaction off the priority queue:
278             double dPriority = vecPriority.front().get<0>();
279             double dFeePerKb = vecPriority.front().get<1>();
280             CTransaction& tx = *(vecPriority.front().get<2>());
281
282             std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer);
283             vecPriority.pop_back();
284
285             // Size limits
286             unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
287             if (nBlockSize + nTxSize >= nBlockMaxSize)
288                 continue;
289
290             // Legacy limits on sigOps:
291             unsigned int nTxSigOps = GetLegacySigOpCount(tx);
292             if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
293                 continue;
294
295             // Skip free transactions if we're past the minimum block size:
296             if (fSortedByFee && (dFeePerKb < CTransaction::nMinTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
297                 continue;
298
299             // Prioritize by fee once past the priority size or we run out of high-priority
300             // transactions:
301             if (!fSortedByFee &&
302                 ((nBlockSize + nTxSize >= nBlockPrioritySize) || !AllowFree(dPriority)))
303             {
304                 fSortedByFee = true;
305                 comparer = TxPriorityCompare(fSortedByFee);
306                 std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
307             }
308
309             if (!view.HaveInputs(tx))
310                 continue;
311
312             int64 nTxFees = view.GetValueIn(tx)-GetValueOut(tx);
313
314             nTxSigOps += GetP2SHSigOpCount(tx, view);
315             if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
316                 continue;
317
318             CValidationState state;
319             if (!CheckInputs(tx, state, view, true, SCRIPT_VERIFY_P2SH))
320                 continue;
321
322             CTxUndo txundo;
323             uint256 hash = tx.GetHash();
324             UpdateCoins(tx, state, view, txundo, pindexPrev->nHeight+1, hash);
325
326             // Added
327             pblock->vtx.push_back(tx);
328             pblocktemplate->vTxFees.push_back(nTxFees);
329             pblocktemplate->vTxSigOps.push_back(nTxSigOps);
330             nBlockSize += nTxSize;
331             ++nBlockTx;
332             nBlockSigOps += nTxSigOps;
333             nFees += nTxFees;
334
335             if (fPrintPriority)
336             {
337                 printf("priority %.1f feeperkb %.1f txid %s\n",
338                        dPriority, dFeePerKb, tx.GetHash().ToString().c_str());
339             }
340
341             // Add transactions that depend on this one to the priority queue
342             if (mapDependers.count(hash))
343             {
344                 BOOST_FOREACH(COrphan* porphan, mapDependers[hash])
345                 {
346                     if (!porphan->setDependsOn.empty())
347                     {
348                         porphan->setDependsOn.erase(hash);
349                         if (porphan->setDependsOn.empty())
350                         {
351                             vecPriority.push_back(TxPriority(porphan->dPriority, porphan->dFeePerKb, porphan->ptx));
352                             std::push_heap(vecPriority.begin(), vecPriority.end(), comparer);
353                         }
354                     }
355                 }
356             }
357         }
358
359         nLastBlockTx = nBlockTx;
360         nLastBlockSize = nBlockSize;
361         printf("CreateNewBlock(): total size %"PRI64u"\n", nBlockSize);
362
363         pblock->vtx[0].vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees);
364         pblocktemplate->vTxFees[0] = -nFees;
365
366         // Fill in header
367         pblock->hashPrevBlock  = pindexPrev->GetBlockHash();
368         UpdateTime(*pblock, pindexPrev);
369         pblock->nBits          = GetNextWorkRequired(pindexPrev, pblock);
370         pblock->nNonce         = 0;
371         pblock->vtx[0].vin[0].scriptSig = CScript() << OP_0 << OP_0;
372         pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
373
374         CBlockIndex indexDummy(*pblock);
375         indexDummy.pprev = pindexPrev;
376         indexDummy.nHeight = pindexPrev->nHeight + 1;
377         CCoinsViewCache viewNew(*pcoinsTip, true);
378         CValidationState state;
379         if (!ConnectBlock(*pblock, state, &indexDummy, viewNew, true))
380             throw std::runtime_error("CreateNewBlock() : ConnectBlock failed");
381     }
382
383     return pblocktemplate.release();
384 }
385
386
387 void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce)
388 {
389     // Update nExtraNonce
390     static uint256 hashPrevBlock;
391     if (hashPrevBlock != pblock->hashPrevBlock)
392     {
393         nExtraNonce = 0;
394         hashPrevBlock = pblock->hashPrevBlock;
395     }
396     ++nExtraNonce;
397     unsigned int nHeight = pindexPrev->nHeight+1; // Height first in coinbase required for block.version=2
398     pblock->vtx[0].vin[0].scriptSig = (CScript() << nHeight << CBigNum(nExtraNonce)) + COINBASE_FLAGS;
399     assert(pblock->vtx[0].vin[0].scriptSig.size() <= 100);
400
401     pblock->hashMerkleRoot = pblock->BuildMerkleTree();
402 }
403
404
405 void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1)
406 {
407     //
408     // Pre-build hash buffers
409     //
410     struct
411     {
412         struct unnamed2
413         {
414             int nVersion;
415             uint256 hashPrevBlock;
416             uint256 hashMerkleRoot;
417             unsigned int nTime;
418             unsigned int nBits;
419             unsigned int nNonce;
420         }
421         block;
422         unsigned char pchPadding0[64];
423         uint256 hash1;
424         unsigned char pchPadding1[64];
425     }
426     tmp;
427     memset(&tmp, 0, sizeof(tmp));
428
429     tmp.block.nVersion       = pblock->nVersion;
430     tmp.block.hashPrevBlock  = pblock->hashPrevBlock;
431     tmp.block.hashMerkleRoot = pblock->hashMerkleRoot;
432     tmp.block.nTime          = pblock->nTime;
433     tmp.block.nBits          = pblock->nBits;
434     tmp.block.nNonce         = pblock->nNonce;
435
436     FormatHashBlocks(&tmp.block, sizeof(tmp.block));
437     FormatHashBlocks(&tmp.hash1, sizeof(tmp.hash1));
438
439     // Byte swap all the input buffer
440     for (unsigned int i = 0; i < sizeof(tmp)/4; i++)
441         ((unsigned int*)&tmp)[i] = ByteReverse(((unsigned int*)&tmp)[i]);
442
443     // Precalc the first half of the first hash, which stays constant
444     SHA256Transform(pmidstate, &tmp.block, pSHA256InitState);
445
446     memcpy(pdata, &tmp.block, 128);
447     memcpy(phash1, &tmp.hash1, 64);
448 }
449
450
451 bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
452 {
453     uint256 hash = pblock->GetHash();
454     uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
455
456     if (hash > hashTarget)
457         return false;
458
459     //// debug print
460     printf("BitcoinMiner:\n");
461     printf("proof-of-work found  \n  hash: %s  \ntarget: %s\n", hash.GetHex().c_str(), hashTarget.GetHex().c_str());
462     pblock->print();
463     printf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue).c_str());
464
465     // Found a solution
466     {
467         LOCK(cs_main);
468         if (pblock->hashPrevBlock != hashBestChain)
469             return error("BitcoinMiner : generated block is stale");
470
471         // Remove key from key pool
472         reservekey.KeepKey();
473
474         // Track how many getdata requests this block gets
475         {
476             LOCK(wallet.cs_wallet);
477             wallet.mapRequestCount[pblock->GetHash()] = 0;
478         }
479
480         // Process this block the same as if we had received it from another node
481         CValidationState state;
482         if (!ProcessBlock(state, NULL, pblock))
483             return error("BitcoinMiner : ProcessBlock, block not accepted");
484     }
485
486     return true;
487 }
488
489 void static BitcoinMiner(CWallet *pwallet)
490 {
491     printf("BitcoinMiner started\n");
492     SetThreadPriority(THREAD_PRIORITY_LOWEST);
493     RenameThread("bitcoin-miner");
494
495     // Each thread has its own key and counter
496     CReserveKey reservekey(pwallet);
497     unsigned int nExtraNonce = 0;
498
499     try { while (true) {
500         if (Params().NetworkID() != CChainParams::REGTEST) {
501             // Busy-wait for the network to come online so we don't waste time mining
502             // on an obsolete chain. In regtest mode we expect to fly solo.
503             while (vNodes.empty())
504                 MilliSleep(1000);
505         }
506
507         //
508         // Create new block
509         //
510         unsigned int nTransactionsUpdatedLast = nTransactionsUpdated;
511         CBlockIndex* pindexPrev = pindexBest;
512
513         auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlock(reservekey));
514         if (!pblocktemplate.get())
515             return;
516         CBlock *pblock = &pblocktemplate->block;
517         IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
518
519         printf("Running BitcoinMiner with %"PRIszu" transactions in block (%u bytes)\n", pblock->vtx.size(),
520                ::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
521
522         //
523         // Pre-build hash buffers
524         //
525         char pmidstatebuf[32+16]; char* pmidstate = alignup<16>(pmidstatebuf);
526         char pdatabuf[128+16];    char* pdata     = alignup<16>(pdatabuf);
527         char phash1buf[64+16];    char* phash1    = alignup<16>(phash1buf);
528
529         FormatHashBuffers(pblock, pmidstate, pdata, phash1);
530
531         unsigned int& nBlockTime = *(unsigned int*)(pdata + 64 + 4);
532         unsigned int& nBlockBits = *(unsigned int*)(pdata + 64 + 8);
533         unsigned int& nBlockNonce = *(unsigned int*)(pdata + 64 + 12);
534
535
536         //
537         // Search
538         //
539         int64 nStart = GetTime();
540         uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
541         uint256 hashbuf[2];
542         uint256& hash = *alignup<16>(hashbuf);
543         while (true)
544         {
545             unsigned int nHashesDone = 0;
546             unsigned int nNonceFound;
547
548             // Crypto++ SHA256
549             nNonceFound = ScanHash_CryptoPP(pmidstate, pdata + 64, phash1,
550                                             (char*)&hash, nHashesDone);
551
552             // Check if something found
553             if (nNonceFound != (unsigned int) -1)
554             {
555                 for (unsigned int i = 0; i < sizeof(hash)/4; i++)
556                     ((unsigned int*)&hash)[i] = ByteReverse(((unsigned int*)&hash)[i]);
557
558                 if (hash <= hashTarget)
559                 {
560                     // Found a solution
561                     pblock->nNonce = ByteReverse(nNonceFound);
562                     assert(hash == pblock->GetHash());
563
564                     SetThreadPriority(THREAD_PRIORITY_NORMAL);
565                     CheckWork(pblock, *pwallet, reservekey);
566                     SetThreadPriority(THREAD_PRIORITY_LOWEST);
567
568                     // In regression test mode, stop mining after a block is found. This
569                     // allows developers to controllably generate a block on demand.
570                     if (Params().NetworkID() == CChainParams::REGTEST)
571                         throw boost::thread_interrupted();
572
573                     break;
574                 }
575             }
576
577             // Meter hashes/sec
578             static int64 nHashCounter;
579             if (nHPSTimerStart == 0)
580             {
581                 nHPSTimerStart = GetTimeMillis();
582                 nHashCounter = 0;
583             }
584             else
585                 nHashCounter += nHashesDone;
586             if (GetTimeMillis() - nHPSTimerStart > 4000)
587             {
588                 static CCriticalSection cs;
589                 {
590                     LOCK(cs);
591                     if (GetTimeMillis() - nHPSTimerStart > 4000)
592                     {
593                         dHashesPerSec = 1000.0 * nHashCounter / (GetTimeMillis() - nHPSTimerStart);
594                         nHPSTimerStart = GetTimeMillis();
595                         nHashCounter = 0;
596                         static int64 nLogTime;
597                         if (GetTime() - nLogTime > 30 * 60)
598                         {
599                             nLogTime = GetTime();
600                             printf("hashmeter %6.0f khash/s\n", dHashesPerSec/1000.0);
601                         }
602                     }
603                 }
604             }
605
606             // Check for stop or if block needs to be rebuilt
607             boost::this_thread::interruption_point();
608             if (vNodes.empty() && Params().NetworkID() != CChainParams::REGTEST)
609                 break;
610             if (nBlockNonce >= 0xffff0000)
611                 break;
612             if (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60)
613                 break;
614             if (pindexPrev != pindexBest)
615                 break;
616
617             // Update nTime every few seconds
618             UpdateTime(*pblock, pindexPrev);
619             nBlockTime = ByteReverse(pblock->nTime);
620             if (TestNet())
621             {
622                 // Changing pblock->nTime can change work required on testnet:
623                 nBlockBits = ByteReverse(pblock->nBits);
624                 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
625             }
626         }
627     } }
628     catch (boost::thread_interrupted)
629     {
630         printf("BitcoinMiner terminated\n");
631         throw;
632     }
633 }
634
635 void GenerateBitcoins(bool fGenerate, CWallet* pwallet)
636 {
637     static boost::thread_group* minerThreads = NULL;
638
639     int nThreads = GetArg("-genproclimit", -1);
640     if (nThreads < 0) {
641         if (Params().NetworkID() == CChainParams::REGTEST)
642             nThreads = 1;
643         else
644             nThreads = boost::thread::hardware_concurrency();
645     }
646
647     if (minerThreads != NULL)
648     {
649         minerThreads->interrupt_all();
650         delete minerThreads;
651         minerThreads = NULL;
652     }
653
654     if (nThreads == 0 || !fGenerate)
655         return;
656
657     minerThreads = new boost::thread_group();
658     for (int i = 0; i < nThreads; i++)
659         minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet));
660 }
661
662
663
This page took 0.066481 seconds and 4 git commands to generate.