Skip to content

Commit 4f4528c

Browse files
committed
[Mining] IncrementExtraNonce without cs_main
Changes the signature of IncrementExtraNonce: Of the values used by IncrementExtraNonce, cs_main only protects the chain tip; the rest are entirely local to the thread. The chain tip, in turn, is only used for getting the Height of the tip. Thus, we can hold cs_main only to get the Height, then perform the work without holding the lock. (Noting that not all accesses to `chainActive.Height()` are locked, so if it's safe, we could remove this usage of cs_main entirely.) 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 cee49d6 commit 4f4528c

File tree

4 files changed

+23
-15
lines changed

4 files changed

+23
-15
lines changed

src/miner.cpp

+13-11
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,7 @@ 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
820820
static uint256 hashPrevBlock;
@@ -824,9 +824,9 @@ void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned
824824
hashPrevBlock = pblock->hashPrevBlock;
825825
}
826826
++nExtraNonce;
827-
unsigned int nHeight = pindexPrev->nHeight+1; // Height first in coinbase required for block.version=2
828827
CMutableTransaction txCoinbase(*pblock->vtx[0]);
829-
txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
828+
// Height first in coinbase required for block.version=2
829+
txCoinbase.vin[0].scriptSig = (CScript() << (nHeight+1) << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
830830
assert(txCoinbase.vin[0].scriptSig.size() <= 100);
831831

832832
pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase));
@@ -964,24 +964,25 @@ void BitcoinMiner(std::shared_ptr<CReserveScript> coinbaseScript, bool fProofOfS
964964
}
965965

966966
CBlock *pblock = &pblocktemplate->block;
967-
int32_t nNonceLocal;
968967

969968
if (!fProofOfStake)
970969
{
971970
{
972971
LOCK(cs_nonce);
973-
nNonceLocal = nNonce_base++;
972+
nExtraNonce = nNonce_base++;
974973
if (!nTimeStart)
975974
nTimeStart = GetTime();
976975
}
977976

978977
pblock->nNonce = 0;
979978
pblock->nNonce64 = rand();
979+
// Avoid holding cs_main during IncrementExtraNonce which doesn't require it.
980+
unsigned int nHeight;
980981
{
981982
LOCK(cs_main);
982-
nExtraNonce = nNonceLocal;
983-
IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce);
983+
nHeight = chainActive.Height();
984984
}
985+
IncrementExtraNonce(pblock, nHeight, nExtraNonce);
985986

986987
int nTries = 0;
987988
if (pblock->IsProgPow() && pblock->nTime >= Params().PowUpdateTimestamp()) {
@@ -1073,21 +1074,22 @@ void BitcoinRandomXMiner(std::shared_ptr<CReserveScript> coinbaseScript, int vm_
10731074
continue;
10741075

10751076
CBlock *pblock = &pblocktemplate->block;
1076-
int32_t nNonceLocal;
10771077

10781078
{
10791079
LOCK(cs_nonce);
1080-
nNonceLocal = nNonce_base++;
1080+
nExtraNonce = nNonce_base++;
10811081
if (!nTimeStart)
10821082
nTimeStart = GetTime();
10831083
}
10841084

10851085
pblock->nNonce = startNonce;
1086+
// Avoid holding cs_main during IncrementExtraNonce which doesn't require it.
1087+
unsigned int nHeight;
10861088
{
10871089
LOCK(cs_main);
1088-
nExtraNonce = nNonceLocal;
1089-
IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce);
1090+
nHeight = chainActive.Height();
10901091
}
1092+
IncrementExtraNonce(pblock, nHeight, nExtraNonce);
10911093

10921094
int nTries = 0;
10931095
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

+4-1
Original file line numberDiff line numberDiff line change
@@ -220,10 +220,13 @@ 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+
// Avoid holding cs_main during IncrementExtraNonce
224+
unsigned int nChainHeight;
223225
{
224226
LOCK(cs_main);
225-
IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce);
227+
nChainHeight = chainActive.Height();
226228
}
229+
IncrementExtraNonce(pblock, nChainHeight, nExtraNonce);
227230

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

src/test/test_veil.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,14 @@ 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+
// Avoid holding cs_main during IncrementExtraNonce
159+
unsigned int nHeight;
158160
{
159161
LOCK(cs_main);
160-
unsigned int extraNonce = 0;
161-
IncrementExtraNonce(&block, chainActive.Tip(), extraNonce);
162+
nHeight = chainActive.Height();
162163
}
164+
unsigned int extraNonce = 0;
165+
IncrementExtraNonce(&block, nHeight, extraNonce);
163166

164167
while (!CheckProofOfWork(block.GetX16RTPoWHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce;
165168

0 commit comments

Comments
 (0)