Skip to content

Commit 48265f3

Browse files
committed
Revert mining changes in #5957
This reverts commit e2edf95 6b04508 0df67f1, except the changes to the RPC tests. A `generate` RPC call is introduced based on the old code.
1 parent 4ac79f9 commit 48265f3

File tree

4 files changed

+97
-91
lines changed

4 files changed

+97
-91
lines changed

src/miner.cpp

Lines changed: 56 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -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

398409
static 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 \ntarget: %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-
477438
void 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 \ntarget: %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
}

src/miner.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,9 @@ struct CBlockTemplate
2424

2525
/** Run the miner threads */
2626
void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads);
27-
/** Create a single block */
28-
bool MineBlock(CWallet *pwallet, uint256& hash);
2927
/** Generate a new block, without valid proof-of-work */
30-
CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CBlockIndex*& pindexPrev);
31-
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, CBlockIndex*& pindexPrev);
28+
CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn);
29+
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey);
3230
/** Modify the extranonce in a block */
3331
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
3432
void UpdateTime(CBlockHeader* block, const CBlockIndex* pindexPrev);

src/rpcmining.cpp

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ Value generate(const Array& params, bool fHelp)
119119
throw runtime_error(
120120
"generate numblocks\n"
121121
"\nMine blocks immediately (before the RPC call returns)\n"
122+
"\nNote: this function can only be used on the regtest network\n"
122123
"1. numblocks (numeric) How many blocks are generated immediately.\n"
123124
"\nResult\n"
124125
"[ blockhashes ] (array) hashes of blocks generated\n"
@@ -129,30 +130,48 @@ Value generate(const Array& params, bool fHelp)
129130

130131
if (pwalletMain == NULL)
131132
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
133+
if (!Params().MineBlocksOnDemand())
134+
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "This method can only be used on regtest");
132135

133136
int nHeightStart = 0;
134137
int nHeightEnd = 0;
135138
int nHeight = 0;
136139
int nGenerate = params[0].get_int();
140+
CReserveKey reservekey(pwalletMain);
137141

138142
{ // Don't keep cs_main locked
139143
LOCK(cs_main);
140144
nHeightStart = chainActive.Height();
141145
nHeight = nHeightStart;
142146
nHeightEnd = nHeightStart+nGenerate;
143147
}
148+
unsigned int nExtraNonce = 0;
144149
Array blockHashes;
145-
while (nHeight < nHeightEnd) {
146-
uint256 hash;
147-
if (!MineBlock(pwalletMain, hash))
150+
while (nHeight < nHeightEnd)
151+
{
152+
auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
153+
if (!pblocktemplate.get())
148154
throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet keypool empty");
149-
155+
CBlock *pblock = &pblocktemplate->block;
156+
{
157+
LOCK(cs_main);
158+
IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce);
159+
}
160+
while (!CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus())) {
161+
// Yes, there is a chance every nonce could fail to satisfy the -regtest
162+
// target -- 1 in 2^(2^32). That ain't gonna happen.
163+
++pblock->nNonce;
164+
}
165+
CValidationState state;
166+
if (!ProcessNewBlock(state, NULL, pblock))
167+
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
150168
++nHeight;
151-
blockHashes.push_back(hash.GetHex());
169+
blockHashes.push_back(pblock->GetHash().GetHex());
152170
}
153171
return blockHashes;
154172
}
155173

174+
156175
Value setgenerate(const Array& params, bool fHelp)
157176
{
158177
if (fHelp || params.size() < 1 || params.size() > 2)
@@ -475,7 +494,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
475494

476495
// Store the pindexBest used before CreateNewBlock, to avoid races
477496
nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
478-
CBlockIndex* pindexPrevNew;
497+
CBlockIndex* pindexPrevNew = chainActive.Tip();
479498
nStart = GetTime();
480499

481500
// Create new block
@@ -485,7 +504,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
485504
pblocktemplate = NULL;
486505
}
487506
CScript scriptDummy = CScript() << OP_TRUE;
488-
pblocktemplate = CreateNewBlock(scriptDummy, pindexPrevNew);
507+
pblocktemplate = CreateNewBlock(scriptDummy);
489508
if (!pblocktemplate)
490509
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
491510

0 commit comments

Comments
 (0)