Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

miner.cpp 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  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. #include "miner.h"
  6. #include "amount.h"
  7. #include "chain.h"
  8. #include "chainparams.h"
  9. #include "coins.h"
  10. #include "consensus/consensus.h"
  11. #include "consensus/merkle.h"
  12. #include "consensus/validation.h"
  13. #include "hash.h"
  14. #include "main.h"
  15. #include "net.h"
  16. #include "policy/policy.h"
  17. #include "pow.h"
  18. #include "primitives/transaction.h"
  19. #include "script/standard.h"
  20. #include "timedata.h"
  21. #include "txmempool.h"
  22. #include "util.h"
  23. #include "utilmoneystr.h"
  24. #include "validationinterface.h"
  25. #include <boost/thread.hpp>
  26. #include <boost/tuple/tuple.hpp>
  27. using namespace std;
  28. //////////////////////////////////////////////////////////////////////////////
  29. //
  30. // BitcoinMiner
  31. //
  32. //
  33. // Unconfirmed transactions in the memory pool often depend on other
  34. // transactions in the memory pool. When we select transactions from the
  35. // pool, we select by highest priority or fee rate, so we might consider
  36. // transactions that depend on transactions that aren't yet in the block.
  37. // The COrphan class keeps track of these 'temporary orphans' while
  38. // CreateBlock is figuring out which transactions to include.
  39. //
  40. class COrphan
  41. {
  42. public:
  43. const CTransaction* ptx;
  44. set<uint256> setDependsOn;
  45. CFeeRate feeRate;
  46. double dPriority;
  47. COrphan(const CTransaction* ptxIn) : ptx(ptxIn), feeRate(0), dPriority(0)
  48. {
  49. }
  50. };
  51. uint64_t nLastBlockTx = 0;
  52. uint64_t nLastBlockSize = 0;
  53. // We want to sort transactions by priority and fee rate, so:
  54. typedef boost::tuple<double, CFeeRate, const CTransaction*> TxPriority;
  55. class TxPriorityCompare
  56. {
  57. bool byFee;
  58. public:
  59. TxPriorityCompare(bool _byFee) : byFee(_byFee) { }
  60. bool operator()(const TxPriority& a, const TxPriority& b)
  61. {
  62. if (byFee)
  63. {
  64. if (a.get<1>() == b.get<1>())
  65. return a.get<0>() < b.get<0>();
  66. return a.get<1>() < b.get<1>();
  67. }
  68. else
  69. {
  70. if (a.get<0>() == b.get<0>())
  71. return a.get<1>() < b.get<1>();
  72. return a.get<0>() < b.get<0>();
  73. }
  74. }
  75. };
  76. int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
  77. {
  78. int64_t nOldTime = pblock->nTime;
  79. int64_t nNewTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
  80. if (nOldTime < nNewTime)
  81. pblock->nTime = nNewTime;
  82. // Updating time can change work required on testnet:
  83. if (consensusParams.fPowAllowMinDifficultyBlocks)
  84. pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
  85. return nNewTime - nOldTime;
  86. }
  87. CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& scriptPubKeyIn)
  88. {
  89. // Create new block
  90. auto_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate());
  91. if(!pblocktemplate.get())
  92. return NULL;
  93. CBlock *pblock = &pblocktemplate->block; // pointer for convenience
  94. // -regtest only: allow overriding block.nVersion with
  95. // -blockversion=N to test forking scenarios
  96. if (chainparams.MineBlocksOnDemand())
  97. pblock->nVersion = GetArg("-blockversion", pblock->nVersion);
  98. // Create coinbase tx
  99. CMutableTransaction txNew;
  100. txNew.vin.resize(1);
  101. txNew.vin[0].prevout.SetNull();
  102. txNew.vout.resize(1);
  103. txNew.vout[0].scriptPubKey = scriptPubKeyIn;
  104. // Add dummy coinbase tx as first transaction
  105. pblock->vtx.push_back(CTransaction());
  106. pblocktemplate->vTxFees.push_back(-1); // updated at end
  107. pblocktemplate->vTxSigOps.push_back(-1); // updated at end
  108. // Largest block you're willing to create:
  109. unsigned int nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE);
  110. // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity:
  111. nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize));
  112. // How much of the block should be dedicated to high-priority transactions,
  113. // included regardless of the fees they pay
  114. unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", DEFAULT_BLOCK_PRIORITY_SIZE);
  115. nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize);
  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:
  118. unsigned int nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE);
  119. nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize);
  120. // Collect memory pool transactions into the block
  121. CAmount nFees = 0;
  122. {
  123. LOCK2(cs_main, mempool.cs);
  124. CBlockIndex* pindexPrev = chainActive.Tip();
  125. const int nHeight = pindexPrev->nHeight + 1;
  126. pblock->nTime = GetAdjustedTime();
  127. const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast();
  128. CCoinsViewCache view(pcoinsTip);
  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. // This vector will be sorted into a priority queue:
  134. vector<TxPriority> vecPriority;
  135. vecPriority.reserve(mempool.mapTx.size());
  136. for (CTxMemPool::indexed_transaction_set::iterator mi = mempool.mapTx.begin();
  137. mi != mempool.mapTx.end(); ++mi)
  138. {
  139. const CTransaction& tx = mi->GetTx();
  140. int64_t nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST)
  141. ? nMedianTimePast
  142. : pblock->GetBlockTime();
  143. if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight, nLockTimeCutoff))
  144. continue;
  145. COrphan* porphan = NULL;
  146. double dPriority = 0;
  147. CAmount nTotalIn = 0;
  148. bool fMissingInputs = false;
  149. BOOST_FOREACH(const CTxIn& txin, tx.vin)
  150. {
  151. // Read prev transaction
  152. if (!view.HaveCoins(txin.prevout.hash))
  153. {
  154. // This should never happen; all transactions in the memory
  155. // pool should connect to either transactions in the chain
  156. // or other transactions in the memory pool.
  157. if (!mempool.mapTx.count(txin.prevout.hash))
  158. {
  159. LogPrintf("ERROR: mempool transaction missing input\n");
  160. if (fDebug) assert("mempool transaction missing input" == 0);
  161. fMissingInputs = true;
  162. if (porphan)
  163. vOrphan.pop_back();
  164. break;
  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);
  175. nTotalIn += mempool.mapTx.find(txin.prevout.hash)->GetTx().vout[txin.prevout.n].nValue;
  176. continue;
  177. }
  178. const CCoins* coins = view.AccessCoins(txin.prevout.hash);
  179. assert(coins);
  180. CAmount nValueIn = coins->vout[txin.prevout.n].nValue;
  181. nTotalIn += nValueIn;
  182. int nConf = nHeight - coins->nHeight;
  183. dPriority += (double)nValueIn * nConf;
  184. }
  185. if (fMissingInputs) continue;
  186. // Priority is sum(valuein * age) / modified_txsize
  187. unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
  188. dPriority = tx.ComputePriority(dPriority, nTxSize);
  189. uint256 hash = tx.GetHash();
  190. mempool.ApplyDeltas(hash, dPriority, nTotalIn);
  191. CFeeRate feeRate(nTotalIn-tx.GetValueOut(), nTxSize);
  192. if (porphan)
  193. {
  194. porphan->dPriority = dPriority;
  195. porphan->feeRate = feeRate;
  196. }
  197. else
  198. vecPriority.push_back(TxPriority(dPriority, feeRate, &(mi->GetTx())));
  199. }
  200. // Collect transactions into block
  201. uint64_t nBlockSize = 1000;
  202. uint64_t nBlockTx = 0;
  203. int nBlockSigOps = 100;
  204. bool fSortedByFee = (nBlockPrioritySize <= 0);
  205. TxPriorityCompare comparer(fSortedByFee);
  206. std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
  207. while (!vecPriority.empty())
  208. {
  209. // Take highest priority transaction off the priority queue:
  210. double dPriority = vecPriority.front().get<0>();
  211. CFeeRate feeRate = vecPriority.front().get<1>();
  212. const CTransaction& tx = *(vecPriority.front().get<2>());
  213. std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer);
  214. vecPriority.pop_back();
  215. // Size limits
  216. unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
  217. if (nBlockSize + nTxSize >= nBlockMaxSize)
  218. continue;
  219. // Legacy limits on sigOps:
  220. unsigned int nTxSigOps = GetLegacySigOpCount(tx);
  221. if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
  222. continue;
  223. // Skip free transactions if we're past the minimum block size:
  224. const uint256& hash = tx.GetHash();
  225. double dPriorityDelta = 0;
  226. CAmount nFeeDelta = 0;
  227. mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta);
  228. if (fSortedByFee && (dPriorityDelta <= 0) && (nFeeDelta <= 0) && (feeRate < ::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
  229. continue;
  230. // Prioritise by fee once past the priority size or we run out of high-priority
  231. // transactions:
  232. if (!fSortedByFee &&
  233. ((nBlockSize + nTxSize >= nBlockPrioritySize) || !AllowFree(dPriority)))
  234. {
  235. fSortedByFee = true;
  236. comparer = TxPriorityCompare(fSortedByFee);
  237. std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
  238. }
  239. if (!view.HaveInputs(tx))
  240. continue;
  241. CAmount nTxFees = view.GetValueIn(tx)-tx.GetValueOut();
  242. nTxSigOps += GetP2SHSigOpCount(tx, view);
  243. if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
  244. continue;
  245. // Note that flags: we don't want to set mempool/IsStandard()
  246. // policy here, but we still have to ensure that the block we
  247. // create only contains transactions that are valid in new blocks.
  248. CValidationState state;
  249. if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true))
  250. continue;
  251. UpdateCoins(tx, state, view, nHeight);
  252. // Added
  253. pblock->vtx.push_back(tx);
  254. pblocktemplate->vTxFees.push_back(nTxFees);
  255. pblocktemplate->vTxSigOps.push_back(nTxSigOps);
  256. nBlockSize += nTxSize;
  257. ++nBlockTx;
  258. nBlockSigOps += nTxSigOps;
  259. nFees += nTxFees;
  260. if (fPrintPriority)
  261. {
  262. LogPrintf("priority %.1f fee %s txid %s\n",
  263. dPriority, feeRate.ToString(), tx.GetHash().ToString());
  264. }
  265. // Add transactions that depend on this one to the priority queue
  266. if (mapDependers.count(hash))
  267. {
  268. BOOST_FOREACH(COrphan* porphan, mapDependers[hash])
  269. {
  270. if (!porphan->setDependsOn.empty())
  271. {
  272. porphan->setDependsOn.erase(hash);
  273. if (porphan->setDependsOn.empty())
  274. {
  275. vecPriority.push_back(TxPriority(porphan->dPriority, porphan->feeRate, porphan->ptx));
  276. std::push_heap(vecPriority.begin(), vecPriority.end(), comparer);
  277. }
  278. }
  279. }
  280. }
  281. }
  282. nLastBlockTx = nBlockTx;
  283. nLastBlockSize = nBlockSize;
  284. LogPrintf("CreateNewBlock(): total size %u\n", nBlockSize);
  285. // Compute final coinbase transaction.
  286. txNew.vout[0].nValue = nFees + GetBlockSubsidy(nHeight, chainparams.GetConsensus());
  287. txNew.vin[0].scriptSig = CScript() << nHeight << OP_0;
  288. pblock->vtx[0] = txNew;
  289. pblocktemplate->vTxFees[0] = -nFees;
  290. // Fill in header
  291. pblock->hashPrevBlock = pindexPrev->GetBlockHash();
  292. UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
  293. pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus());
  294. pblock->nNonce = 0;
  295. pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
  296. CValidationState state;
  297. if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false))
  298. throw std::runtime_error("CreateNewBlock(): TestBlockValidity failed");
  299. }
  300. return pblocktemplate.release();
  301. }
  302. void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce)
  303. {
  304. // Update nExtraNonce
  305. static uint256 hashPrevBlock;
  306. if (hashPrevBlock != pblock->hashPrevBlock)
  307. {
  308. nExtraNonce = 0;
  309. hashPrevBlock = pblock->hashPrevBlock;
  310. }
  311. ++nExtraNonce;
  312. unsigned int nHeight = pindexPrev->nHeight+1; // Height first in coinbase required for block.version=2
  313. CMutableTransaction txCoinbase(pblock->vtx[0]);
  314. txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
  315. assert(txCoinbase.vin[0].scriptSig.size() <= 100);
  316. pblock->vtx[0] = txCoinbase;
  317. pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
  318. }
  319. //////////////////////////////////////////////////////////////////////////////
  320. //
  321. // Internal miner
  322. //
  323. //
  324. // ScanHash scans nonces looking for a hash with at least some zero bits.
  325. // The nonce is usually preserved between calls, but periodically or if the
  326. // nonce is 0xffff0000 or above, the block is rebuilt and nNonce starts over at
  327. // zero.
  328. //
  329. bool static ScanHash(const CBlockHeader *pblock, uint32_t& nNonce, uint256 *phash)
  330. {
  331. // Write the first 76 bytes of the block header to a double-SHA256 state.
  332. CHash256 hasher;
  333. CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
  334. ss << *pblock;
  335. assert(ss.size() == 80);
  336. hasher.Write((unsigned char*)&ss[0], 76);
  337. while (true) {
  338. nNonce++;
  339. // Write the last 4 bytes of the block header (the nonce) to a copy of
  340. // the double-SHA256 state, and compute the result.
  341. CHash256(hasher).Write((unsigned char*)&nNonce, 4).Finalize((unsigned char*)phash);
  342. // Return the nonce if the hash has at least some zero bits,
  343. // caller will check if it has enough to reach the target
  344. if (((uint16_t*)phash)[15] == 0)
  345. return true;
  346. // If nothing found after trying for a while, return -1
  347. if ((nNonce & 0xfff) == 0)
  348. return false;
  349. }
  350. }
  351. static bool ProcessBlockFound(const CBlock* pblock, const CChainParams& chainparams)
  352. {
  353. LogPrintf("%s\n", pblock->ToString());
  354. LogPrintf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue));
  355. // Found a solution
  356. {
  357. LOCK(cs_main);
  358. if (pblock->hashPrevBlock != chainActive.Tip()->GetBlockHash())
  359. return error("BitcoinMiner: generated block is stale");
  360. }
  361. // Inform about the new block
  362. GetMainSignals().BlockFound(pblock->GetHash());
  363. // Process this block the same as if we had received it from another node
  364. CValidationState state;
  365. if (!ProcessNewBlock(state, chainparams, NULL, pblock, true, NULL))
  366. return error("BitcoinMiner: ProcessNewBlock, block not accepted");
  367. return true;
  368. }
  369. void static BitcoinMiner(const CChainParams& chainparams)
  370. {
  371. LogPrintf("BitcoinMiner started\n");
  372. SetThreadPriority(THREAD_PRIORITY_LOWEST);
  373. RenameThread("bitcoin-miner");
  374. unsigned int nExtraNonce = 0;
  375. boost::shared_ptr<CReserveScript> coinbaseScript;
  376. GetMainSignals().ScriptForMining(coinbaseScript);
  377. try {
  378. // Throw an error if no script was provided. This can happen
  379. // due to some internal error but also if the keypool is empty.
  380. // In the latter case, already the pointer is NULL.
  381. if (!coinbaseScript || coinbaseScript->reserveScript.empty())
  382. throw std::runtime_error("No coinbase script available (mining requires a wallet)");
  383. while (true) {
  384. if (chainparams.MiningRequiresPeers()) {
  385. // Busy-wait for the network to come online so we don't waste time mining
  386. // on an obsolete chain. In regtest mode we expect to fly solo.
  387. do {
  388. bool fvNodesEmpty;
  389. {
  390. LOCK(cs_vNodes);
  391. fvNodesEmpty = vNodes.empty();
  392. }
  393. if (!fvNodesEmpty && !IsInitialBlockDownload())
  394. break;
  395. MilliSleep(1000);
  396. } while (true);
  397. }
  398. //
  399. // Create new block
  400. //
  401. unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
  402. CBlockIndex* pindexPrev = chainActive.Tip();
  403. auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlock(chainparams, coinbaseScript->reserveScript));
  404. if (!pblocktemplate.get())
  405. {
  406. LogPrintf("Error in BitcoinMiner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n");
  407. return;
  408. }
  409. CBlock *pblock = &pblocktemplate->block;
  410. IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
  411. LogPrintf("Running BitcoinMiner with %u transactions in block (%u bytes)\n", pblock->vtx.size(),
  412. ::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
  413. //
  414. // Search
  415. //
  416. int64_t nStart = GetTime();
  417. arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
  418. uint256 hash;
  419. uint32_t nNonce = 0;
  420. while (true) {
  421. // Check if something found
  422. if (ScanHash(pblock, nNonce, &hash))
  423. {
  424. if (UintToArith256(hash) <= hashTarget)
  425. {
  426. // Found a solution
  427. pblock->nNonce = nNonce;
  428. assert(hash == pblock->GetHash());
  429. SetThreadPriority(THREAD_PRIORITY_NORMAL);
  430. LogPrintf("BitcoinMiner:\n");
  431. LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex(), hashTarget.GetHex());
  432. ProcessBlockFound(pblock, chainparams);
  433. SetThreadPriority(THREAD_PRIORITY_LOWEST);
  434. coinbaseScript->KeepScript();
  435. // In regression test mode, stop mining after a block is found.
  436. if (chainparams.MineBlocksOnDemand())
  437. throw boost::thread_interrupted();
  438. break;
  439. }
  440. }
  441. // Check for stop or if block needs to be rebuilt
  442. boost::this_thread::interruption_point();
  443. // Regtest mode doesn't require peers
  444. if (vNodes.empty() && chainparams.MiningRequiresPeers())
  445. break;
  446. if (nNonce >= 0xffff0000)
  447. break;
  448. if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
  449. break;
  450. if (pindexPrev != chainActive.Tip())
  451. break;
  452. // Update nTime every few seconds
  453. if (UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev) < 0)
  454. break; // Recreate the block if the clock has run backwards,
  455. // so that we can use the correct time.
  456. if (chainparams.GetConsensus().fPowAllowMinDifficultyBlocks)
  457. {
  458. // Changing pblock->nTime can change work required on testnet:
  459. hashTarget.SetCompact(pblock->nBits);
  460. }
  461. }
  462. }
  463. }
  464. catch (const boost::thread_interrupted&)
  465. {
  466. LogPrintf("BitcoinMiner terminated\n");
  467. throw;
  468. }
  469. catch (const std::runtime_error &e)
  470. {
  471. LogPrintf("BitcoinMiner runtime error: %s\n", e.what());
  472. return;
  473. }
  474. }
  475. void GenerateBitcoins(bool fGenerate, int nThreads, const CChainParams& chainparams)
  476. {
  477. static boost::thread_group* minerThreads = NULL;
  478. if (nThreads < 0)
  479. nThreads = GetNumCores();
  480. if (minerThreads != NULL)
  481. {
  482. minerThreads->interrupt_all();
  483. delete minerThreads;
  484. minerThreads = NULL;
  485. }
  486. if (nThreads == 0 || !fGenerate)
  487. return;
  488. minerThreads = new boost::thread_group();
  489. for (int i = 0; i < nThreads; i++)
  490. minerThreads->create_thread(boost::bind(&BitcoinMiner, boost::cref(chainparams)));
  491. }