aboutsummaryrefslogtreecommitdiff
path: root/src/miner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/miner.cpp')
-rw-r--r--src/miner.cpp448
1 files changed, 185 insertions, 263 deletions
diff --git a/src/miner.cpp b/src/miner.cpp
index 3351908e65..17918a1280 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -3,90 +3,67 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <inttypes.h>
+
#include "miner.h"
#include "core.h"
+#include "hash.h"
#include "main.h"
#include "net.h"
+#include "pow.h"
#ifdef ENABLE_WALLET
#include "wallet.h"
#endif
+
+using namespace std;
+
//////////////////////////////////////////////////////////////////////////////
//
// BitcoinMiner
//
-int static FormatHashBlocks(void* pbuffer, unsigned int len)
-{
- unsigned char* pdata = (unsigned char*)pbuffer;
- unsigned int blocks = 1 + ((len + 8) / 64);
- unsigned char* pend = pdata + 64 * blocks;
- memset(pdata + len, 0, 64 * blocks - len);
- pdata[len] = 0x80;
- unsigned int bits = len * 8;
- pend[-1] = (bits >> 0) & 0xff;
- pend[-2] = (bits >> 8) & 0xff;
- pend[-3] = (bits >> 16) & 0xff;
- pend[-4] = (bits >> 24) & 0xff;
- return blocks;
-}
-
-static const unsigned int pSHA256InitState[8] =
-{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
-
-void SHA256Transform(void* pstate, void* pinput, const void* pinit)
-{
- SHA256_CTX ctx;
- unsigned char data[64];
-
- SHA256_Init(&ctx);
-
- for (int i = 0; i < 16; i++)
- ((uint32_t*)data)[i] = ByteReverse(((uint32_t*)pinput)[i]);
-
- for (int i = 0; i < 8; i++)
- ctx.h[i] = ((uint32_t*)pinit)[i];
-
- SHA256_Update(&ctx, data, sizeof(data));
- for (int i = 0; i < 8; i++)
- ((uint32_t*)pstate)[i] = ctx.h[i];
-}
-
-// Some explaining would be appreciated
+//
+// Unconfirmed transactions in the memory pool often depend on other
+// transactions in the memory pool. When we select transactions from the
+// pool, we select by highest priority or fee rate, so we might consider
+// transactions that depend on transactions that aren't yet in the block.
+// The COrphan class keeps track of these 'temporary orphans' while
+// CreateBlock is figuring out which transactions to include.
+//
class COrphan
{
public:
const CTransaction* ptx;
set<uint256> setDependsOn;
+ CFeeRate feeRate;
double dPriority;
- double dFeePerKb;
- COrphan(const CTransaction* ptxIn)
+ COrphan(const CTransaction* ptxIn) : ptx(ptxIn), feeRate(0), dPriority(0)
{
- ptx = ptxIn;
- dPriority = dFeePerKb = 0;
}
void print() const
{
- LogPrintf("COrphan(hash=%s, dPriority=%.1f, dFeePerKb=%.1f)\n",
- ptx->GetHash().ToString(), dPriority, dFeePerKb);
+ LogPrintf("COrphan(hash=%s, dPriority=%.1f, fee=%s)\n",
+ ptx->GetHash().ToString(), dPriority, feeRate.ToString());
BOOST_FOREACH(uint256 hash, setDependsOn)
LogPrintf(" setDependsOn %s\n", hash.ToString());
}
};
-
uint64_t nLastBlockTx = 0;
uint64_t nLastBlockSize = 0;
-// We want to sort transactions by priority and fee, so:
-typedef boost::tuple<double, double, const CTransaction*> TxPriority;
+// We want to sort transactions by priority and fee rate, so:
+typedef boost::tuple<double, CFeeRate, const CTransaction*> TxPriority;
class TxPriorityCompare
{
bool byFee;
+
public:
TxPriorityCompare(bool _byFee) : byFee(_byFee) { }
+
bool operator()(const TxPriority& a, const TxPriority& b)
{
if (byFee)
@@ -113,14 +90,14 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
// Create coinbase tx
- CTransaction txNew;
+ CMutableTransaction txNew;
txNew.vin.resize(1);
txNew.vin[0].prevout.SetNull();
txNew.vout.resize(1);
txNew.vout[0].scriptPubKey = scriptPubKeyIn;
- // Add our coinbase tx as first transaction
- pblock->vtx.push_back(txNew);
+ // Add dummy coinbase tx as first transaction
+ pblock->vtx.push_back(CTransaction());
pblocktemplate->vTxFees.push_back(-1); // updated at end
pblocktemplate->vTxSigOps.push_back(-1); // updated at end
@@ -141,6 +118,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
// Collect memory pool transactions into the block
int64_t nFees = 0;
+
{
LOCK2(cs_main, mempool.cs);
CBlockIndex* pindexPrev = chainActive.Tip();
@@ -210,18 +188,18 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
dPriority = tx.ComputePriority(dPriority, nTxSize);
- // This is a more accurate fee-per-kilobyte than is used by the client code, because the
- // client code rounds up the size to the nearest 1K. That's good, because it gives an
- // incentive to create smaller transactions.
- double dFeePerKb = double(nTotalIn-tx.GetValueOut()) / (double(nTxSize)/1000.0);
+ uint256 hash = tx.GetHash();
+ mempool.ApplyDeltas(hash, dPriority, nTotalIn);
+
+ CFeeRate feeRate(nTotalIn-tx.GetValueOut(), nTxSize);
if (porphan)
{
porphan->dPriority = dPriority;
- porphan->dFeePerKb = dFeePerKb;
+ porphan->feeRate = feeRate;
}
else
- vecPriority.push_back(TxPriority(dPriority, dFeePerKb, &mi->second.GetTx()));
+ vecPriority.push_back(TxPriority(dPriority, feeRate, &mi->second.GetTx()));
}
// Collect transactions into block
@@ -237,7 +215,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
{
// Take highest priority transaction off the priority queue:
double dPriority = vecPriority.front().get<0>();
- double dFeePerKb = vecPriority.front().get<1>();
+ CFeeRate feeRate = vecPriority.front().get<1>();
const CTransaction& tx = *(vecPriority.front().get<2>());
std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer);
@@ -254,10 +232,14 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
continue;
// Skip free transactions if we're past the minimum block size:
- if (fSortedByFee && (dFeePerKb < CTransaction::nMinRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
+ const uint256& hash = tx.GetHash();
+ double dPriorityDelta = 0;
+ int64_t nFeeDelta = 0;
+ mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta);
+ if (fSortedByFee && (dPriorityDelta <= 0) && (nFeeDelta <= 0) && (feeRate < ::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
continue;
- // Prioritize by fee once past the priority size or we run out of high-priority
+ // Prioritise by fee once past the priority size or we run out of high-priority
// transactions:
if (!fSortedByFee &&
((nBlockSize + nTxSize >= nBlockPrioritySize) || !AllowFree(dPriority)))
@@ -276,13 +258,15 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
continue;
+ // Note that flags: we don't want to set mempool/IsStandard()
+ // policy here, but we still have to ensure that the block we
+ // create only contains transactions that are valid in new blocks.
CValidationState state;
- if (!CheckInputs(tx, state, view, true, SCRIPT_VERIFY_P2SH))
+ if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS))
continue;
CTxUndo txundo;
- uint256 hash = tx.GetHash();
- UpdateCoins(tx, state, view, txundo, pindexPrev->nHeight+1, hash);
+ UpdateCoins(tx, state, view, txundo, pindexPrev->nHeight+1);
// Added
pblock->vtx.push_back(tx);
@@ -295,8 +279,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
if (fPrintPriority)
{
- LogPrintf("priority %.1f feeperkb %.1f txid %s\n",
- dPriority, dFeePerKb, tx.GetHash().ToString());
+ LogPrintf("priority %.1f fee %s txid %s\n",
+ dPriority, feeRate.ToString(), tx.GetHash().ToString());
}
// Add transactions that depend on this one to the priority queue
@@ -309,7 +293,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
porphan->setDependsOn.erase(hash);
if (porphan->setDependsOn.empty())
{
- vecPriority.push_back(TxPriority(porphan->dPriority, porphan->dFeePerKb, porphan->ptx));
+ vecPriority.push_back(TxPriority(porphan->dPriority, porphan->feeRate, porphan->ptx));
std::push_heap(vecPriority.begin(), vecPriority.end(), comparer);
}
}
@@ -321,7 +305,10 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
nLastBlockSize = nBlockSize;
LogPrintf("CreateNewBlock(): total size %u\n", nBlockSize);
- pblock->vtx[0].vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees);
+ // Compute final coinbase transaction.
+ txNew.vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees);
+ txNew.vin[0].scriptSig = CScript() << OP_0 << OP_0;
+ pblock->vtx[0] = txNew;
pblocktemplate->vTxFees[0] = -nFees;
// Fill in header
@@ -329,7 +316,6 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
UpdateTime(*pblock, pindexPrev);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock);
pblock->nNonce = 0;
- pblock->vtx[0].vin[0].scriptSig = CScript() << OP_0 << OP_0;
pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
CBlockIndex indexDummy(*pblock);
@@ -355,58 +341,14 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
}
++nExtraNonce;
unsigned int nHeight = pindexPrev->nHeight+1; // Height first in coinbase required for block.version=2
- pblock->vtx[0].vin[0].scriptSig = (CScript() << nHeight << CBigNum(nExtraNonce)) + COINBASE_FLAGS;
- assert(pblock->vtx[0].vin[0].scriptSig.size() <= 100);
+ CMutableTransaction txCoinbase(pblock->vtx[0]);
+ txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
+ assert(txCoinbase.vin[0].scriptSig.size() <= 100);
+ pblock->vtx[0] = txCoinbase;
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
}
-
-void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1)
-{
- //
- // Pre-build hash buffers
- //
- struct
- {
- struct unnamed2
- {
- int nVersion;
- uint256 hashPrevBlock;
- uint256 hashMerkleRoot;
- unsigned int nTime;
- unsigned int nBits;
- unsigned int nNonce;
- }
- block;
- unsigned char pchPadding0[64];
- uint256 hash1;
- unsigned char pchPadding1[64];
- }
- tmp;
- memset(&tmp, 0, sizeof(tmp));
-
- tmp.block.nVersion = pblock->nVersion;
- tmp.block.hashPrevBlock = pblock->hashPrevBlock;
- tmp.block.hashMerkleRoot = pblock->hashMerkleRoot;
- tmp.block.nTime = pblock->nTime;
- tmp.block.nBits = pblock->nBits;
- tmp.block.nNonce = pblock->nNonce;
-
- FormatHashBlocks(&tmp.block, sizeof(tmp.block));
- FormatHashBlocks(&tmp.hash1, sizeof(tmp.hash1));
-
- // Byte swap all the input buffer
- for (unsigned int i = 0; i < sizeof(tmp)/4; i++)
- ((unsigned int*)&tmp)[i] = ByteReverse(((unsigned int*)&tmp)[i]);
-
- // Precalc the first half of the first hash, which stays constant
- SHA256Transform(pmidstate, &tmp.block, pSHA256InitState);
-
- memcpy(pdata, &tmp.block, 128);
- memcpy(phash1, &tmp.hash1, 64);
-}
-
#ifdef ENABLE_WALLET
//////////////////////////////////////////////////////////////////////////////
//
@@ -417,34 +359,34 @@ int64_t nHPSTimerStart = 0;
//
// ScanHash scans nonces looking for a hash with at least some zero bits.
-// It operates on big endian data. Caller does the byte reversing.
-// All input buffers are 16-byte aligned. nNonce is usually preserved
-// between calls, but periodically or if nNonce is 0xffff0000 or above,
-// the block is rebuilt and nNonce starts over at zero.
+// The nonce is usually preserved between calls, but periodically or if the
+// nonce is 0xffff0000 or above, the block is rebuilt and nNonce starts over at
+// zero.
//
-unsigned int static ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1, char* phash, unsigned int& nHashesDone)
+bool static ScanHash(const CBlockHeader *pblock, uint32_t& nNonce, uint256 *phash)
{
- unsigned int& nNonce = *(unsigned int*)(pdata + 12);
- for (;;)
- {
- // Crypto++ SHA256
- // Hash pdata using pmidstate as the starting state into
- // pre-formatted buffer phash1, then hash phash1 into phash
+ // Write the first 76 bytes of the block header to a double-SHA256 state.
+ CHash256 hasher;
+ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
+ ss << *pblock;
+ assert(ss.size() == 80);
+ hasher.Write((unsigned char*)&ss[0], 76);
+
+ while (true) {
nNonce++;
- SHA256Transform(phash1, pdata, pmidstate);
- SHA256Transform(phash, phash1, pSHA256InitState);
+
+ // Write the last 4 bytes of the block header (the nonce) to a copy of
+ // the double-SHA256 state, and compute the result.
+ CHash256(hasher).Write((unsigned char*)&nNonce, 4).Finalize((unsigned char*)phash);
// Return the nonce if the hash has at least some zero bits,
// caller will check if it has enough to reach the target
- if (((unsigned short*)phash)[14] == 0)
- return nNonce;
+ if (((uint16_t*)phash)[15] == 0)
+ return true;
// If nothing found after trying for a while, return -1
if ((nNonce & 0xffff) == 0)
- {
- nHashesDone = 0xffff+1;
- return (unsigned int) -1;
- }
+ return false;
if ((nNonce & 0xfff) == 0)
boost::this_thread::interruption_point();
}
@@ -463,7 +405,7 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey)
bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
{
uint256 hash = pblock->GetHash();
- uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
+ uint256 hashTarget = uint256().SetCompact(pblock->nBits);
if (hash > hashTarget)
return false;
@@ -479,22 +421,22 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
LOCK(cs_main);
if (pblock->hashPrevBlock != chainActive.Tip()->GetBlockHash())
return error("BitcoinMiner : generated block is stale");
+ }
- // Remove key from key pool
- reservekey.KeepKey();
+ // Remove key from key pool
+ reservekey.KeepKey();
- // Track how many getdata requests this block gets
- {
- LOCK(wallet.cs_wallet);
- wallet.mapRequestCount[pblock->GetHash()] = 0;
- }
-
- // Process this block the same as if we had received it from another node
- CValidationState state;
- if (!ProcessBlock(state, NULL, pblock))
- return error("BitcoinMiner : ProcessBlock, block not accepted");
+ // Track how many getdata requests this block gets
+ {
+ LOCK(wallet.cs_wallet);
+ wallet.mapRequestCount[pblock->GetHash()] = 0;
}
+ // Process this block the same as if we had received it from another node
+ CValidationState state;
+ if (!ProcessBlock(state, NULL, pblock))
+ return error("BitcoinMiner : ProcessBlock, block not accepted");
+
return true;
}
@@ -508,135 +450,115 @@ void static BitcoinMiner(CWallet *pwallet)
CReserveKey reservekey(pwallet);
unsigned int nExtraNonce = 0;
- try { while (true) {
- if (Params().NetworkID() != CChainParams::REGTEST) {
- // Busy-wait for the network to come online so we don't waste time mining
- // on an obsolete chain. In regtest mode we expect to fly solo.
- while (vNodes.empty())
- MilliSleep(1000);
- }
-
- //
- // Create new block
- //
- unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
- CBlockIndex* pindexPrev = chainActive.Tip();
-
- auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
- if (!pblocktemplate.get())
- return;
- CBlock *pblock = &pblocktemplate->block;
- IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
-
- LogPrintf("Running BitcoinMiner with %"PRIszu" transactions in block (%u bytes)\n", pblock->vtx.size(),
- ::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
-
- //
- // Pre-build hash buffers
- //
- char pmidstatebuf[32+16]; char* pmidstate = alignup<16>(pmidstatebuf);
- char pdatabuf[128+16]; char* pdata = alignup<16>(pdatabuf);
- char phash1buf[64+16]; char* phash1 = alignup<16>(phash1buf);
-
- FormatHashBuffers(pblock, pmidstate, pdata, phash1);
-
- unsigned int& nBlockTime = *(unsigned int*)(pdata + 64 + 4);
- unsigned int& nBlockBits = *(unsigned int*)(pdata + 64 + 8);
- unsigned int& nBlockNonce = *(unsigned int*)(pdata + 64 + 12);
-
-
- //
- // Search
- //
- int64_t nStart = GetTime();
- uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
- uint256 hashbuf[2];
- uint256& hash = *alignup<16>(hashbuf);
- while (true)
- {
- unsigned int nHashesDone = 0;
- unsigned int nNonceFound;
-
- // Crypto++ SHA256
- nNonceFound = ScanHash_CryptoPP(pmidstate, pdata + 64, phash1,
- (char*)&hash, nHashesDone);
-
- // Check if something found
- if (nNonceFound != (unsigned int) -1)
- {
- for (unsigned int i = 0; i < sizeof(hash)/4; i++)
- ((unsigned int*)&hash)[i] = ByteReverse(((unsigned int*)&hash)[i]);
+ try {
+ while (true) {
+ if (Params().MiningRequiresPeers()) {
+ // Busy-wait for the network to come online so we don't waste time mining
+ // on an obsolete chain. In regtest mode we expect to fly solo.
+ while (vNodes.empty())
+ MilliSleep(1000);
+ }
- if (hash <= hashTarget)
+ //
+ // Create new block
+ //
+ unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
+ CBlockIndex* pindexPrev = chainActive.Tip();
+
+ auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
+ if (!pblocktemplate.get())
+ return;
+ CBlock *pblock = &pblocktemplate->block;
+ IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
+
+ LogPrintf("Running BitcoinMiner with %u transactions in block (%u bytes)\n", pblock->vtx.size(),
+ ::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
+
+ //
+ // Search
+ //
+ int64_t nStart = GetTime();
+ uint256 hashTarget = uint256().SetCompact(pblock->nBits);
+ uint256 hash;
+ uint32_t nNonce = 0;
+ uint32_t nOldNonce = 0;
+ while (true) {
+ bool fFound = ScanHash(pblock, nNonce, &hash);
+ uint32_t nHashesDone = nNonce - nOldNonce;
+ nOldNonce = nNonce;
+
+ // Check if something found
+ if (fFound)
{
- // Found a solution
- pblock->nNonce = ByteReverse(nNonceFound);
- assert(hash == pblock->GetHash());
+ if (hash <= hashTarget)
+ {
+ // Found a solution
+ pblock->nNonce = nNonce;
+ assert(hash == pblock->GetHash());
- SetThreadPriority(THREAD_PRIORITY_NORMAL);
- CheckWork(pblock, *pwallet, reservekey);
- SetThreadPriority(THREAD_PRIORITY_LOWEST);
+ SetThreadPriority(THREAD_PRIORITY_NORMAL);
+ CheckWork(pblock, *pwallet, reservekey);
+ SetThreadPriority(THREAD_PRIORITY_LOWEST);
- // In regression test mode, stop mining after a block is found. This
- // allows developers to controllably generate a block on demand.
- if (Params().NetworkID() == CChainParams::REGTEST)
- throw boost::thread_interrupted();
+ // In regression test mode, stop mining after a block is found.
+ if (Params().MineBlocksOnDemand())
+ throw boost::thread_interrupted();
- break;
+ break;
+ }
}
- }
- // Meter hashes/sec
- static int64_t nHashCounter;
- if (nHPSTimerStart == 0)
- {
- nHPSTimerStart = GetTimeMillis();
- nHashCounter = 0;
- }
- else
- nHashCounter += nHashesDone;
- if (GetTimeMillis() - nHPSTimerStart > 4000)
- {
- static CCriticalSection cs;
+ // Meter hashes/sec
+ static int64_t nHashCounter;
+ if (nHPSTimerStart == 0)
{
- LOCK(cs);
- if (GetTimeMillis() - nHPSTimerStart > 4000)
+ nHPSTimerStart = GetTimeMillis();
+ nHashCounter = 0;
+ }
+ else
+ nHashCounter += nHashesDone;
+ if (GetTimeMillis() - nHPSTimerStart > 4000)
+ {
+ static CCriticalSection cs;
{
- dHashesPerSec = 1000.0 * nHashCounter / (GetTimeMillis() - nHPSTimerStart);
- nHPSTimerStart = GetTimeMillis();
- nHashCounter = 0;
- static int64_t nLogTime;
- if (GetTime() - nLogTime > 30 * 60)
+ LOCK(cs);
+ if (GetTimeMillis() - nHPSTimerStart > 4000)
{
- nLogTime = GetTime();
- LogPrintf("hashmeter %6.0f khash/s\n", dHashesPerSec/1000.0);
+ dHashesPerSec = 1000.0 * nHashCounter / (GetTimeMillis() - nHPSTimerStart);
+ nHPSTimerStart = GetTimeMillis();
+ nHashCounter = 0;
+ static int64_t nLogTime;
+ if (GetTime() - nLogTime > 30 * 60)
+ {
+ nLogTime = GetTime();
+ LogPrintf("hashmeter %6.0f khash/s\n", dHashesPerSec/1000.0);
+ }
}
}
}
- }
- // Check for stop or if block needs to be rebuilt
- boost::this_thread::interruption_point();
- if (vNodes.empty() && Params().NetworkID() != CChainParams::REGTEST)
- break;
- if (nBlockNonce >= 0xffff0000)
- break;
- if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
- break;
- if (pindexPrev != chainActive.Tip())
- break;
-
- // Update nTime every few seconds
- UpdateTime(*pblock, pindexPrev);
- nBlockTime = ByteReverse(pblock->nTime);
- if (TestNet())
- {
- // Changing pblock->nTime can change work required on testnet:
- nBlockBits = ByteReverse(pblock->nBits);
- hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
+ // Check for stop or if block needs to be rebuilt
+ boost::this_thread::interruption_point();
+ // Regtest mode doesn't require peers
+ if (vNodes.empty() && Params().MiningRequiresPeers())
+ break;
+ if (nNonce >= 0xffff0000)
+ break;
+ if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
+ break;
+ if (pindexPrev != chainActive.Tip())
+ break;
+
+ // Update nTime every few seconds
+ UpdateTime(*pblock, pindexPrev);
+ if (Params().AllowMinDifficultyBlocks())
+ {
+ // Changing pblock->nTime can change work required on testnet:
+ hashTarget.SetCompact(pblock->nBits);
+ }
}
}
- } }
+ }
catch (boost::thread_interrupted)
{
LogPrintf("BitcoinMiner terminated\n");
@@ -649,8 +571,9 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads)
static boost::thread_group* minerThreads = NULL;
if (nThreads < 0) {
- if (Params().NetworkID() == CChainParams::REGTEST)
- nThreads = 1;
+ // In regtest threads defaults to 1
+ if (Params().DefaultMinerThreads())
+ nThreads = Params().DefaultMinerThreads();
else
nThreads = boost::thread::hardware_concurrency();
}
@@ -670,5 +593,4 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads)
minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet));
}
-#endif
-
+#endif // ENABLE_WALLET