@@ -87,7 +87,7 @@ void UpdateTime(CBlockHeader* pblock, const CBlockIndex* pindexPrev)
87
87
pblock->nBits = GetNextWorkRequired (pindexPrev, pblock, Params ().GetConsensus ());
88
88
}
89
89
90
- CBlockTemplate* CreateNewBlock (const CScript& scriptPubKeyIn, CBlockIndex*& pindexPrev )
90
+ CBlockTemplate* CreateNewBlock (const CScript& scriptPubKeyIn)
91
91
{
92
92
// Create new block
93
93
auto_ptr<CBlockTemplate> pblocktemplate (new CBlockTemplate ());
@@ -132,7 +132,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CBlockIndex*& pind
132
132
133
133
{
134
134
LOCK2 (cs_main, mempool.cs );
135
- pindexPrev = chainActive.Tip ();
135
+ CBlockIndex* pindexPrev = chainActive.Tip ();
136
136
const int nHeight = pindexPrev->nHeight + 1 ;
137
137
CCoinsViewCache view (pcoinsTip);
138
138
@@ -365,34 +365,45 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
365
365
366
366
//
367
367
// 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.
370
371
//
371
- bool static ScanHash (CBlockHeader *pblock, uint256 *phash)
372
+ bool static ScanHash (const CBlockHeader *pblock, uint32_t & nNonce , uint256 *phash)
372
373
{
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
+
373
381
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);
376
387
377
388
// Return the nonce if the hash has at least some zero bits,
378
389
// caller will check if it has enough to reach the target
379
390
if (((uint16_t *)phash)[15 ] == 0 )
380
391
return true ;
381
392
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 )
384
395
return false ;
385
396
}
386
397
}
387
398
388
- CBlockTemplate* CreateNewBlockWithKey (CReserveKey& reservekey, CBlockIndex*& pindexPrev )
399
+ CBlockTemplate* CreateNewBlockWithKey (CReserveKey& reservekey)
389
400
{
390
401
CPubKey pubkey;
391
402
if (!reservekey.GetReservedKey (pubkey))
392
403
return NULL ;
393
404
394
405
CScript scriptPubKey = CScript () << ToByteVector (pubkey) << OP_CHECKSIG;
395
- return CreateNewBlock (scriptPubKey, pindexPrev );
406
+ return CreateNewBlock (scriptPubKey);
396
407
}
397
408
398
409
static bool ProcessBlockFound (CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
@@ -424,56 +435,6 @@ static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& rese
424
435
return true ;
425
436
}
426
437
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
-
477
438
void static BitcoinMiner (CWallet *pwallet)
478
439
{
479
440
LogPrintf (" BitcoinMiner started\n " );
@@ -497,9 +458,9 @@ void static BitcoinMiner(CWallet *pwallet)
497
458
// Create new block
498
459
//
499
460
unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated ();
500
- CBlockIndex* pindexPrev;
461
+ CBlockIndex* pindexPrev = chainActive. Tip () ;
501
462
502
- auto_ptr<CBlockTemplate> pblocktemplate (CreateNewBlockWithKey (reservekey, pindexPrev ));
463
+ auto_ptr<CBlockTemplate> pblocktemplate (CreateNewBlockWithKey (reservekey));
503
464
if (!pblocktemplate.get ())
504
465
{
505
466
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)
515
476
// Search
516
477
//
517
478
int64_t nStart = GetTime ();
479
+ arith_uint256 hashTarget = arith_uint256 ().SetCompact (pblock->nBits );
480
+ uint256 hash;
481
+ uint32_t nNonce = 0 ;
518
482
while (true ) {
519
483
// 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
+ }
522
505
523
506
// Check for stop or if block needs to be rebuilt
524
507
boost::this_thread::interruption_point ();
525
508
// Regtest mode doesn't require peers
526
509
if (vNodes.empty () && Params ().MiningRequiresPeers ())
527
510
break ;
528
- if (pblock-> nNonce >= 0xffff0000 )
511
+ if (nNonce >= 0xffff0000 )
529
512
break ;
530
513
if (mempool.GetTransactionsUpdated () != nTransactionsUpdatedLast && GetTime () - nStart > 60 )
531
514
break ;
532
515
if (pindexPrev != chainActive.Tip ())
533
516
break ;
534
517
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
+ }
535
525
}
536
526
}
537
527
}
0 commit comments