From 0df67f1f7ab4adfe9f0b3ba6276e737b37826464 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 31 Mar 2015 19:15:42 -0700 Subject: Simplify hash loop code --- src/miner.cpp | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) (limited to 'src/miner.cpp') diff --git a/src/miner.cpp b/src/miner.cpp index cf08b78229..44661fd13e 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -365,33 +365,23 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& // // ScanHash scans nonces looking for a hash with at least some zero bits. -// 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. +// The nonce is usually preserved between calls, but periodically the block is +// rebuilt and nNonce starts over at zero. // -bool static ScanHash(const CBlockHeader *pblock, uint32_t& nNonce, uint256 *phash) +bool static ScanHash(CBlockHeader *pblock, uint256 *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++; + pblock->nNonce++; - // 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); + *phash = (CHashWriter(SER_GETHASH, 0) << *pblock).GetHash(); // Return the nonce if the hash has at least some zero bits, // caller will check if it has enough to reach the target if (((uint16_t*)phash)[15] == 0) return true; - // If nothing found after trying for a while, return -1 - if ((nNonce & 0xfff) == 0) + // If nothing found after trying for a while, return false. + if ((pblock->nNonce & 0xfff) == 0) return false; } } @@ -478,15 +468,13 @@ void static BitcoinMiner(CWallet *pwallet) int64_t nStart = GetTime(); arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits); uint256 hash; - uint32_t nNonce = 0; while (true) { // Check if something found - if (ScanHash(pblock, nNonce, &hash)) + if (ScanHash(pblock, &hash)) { if (UintToArith256(hash) <= hashTarget) { // Found a solution - pblock->nNonce = nNonce; assert(hash == pblock->GetHash()); SetThreadPriority(THREAD_PRIORITY_NORMAL); @@ -508,7 +496,7 @@ void static BitcoinMiner(CWallet *pwallet) // Regtest mode doesn't require peers if (vNodes.empty() && Params().MiningRequiresPeers()) break; - if (nNonce >= 0xffff0000) + if (pblock->nNonce >= 0xffff0000) break; if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60) break; -- cgit v1.2.3 From 6b04508e37c5dd18cec1cd61cc4356bd208aa991 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 31 Mar 2015 20:28:28 -0700 Subject: Introduce separate 'generate' RPC call --- src/miner.cpp | 86 +++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 54 insertions(+), 32 deletions(-) (limited to 'src/miner.cpp') diff --git a/src/miner.cpp b/src/miner.cpp index 44661fd13e..fdbc47a1c3 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -372,8 +372,7 @@ bool static ScanHash(CBlockHeader *pblock, uint256 *phash) { while (true) { pblock->nNonce++; - - *phash = (CHashWriter(SER_GETHASH, 0) << *pblock).GetHash(); + *phash = pblock->GetHash(); // Return the nonce if the hash has at least some zero bits, // caller will check if it has enough to reach the target @@ -425,6 +424,56 @@ static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& rese return true; } +bool static ScanLoop(CBlock *pblock, CBlockIndex *pindexPrev, CWallet *pwallet, CReserveKey& reservekey) +{ + UpdateTime(pblock, pindexPrev); + arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits); + + uint256 hash; + if (ScanHash(pblock, &hash)) { + if (UintToArith256(hash) <= hashTarget) { + // Found a solution + SetThreadPriority(THREAD_PRIORITY_NORMAL); + LogPrintf("BitcoinMiner:\n"); + LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex(), hashTarget.GetHex()); + ProcessBlockFound(pblock, *pwallet, reservekey); + SetThreadPriority(THREAD_PRIORITY_LOWEST); + + return true; + } + } + + return false; +} + +bool MineBlock(CWallet *pwallet, uint256& hash) +{ + CReserveKey reservekey(pwallet); + unsigned int nExtraNonce = 0; + + while (true) { + CBlockIndex *pindexPrev = chainActive.Tip(); // Actually needs cs_main... + + auto_ptr pblocktemplate(CreateNewBlockWithKey(reservekey)); + if (!pblocktemplate.get()) { + return false; + } + + CBlock *pblock = &pblocktemplate->block; + IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); + + while (true) { + if (ScanLoop(pblock, pindexPrev, pwallet, reservekey)) { + hash = pblock->GetHash(); + return true; + } + boost::this_thread::interruption_point(); + if (pblock->nNonce >= 0xffff0000) + break; + } + } +} + void static BitcoinMiner(CWallet *pwallet) { LogPrintf("BitcoinMiner started\n"); @@ -448,7 +497,7 @@ void static BitcoinMiner(CWallet *pwallet) // Create new block // unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); - CBlockIndex* pindexPrev = chainActive.Tip(); + CBlockIndex* pindexPrev = chainActive.Tip(); // Actually needs cs_main... auto_ptr pblocktemplate(CreateNewBlockWithKey(reservekey)); if (!pblocktemplate.get()) @@ -466,30 +515,10 @@ void static BitcoinMiner(CWallet *pwallet) // Search // int64_t nStart = GetTime(); - arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits); - uint256 hash; while (true) { // Check if something found - if (ScanHash(pblock, &hash)) - { - if (UintToArith256(hash) <= hashTarget) - { - // Found a solution - assert(hash == pblock->GetHash()); - - SetThreadPriority(THREAD_PRIORITY_NORMAL); - LogPrintf("BitcoinMiner:\n"); - LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex(), hashTarget.GetHex()); - ProcessBlockFound(pblock, *pwallet, reservekey); - SetThreadPriority(THREAD_PRIORITY_LOWEST); - - // In regression test mode, stop mining after a block is found. - if (Params().MineBlocksOnDemand()) - throw boost::thread_interrupted(); - - break; - } - } + if (ScanLoop(pblock, pindexPrev, pwallet, reservekey)) + break; // Check for stop or if block needs to be rebuilt boost::this_thread::interruption_point(); @@ -503,13 +532,6 @@ void static BitcoinMiner(CWallet *pwallet) 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); - } } } } -- cgit v1.2.3 From e2edf95cd3f43331843676e49a82830128a95050 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 31 Mar 2015 20:35:04 -0700 Subject: Bugfix: make CreateNewBlock return pindexPrev --- src/miner.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/miner.cpp') diff --git a/src/miner.cpp b/src/miner.cpp index fdbc47a1c3..7f01918eef 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -87,7 +87,7 @@ void UpdateTime(CBlockHeader* pblock, const CBlockIndex* pindexPrev) pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus()); } -CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) +CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CBlockIndex*& pindexPrev) { // Create new block auto_ptr pblocktemplate(new CBlockTemplate()); @@ -132,7 +132,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) { LOCK2(cs_main, mempool.cs); - CBlockIndex* pindexPrev = chainActive.Tip(); + pindexPrev = chainActive.Tip(); const int nHeight = pindexPrev->nHeight + 1; CCoinsViewCache view(pcoinsTip); @@ -385,14 +385,14 @@ bool static ScanHash(CBlockHeader *pblock, uint256 *phash) } } -CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey) +CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, CBlockIndex*& pindexPrev) { CPubKey pubkey; if (!reservekey.GetReservedKey(pubkey)) return NULL; CScript scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; - return CreateNewBlock(scriptPubKey); + return CreateNewBlock(scriptPubKey, pindexPrev); } static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) @@ -452,9 +452,9 @@ bool MineBlock(CWallet *pwallet, uint256& hash) unsigned int nExtraNonce = 0; while (true) { - CBlockIndex *pindexPrev = chainActive.Tip(); // Actually needs cs_main... + CBlockIndex *pindexPrev; - auto_ptr pblocktemplate(CreateNewBlockWithKey(reservekey)); + auto_ptr pblocktemplate(CreateNewBlockWithKey(reservekey, pindexPrev)); if (!pblocktemplate.get()) { return false; } @@ -497,9 +497,9 @@ void static BitcoinMiner(CWallet *pwallet) // Create new block // unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); - CBlockIndex* pindexPrev = chainActive.Tip(); // Actually needs cs_main... + CBlockIndex* pindexPrev; - auto_ptr pblocktemplate(CreateNewBlockWithKey(reservekey)); + auto_ptr pblocktemplate(CreateNewBlockWithKey(reservekey, pindexPrev)); if (!pblocktemplate.get()) { LogPrintf("Error in BitcoinMiner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n"); -- cgit v1.2.3