Skip to content

Commit 94daebf

Browse files
author
MarcoFalke
committed
Merge bitcoin#15932: rpc: Serialize in getblock without cs_main
faea564 rpc: Add lock annotations to block{,header}ToJSON (MarcoFalke) fab00a5 rpc: Serialize in getblock without cs_main (MarcoFalke) fa1c359 rpc: Use IsValidNumArgs in getblock (MarcoFalke) Pull request description: No need to hold cs_main when serializing a struct to json Fixes: bitcoin#15925 ACKs for commit faea56: jnewbery: utACK faea564 jonasschnelli: utACK faea564 Tree-SHA512: 005d378cda1e6024e9f5142f99a8adbefe202cd7bfeaafee55eb909e8990a3790aa27fcf5dd16119cc9afe9dc8bd30f660de40233316781669be166bac3018e7
2 parents 24dfcf3 + faea564 commit 94daebf

File tree

2 files changed

+33
-15
lines changed

2 files changed

+33
-15
lines changed

src/rpc/blockchain.cpp

+25-11
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ static int ComputeNextBlockAndDepth(const CBlockIndex* tip, const CBlockIndex* b
9393

9494
UniValue blockheaderToJSON(const CBlockIndex* tip, const CBlockIndex* blockindex)
9595
{
96+
// Serialize passed information without accessing chain state of the active chain!
97+
AssertLockNotHeld(cs_main); // For performance reasons
98+
9699
UniValue result(UniValue::VOBJ);
97100
result.pushKV("hash", blockindex->GetBlockHash().GetHex());
98101
const CBlockIndex* pnext;
@@ -119,6 +122,9 @@ UniValue blockheaderToJSON(const CBlockIndex* tip, const CBlockIndex* blockindex
119122

120123
UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIndex* blockindex, bool txDetails)
121124
{
125+
// Serialize passed information without accessing chain state of the active chain!
126+
AssertLockNotHeld(cs_main); // For performance reasons
127+
122128
UniValue result(UniValue::VOBJ);
123129
result.pushKV("hash", blockindex->GetBlockHash().GetHex());
124130
const CBlockIndex* pnext;
@@ -824,9 +830,7 @@ static CBlock GetBlockChecked(const CBlockIndex* pblockindex)
824830

825831
static UniValue getblock(const JSONRPCRequest& request)
826832
{
827-
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
828-
throw std::runtime_error(
829-
RPCHelpMan{"getblock",
833+
const RPCHelpMan help{"getblock",
830834
"\nIf verbosity is 0, returns a string that is serialized, hex-encoded data for block 'hash'.\n"
831835
"If verbosity is 1, returns an Object with information about block <hash>.\n"
832836
"If verbosity is 2, returns an Object with information about block <hash> and information about each transaction. \n",
@@ -878,9 +882,11 @@ static UniValue getblock(const JSONRPCRequest& request)
878882
HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
879883
+ HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
880884
},
881-
}.ToString());
885+
};
882886

883-
LOCK(cs_main);
887+
if (request.fHelp || !help.IsValidNumArgs(request.params.size())) {
888+
throw std::runtime_error(help.ToString());
889+
}
884890

885891
uint256 hash(ParseHashV(request.params[0], "blockhash"));
886892

@@ -892,12 +898,20 @@ static UniValue getblock(const JSONRPCRequest& request)
892898
verbosity = request.params[1].get_bool() ? 1 : 0;
893899
}
894900

895-
const CBlockIndex* pblockindex = LookupBlockIndex(hash);
896-
if (!pblockindex) {
897-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
898-
}
901+
CBlock block;
902+
const CBlockIndex* pblockindex;
903+
const CBlockIndex* tip;
904+
{
905+
LOCK(cs_main);
906+
pblockindex = LookupBlockIndex(hash);
907+
tip = chainActive.Tip();
908+
909+
if (!pblockindex) {
910+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
911+
}
899912

900-
const CBlock block = GetBlockChecked(pblockindex);
913+
block = GetBlockChecked(pblockindex);
914+
}
901915

902916
if (verbosity <= 0)
903917
{
@@ -907,7 +921,7 @@ static UniValue getblock(const JSONRPCRequest& request)
907921
return strHex;
908922
}
909923

910-
return blockToJSON(block, chainActive.Tip(), pblockindex, verbosity >= 2);
924+
return blockToJSON(block, tip, pblockindex, verbosity >= 2);
911925
}
912926

913927
struct CCoinsStats

src/rpc/blockchain.h

+8-4
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@
55
#ifndef BITCOIN_RPC_BLOCKCHAIN_H
66
#define BITCOIN_RPC_BLOCKCHAIN_H
77

8-
#include <vector>
9-
#include <stdint.h>
108
#include <amount.h>
9+
#include <sync.h>
10+
11+
#include <stdint.h>
12+
#include <vector>
13+
14+
extern RecursiveMutex cs_main;
1115

1216
class CBlock;
1317
class CBlockIndex;
@@ -28,7 +32,7 @@ double GetDifficulty(const CBlockIndex* blockindex);
2832
void RPCNotifyBlockChange(bool ibd, const CBlockIndex *);
2933

3034
/** Block description to JSON */
31-
UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIndex* blockindex, bool txDetails = false);
35+
UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIndex* blockindex, bool txDetails = false) LOCKS_EXCLUDED(cs_main);
3236

3337
/** Mempool information to JSON */
3438
UniValue MempoolInfoToJSON(const CTxMemPool& pool);
@@ -37,7 +41,7 @@ UniValue MempoolInfoToJSON(const CTxMemPool& pool);
3741
UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose = false);
3842

3943
/** Block header to JSON */
40-
UniValue blockheaderToJSON(const CBlockIndex* tip, const CBlockIndex* blockindex);
44+
UniValue blockheaderToJSON(const CBlockIndex* tip, const CBlockIndex* blockindex) LOCKS_EXCLUDED(cs_main);
4145

4246
/** Used by getblockstats to get feerates at different percentiles by weight */
4347
void CalculatePercentilesByWeight(CAmount result[NUM_GETBLOCKSTATS_PERCENTILES], std::vector<std::pair<CAmount, int64_t>>& scores, int64_t total_weight);

0 commit comments

Comments
 (0)