Resolve misc clang lock annotation warnings.
Double lock of cs_main can be replaced with an assertion.
blockheaderToJSON requires **not** holding cs_main.
cs_main is required for: GetBlocksToMaturity, GetAddressBalances,
IsSpent, and TestBlockValidity.
MODIFY
src/interfaces/wallet.cpp
src/interfaces/wallet.cpp
@@ -235,6 +235,7 @@ WalletTx MakeWalletTx(CHDWallet& wallet, MapRecords_t::const_iterator irtx)
//! Construct wallet tx status struct.
WalletTxStatus MakeWalletTxStatus(const CWalletTx& wtx)
{
+ LOCK(cs_main);
WalletTxStatus result;
auto mi = ::mapBlockIndex.find(wtx.hashBlock);
CBlockIndex* block = mi != ::mapBlockIndex.end() ? mi->second : nullptr;

MODIFY
src/miner.cpp
src/miner.cpp
@@ -499,7 +499,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
if(fProofOfFullNode && !fProofOfStake)
LogPrint(BCLog::BLOCKCREATION, "%s: A block can not be proof of full node and proof of work.\n", __func__);
else if(fProofOfFullNode && fProofOfStake) {
- LOCK(cs_main);
+ AssertLockHeld(cs_main);
pblock->hashPoFN = veil::GetFullNodeHash(*pblock, pindexPrev);
}

MODIFY
src/rpc/blockchain.cpp
src/rpc/blockchain.cpp
@@ -960,6 +960,9 @@ static UniValue getblockheader(const JSONRPCRequest& request)
+ HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
);
+ const CBlockIndex* pChainTip;
+ const CBlockIndex* pblockindex;
+ {
LOCK(cs_main);
std::string strHash = request.params[0].get_str();
@@ -969,7 +972,7 @@ static UniValue getblockheader(const JSONRPCRequest& request)
if (!request.params[1].isNull())
fVerbose = request.params[1].get_bool();
- const CBlockIndex* pblockindex = LookupBlockIndex(hash);
+ pblockindex = LookupBlockIndex(hash);
if (!pblockindex) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
}
@@ -982,7 +985,10 @@ static UniValue getblockheader(const JSONRPCRequest& request)
return strHex;
}
- return blockheaderToJSON(chainActive.Tip(), pblockindex);
+ pChainTip = chainActive.Tip();
+ }
+
+ return blockheaderToJSON(pChainTip, pblockindex);
}
static CBlock GetBlockChecked(const CBlockIndex* pblockindex)

MODIFY
src/wallet/rpcwallet.cpp
src/wallet/rpcwallet.cpp
@@ -721,7 +721,7 @@ static UniValue listaddresses(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_PARAMETER, type + " is not a valid address type");
}
}
- LOCK(pwallet->cs_wallet);
+ LOCK2(cs_main, pwallet->cs_wallet);
UniValue results(UniValue::VARR);
AnonWallet* pAnonWallet = wallet->GetAnonWallet();
@@ -2110,11 +2110,19 @@ static void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, const
{
if (wtx.GetDepthInMainChain() < 1)
entry.pushKV("category", "orphan");
- else if (wtx.GetBlocksToMaturity() > 0)
+ else
+ {
+ int nBlocksToMaturity;
+ {
+ LOCK(cs_main);
+ nBlocksToMaturity = wtx.GetBlocksToMaturity();
+ }
+ if (nBlocksToMaturity > 0)
entry.pushKV("category", "immature");
else
entry.pushKV("category", "generate");
}
+ }
else
{
entry.pushKV("category", "receive");

MODIFY
src/wallet/wallet.cpp
src/wallet/wallet.cpp
@@ -771,8 +771,10 @@ bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
}
}
- if (setAnonTx.count(hash))
+ if (setAnonTx.count(hash)) {
+ LOCK(cs_main);
return pAnonWalletMain->IsSpent(hash, n);
+ }
return false;
}
@@ -2310,9 +2312,12 @@ CAmount CWalletTx::GetDebit(const isminefilter& filter) const
CAmount CWalletTx::GetCredit(const isminefilter& filter, bool fResetCache) const
{
+ {
+ LOCK(cs_main);
// Must wait until coinbase is safely deep enough in the chain before valuing it
if (IsCoinBase() && GetBlocksToMaturity() > 0)
return 0;
+ }
CAmount credit = 0;
if (filter & ISMINE_SPENDABLE)
@@ -2345,6 +2350,7 @@ CAmount CWalletTx::GetCredit(const isminefilter& filter, bool fResetCache) const
CAmount CWalletTx::GetImmatureCredit(bool fUseCache) const
{
+ LOCK(cs_main);
if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
{
if (fUseCache && fImmatureCreditCached)
@@ -2362,9 +2368,12 @@ CAmount CWalletTx::GetAvailableCredit(bool fUseCache, const isminefilter& filter
if (pwallet == nullptr)
return 0;
+ {
+ LOCK(cs_main);
// Must wait until coinbase is safely deep enough in the chain before valuing it
if (IsCoinBase() && GetBlocksToMaturity() > 0)
return 0;
+ }
CAmount* cache = nullptr;
bool* cache_used = nullptr;
@@ -2408,6 +2417,7 @@ CAmount CWalletTx::GetAvailableCredit(bool fUseCache, const isminefilter& filter
CAmount CWalletTx::GetImmatureWatchOnlyCredit(const bool fUseCache) const
{
+ LOCK(cs_main);
if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
{
if (fUseCache && fImmatureWatchCreditCached)
@@ -4496,7 +4506,7 @@ std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
std::map<CTxDestination, CAmount> balances;
{
- LOCK(cs_wallet);
+ LOCK2(cs_main, cs_wallet);
for (const auto& walletEntry : mapWallet)
{
const CWalletTx *pcoin = &walletEntry.second;

Resolve misc clang lock annotation warnings.

- Double lock of cs_main can be replaced with an assertion.
- blockheaderToJSON requires **not** holding cs_main.
- cs_main is required for: GetBlocksToMaturity, GetAddressBalances,
  IsSpent, and TestBlockValidity.