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.
8 #include "pow/tromp/equi_miner.h"
12 #include "chainparams.h"
13 #include "consensus/consensus.h"
14 #include "consensus/upgrades.h"
15 #include "consensus/validation.h"
17 #include "crypto/equihash.h"
25 #include "primitives/transaction.h"
28 #include "ui_interface.h"
30 #include "utilmoneystr.h"
31 #include "validationinterface.h"
35 #include <boost/thread.hpp>
36 #include <boost/tuple/tuple.hpp>
44 //////////////////////////////////////////////////////////////////////////////
50 // Unconfirmed transactions in the memory pool often depend on other
51 // transactions in the memory pool. When we select transactions from the
52 // pool, we select by highest priority or fee rate, so we might consider
53 // transactions that depend on transactions that aren't yet in the block.
54 // The COrphan class keeps track of these 'temporary orphans' while
55 // CreateBlock is figuring out which transactions to include.
60 const CTransaction* ptx;
61 set<uint256> setDependsOn;
65 COrphan(const CTransaction* ptxIn) : ptx(ptxIn), feeRate(0), dPriority(0)
70 uint64_t nLastBlockTx = 0;
71 uint64_t nLastBlockSize = 0;
73 // We want to sort transactions by priority and fee rate, so:
74 typedef boost::tuple<double, CFeeRate, const CTransaction*> TxPriority;
75 class TxPriorityCompare
80 TxPriorityCompare(bool _byFee) : byFee(_byFee) { }
82 bool operator()(const TxPriority& a, const TxPriority& b)
86 if (a.get<1>() == b.get<1>())
87 return a.get<0>() < b.get<0>();
88 return a.get<1>() < b.get<1>();
92 if (a.get<0>() == b.get<0>())
93 return a.get<1>() < b.get<1>();
94 return a.get<0>() < b.get<0>();
99 void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
101 pblock->nTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
103 // Updating time can change work required on testnet:
104 if (consensusParams.nPowAllowMinDifficultyBlocksAfterHeight != boost::none) {
105 pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
109 CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
111 const CChainParams& chainparams = Params();
113 std::unique_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate());
114 if(!pblocktemplate.get())
116 CBlock *pblock = &pblocktemplate->block; // pointer for convenience
118 // -regtest only: allow overriding block.nVersion with
119 // -blockversion=N to test forking scenarios
120 if (Params().MineBlocksOnDemand())
121 pblock->nVersion = GetArg("-blockversion", pblock->nVersion);
123 // Add dummy coinbase tx as first transaction
124 pblock->vtx.push_back(CTransaction());
125 pblocktemplate->vTxFees.push_back(-1); // updated at end
126 pblocktemplate->vTxSigOps.push_back(-1); // updated at end
128 // Largest block you're willing to create:
129 unsigned int nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE);
130 // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity:
131 nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize));
133 // How much of the block should be dedicated to high-priority transactions,
134 // included regardless of the fees they pay
135 unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", DEFAULT_BLOCK_PRIORITY_SIZE);
136 nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize);
138 // Minimum block size you want to create; block will be filled with free transactions
139 // until there are no more or the block reaches this size:
140 unsigned int nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE);
141 nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize);
143 // Collect memory pool transactions into the block
147 LOCK2(cs_main, mempool.cs);
148 CBlockIndex* pindexPrev = chainActive.Tip();
149 const int nHeight = pindexPrev->nHeight + 1;
150 uint32_t consensusBranchId = CurrentEpochBranchId(nHeight, chainparams.GetConsensus());
151 pblock->nTime = GetAdjustedTime();
152 const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast();
153 CCoinsViewCache view(pcoinsTip);
155 SaplingMerkleTree sapling_tree;
156 assert(view.GetSaplingAnchorAt(view.GetBestAnchor(SAPLING), sapling_tree));
158 // Priority order to process transactions
159 list<COrphan> vOrphan; // list memory doesn't move
160 map<uint256, vector<COrphan*> > mapDependers;
161 bool fPrintPriority = GetBoolArg("-printpriority", false);
163 // This vector will be sorted into a priority queue:
164 vector<TxPriority> vecPriority;
165 vecPriority.reserve(mempool.mapTx.size());
166 for (CTxMemPool::indexed_transaction_set::iterator mi = mempool.mapTx.begin();
167 mi != mempool.mapTx.end(); ++mi)
169 const CTransaction& tx = mi->GetTx();
171 int64_t nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST)
173 : pblock->GetBlockTime();
175 if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight, nLockTimeCutoff) || IsExpiredTx(tx, nHeight))
178 COrphan* porphan = NULL;
179 double dPriority = 0;
180 CAmount nTotalIn = 0;
181 bool fMissingInputs = false;
182 BOOST_FOREACH(const CTxIn& txin, tx.vin)
184 // Read prev transaction
185 if (!view.HaveCoins(txin.prevout.hash))
187 // This should never happen; all transactions in the memory
188 // pool should connect to either transactions in the chain
189 // or other transactions in the memory pool.
190 if (!mempool.mapTx.count(txin.prevout.hash))
192 LogPrintf("ERROR: mempool transaction missing input\n");
193 if (fDebug) assert("mempool transaction missing input" == 0);
194 fMissingInputs = true;
200 // Has to wait for dependencies
203 // Use list for automatic deletion
204 vOrphan.push_back(COrphan(&tx));
205 porphan = &vOrphan.back();
207 mapDependers[txin.prevout.hash].push_back(porphan);
208 porphan->setDependsOn.insert(txin.prevout.hash);
209 nTotalIn += mempool.mapTx.find(txin.prevout.hash)->GetTx().vout[txin.prevout.n].nValue;
212 const CCoins* coins = view.AccessCoins(txin.prevout.hash);
215 CAmount nValueIn = coins->vout[txin.prevout.n].nValue;
216 nTotalIn += nValueIn;
218 int nConf = nHeight - coins->nHeight;
220 dPriority += (double)nValueIn * nConf;
222 nTotalIn += tx.GetShieldedValueIn();
224 if (fMissingInputs) continue;
226 // Priority is sum(valuein * age) / modified_txsize
227 unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
228 dPriority = tx.ComputePriority(dPriority, nTxSize);
230 uint256 hash = tx.GetHash();
231 mempool.ApplyDeltas(hash, dPriority, nTotalIn);
233 CFeeRate feeRate(nTotalIn-tx.GetValueOut(), nTxSize);
237 porphan->dPriority = dPriority;
238 porphan->feeRate = feeRate;
241 vecPriority.push_back(TxPriority(dPriority, feeRate, &(mi->GetTx())));
244 // Collect transactions into block
245 uint64_t nBlockSize = 1000;
246 uint64_t nBlockTx = 0;
247 int nBlockSigOps = 100;
248 bool fSortedByFee = (nBlockPrioritySize <= 0);
250 TxPriorityCompare comparer(fSortedByFee);
251 std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
253 // We want to track the value pool, but if the miner gets
254 // invoked on an old block before the hardcoded fallback
255 // is active we don't want to trip up any assertions. So,
256 // we only adhere to the turnstile (as a miner) if we
257 // actually have all of the information necessary to do
259 CAmount sproutValue = 0;
260 CAmount saplingValue = 0;
261 bool monitoring_pool_balances = true;
262 if (chainparams.ZIP209Enabled()) {
263 if (pindexPrev->nChainSproutValue) {
264 sproutValue = *pindexPrev->nChainSproutValue;
266 monitoring_pool_balances = false;
268 if (pindexPrev->nChainSaplingValue) {
269 saplingValue = *pindexPrev->nChainSaplingValue;
271 monitoring_pool_balances = false;
275 while (!vecPriority.empty())
277 // Take highest priority transaction off the priority queue:
278 double dPriority = vecPriority.front().get<0>();
279 CFeeRate feeRate = vecPriority.front().get<1>();
280 const CTransaction& tx = *(vecPriority.front().get<2>());
282 std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer);
283 vecPriority.pop_back();
286 unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
287 if (nBlockSize + nTxSize >= nBlockMaxSize)
290 // Legacy limits on sigOps:
291 unsigned int nTxSigOps = GetLegacySigOpCount(tx);
292 if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
295 // Skip free transactions if we're past the minimum block size:
296 const uint256& hash = tx.GetHash();
297 double dPriorityDelta = 0;
298 CAmount nFeeDelta = 0;
299 mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta);
300 if (fSortedByFee && (dPriorityDelta <= 0) && (nFeeDelta <= 0) && (feeRate < ::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
303 // Prioritise by fee once past the priority size or we run out of high-priority
306 ((nBlockSize + nTxSize >= nBlockPrioritySize) || !AllowFree(dPriority)))
309 comparer = TxPriorityCompare(fSortedByFee);
310 std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
313 if (!view.HaveInputs(tx))
316 CAmount nTxFees = view.GetValueIn(tx)-tx.GetValueOut();
318 nTxSigOps += GetP2SHSigOpCount(tx, view);
319 if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
322 // Note that flags: we don't want to set mempool/IsStandard()
323 // policy here, but we still have to ensure that the block we
324 // create only contains transactions that are valid in new blocks.
325 CValidationState state;
326 PrecomputedTransactionData txdata(tx);
327 if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId))
330 if (chainparams.ZIP209Enabled() && monitoring_pool_balances) {
331 // Does this transaction lead to a turnstile violation?
333 CAmount sproutValueDummy = sproutValue;
334 CAmount saplingValueDummy = saplingValue;
336 saplingValueDummy += -tx.valueBalance;
338 for (auto js : tx.vjoinsplit) {
339 sproutValueDummy += js.vpub_old;
340 sproutValueDummy -= js.vpub_new;
343 if (sproutValueDummy < 0) {
344 LogPrintf("CreateNewBlock(): tx %s appears to violate Sprout turnstile\n", tx.GetHash().ToString());
347 if (saplingValueDummy < 0) {
348 LogPrintf("CreateNewBlock(): tx %s appears to violate Sapling turnstile\n", tx.GetHash().ToString());
352 sproutValue = sproutValueDummy;
353 saplingValue = saplingValueDummy;
356 UpdateCoins(tx, view, nHeight);
358 BOOST_FOREACH(const OutputDescription &outDescription, tx.vShieldedOutput) {
359 sapling_tree.append(outDescription.cm);
363 pblock->vtx.push_back(tx);
364 pblocktemplate->vTxFees.push_back(nTxFees);
365 pblocktemplate->vTxSigOps.push_back(nTxSigOps);
366 nBlockSize += nTxSize;
368 nBlockSigOps += nTxSigOps;
373 LogPrintf("priority %.1f fee %s txid %s\n",
374 dPriority, feeRate.ToString(), tx.GetHash().ToString());
377 // Add transactions that depend on this one to the priority queue
378 if (mapDependers.count(hash))
380 BOOST_FOREACH(COrphan* porphan, mapDependers[hash])
382 if (!porphan->setDependsOn.empty())
384 porphan->setDependsOn.erase(hash);
385 if (porphan->setDependsOn.empty())
387 vecPriority.push_back(TxPriority(porphan->dPriority, porphan->feeRate, porphan->ptx));
388 std::push_heap(vecPriority.begin(), vecPriority.end(), comparer);
395 nLastBlockTx = nBlockTx;
396 nLastBlockSize = nBlockSize;
397 LogPrintf("CreateNewBlock(): total size %u\n", nBlockSize);
399 // Create coinbase tx
400 CMutableTransaction txNew = CreateNewContextualCMutableTransaction(chainparams.GetConsensus(), nHeight);
402 txNew.vin[0].prevout.SetNull();
403 txNew.vout.resize(1);
404 txNew.vout[0].scriptPubKey = scriptPubKeyIn;
405 txNew.vout[0].nValue = GetBlockSubsidy(nHeight, chainparams.GetConsensus());
406 // Set to 0 so expiry height does not apply to coinbase txs
407 txNew.nExpiryHeight = 0;
409 if ((nHeight > 0) && (nHeight <= chainparams.GetConsensus().GetLastFoundersRewardBlockHeight())) {
410 // Founders reward is 20% of the block subsidy
411 auto vFoundersReward = txNew.vout[0].nValue / 5;
412 // Take some reward away from us
413 txNew.vout[0].nValue -= vFoundersReward;
415 // And give it to the founders
416 txNew.vout.push_back(CTxOut(vFoundersReward, chainparams.GetFoundersRewardScriptAtHeight(nHeight)));
420 txNew.vout[0].nValue += nFees;
421 txNew.vin[0].scriptSig = CScript() << nHeight << OP_0;
423 pblock->vtx[0] = txNew;
424 pblocktemplate->vTxFees[0] = -nFees;
427 arith_uint256 nonce = UintToArith256(GetRandHash());
428 // Clear the top and bottom 16 bits (for local use as thread flags and counters)
431 pblock->nNonce = ArithToUint256(nonce);
434 pblock->hashPrevBlock = pindexPrev->GetBlockHash();
435 pblock->hashFinalSaplingRoot = sapling_tree.root();
436 UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
437 pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus());
438 pblock->nSolution.clear();
439 pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
441 CValidationState state;
442 if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false))
443 throw std::runtime_error("CreateNewBlock(): TestBlockValidity failed");
446 return pblocktemplate.release();
449 //////////////////////////////////////////////////////////////////////////////
456 class MinerAddressScript : public CReserveScript
458 // CReserveScript requires implementing this function, so that if an
459 // internal (not-visible) wallet address is used, the wallet can mark it as
460 // important when a block is mined (so it then appears to the user).
461 // If -mineraddress is set, the user already knows about and is managing the
462 // address, so we don't need to do anything here.
466 void GetScriptForMinerAddress(boost::shared_ptr<CReserveScript> &script)
468 CTxDestination addr = DecodeDestination(GetArg("-mineraddress", ""));
469 if (!IsValidDestination(addr)) {
473 boost::shared_ptr<MinerAddressScript> mAddr(new MinerAddressScript());
474 CKeyID keyID = boost::get<CKeyID>(addr);
477 script->reserveScript = CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
480 void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce)
482 // Update nExtraNonce
483 static uint256 hashPrevBlock;
484 if (hashPrevBlock != pblock->hashPrevBlock)
487 hashPrevBlock = pblock->hashPrevBlock;
490 unsigned int nHeight = pindexPrev->nHeight+1; // Height first in coinbase required for block.version=2
491 CMutableTransaction txCoinbase(pblock->vtx[0]);
492 txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
493 assert(txCoinbase.vin[0].scriptSig.size() <= 100);
495 pblock->vtx[0] = txCoinbase;
496 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
499 static bool ProcessBlockFound(const CBlock* pblock, const CChainParams& chainparams)
501 LogPrintf("%s\n", pblock->ToString());
502 LogPrintf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue));
507 if (pblock->hashPrevBlock != chainActive.Tip()->GetBlockHash())
508 return error("ZcashMiner: generated block is stale");
511 // Inform about the new block
512 GetMainSignals().BlockFound(pblock->GetHash());
514 // Process this block the same as if we had received it from another node
515 CValidationState state;
516 if (!ProcessNewBlock(state, chainparams, NULL, pblock, true, NULL))
517 return error("ZcashMiner: ProcessNewBlock, block not accepted");
519 TrackMinedBlock(pblock->GetHash());
524 void static BitcoinMiner(const CChainParams& chainparams)
526 LogPrintf("ZcashMiner started\n");
527 SetThreadPriority(THREAD_PRIORITY_LOWEST);
528 RenameThread("zcash-miner");
530 // Each thread has its own counter
531 unsigned int nExtraNonce = 0;
533 boost::shared_ptr<CReserveScript> coinbaseScript;
534 GetMainSignals().ScriptForMining(coinbaseScript);
536 unsigned int n = chainparams.GetConsensus().nEquihashN;
537 unsigned int k = chainparams.GetConsensus().nEquihashK;
539 std::string solver = GetArg("-equihashsolver", "default");
540 assert(solver == "tromp" || solver == "default");
541 LogPrint("pow", "Using Equihash solver \"%s\" with n = %u, k = %u\n", solver, n, k);
544 bool cancelSolver = false;
545 boost::signals2::connection c = uiInterface.NotifyBlockTip.connect(
546 [&m_cs, &cancelSolver](const uint256& hashNewTip) mutable {
547 std::lock_guard<std::mutex> lock{m_cs};
554 //throw an error if no script was provided
555 if (!coinbaseScript->reserveScript.size())
556 throw std::runtime_error("No coinbase script available (mining requires a wallet or -mineraddress)");
559 if (chainparams.MiningRequiresPeers()) {
560 // Busy-wait for the network to come online so we don't waste time mining
561 // on an obsolete chain. In regtest mode we expect to fly solo.
567 fvNodesEmpty = vNodes.empty();
569 if (!fvNodesEmpty && !IsInitialBlockDownload())
579 unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
580 CBlockIndex* pindexPrev = chainActive.Tip();
582 unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlock(coinbaseScript->reserveScript));
583 if (!pblocktemplate.get())
585 if (GetArg("-mineraddress", "").empty()) {
586 LogPrintf("Error in ZcashMiner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n");
588 // Should never reach here, because -mineraddress validity is checked in init.cpp
589 LogPrintf("Error in ZcashMiner: Invalid -mineraddress\n");
593 CBlock *pblock = &pblocktemplate->block;
594 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
596 LogPrintf("Running ZcashMiner with %u transactions in block (%u bytes)\n", pblock->vtx.size(),
597 ::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
602 int64_t nStart = GetTime();
603 arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
607 crypto_generichash_blake2b_state state;
608 EhInitialiseState(n, k, state);
610 // I = the block header minus nonce and solution.
611 CEquihashInput I{*pblock};
612 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
616 crypto_generichash_blake2b_update(&state, (unsigned char*)&ss[0], ss.size());
619 crypto_generichash_blake2b_state curr_state;
621 crypto_generichash_blake2b_update(&curr_state,
622 pblock->nNonce.begin(),
623 pblock->nNonce.size());
625 // (x_1, x_2, ...) = A(I, V, n, k)
626 LogPrint("pow", "Running Equihash solver \"%s\" with nNonce = %s\n",
627 solver, pblock->nNonce.ToString());
629 std::function<bool(std::vector<unsigned char>)> validBlock =
630 [&pblock, &hashTarget, &chainparams, &m_cs, &cancelSolver, &coinbaseScript]
631 (std::vector<unsigned char> soln) {
632 // Write the solution to the hash and compute the result.
633 LogPrint("pow", "- Checking solution against target\n");
634 pblock->nSolution = soln;
635 solutionTargetChecks.increment();
637 if (UintToArith256(pblock->GetHash()) > hashTarget) {
642 SetThreadPriority(THREAD_PRIORITY_NORMAL);
643 LogPrintf("ZcashMiner:\n");
644 LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex());
645 if (ProcessBlockFound(pblock, chainparams)) {
646 // Ignore chain updates caused by us
647 std::lock_guard<std::mutex> lock{m_cs};
648 cancelSolver = false;
650 SetThreadPriority(THREAD_PRIORITY_LOWEST);
651 coinbaseScript->KeepScript();
653 // In regression test mode, stop mining after a block is found.
654 if (chainparams.MineBlocksOnDemand()) {
655 // Increment here because throwing skips the call below
656 ehSolverRuns.increment();
657 throw boost::thread_interrupted();
662 std::function<bool(EhSolverCancelCheck)> cancelled = [&m_cs, &cancelSolver](EhSolverCancelCheck pos) {
663 std::lock_guard<std::mutex> lock{m_cs};
667 // TODO: factor this out into a function with the same API for each solver.
668 if (solver == "tromp") {
669 // Create solver and initialize it.
671 eq.setstate(&curr_state);
673 // Initialization done, start algo driver.
675 eq.xfull = eq.bfull = eq.hfull = 0;
677 for (u32 r = 1; r < WK; r++) {
678 (r&1) ? eq.digitodd(r, 0) : eq.digiteven(r, 0);
679 eq.xfull = eq.bfull = eq.hfull = 0;
683 ehSolverRuns.increment();
685 // Convert solution indices to byte array (decompress) and pass it to validBlock method.
686 for (size_t s = 0; s < eq.nsols; s++) {
687 LogPrint("pow", "Checking solution %d\n", s+1);
688 std::vector<eh_index> index_vector(PROOFSIZE);
689 for (size_t i = 0; i < PROOFSIZE; i++) {
690 index_vector[i] = eq.sols[s][i];
692 std::vector<unsigned char> sol_char = GetMinimalFromIndices(index_vector, DIGITBITS);
694 if (validBlock(sol_char)) {
695 // If we find a POW solution, do not try other solutions
696 // because they become invalid as we created a new block in blockchain.
702 // If we find a valid block, we rebuild
703 bool found = EhOptimisedSolve(n, k, curr_state, validBlock, cancelled);
704 ehSolverRuns.increment();
708 } catch (EhSolverCancelledException&) {
709 LogPrint("pow", "Equihash solver cancelled\n");
710 std::lock_guard<std::mutex> lock{m_cs};
711 cancelSolver = false;
715 // Check for stop or if block needs to be rebuilt
716 boost::this_thread::interruption_point();
717 // Regtest mode doesn't require peers
718 if (vNodes.empty() && chainparams.MiningRequiresPeers())
720 if ((UintToArith256(pblock->nNonce) & 0xffff) == 0xffff)
722 if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
724 if (pindexPrev != chainActive.Tip())
727 // Update nNonce and nTime
728 pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1);
729 UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
730 if (chainparams.GetConsensus().nPowAllowMinDifficultyBlocksAfterHeight != boost::none)
732 // Changing pblock->nTime can change work required on testnet:
733 hashTarget.SetCompact(pblock->nBits);
738 catch (const boost::thread_interrupted&)
742 LogPrintf("ZcashMiner terminated\n");
745 catch (const std::runtime_error &e)
749 LogPrintf("ZcashMiner runtime error: %s\n", e.what());
756 void GenerateBitcoins(bool fGenerate, int nThreads, const CChainParams& chainparams)
758 static boost::thread_group* minerThreads = NULL;
761 nThreads = GetNumCores();
763 if (minerThreads != NULL)
765 minerThreads->interrupt_all();
766 minerThreads->join_all();
771 if (nThreads == 0 || !fGenerate)
774 minerThreads = new boost::thread_group();
775 for (int i = 0; i < nThreads; i++) {
776 minerThreads->create_thread(boost::bind(&BitcoinMiner, boost::cref(chainparams)));
780 #endif // ENABLE_MINING