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
This commit is contained in:
Jack Grigg 2016-06-28 11:26:19 +12:00
parent 658cdb15f7
commit 8e165d57d9
1 changed files with 41 additions and 41 deletions

View File

@ -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,9 +508,6 @@ 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;
@ -537,27 +541,23 @@ void static BitcoinMiner(CWallet *pwallet)
if (chainparams.MineBlocksOnDemand())
throw boost::thread_interrupted();
goto updateblock;
}
pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1);
if ((UintToArith256(pblock->nNonce) & 0x1) == 0)
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)
{