]> Git Repo - VerusCoin.git/blame - src/miner.cpp
TestBlockValidity function for CBlock proposals (used by CreateNewBlock)
[VerusCoin.git] / src / miner.cpp
CommitLineData
d247a5d1 1// Copyright (c) 2009-2010 Satoshi Nakamoto
57702541 2// Copyright (c) 2009-2014 The Bitcoin developers
d247a5d1
JG
3// Distributed under the MIT/X11 software license, see the accompanying
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
d247a5d1 6#include "miner.h"
51ed9ec9 7
eda37330 8#include "amount.h"
99f41b9c 9#include "core/block.h"
4a3587d8 10#include "core/transaction.h"
85aab2a0 11#include "hash.h"
d247a5d1 12#include "main.h"
51ed9ec9 13#include "net.h"
df852d2b 14#include "pow.h"
ad49c256
WL
15#include "util.h"
16#include "utilmoneystr.h"
df840de5 17#ifdef ENABLE_WALLET
51ed9ec9 18#include "wallet.h"
df840de5 19#endif
09eb201b 20
ad49c256 21#include <boost/thread.hpp>
a3c26c2e 22#include <boost/tuple/tuple.hpp>
ad49c256 23
09eb201b 24using namespace std;
7b4737c8 25
d247a5d1
JG
26//////////////////////////////////////////////////////////////////////////////
27//
28// BitcoinMiner
29//
30
c6cb21d1
GA
31//
32// Unconfirmed transactions in the memory pool often depend on other
33// transactions in the memory pool. When we select transactions from the
34// pool, we select by highest priority or fee rate, so we might consider
35// transactions that depend on transactions that aren't yet in the block.
36// The COrphan class keeps track of these 'temporary orphans' while
37// CreateBlock is figuring out which transactions to include.
38//
d247a5d1
JG
39class COrphan
40{
41public:
4d707d51 42 const CTransaction* ptx;
d247a5d1 43 set<uint256> setDependsOn;
c6cb21d1 44 CFeeRate feeRate;
02bec4b2 45 double dPriority;
d247a5d1 46
c6cb21d1 47 COrphan(const CTransaction* ptxIn) : ptx(ptxIn), feeRate(0), dPriority(0)
d247a5d1 48 {
d247a5d1 49 }
d247a5d1
JG
50};
51
51ed9ec9
BD
52uint64_t nLastBlockTx = 0;
53uint64_t nLastBlockSize = 0;
d247a5d1 54
c6cb21d1
GA
55// We want to sort transactions by priority and fee rate, so:
56typedef boost::tuple<double, CFeeRate, const CTransaction*> TxPriority;
d247a5d1
JG
57class TxPriorityCompare
58{
59 bool byFee;
0655fac0 60
d247a5d1
JG
61public:
62 TxPriorityCompare(bool _byFee) : byFee(_byFee) { }
0655fac0 63
d247a5d1
JG
64 bool operator()(const TxPriority& a, const TxPriority& b)
65 {
66 if (byFee)
67 {
68 if (a.get<1>() == b.get<1>())
69 return a.get<0>() < b.get<0>();
70 return a.get<1>() < b.get<1>();
71 }
72 else
73 {
74 if (a.get<0>() == b.get<0>())
75 return a.get<1>() < b.get<1>();
76 return a.get<0>() < b.get<0>();
77 }
78 }
79};
80
f1dbed92 81CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
d247a5d1
JG
82{
83 // Create new block
84 auto_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate());
85 if(!pblocktemplate.get())
86 return NULL;
87 CBlock *pblock = &pblocktemplate->block; // pointer for convenience
88
dbca89b7
GA
89 // -regtest only: allow overriding block.nVersion with
90 // -blockversion=N to test forking scenarios
91 if (Params().MineBlocksOnDemand())
92 pblock->nVersion = GetArg("-blockversion", pblock->nVersion);
93
d247a5d1 94 // Create coinbase tx
4949004d 95 CMutableTransaction txNew;
d247a5d1
JG
96 txNew.vin.resize(1);
97 txNew.vin[0].prevout.SetNull();
98 txNew.vout.resize(1);
7e170189 99 txNew.vout[0].scriptPubKey = scriptPubKeyIn;
d247a5d1 100
4949004d
PW
101 // Add dummy coinbase tx as first transaction
102 pblock->vtx.push_back(CTransaction());
d247a5d1
JG
103 pblocktemplate->vTxFees.push_back(-1); // updated at end
104 pblocktemplate->vTxSigOps.push_back(-1); // updated at end
105
106 // Largest block you're willing to create:
ad898b40 107 unsigned int nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE);
d247a5d1
JG
108 // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity:
109 nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize));
110
111 // How much of the block should be dedicated to high-priority transactions,
112 // included regardless of the fees they pay
113 unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", DEFAULT_BLOCK_PRIORITY_SIZE);
114 nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize);
115
116 // Minimum block size you want to create; block will be filled with free transactions
117 // until there are no more or the block reaches this size:
037b4f14 118 unsigned int nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE);
d247a5d1
JG
119 nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize);
120
121 // Collect memory pool transactions into the block
a372168e 122 CAmount nFees = 0;
0655fac0 123
d247a5d1
JG
124 {
125 LOCK2(cs_main, mempool.cs);
4c6d41b8 126 CBlockIndex* pindexPrev = chainActive.Tip();
7c70438d 127 CCoinsViewCache view(pcoinsTip);
d247a5d1
JG
128
129 // Priority order to process transactions
130 list<COrphan> vOrphan; // list memory doesn't move
131 map<uint256, vector<COrphan*> > mapDependers;
132 bool fPrintPriority = GetBoolArg("-printpriority", false);
133
134 // This vector will be sorted into a priority queue:
135 vector<TxPriority> vecPriority;
136 vecPriority.reserve(mempool.mapTx.size());
4d707d51
GA
137 for (map<uint256, CTxMemPoolEntry>::iterator mi = mempool.mapTx.begin();
138 mi != mempool.mapTx.end(); ++mi)
d247a5d1 139 {
4d707d51 140 const CTransaction& tx = mi->second.GetTx();
665bdd3b 141 if (tx.IsCoinBase() || !IsFinalTx(tx, pindexPrev->nHeight + 1))
d247a5d1
JG
142 continue;
143
144 COrphan* porphan = NULL;
145 double dPriority = 0;
a372168e 146 CAmount nTotalIn = 0;
d247a5d1
JG
147 bool fMissingInputs = false;
148 BOOST_FOREACH(const CTxIn& txin, tx.vin)
149 {
150 // Read prev transaction
151 if (!view.HaveCoins(txin.prevout.hash))
152 {
153 // This should never happen; all transactions in the memory
154 // pool should connect to either transactions in the chain
155 // or other transactions in the memory pool.
156 if (!mempool.mapTx.count(txin.prevout.hash))
157 {
881a85a2 158 LogPrintf("ERROR: mempool transaction missing input\n");
d247a5d1
JG
159 if (fDebug) assert("mempool transaction missing input" == 0);
160 fMissingInputs = true;
161 if (porphan)
162 vOrphan.pop_back();
163 break;
164 }
165
166 // Has to wait for dependencies
167 if (!porphan)
168 {
169 // Use list for automatic deletion
170 vOrphan.push_back(COrphan(&tx));
171 porphan = &vOrphan.back();
172 }
173 mapDependers[txin.prevout.hash].push_back(porphan);
174 porphan->setDependsOn.insert(txin.prevout.hash);
4d707d51 175 nTotalIn += mempool.mapTx[txin.prevout.hash].GetTx().vout[txin.prevout.n].nValue;
d247a5d1
JG
176 continue;
177 }
629d75fa
PW
178 const CCoins* coins = view.AccessCoins(txin.prevout.hash);
179 assert(coins);
d247a5d1 180
a372168e 181 CAmount nValueIn = coins->vout[txin.prevout.n].nValue;
d247a5d1
JG
182 nTotalIn += nValueIn;
183
629d75fa 184 int nConf = pindexPrev->nHeight - coins->nHeight + 1;
d247a5d1
JG
185
186 dPriority += (double)nValueIn * nConf;
187 }
188 if (fMissingInputs) continue;
189
d6eb2599 190 // Priority is sum(valuein * age) / modified_txsize
d247a5d1 191 unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
4d707d51 192 dPriority = tx.ComputePriority(dPriority, nTxSize);
d247a5d1 193
2a72d459
LD
194 uint256 hash = tx.GetHash();
195 mempool.ApplyDeltas(hash, dPriority, nTotalIn);
196
c6cb21d1 197 CFeeRate feeRate(nTotalIn-tx.GetValueOut(), nTxSize);
d247a5d1
JG
198
199 if (porphan)
200 {
201 porphan->dPriority = dPriority;
c6cb21d1 202 porphan->feeRate = feeRate;
d247a5d1
JG
203 }
204 else
c6cb21d1 205 vecPriority.push_back(TxPriority(dPriority, feeRate, &mi->second.GetTx()));
d247a5d1
JG
206 }
207
208 // Collect transactions into block
51ed9ec9
BD
209 uint64_t nBlockSize = 1000;
210 uint64_t nBlockTx = 0;
d247a5d1
JG
211 int nBlockSigOps = 100;
212 bool fSortedByFee = (nBlockPrioritySize <= 0);
213
214 TxPriorityCompare comparer(fSortedByFee);
215 std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
216
217 while (!vecPriority.empty())
218 {
219 // Take highest priority transaction off the priority queue:
220 double dPriority = vecPriority.front().get<0>();
c6cb21d1 221 CFeeRate feeRate = vecPriority.front().get<1>();
4d707d51 222 const CTransaction& tx = *(vecPriority.front().get<2>());
d247a5d1
JG
223
224 std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer);
225 vecPriority.pop_back();
226
227 // Size limits
228 unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
229 if (nBlockSize + nTxSize >= nBlockMaxSize)
230 continue;
231
232 // Legacy limits on sigOps:
233 unsigned int nTxSigOps = GetLegacySigOpCount(tx);
234 if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
235 continue;
236
237 // Skip free transactions if we're past the minimum block size:
2a72d459
LD
238 const uint256& hash = tx.GetHash();
239 double dPriorityDelta = 0;
a372168e 240 CAmount nFeeDelta = 0;
2a72d459 241 mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta);
13fc83c7 242 if (fSortedByFee && (dPriorityDelta <= 0) && (nFeeDelta <= 0) && (feeRate < ::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
d247a5d1
JG
243 continue;
244
2a72d459 245 // Prioritise by fee once past the priority size or we run out of high-priority
d247a5d1
JG
246 // transactions:
247 if (!fSortedByFee &&
248 ((nBlockSize + nTxSize >= nBlockPrioritySize) || !AllowFree(dPriority)))
249 {
250 fSortedByFee = true;
251 comparer = TxPriorityCompare(fSortedByFee);
252 std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
253 }
254
255 if (!view.HaveInputs(tx))
256 continue;
257
a372168e 258 CAmount nTxFees = view.GetValueIn(tx)-tx.GetValueOut();
d247a5d1
JG
259
260 nTxSigOps += GetP2SHSigOpCount(tx, view);
261 if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
262 continue;
263
68f7d1d7
PT
264 // Note that flags: we don't want to set mempool/IsStandard()
265 // policy here, but we still have to ensure that the block we
266 // create only contains transactions that are valid in new blocks.
d247a5d1 267 CValidationState state;
e790c370 268 if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true))
d247a5d1
JG
269 continue;
270
271 CTxUndo txundo;
d38da59b 272 UpdateCoins(tx, state, view, txundo, pindexPrev->nHeight+1);
d247a5d1
JG
273
274 // Added
275 pblock->vtx.push_back(tx);
276 pblocktemplate->vTxFees.push_back(nTxFees);
277 pblocktemplate->vTxSigOps.push_back(nTxSigOps);
278 nBlockSize += nTxSize;
279 ++nBlockTx;
280 nBlockSigOps += nTxSigOps;
281 nFees += nTxFees;
282
283 if (fPrintPriority)
284 {
c6cb21d1 285 LogPrintf("priority %.1f fee %s txid %s\n",
0655fac0 286 dPriority, feeRate.ToString(), tx.GetHash().ToString());
d247a5d1
JG
287 }
288
289 // Add transactions that depend on this one to the priority queue
290 if (mapDependers.count(hash))
291 {
292 BOOST_FOREACH(COrphan* porphan, mapDependers[hash])
293 {
294 if (!porphan->setDependsOn.empty())
295 {
296 porphan->setDependsOn.erase(hash);
297 if (porphan->setDependsOn.empty())
298 {
c6cb21d1 299 vecPriority.push_back(TxPriority(porphan->dPriority, porphan->feeRate, porphan->ptx));
d247a5d1
JG
300 std::push_heap(vecPriority.begin(), vecPriority.end(), comparer);
301 }
302 }
303 }
304 }
305 }
306
307 nLastBlockTx = nBlockTx;
308 nLastBlockSize = nBlockSize;
f48742c2 309 LogPrintf("CreateNewBlock(): total size %u\n", nBlockSize);
d247a5d1 310
4949004d
PW
311 // Compute final coinbase transaction.
312 txNew.vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees);
313 txNew.vin[0].scriptSig = CScript() << OP_0 << OP_0;
314 pblock->vtx[0] = txNew;
d247a5d1
JG
315 pblocktemplate->vTxFees[0] = -nFees;
316
317 // Fill in header
318 pblock->hashPrevBlock = pindexPrev->GetBlockHash();
c2c02f3f 319 UpdateTime(pblock, pindexPrev);
d247a5d1
JG
320 pblock->nBits = GetNextWorkRequired(pindexPrev, pblock);
321 pblock->nNonce = 0;
d247a5d1
JG
322 pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
323
d247a5d1 324 CValidationState state;
df08a626
LD
325 if (!TestBlockValidity(state, *pblock, pindexPrev, false, false))
326 throw std::runtime_error("CreateNewBlock() : TestBlockValidity failed");
d247a5d1
JG
327 }
328
329 return pblocktemplate.release();
330}
331
d247a5d1
JG
332void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce)
333{
334 // Update nExtraNonce
335 static uint256 hashPrevBlock;
336 if (hashPrevBlock != pblock->hashPrevBlock)
337 {
338 nExtraNonce = 0;
339 hashPrevBlock = pblock->hashPrevBlock;
340 }
341 ++nExtraNonce;
342 unsigned int nHeight = pindexPrev->nHeight+1; // Height first in coinbase required for block.version=2
4949004d
PW
343 CMutableTransaction txCoinbase(pblock->vtx[0]);
344 txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
345 assert(txCoinbase.vin[0].scriptSig.size() <= 100);
d247a5d1 346
4949004d 347 pblock->vtx[0] = txCoinbase;
d247a5d1
JG
348 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
349}
350
4a85e067 351#ifdef ENABLE_WALLET
acfa0333
WL
352//////////////////////////////////////////////////////////////////////////////
353//
354// Internal miner
355//
356double dHashesPerSec = 0.0;
357int64_t nHPSTimerStart = 0;
358
359//
360// ScanHash scans nonces looking for a hash with at least some zero bits.
85aab2a0
PW
361// The nonce is usually preserved between calls, but periodically or if the
362// nonce is 0xffff0000 or above, the block is rebuilt and nNonce starts over at
363// zero.
acfa0333 364//
0655fac0
PK
365bool static ScanHash(const CBlockHeader *pblock, uint32_t& nNonce, uint256 *phash)
366{
85aab2a0
PW
367 // Write the first 76 bytes of the block header to a double-SHA256 state.
368 CHash256 hasher;
369 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
370 ss << *pblock;
371 assert(ss.size() == 80);
372 hasher.Write((unsigned char*)&ss[0], 76);
373
0655fac0 374 while (true) {
acfa0333 375 nNonce++;
85aab2a0
PW
376
377 // Write the last 4 bytes of the block header (the nonce) to a copy of
378 // the double-SHA256 state, and compute the result.
379 CHash256(hasher).Write((unsigned char*)&nNonce, 4).Finalize((unsigned char*)phash);
acfa0333
WL
380
381 // Return the nonce if the hash has at least some zero bits,
382 // caller will check if it has enough to reach the target
85aab2a0
PW
383 if (((uint16_t*)phash)[15] == 0)
384 return true;
acfa0333
WL
385
386 // If nothing found after trying for a while, return -1
387 if ((nNonce & 0xffff) == 0)
85aab2a0 388 return false;
acfa0333
WL
389 if ((nNonce & 0xfff) == 0)
390 boost::this_thread::interruption_point();
391 }
392}
393
394CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey)
395{
396 CPubKey pubkey;
397 if (!reservekey.GetReservedKey(pubkey))
398 return NULL;
399
e9ca4280 400 CScript scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
acfa0333
WL
401 return CreateNewBlock(scriptPubKey);
402}
403
f0c2915f 404bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
d247a5d1 405{
81212588 406 LogPrintf("%s\n", pblock->ToString());
7d9d134b 407 LogPrintf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue));
d247a5d1
JG
408
409 // Found a solution
410 {
411 LOCK(cs_main);
4c6d41b8 412 if (pblock->hashPrevBlock != chainActive.Tip()->GetBlockHash())
d247a5d1 413 return error("BitcoinMiner : generated block is stale");
18e72167 414 }
d247a5d1 415
18e72167
PW
416 // Remove key from key pool
417 reservekey.KeepKey();
d247a5d1 418
18e72167
PW
419 // Track how many getdata requests this block gets
420 {
421 LOCK(wallet.cs_wallet);
422 wallet.mapRequestCount[pblock->GetHash()] = 0;
d247a5d1
JG
423 }
424
18e72167
PW
425 // Process this block the same as if we had received it from another node
426 CValidationState state;
1bea2bbd
LD
427 if (!ProcessNewBlock(state, NULL, pblock))
428 return error("BitcoinMiner : ProcessNewBlock, block not accepted");
18e72167 429
d247a5d1
JG
430 return true;
431}
432
433void static BitcoinMiner(CWallet *pwallet)
434{
881a85a2 435 LogPrintf("BitcoinMiner started\n");
d247a5d1
JG
436 SetThreadPriority(THREAD_PRIORITY_LOWEST);
437 RenameThread("bitcoin-miner");
438
439 // Each thread has its own key and counter
440 CReserveKey reservekey(pwallet);
441 unsigned int nExtraNonce = 0;
442
0655fac0
PK
443 try {
444 while (true) {
445 if (Params().MiningRequiresPeers()) {
446 // Busy-wait for the network to come online so we don't waste time mining
447 // on an obsolete chain. In regtest mode we expect to fly solo.
448 while (vNodes.empty())
449 MilliSleep(1000);
450 }
d247a5d1 451
0655fac0
PK
452 //
453 // Create new block
454 //
455 unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
456 CBlockIndex* pindexPrev = chainActive.Tip();
457
458 auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
459 if (!pblocktemplate.get())
6c37f7fd
WL
460 {
461 LogPrintf("Error in BitcoinMiner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n");
0655fac0 462 return;
6c37f7fd 463 }
0655fac0
PK
464 CBlock *pblock = &pblocktemplate->block;
465 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
466
467 LogPrintf("Running BitcoinMiner with %u transactions in block (%u bytes)\n", pblock->vtx.size(),
468 ::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
469
470 //
471 // Search
472 //
473 int64_t nStart = GetTime();
474 uint256 hashTarget = uint256().SetCompact(pblock->nBits);
475 uint256 hash;
476 uint32_t nNonce = 0;
477 uint32_t nOldNonce = 0;
478 while (true) {
479 bool fFound = ScanHash(pblock, nNonce, &hash);
480 uint32_t nHashesDone = nNonce - nOldNonce;
481 nOldNonce = nNonce;
482
483 // Check if something found
484 if (fFound)
d247a5d1 485 {
0655fac0
PK
486 if (hash <= hashTarget)
487 {
488 // Found a solution
489 pblock->nNonce = nNonce;
490 assert(hash == pblock->GetHash());
d247a5d1 491
0655fac0 492 SetThreadPriority(THREAD_PRIORITY_NORMAL);
f0c2915f 493 LogPrintf("BitcoinMiner:\n");
494 LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex(), hashTarget.GetHex());
495 ProcessBlockFound(pblock, *pwallet, reservekey);
0655fac0 496 SetThreadPriority(THREAD_PRIORITY_LOWEST);
d247a5d1 497
0655fac0
PK
498 // In regression test mode, stop mining after a block is found.
499 if (Params().MineBlocksOnDemand())
500 throw boost::thread_interrupted();
d247a5d1 501
0655fac0
PK
502 break;
503 }
d247a5d1 504 }
d247a5d1 505
0655fac0
PK
506 // Meter hashes/sec
507 static int64_t nHashCounter;
508 if (nHPSTimerStart == 0)
d247a5d1 509 {
0655fac0
PK
510 nHPSTimerStart = GetTimeMillis();
511 nHashCounter = 0;
512 }
513 else
514 nHashCounter += nHashesDone;
515 if (GetTimeMillis() - nHPSTimerStart > 4000)
516 {
517 static CCriticalSection cs;
d247a5d1 518 {
0655fac0
PK
519 LOCK(cs);
520 if (GetTimeMillis() - nHPSTimerStart > 4000)
d247a5d1 521 {
0655fac0
PK
522 dHashesPerSec = 1000.0 * nHashCounter / (GetTimeMillis() - nHPSTimerStart);
523 nHPSTimerStart = GetTimeMillis();
524 nHashCounter = 0;
525 static int64_t nLogTime;
526 if (GetTime() - nLogTime > 30 * 60)
527 {
528 nLogTime = GetTime();
529 LogPrintf("hashmeter %6.0f khash/s\n", dHashesPerSec/1000.0);
530 }
d247a5d1
JG
531 }
532 }
533 }
d247a5d1 534
0655fac0
PK
535 // Check for stop or if block needs to be rebuilt
536 boost::this_thread::interruption_point();
537 // Regtest mode doesn't require peers
538 if (vNodes.empty() && Params().MiningRequiresPeers())
539 break;
540 if (nNonce >= 0xffff0000)
541 break;
542 if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
543 break;
544 if (pindexPrev != chainActive.Tip())
545 break;
546
547 // Update nTime every few seconds
c2c02f3f 548 UpdateTime(pblock, pindexPrev);
0655fac0
PK
549 if (Params().AllowMinDifficultyBlocks())
550 {
551 // Changing pblock->nTime can change work required on testnet:
552 hashTarget.SetCompact(pblock->nBits);
553 }
d247a5d1
JG
554 }
555 }
0655fac0 556 }
d247a5d1
JG
557 catch (boost::thread_interrupted)
558 {
881a85a2 559 LogPrintf("BitcoinMiner terminated\n");
d247a5d1
JG
560 throw;
561 }
562}
563
c8b74258 564void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads)
d247a5d1
JG
565{
566 static boost::thread_group* minerThreads = NULL;
567
d247a5d1 568 if (nThreads < 0) {
2595b9ac 569 // In regtest threads defaults to 1
570 if (Params().DefaultMinerThreads())
571 nThreads = Params().DefaultMinerThreads();
d247a5d1
JG
572 else
573 nThreads = boost::thread::hardware_concurrency();
574 }
575
576 if (minerThreads != NULL)
577 {
578 minerThreads->interrupt_all();
579 delete minerThreads;
580 minerThreads = NULL;
581 }
582
583 if (nThreads == 0 || !fGenerate)
584 return;
585
586 minerThreads = new boost::thread_group();
587 for (int i = 0; i < nThreads; i++)
588 minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet));
589}
590
0655fac0 591#endif // ENABLE_WALLET
This page took 0.207434 seconds and 4 git commands to generate.