Skip to content

Commit

Permalink
rpc: Remove cs_main lock from TxToJSON
Browse files Browse the repository at this point in the history
  • Loading branch information
random-zebra committed Feb 1, 2022
1 parent fe7b1cf commit 5e0d308
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 24 deletions.
17 changes: 12 additions & 5 deletions src/rest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ struct CCoin {
}
};

extern void TxToJSON(CWallet* const pwallet, const CTransaction& tx, const uint256 hashBlock, UniValue& entry);
extern void TxToJSON(CWallet* const pwallet, const CTransaction& tx, const CBlockIndex* tip, const CBlockIndex* blockindex, UniValue& entry);
extern UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIndex* blockindex, bool txDetails = false);
extern UniValue mempoolInfoToJSON();
extern UniValue mempoolToJSON(bool fVerbose = false);
Expand Down Expand Up @@ -127,7 +127,7 @@ static bool rest_headers(HTTPRequest* req,
if (!ParseHashStr(hashStr, hash))
return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hashStr);

const CBlockIndex* tip = nullptr;
const CBlockIndex* tip;
std::vector<const CBlockIndex *> headers;
headers.reserve(count);
{
Expand Down Expand Up @@ -192,8 +192,8 @@ static bool rest_block(HTTPRequest* req,
return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hashStr);

CBlock block;
CBlockIndex* pblockindex = nullptr;
CBlockIndex* tip = nullptr;
const CBlockIndex* pblockindex;
const CBlockIndex* tip;
{
LOCK(cs_main);
tip = chainActive.Tip();
Expand Down Expand Up @@ -357,8 +357,15 @@ static bool rest_tx(HTTPRequest* req, const std::string& strURIPart)
}

case RF_JSON: {
const CBlockIndex* pblockindex;
const CBlockIndex* tip;
{
LOCK(cs_main);
tip = chainActive.Tip();
pblockindex = LookupBlockIndex(hashBlock);
}
UniValue objTx(UniValue::VOBJ);
WITH_LOCK(cs_main, TxToJSON(nullptr, *tx, hashBlock, objTx); );
TxToJSON(nullptr, *tx, tip, pblockindex, objTx);
std::string strJSON = objTx.write() + "\n";
req->WriteHeader("Content-Type", "application/json");
req->WriteReply(HTTP_OK, strJSON);
Expand Down
6 changes: 3 additions & 3 deletions src/rpc/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ static std::mutex cs_blockchange;
static std::condition_variable cond_blockchange;
static CUpdatedBlock latestblock;

extern void TxToJSON(CWallet* const pwallet, const CTransaction& tx, const uint256 hashBlock, UniValue& entry);
extern void TxToJSON(CWallet* const pwallet, const CTransaction& tx, const CBlockIndex* tip, const CBlockIndex* blockindex, UniValue& entry);

UniValue syncwithvalidationinterfacequeue(const JSONRPCRequest& request)
{
Expand Down Expand Up @@ -99,7 +99,7 @@ static UniValue ValuePoolDesc(
return rv;
}

static int ComputeNextBlockAndDepth(const CBlockIndex* tip, const CBlockIndex* blockindex, const CBlockIndex*& next)
int ComputeNextBlockAndDepth(const CBlockIndex* tip, const CBlockIndex* blockindex, const CBlockIndex*& next)
{
next = tip->GetAncestor(blockindex->nHeight + 1);
if (next && next->pprev == blockindex) {
Expand Down Expand Up @@ -153,7 +153,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIn
const CTransaction& tx = *txIn;
if (txDetails) {
UniValue objTx(UniValue::VOBJ);
TxToJSON(nullptr, tx, UINT256_ZERO, objTx);
TxToJSON(nullptr, tx, nullptr, nullptr, objTx);
txs.push_back(objTx);
} else
txs.push_back(tx.GetHash().GetHex());
Expand Down
37 changes: 21 additions & 16 deletions src/rpc/rawtransaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,17 @@ static void PayloadToJSON(const CTransaction& tx, UniValue& entry)
}
}

// pwallet can be nullptr. If not null, the json could include information available only to the wallet.
void TxToJSON(CWallet* const pwallet, const CTransaction& tx, const uint256 hashBlock, UniValue& entry) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
extern int ComputeNextBlockAndDepth(const CBlockIndex* tip, const CBlockIndex* blockindex, const CBlockIndex*& next);

static int ComputeConfirmations(const CBlockIndex* tip, const CBlockIndex* blockindex)
{
AssertLockHeld(cs_main);
const CBlockIndex* next{nullptr};
return ComputeNextBlockAndDepth(tip, blockindex, next);
}

// pwallet can be nullptr. If not null, the json could include information available only to the wallet.
void TxToJSON(CWallet* const pwallet, const CTransaction& tx, const CBlockIndex* tip, const CBlockIndex* blockindex, UniValue& entry)
{
// Call into TxToUniv() in bitcoin-common to decode the transaction hex.
//
// Blockchain contextual information (confirmations and blocktime) is not
Expand All @@ -99,17 +105,15 @@ void TxToJSON(CWallet* const pwallet, const CTransaction& tx, const uint256 hash
PayloadToJSON(tx, entry);
}

if (!hashBlock.IsNull()) {
entry.pushKV("blockhash", hashBlock.GetHex());
CBlockIndex* pindex = LookupBlockIndex(hashBlock);
if (pindex) {
if (chainActive.Contains(pindex)) {
entry.pushKV("confirmations", 1 + chainActive.Height() - pindex->nHeight);
entry.pushKV("time", pindex->GetBlockTime());
entry.pushKV("blocktime", pindex->GetBlockTime());
}
else
entry.pushKV("confirmations", 0);
if (blockindex && tip) {
entry.pushKV("blockhash", blockindex->GetBlockHash().ToString());
int confirmations = ComputeConfirmations(tip, blockindex);
if (confirmations != -1) {
entry.pushKV("confirmations", confirmations);
entry.pushKV("time", blockindex->GetBlockTime());
entry.pushKV("blocktime", blockindex->GetBlockTime());
} else {
entry.pushKV("confirmations", 0);
}
}
}
Expand Down Expand Up @@ -267,8 +271,9 @@ UniValue getrawtransaction(const JSONRPCRequest& request)

UniValue result(UniValue::VOBJ);
if (blockindex) result.pushKV("in_active_chain", in_active_chain);
else blockindex = LookupBlockIndex(hash_block);
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
TxToJSON(pwallet, *tx, hash_block, result);
TxToJSON(pwallet, *tx, chainActive.Tip(), blockindex, result);
return result;
}

Expand Down Expand Up @@ -437,7 +442,7 @@ UniValue decoderawtransaction(const JSONRPCRequest& request)

UniValue result(UniValue::VOBJ);
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
TxToJSON(pwallet, CTransaction(std::move(mtx)), UINT256_ZERO, result);
TxToJSON(pwallet, CTransaction(std::move(mtx)), nullptr, nullptr, result);

return result;
}
Expand Down

0 comments on commit 5e0d308

Please sign in to comment.