@@ -87,7 +87,7 @@ void UpdateTime(CBlockHeader* pblock, const CBlockIndex* pindexPrev)
8787 pblock->nBits = GetNextWorkRequired (pindexPrev, pblock, Params ().GetConsensus ());
8888}
8989
90- CBlockTemplate* CreateNewBlock (const CScript& scriptPubKeyIn, CBlockIndex*& pindexPrev )
90+ CBlockTemplate* CreateNewBlock (const CScript& scriptPubKeyIn)
9191{
9292 // Create new block
9393 auto_ptr<CBlockTemplate> pblocktemplate (new CBlockTemplate ());
@@ -132,7 +132,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CBlockIndex*& pind
132132
133133 {
134134 LOCK2 (cs_main, mempool.cs );
135- pindexPrev = chainActive.Tip ();
135+ CBlockIndex* pindexPrev = chainActive.Tip ();
136136 const int nHeight = pindexPrev->nHeight + 1 ;
137137 CCoinsViewCache view (pcoinsTip);
138138
@@ -365,34 +365,45 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
365365
366366//
367367// ScanHash scans nonces looking for a hash with at least some zero bits.
368- // The nonce is usually preserved between calls, but periodically the block is
369- // rebuilt and nNonce starts over at zero.
368+ // The nonce is usually preserved between calls, but periodically or if the
369+ // nonce is 0xffff0000 or above, the block is rebuilt and nNonce starts over at
370+ // zero.
370371//
371- bool static ScanHash (CBlockHeader *pblock, uint256 *phash)
372+ bool static ScanHash (const CBlockHeader *pblock, uint32_t & nNonce , uint256 *phash)
372373{
374+ // Write the first 76 bytes of the block header to a double-SHA256 state.
375+ CHash256 hasher;
376+ CDataStream ss (SER_NETWORK, PROTOCOL_VERSION);
377+ ss << *pblock;
378+ assert (ss.size () == 80 );
379+ hasher.Write ((unsigned char *)&ss[0 ], 76 );
380+
373381 while (true ) {
374- pblock->nNonce ++;
375- *phash = pblock->GetHash ();
382+ nNonce++;
383+
384+ // Write the last 4 bytes of the block header (the nonce) to a copy of
385+ // the double-SHA256 state, and compute the result.
386+ CHash256 (hasher).Write ((unsigned char *)&nNonce, 4 ).Finalize ((unsigned char *)phash);
376387
377388 // Return the nonce if the hash has at least some zero bits,
378389 // caller will check if it has enough to reach the target
379390 if (((uint16_t *)phash)[15 ] == 0 )
380391 return true ;
381392
382- // If nothing found after trying for a while, return false.
383- if ((pblock-> nNonce & 0xfff ) == 0 )
393+ // If nothing found after trying for a while, return -1
394+ if ((nNonce & 0xfff ) == 0 )
384395 return false ;
385396 }
386397}
387398
388- CBlockTemplate* CreateNewBlockWithKey (CReserveKey& reservekey, CBlockIndex*& pindexPrev )
399+ CBlockTemplate* CreateNewBlockWithKey (CReserveKey& reservekey)
389400{
390401 CPubKey pubkey;
391402 if (!reservekey.GetReservedKey (pubkey))
392403 return NULL ;
393404
394405 CScript scriptPubKey = CScript () << ToByteVector (pubkey) << OP_CHECKSIG;
395- return CreateNewBlock (scriptPubKey, pindexPrev );
406+ return CreateNewBlock (scriptPubKey);
396407}
397408
398409static bool ProcessBlockFound (CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
@@ -424,56 +435,6 @@ static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& rese
424435 return true ;
425436}
426437
427- bool static ScanLoop (CBlock *pblock, CBlockIndex *pindexPrev, CWallet *pwallet, CReserveKey& reservekey)
428- {
429- UpdateTime (pblock, pindexPrev);
430- arith_uint256 hashTarget = arith_uint256 ().SetCompact (pblock->nBits );
431-
432- uint256 hash;
433- if (ScanHash (pblock, &hash)) {
434- if (UintToArith256 (hash) <= hashTarget) {
435- // Found a solution
436- SetThreadPriority (THREAD_PRIORITY_NORMAL);
437- LogPrintf (" BitcoinMiner:\n " );
438- LogPrintf (" proof-of-work found \n hash: %s \n target: %s\n " , hash.GetHex (), hashTarget.GetHex ());
439- ProcessBlockFound (pblock, *pwallet, reservekey);
440- SetThreadPriority (THREAD_PRIORITY_LOWEST);
441-
442- return true ;
443- }
444- }
445-
446- return false ;
447- }
448-
449- bool MineBlock (CWallet *pwallet, uint256& hash)
450- {
451- CReserveKey reservekey (pwallet);
452- unsigned int nExtraNonce = 0 ;
453-
454- while (true ) {
455- CBlockIndex *pindexPrev;
456-
457- auto_ptr<CBlockTemplate> pblocktemplate (CreateNewBlockWithKey (reservekey, pindexPrev));
458- if (!pblocktemplate.get ()) {
459- return false ;
460- }
461-
462- CBlock *pblock = &pblocktemplate->block ;
463- IncrementExtraNonce (pblock, pindexPrev, nExtraNonce);
464-
465- while (true ) {
466- if (ScanLoop (pblock, pindexPrev, pwallet, reservekey)) {
467- hash = pblock->GetHash ();
468- return true ;
469- }
470- boost::this_thread::interruption_point ();
471- if (pblock->nNonce >= 0xffff0000 )
472- break ;
473- }
474- }
475- }
476-
477438void static BitcoinMiner (CWallet *pwallet)
478439{
479440 LogPrintf (" BitcoinMiner started\n " );
@@ -497,9 +458,9 @@ void static BitcoinMiner(CWallet *pwallet)
497458 // Create new block
498459 //
499460 unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated ();
500- CBlockIndex* pindexPrev;
461+ CBlockIndex* pindexPrev = chainActive. Tip () ;
501462
502- auto_ptr<CBlockTemplate> pblocktemplate (CreateNewBlockWithKey (reservekey, pindexPrev ));
463+ auto_ptr<CBlockTemplate> pblocktemplate (CreateNewBlockWithKey (reservekey));
503464 if (!pblocktemplate.get ())
504465 {
505466 LogPrintf (" Error in BitcoinMiner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n " );
@@ -515,23 +476,52 @@ void static BitcoinMiner(CWallet *pwallet)
515476 // Search
516477 //
517478 int64_t nStart = GetTime ();
479+ arith_uint256 hashTarget = arith_uint256 ().SetCompact (pblock->nBits );
480+ uint256 hash;
481+ uint32_t nNonce = 0 ;
518482 while (true ) {
519483 // Check if something found
520- if (ScanLoop (pblock, pindexPrev, pwallet, reservekey))
521- break ;
484+ if (ScanHash (pblock, nNonce, &hash))
485+ {
486+ if (UintToArith256 (hash) <= hashTarget)
487+ {
488+ // Found a solution
489+ pblock->nNonce = nNonce;
490+ assert (hash == pblock->GetHash ());
491+
492+ SetThreadPriority (THREAD_PRIORITY_NORMAL);
493+ LogPrintf (" BitcoinMiner:\n " );
494+ LogPrintf (" proof-of-work found \n hash: %s \n target: %s\n " , hash.GetHex (), hashTarget.GetHex ());
495+ ProcessBlockFound (pblock, *pwallet, reservekey);
496+ SetThreadPriority (THREAD_PRIORITY_LOWEST);
497+
498+ // In regression test mode, stop mining after a block is found.
499+ if (Params ().MineBlocksOnDemand ())
500+ throw boost::thread_interrupted ();
501+
502+ break ;
503+ }
504+ }
522505
523506 // Check for stop or if block needs to be rebuilt
524507 boost::this_thread::interruption_point ();
525508 // Regtest mode doesn't require peers
526509 if (vNodes.empty () && Params ().MiningRequiresPeers ())
527510 break ;
528- if (pblock-> nNonce >= 0xffff0000 )
511+ if (nNonce >= 0xffff0000 )
529512 break ;
530513 if (mempool.GetTransactionsUpdated () != nTransactionsUpdatedLast && GetTime () - nStart > 60 )
531514 break ;
532515 if (pindexPrev != chainActive.Tip ())
533516 break ;
534517
518+ // Update nTime every few seconds
519+ UpdateTime (pblock, pindexPrev);
520+ if (Params ().AllowMinDifficultyBlocks ())
521+ {
522+ // Changing pblock->nTime can change work required on testnet:
523+ hashTarget.SetCompact (pblock->nBits );
524+ }
535525 }
536526 }
537527 }
0 commit comments