From 8e165d57d9dec4f5d27478de7a862172264f664e Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 28 Jun 2016 11:26:19 +1200 Subject: [PATCH] Randomise the nonce in the block header The top and bottom 16 bits of the nonce are left clear for local use as thread flags and counters. This does not leak any more local information about the miner than is currently exposed. The cleared bits should not be considered a consensus rule, as miners are free to set all bits of the nonce however they wish. Closes #1033 --- src/miner.cpp | 82 +++++++++++++++++++++++++-------------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index 2f9caf02f..95ec6df85 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -14,6 +14,7 @@ #include "net.h" #include "pow.h" #include "primitives/transaction.h" +#include "random.h" #include "timedata.h" #include "util.h" #include "utilmoneystr.h" @@ -352,12 +353,18 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) pblock->vtx[0] = txNew; pblocktemplate->vTxFees[0] = -nFees; + // Randomise nonce + arith_uint256 nonce = UintToArith256(GetRandHash()); + // Clear the top and bottom 16 bits (for local use as thread flags and counters) + nonce <<= 32; + nonce >>= 16; + pblock->nNonce = ArithToUint256(nonce); + // Fill in header pblock->hashPrevBlock = pindexPrev->GetBlockHash(); pblock->hashReserved = uint256(); UpdateTime(pblock, Params().GetConsensus(), pindexPrev); pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus()); - pblock->nNonce = uint256(); pblock->nSolution.clear(); pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]); @@ -501,63 +508,56 @@ void static BitcoinMiner(CWallet *pwallet) // H(I||... crypto_generichash_blake2b_update(&state, (unsigned char*)&ss[0], ss.size()); - // Find valid nonce - while (true) - { - // H(I||V||... - crypto_generichash_blake2b_state curr_state; - curr_state = state; - crypto_generichash_blake2b_update(&curr_state, - pblock->nNonce.begin(), - pblock->nNonce.size()); + // H(I||V||... + crypto_generichash_blake2b_state curr_state; + curr_state = state; + crypto_generichash_blake2b_update(&curr_state, + pblock->nNonce.begin(), + pblock->nNonce.size()); - // (x_1, x_2, ...) = A(I, V, n, k) - LogPrint("pow", "Running Equihash solver with nNonce = %s\n", - pblock->nNonce.ToString()); - std::set> solns; - EhOptimisedSolve(n, k, curr_state, solns); - LogPrint("pow", "Solutions: %d\n", solns.size()); + // (x_1, x_2, ...) = A(I, V, n, k) + LogPrint("pow", "Running Equihash solver with nNonce = %s\n", + pblock->nNonce.ToString()); + std::set> solns; + EhOptimisedSolve(n, k, curr_state, solns); + LogPrint("pow", "Solutions: %d\n", solns.size()); - // Write the solution to the hash and compute the result. - for (auto soln : solns) { - pblock->nSolution = soln; + // Write the solution to the hash and compute the result. + for (auto soln : solns) { + pblock->nSolution = soln; - if (UintToArith256(pblock->GetHash()) > hashTarget) { - continue; - } - - // Found a solution - SetThreadPriority(THREAD_PRIORITY_NORMAL); - LogPrintf("ZcashMiner:\n"); - LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex()); - ProcessBlockFound(pblock, *pwallet, reservekey); - SetThreadPriority(THREAD_PRIORITY_LOWEST); - - // In regression test mode, stop mining after a block is found. - if (chainparams.MineBlocksOnDemand()) - throw boost::thread_interrupted(); - - goto updateblock; + if (UintToArith256(pblock->GetHash()) > hashTarget) { + continue; } - pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1); - if ((UintToArith256(pblock->nNonce) & 0x1) == 0) - break; + + // Found a solution + SetThreadPriority(THREAD_PRIORITY_NORMAL); + LogPrintf("ZcashMiner:\n"); + LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex()); + ProcessBlockFound(pblock, *pwallet, reservekey); + SetThreadPriority(THREAD_PRIORITY_LOWEST); + + // In regression test mode, stop mining after a block is found. + if (chainparams.MineBlocksOnDemand()) + throw boost::thread_interrupted(); + + break; } -updateblock: // Check for stop or if block needs to be rebuilt boost::this_thread::interruption_point(); // Regtest mode doesn't require peers if (vNodes.empty() && chainparams.MiningRequiresPeers()) break; - if (UintToArith256(pblock->nNonce) >= 0xffff) + if ((UintToArith256(pblock->nNonce) & 0xffff) == 0xffff) break; if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60) break; if (pindexPrev != chainActive.Tip()) break; - // Update nTime every few seconds + // Update nNonce and nTime + pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1); UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); if (chainparams.GetConsensus().fPowAllowMinDifficultyBlocks) {