Skip to content

Commit a3168e7

Browse files
committed
[Mining] IncrementExtraNonce without cs_main
Removes the `cs_main` lock usage from the nonce setup in the miners. The chain tip is only used for getting the Height of the tip, so instead we can just retrieve the height directly. This requires a change to the signature of `IncrementExtraNonce`. The other item cs_main was protecting is the static `prevHeaderHash`; this is only used to reset `nExtraNonce`. However, `nExtraNonce` is thread-local, so the thread nonces will increment indefinitely, with the occasional 0 thrown in. This is therefore unnecessary--and rarely may result in a race: - Thread 1: creates block template on block N-1 - Thread 2: accepts new block N - Thread 3: creates block template on block N, resets local nonce - Thread 1: resets local nonce - Thread 4: creates block template on block N, resets local nonce Thread 1 is doing useless work on the old block, this happens. Threads 3 and 4 are doing the same work since they have the same nonce. (If I understand right, and the nonces are used here mainly to give the threads distinct works sets, I believe this means actually incrementing `nExtraNonce` is unnecessary, since we take `cs_nonce` to increment `nNonce_base` in order to give each thread a unique nonce. We would need to rename `IncrementExtraNonce` to describe what it's actually doing then.) Removes one extraneous copy of the nonce into a thread local variable (there were previously two, and I suspect the extra was already being optimized away).
1 parent 7e19268 commit a3168e7

File tree

4 files changed

+11
-33
lines changed

4 files changed

+11
-33
lines changed

src/miner.cpp

+7-23
Original file line numberDiff line numberDiff line change
@@ -814,19 +814,13 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
814814
}
815815
}
816816

817-
void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce)
817+
void IncrementExtraNonce(CBlock* pblock, unsigned int nHeight, unsigned int& nExtraNonce)
818818
{
819819
// Update nExtraNonce
820-
static uint256 hashPrevBlock;
821-
if (hashPrevBlock != pblock->hashPrevBlock)
822-
{
823-
nExtraNonce = 0;
824-
hashPrevBlock = pblock->hashPrevBlock;
825-
}
826820
++nExtraNonce;
827-
unsigned int nHeight = pindexPrev->nHeight+1; // Height first in coinbase required for block.version=2
828821
CMutableTransaction txCoinbase(*pblock->vtx[0]);
829-
txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
822+
// Height first in coinbase required for block.version=2
823+
txCoinbase.vin[0].scriptSig = (CScript() << (nHeight+1) << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
830824
assert(txCoinbase.vin[0].scriptSig.size() <= 100);
831825

832826
pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase));
@@ -964,24 +958,19 @@ void BitcoinMiner(std::shared_ptr<CReserveScript> coinbaseScript, bool fProofOfS
964958
}
965959

966960
CBlock *pblock = &pblocktemplate->block;
967-
int32_t nNonceLocal;
968961

969962
if (!fProofOfStake)
970963
{
971964
{
972965
LOCK(cs_nonce);
973-
nNonceLocal = nNonce_base++;
966+
nExtraNonce = nNonce_base++;
974967
if (!nTimeStart)
975968
nTimeStart = GetTime();
976969
}
977970

978971
pblock->nNonce = 0;
979972
pblock->nNonce64 = rand();
980-
{
981-
LOCK(cs_main);
982-
nExtraNonce = nNonceLocal;
983-
IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce);
984-
}
973+
IncrementExtraNonce(pblock, chainActive.Height(), nExtraNonce);
985974

986975
int nTries = 0;
987976
if (pblock->IsProgPow() && pblock->nTime >= Params().PowUpdateTimestamp()) {
@@ -1073,21 +1062,16 @@ void BitcoinRandomXMiner(std::shared_ptr<CReserveScript> coinbaseScript, int vm_
10731062
continue;
10741063

10751064
CBlock *pblock = &pblocktemplate->block;
1076-
int32_t nNonceLocal;
10771065

10781066
{
10791067
LOCK(cs_nonce);
1080-
nNonceLocal = nNonce_base++;
1068+
nExtraNonce = nNonce_base++;
10811069
if (!nTimeStart)
10821070
nTimeStart = GetTime();
10831071
}
10841072

10851073
pblock->nNonce = startNonce;
1086-
{
1087-
LOCK(cs_main);
1088-
nExtraNonce = nNonceLocal;
1089-
IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce);
1090-
}
1074+
IncrementExtraNonce(pblock, chainActive.Height(), nExtraNonce);
10911075

10921076
int nTries = 0;
10931077
if (pblock->IsRandomX() && pblock->nTime >= Params().PowUpdateTimestamp()) {

src/miner.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ bool GenerateActive();
247247
void setGenerate(bool fGenerate);
248248

249249
/** Modify the extranonce in a block */
250-
void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
250+
void IncrementExtraNonce(CBlock* pblock, unsigned int nHeight, unsigned int& nExtraNonce);
251251
int64_t UpdateTime(CBlock* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev);
252252
void GenerateBitcoins(bool fGenerate, int nThreads, std::shared_ptr<CReserveScript> coinbaseScript);
253253
void ThreadStakeMiner();

src/rpc/mining.cpp

+1-4
Original file line numberDiff line numberDiff line change
@@ -220,10 +220,7 @@ UniValue generateBlocks(std::shared_ptr<CReserveScript> coinbaseScript, int nGen
220220
if (!pblocktemplate.get())
221221
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
222222
CBlock *pblock = &pblocktemplate->block;
223-
{
224-
LOCK(cs_main);
225-
IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce);
226-
}
223+
IncrementExtraNonce(pblock, chainActive.Height(), nExtraNonce);
227224

228225
// This will check if the key block needs to change and will take down the cache and vm, and spin up the new ones
229226
CheckIfValidationKeyShouldChangeAndUpdate(GetKeyBlock(pblock->nHeight));

src/test/test_veil.cpp

+2-5
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,8 @@ TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>&
155155
for (const CMutableTransaction& tx : txns)
156156
block.vtx.push_back(MakeTransactionRef(tx));
157157
// IncrementExtraNonce creates a valid coinbase and merkleRoot
158-
{
159-
LOCK(cs_main);
160-
unsigned int extraNonce = 0;
161-
IncrementExtraNonce(&block, chainActive.Tip(), extraNonce);
162-
}
158+
unsigned int extraNonce = 0;
159+
IncrementExtraNonce(&block, chainActive.Height(), extraNonce);
163160

164161
while (!CheckProofOfWork(block.GetX16RTPoWHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce;
165162

0 commit comments

Comments
 (0)