Skip to content

Commit 08ab065

Browse files
committed
merge bitcoin#26308: reduce LOCK(cs_main) scope: ~6 times as many requests per second
1 parent 0e507b6 commit 08ab065

File tree

4 files changed

+27
-29
lines changed

4 files changed

+27
-29
lines changed

src/rest.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,9 +316,10 @@ static bool rest_block(const CoreContext& context,
316316

317317
if (chainman.m_blockman.IsBlockPruned(pblockindex))
318318
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not available (pruned data)");
319+
}
319320

320-
if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus()))
321-
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
321+
if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) {
322+
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
322323
}
323324

324325
switch (rf) {

src/rpc/blockchain.cpp

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ UniValue blockToJSON(BlockManager& blockman, const CBlock& block, const CBlockIn
170170
case TxVerbosity::SHOW_DETAILS:
171171
case TxVerbosity::SHOW_DETAILS_AND_PREVOUT:
172172
CBlockUndo blockUndo;
173-
const bool have_undo{WITH_LOCK(::cs_main, return !blockman.IsBlockPruned(blockindex) && UndoReadFromDisk(blockUndo, blockindex))};
173+
const bool is_not_pruned{WITH_LOCK(::cs_main, return !blockman.IsBlockPruned(blockindex))};
174+
const bool have_undo{is_not_pruned && UndoReadFromDisk(blockUndo, blockindex)};
174175

175176
for (size_t i = 0; i < block.vtx.size(); ++i) {
176177
const CTransactionRef& tx = block.vtx.at(i);
@@ -762,34 +763,38 @@ static RPCHelpMan getblockheaders()
762763
};
763764
}
764765

765-
static CBlock GetBlockChecked(BlockManager& blockman, const CBlockIndex* pblockindex) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
766+
static CBlock GetBlockChecked(BlockManager& blockman, const CBlockIndex* pblockindex)
766767
{
767-
AssertLockHeld(::cs_main);
768768
CBlock block;
769-
if (blockman.IsBlockPruned(pblockindex)) {
770-
throw JSONRPCError(RPC_MISC_ERROR, "Block not available (pruned data)");
769+
{
770+
LOCK(cs_main);
771+
if (blockman.IsBlockPruned(pblockindex)) {
772+
throw JSONRPCError(RPC_MISC_ERROR, "Block not available (pruned data)");
773+
}
771774
}
772775

773776
if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) {
774777
// Block not found on disk. This could be because we have the block
775778
// header in our index but not yet have the block or did not accept the
776-
// block.
779+
// block. Or if the block was pruned right after we released the lock above.
777780
throw JSONRPCError(RPC_MISC_ERROR, "Block not found on disk");
778781
}
779782

780783
return block;
781784
}
782785

783-
static CBlockUndo GetUndoChecked(BlockManager& blockman, const CBlockIndex* pblockindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
786+
static CBlockUndo GetUndoChecked(BlockManager& blockman, const CBlockIndex* pblockindex)
784787
{
785-
AssertLockHeld(::cs_main);
786788
CBlockUndo blockUndo;
787789

788790
// The Genesis block does not have undo data
789791
if (pblockindex->nHeight == 0) return blockUndo;
790792

791-
if (blockman.IsBlockPruned(pblockindex)) {
792-
throw JSONRPCError(RPC_MISC_ERROR, "Undo data not available (pruned data)");
793+
{
794+
LOCK(cs_main);
795+
if (blockman.IsBlockPruned(pblockindex)) {
796+
throw JSONRPCError(RPC_MISC_ERROR, "Undo data not available (pruned data)");
797+
}
793798
}
794799

795800
if (!UndoReadFromDisk(blockUndo, pblockindex)) {
@@ -982,7 +987,6 @@ static RPCHelpMan getblock()
982987

983988
const NodeContext& node = EnsureAnyNodeContext(request.context);
984989

985-
CBlock block;
986990
const CBlockIndex* pblockindex;
987991
const CBlockIndex* tip;
988992
ChainstateManager& chainman = EnsureChainman(node);
@@ -994,10 +998,10 @@ static RPCHelpMan getblock()
994998
if (!pblockindex) {
995999
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
9961000
}
997-
998-
block = GetBlockChecked(chainman.m_blockman, pblockindex);
9991001
}
10001002

1003+
const CBlock block{GetBlockChecked(chainman.m_blockman, pblockindex)};
1004+
10011005
if (verbosity <= 0)
10021006
{
10031007
CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
@@ -2023,7 +2027,6 @@ static RPCHelpMan getblockstats()
20232027
}
20242028

20252029
ChainstateManager& chainman = EnsureAnyChainman(request.context);
2026-
LOCK(cs_main);
20272030
const CBlockIndex& pindex{*CHECK_NONFATAL(ParseHashOrHeight(request.params[0], chainman))};
20282031

20292032
std::set<std::string> stats;

src/rpc/txoutproof.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,12 @@ static RPCHelpMan gettxoutproof()
8585
g_txindex->BlockUntilSyncedToCurrentChain();
8686
}
8787

88-
LOCK(cs_main);
89-
9088
if (pblockindex == nullptr) {
9189
const CTransactionRef tx = GetTransaction(/* block_index */ nullptr, /* mempool */ nullptr, *setTxids.begin(), Params().GetConsensus(), hashBlock);
9290
if (!tx || hashBlock.IsNull()) {
9391
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not yet in block");
9492
}
95-
pblockindex = chainman.m_blockman.LookupBlockIndex(hashBlock);
93+
pblockindex = WITH_LOCK(::cs_main, return chainman.m_blockman.LookupBlockIndex(hashBlock));
9694
if (!pblockindex) {
9795
throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction index corrupt");
9896
}

src/zmq/zmqpublishnotifier.cpp

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -310,18 +310,14 @@ bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
310310

311311
const Consensus::Params& consensusParams = Params().GetConsensus();
312312
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
313-
{
314-
LOCK(cs_main);
315-
CBlock block;
316-
if(!ReadBlockFromDisk(block, pindex, consensusParams))
317-
{
318-
zmqError("Can't read block from disk");
319-
return false;
320-
}
321-
322-
ss << block;
313+
CBlock block;
314+
if(!ReadBlockFromDisk(block, pindex, consensusParams)) {
315+
zmqError("Can't read block from disk");
316+
return false;
323317
}
324318

319+
ss << block;
320+
325321
return SendZmqMessage(MSG_RAWBLOCK, &(*ss.begin()), ss.size());
326322
}
327323

0 commit comments

Comments
 (0)